Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1,210 +1,76 @@
|
|
1 |
import os
|
2 |
import gradio as gr
|
3 |
import google.generativeai as genai
|
4 |
-
from PIL import Image
|
5 |
import io
|
6 |
import base64
|
7 |
-
import json
|
8 |
import time
|
9 |
-
import traceback
|
10 |
-
try:
|
11 |
-
import pyperclip
|
12 |
-
except ImportError:
|
13 |
-
pyperclip = None
|
14 |
|
15 |
-
#
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
# --- Style Template Optimization ---
|
20 |
-
BASE_TEMPLATE = """Describe this design as a concise Flux 1.1 Pro prompt focusing on:
|
21 |
-
- Key visual elements
|
22 |
-
- Technical specifications
|
23 |
-
- Style consistency
|
24 |
-
- Functional requirements"""
|
25 |
|
|
|
26 |
STYLE_INSTRUCTIONS = {
|
27 |
-
"General":
|
28 |
-
"
|
29 |
-
"
|
30 |
-
"Vector": f"{BASE_TEMPLATE}\nVECTOR RULES: Clean lines, geometric shapes, B&W gradients",
|
31 |
-
"Silhouette": f"{BASE_TEMPLATE}\nSILHOUETTE RULES: High contrast, minimal details, strong outlines"
|
32 |
-
}
|
33 |
-
|
34 |
-
# --- Flux Configuration ---
|
35 |
-
FLUX_SPECS = {
|
36 |
-
"aspect_ratios": ["1:1", "16:9", "4:3", "9:16"],
|
37 |
-
"formats": ["SVG", "PNG", "PDF"],
|
38 |
-
"color_modes": ["B&W", "CMYK", "RGB"],
|
39 |
-
"dpi_options": [72, 150, 300, 600]
|
40 |
}
|
41 |
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
3. Suggest improvements
|
48 |
-
Respond ONLY as JSON: {"score": x/10, "issues": [], "suggestions": []}"""
|
49 |
|
50 |
-
|
51 |
-
|
52 |
try:
|
53 |
-
|
54 |
-
return json.loads(response.text)
|
55 |
-
except:
|
56 |
-
return {"score": 0, "issues": ["Validation failed"], "suggestions": []}
|
57 |
-
|
58 |
-
# --- Image Processing Pipeline ---
|
59 |
-
def preprocess_image(img):
|
60 |
-
"""Convert and enhance uploaded images"""
|
61 |
-
try:
|
62 |
-
if isinstance(img, str): # Handle file paths
|
63 |
-
img = Image.open(img)
|
64 |
-
img = img.convert("RGB")
|
65 |
-
img = ImageEnhance.Contrast(img).enhance(1.2)
|
66 |
-
img = img.filter(ImageFilter.SHARPEN)
|
67 |
-
return img
|
68 |
-
except Exception as e:
|
69 |
-
raise ValueError(f"Image processing error: {str(e)}")
|
70 |
-
|
71 |
-
# --- Core Generation Engine ---
|
72 |
-
def generate_prompt(image, api_key, style, creativity, neg_prompt, aspect, color_mode, dpi):
|
73 |
-
try:
|
74 |
-
# Validate inputs
|
75 |
-
if not image:
|
76 |
-
raise ValueError("Please upload an image")
|
77 |
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
def create_advanced_controls():
|
125 |
-
with gr.Accordion("⚙️ Advanced Settings", open=False):
|
126 |
-
with gr.Row():
|
127 |
-
creativity = gr.Slider(0.0, 1.0, 0.7, label="Creativity Level")
|
128 |
-
neg_prompt = gr.Textbox(label="🚫 Negative Prompts", placeholder="What to avoid")
|
129 |
-
with gr.Row():
|
130 |
-
aspect = gr.Dropdown(FLUX_SPECS["aspect_ratios"], label="Aspect Ratio")
|
131 |
-
color_mode = gr.Dropdown(FLUX_SPECS["color_modes"], label="Color Mode")
|
132 |
-
dpi = gr.Dropdown(FLUX_SPECS["dpi_options"], label="Output DPI")
|
133 |
-
return [creativity, neg_prompt, aspect, color_mode, dpi]
|
134 |
-
|
135 |
-
# --- Main Interface ---
|
136 |
-
def build_interface():
|
137 |
-
with gr.Blocks(title="Flux Pro Generator", theme=gr.themes.Soft()) as app:
|
138 |
-
# Security Section
|
139 |
-
api_key = gr.Textbox(
|
140 |
-
label="🔑 Gemini API Key",
|
141 |
-
value=GEMINI_KEY,
|
142 |
-
type="password",
|
143 |
-
info="Set GEMINI_KEY environment variable for production"
|
144 |
-
)
|
145 |
-
|
146 |
-
# Main Workflow
|
147 |
-
with gr.Row(variant="panel"):
|
148 |
-
with gr.Column(scale=1):
|
149 |
-
img_input = gr.Image(
|
150 |
-
label="🖼️ Upload Design",
|
151 |
-
type="pil",
|
152 |
-
sources=["upload"],
|
153 |
-
interactive=True
|
154 |
-
)
|
155 |
-
style = gr.Dropdown(
|
156 |
-
list(STYLE_INSTRUCTIONS.keys()),
|
157 |
-
value="General",
|
158 |
-
label="🎨 Target Style"
|
159 |
-
)
|
160 |
-
adv_controls = create_advanced_controls()
|
161 |
-
gen_btn = gr.Button("✨ Generate Prompt", variant="primary")
|
162 |
-
|
163 |
-
with gr.Column(scale=2):
|
164 |
-
prompt_output = gr.Textbox(
|
165 |
-
label="📝 Optimized Prompt",
|
166 |
-
lines=8,
|
167 |
-
interactive=False
|
168 |
-
)
|
169 |
-
with gr.Row():
|
170 |
-
copy_btn = gr.Button("📋 Copy")
|
171 |
-
history_btn = gr.Button("🕒 History")
|
172 |
-
quality_report = gr.JSON(
|
173 |
-
label="🔍 Quality Report",
|
174 |
-
visible=True
|
175 |
-
)
|
176 |
-
token_stats = gr.JSON(
|
177 |
-
label="🧮 Token Usage",
|
178 |
-
visible=True
|
179 |
-
)
|
180 |
-
|
181 |
-
# History System
|
182 |
-
history = gr.State([])
|
183 |
-
|
184 |
-
# Event Handling
|
185 |
-
gen_btn.click(
|
186 |
-
lambda *args: generate_prompt(*args),
|
187 |
-
inputs=[img_input, api_key, style] + adv_controls,
|
188 |
-
outputs=[prompt_output, quality_report, token_stats]
|
189 |
-
)
|
190 |
-
|
191 |
-
copy_btn.click(
|
192 |
-
lambda x: pyperclip.copy(x) if pyperclip else None,
|
193 |
-
inputs=prompt_output,
|
194 |
-
outputs=None
|
195 |
-
)
|
196 |
-
|
197 |
-
return app
|
198 |
-
|
199 |
-
# --- Production Launch ---
|
200 |
-
if __name__ == "__main__":
|
201 |
-
app = build_interface()
|
202 |
-
app.launch(
|
203 |
-
server_name="0.0.0.0",
|
204 |
-
server_port=DEFAULT_PORT,
|
205 |
-
share=False,
|
206 |
-
auth=(
|
207 |
-
os.environ.get("APP_USER", "admin"),
|
208 |
-
os.environ.get("APP_PWD", "admin")
|
209 |
-
) if os.environ.get("ENV") == "prod" else None
|
210 |
-
)
|
|
|
1 |
import os
|
2 |
import gradio as gr
|
3 |
import google.generativeai as genai
|
4 |
+
from PIL import Image
|
5 |
import io
|
6 |
import base64
|
|
|
7 |
import time
|
|
|
|
|
|
|
|
|
|
|
8 |
|
9 |
+
# Configuration optimized for Hugging Face
|
10 |
+
MAX_RETRIES = 3
|
11 |
+
TIMEOUT = 10 # Keep under 20s Hugging Face limit
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
|
13 |
+
# Simplified style instructions for faster processing
|
14 |
STYLE_INSTRUCTIONS = {
|
15 |
+
"General": "Describe as Flux prompt focusing on key elements",
|
16 |
+
"Vector": "Clean vector style with sharp lines and B&W",
|
17 |
+
"Realistic": "Photorealistic details with accurate textures",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
}
|
19 |
|
20 |
+
def optimize_image(img):
|
21 |
+
"""Fast image optimization for web"""
|
22 |
+
img = img.convert("RGB")
|
23 |
+
img.thumbnail((512, 512)) # Reduce image size
|
24 |
+
return img
|
|
|
|
|
25 |
|
26 |
+
def generate_prompt(image, api_key, style):
|
27 |
+
for attempt in range(MAX_RETRIES):
|
28 |
try:
|
29 |
+
start_time = time.time()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
|
31 |
+
# Configure API
|
32 |
+
genai.configure(api_key=api_key)
|
33 |
+
model = genai.GenerativeModel('gemini-pro-vision')
|
34 |
+
|
35 |
+
# Optimize image
|
36 |
+
img = optimize_image(image)
|
37 |
+
img_byte_arr = io.BytesIO()
|
38 |
+
img.save(img_byte_arr, format='JPEG', quality=85)
|
39 |
+
|
40 |
+
# Timeout control
|
41 |
+
if time.time() - start_time > TIMEOUT - 2:
|
42 |
+
raise TimeoutError("Image processing too slow")
|
43 |
+
|
44 |
+
response = model.generate_content([
|
45 |
+
STYLE_INSTRUCTIONS[style],
|
46 |
+
{"mime_type": "image/jpeg", "data": img_byte_arr.getvalue()}
|
47 |
+
], request_options={"timeout": TIMEOUT})
|
48 |
+
|
49 |
+
return response.text
|
50 |
+
|
51 |
+
except Exception as e:
|
52 |
+
if attempt == MAX_RETRIES - 1:
|
53 |
+
return f"Error: {str(e)}"
|
54 |
+
time.sleep(1)
|
55 |
+
|
56 |
+
# Hugging Face optimized interface
|
57 |
+
with gr.Blocks() as app:
|
58 |
+
gr.Markdown("## 🚀 HF-Friendly Flux Generator")
|
59 |
+
|
60 |
+
with gr.Row():
|
61 |
+
api_key = gr.Textbox(label="Gemini Key", type="password")
|
62 |
+
style = gr.Dropdown(list(STYLE_INSTRUCTIONS), label="Style")
|
63 |
+
|
64 |
+
image_input = gr.Image(type="pil", label="Upload Design")
|
65 |
+
generate_btn = gr.Button("Generate", variant="primary")
|
66 |
+
output = gr.Textbox(label="Prompt", interactive=False)
|
67 |
+
|
68 |
+
generate_btn.click(
|
69 |
+
generate_prompt,
|
70 |
+
inputs=[image_input, api_key, style],
|
71 |
+
outputs=output,
|
72 |
+
concurrency_limit=3 # Better HF resource management
|
73 |
+
)
|
74 |
+
|
75 |
+
# HF-specific launch settings
|
76 |
+
app.queue(concurrency_count=3, max_size=20).launch(debug=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|