mroccuper commited on
Commit
9abec8f
Β·
verified Β·
1 Parent(s): c5bbe4b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +111 -39
app.py CHANGED
@@ -1,12 +1,21 @@
1
  import os
2
  import gradio as gr
3
- import google.generativeai as genai
4
- from PIL import Image, ImageEnhance, ImageFilter
5
- import io
6
- import base64
7
  import json
8
  import time
9
  import traceback
 
 
 
 
 
 
 
 
 
 
 
 
10
  try:
11
  import pyperclip
12
  except ImportError:
@@ -15,6 +24,7 @@ except ImportError:
15
  # --- Environment Configuration ---
16
  GEMINI_KEY = os.environ.get("GEMINI_KEY", "")
17
  DEFAULT_PORT = int(os.environ.get("PORT", 7860))
 
18
 
19
  # --- Style Template Optimization ---
20
  BASE_TEMPLATE = """Describe this design as a concise Flux 1.1 Pro prompt focusing on:
@@ -50,11 +60,38 @@ Respond ONLY as JSON: {"score": x/10, "issues": [], "suggestions": []}"""
50
  @classmethod
51
  def validate(cls, prompt, model):
52
  try:
53
- response = model.generate_content([cls.VALIDATION_TEMPLATE, prompt])
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"""
@@ -73,17 +110,20 @@ def generate_prompt(image, api_key, style, creativity, neg_prompt, aspect, color
73
  try:
74
  # Validate inputs
75
  if not image:
76
- raise ValueError("Please upload an image")
77
 
78
  api_key = api_key or GEMINI_KEY
79
  if not api_key:
80
- raise ValueError("API key required - set in env (GEMINI_KEY) or input field")
81
 
82
- # Initialize model
83
- genai.configure(api_key=api_key)
84
- model = genai.GenerativeModel("gemini-1.5-pro")
 
 
85
 
86
- # Process image
 
87
  img = preprocess_image(image)
88
  img_bytes = io.BytesIO()
89
  img.save(img_bytes, format="PNG")
@@ -93,18 +133,33 @@ def generate_prompt(image, api_key, style, creativity, neg_prompt, aspect, color
93
  instruction = f"{STYLE_INSTRUCTIONS[style]}\nAVOID: {neg_prompt}\n"
94
  instruction += f"ASPECT: {aspect}, COLORS: {color_mode}, DPI: {dpi}\n"
95
 
96
- # Generate prompt
97
- response = model.generate_content(
98
- contents=[instruction, {"mime_type": "image/png", "data": img_b64}],
99
- generation_config={"temperature": creativity}
100
- )
101
- raw_prompt = response.text
102
-
103
- # Quality validation
104
- validation = QualityValidator.validate(raw_prompt, model)
105
- if validation.get("score", 0) < 7:
106
- response = model.generate_content(f"Improve this prompt: {raw_prompt}\nIssues: {validation['issues']}")
107
  raw_prompt = response.text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
 
109
  # Token tracking
110
  input_tokens = len(img_b64) // 4 # Approximate base64 token count
@@ -127,14 +182,26 @@ def create_advanced_controls():
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",
@@ -159,6 +226,7 @@ def build_interface():
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(
@@ -168,7 +236,6 @@ def build_interface():
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
@@ -178,25 +245,30 @@ def build_interface():
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()
 
1
  import os
2
  import gradio as gr
3
+ import requests
 
 
 
4
  import json
5
  import time
6
  import traceback
7
+ import io
8
+ import base64
9
+ from PIL import Image, ImageEnhance, ImageFilter
10
+
11
+ # Conditional imports
12
+ try:
13
+ import google.generativeai as genai
14
+ GENAI_AVAILABLE = True
15
+ except ImportError:
16
+ GENAI_AVAILABLE = False
17
+ print("Warning: google-generativeai not installed, will attempt on-demand import")
18
+
19
  try:
20
  import pyperclip
21
  except ImportError:
 
24
  # --- Environment Configuration ---
25
  GEMINI_KEY = os.environ.get("GEMINI_KEY", "")
26
  DEFAULT_PORT = int(os.environ.get("PORT", 7860))
27
+ API_TIMEOUT = 30 # seconds
28
 
29
  # --- Style Template Optimization ---
30
  BASE_TEMPLATE = """Describe this design as a concise Flux 1.1 Pro prompt focusing on:
 
60
  @classmethod
61
  def validate(cls, prompt, model):
62
  try:
63
+ with gr.utils.TempFiles() as temp:
64
+ response = model.generate_content([cls.VALIDATION_TEMPLATE, prompt])
65
+ return json.loads(response.text)
66
+ except Exception as e:
67
+ print(f"Validation error: {str(e)}")
68
  return {"score": 0, "issues": ["Validation failed"], "suggestions": []}
69
 
70
+ # --- Lazy API Initialization ---
71
+ def init_genai_api(api_key):
72
+ """Initialize Gemini API with error handling"""
73
+ if not GENAI_AVAILABLE:
74
+ try:
75
+ # Attempt dynamic import
76
+ global genai
77
+ import google.generativeai as genai
78
+ except ImportError:
79
+ raise ValueError("Failed to import google.generativeai. Install with: pip install google-generativeai")
80
+
81
+ try:
82
+ genai.configure(api_key=api_key)
83
+ # Test connection with minimal request
84
+ model = genai.GenerativeModel("gemini-1.5-pro")
85
+ model.generate_content("test", request_options={"timeout": 5})
86
+ return model
87
+ except Exception as e:
88
+ if "authentication" in str(e).lower():
89
+ raise ValueError("Invalid API key or authentication error")
90
+ elif "timeout" in str(e).lower():
91
+ raise ValueError("API connection timeout - check your internet connection")
92
+ else:
93
+ raise ValueError(f"API initialization error: {str(e)}")
94
+
95
  # --- Image Processing Pipeline ---
96
  def preprocess_image(img):
97
  """Convert and enhance uploaded images"""
 
110
  try:
111
  # Validate inputs
112
  if not image:
113
+ return {"error": "Please upload an image"}
114
 
115
  api_key = api_key or GEMINI_KEY
116
  if not api_key:
117
+ return {"error": "API key required - set in env (GEMINI_KEY) or input field"}
118
 
119
+ # Initialize model with proper error handling
120
+ try:
121
+ model = init_genai_api(api_key)
122
+ except ValueError as e:
123
+ return {"error": str(e)}
124
 
125
+ # Process image with timeout protection
126
+ start_time = time.time()
127
  img = preprocess_image(image)
128
  img_bytes = io.BytesIO()
129
  img.save(img_bytes, format="PNG")
 
133
  instruction = f"{STYLE_INSTRUCTIONS[style]}\nAVOID: {neg_prompt}\n"
134
  instruction += f"ASPECT: {aspect}, COLORS: {color_mode}, DPI: {dpi}\n"
135
 
136
+ # Generate prompt with timeout protection
137
+ try:
138
+ response = model.generate_content(
139
+ contents=[instruction, {"mime_type": "image/png", "data": img_b64}],
140
+ generation_config={"temperature": creativity},
141
+ request_options={"timeout": API_TIMEOUT}
142
+ )
 
 
 
 
143
  raw_prompt = response.text
144
+ except requests.exceptions.Timeout:
145
+ return {"error": "API request timed out (>30s). Try a smaller image or check your connection."}
146
+ except Exception as e:
147
+ return {"error": f"Generation failed: {str(e)}"}
148
+
149
+ # Quality validation (skip if taking too long)
150
+ validation = {"score": 8, "issues": [], "suggestions": []}
151
+ if time.time() - start_time < 20: # Only validate if we have time
152
+ try:
153
+ validation = QualityValidator.validate(raw_prompt, model)
154
+ if validation.get("score", 0) < 7:
155
+ response = model.generate_content(
156
+ f"Improve this prompt: {raw_prompt}\nIssues: {validation['issues']}",
157
+ request_options={"timeout": 10}
158
+ )
159
+ raw_prompt = response.text
160
+ except:
161
+ # Continue even if validation fails
162
+ pass
163
 
164
  # Token tracking
165
  input_tokens = len(img_b64) // 4 # Approximate base64 token count
 
182
  creativity = gr.Slider(0.0, 1.0, 0.7, label="Creativity Level")
183
  neg_prompt = gr.Textbox(label="🚫 Negative Prompts", placeholder="What to avoid")
184
  with gr.Row():
185
+ aspect = gr.Dropdown(FLUX_SPECS["aspect_ratios"], value="1:1", label="Aspect Ratio")
186
+ color_mode = gr.Dropdown(FLUX_SPECS["color_modes"], value="RGB", label="Color Mode")
187
+ dpi = gr.Dropdown([str(d) for d in FLUX_SPECS["dpi_options"]], value="300", label="Output DPI")
188
  return [creativity, neg_prompt, aspect, color_mode, dpi]
189
 
190
+ # --- UI Response Formatting ---
191
+ def format_generation_response(result):
192
+ """Format the response from generate_prompt for the UI"""
193
+ if "error" in result:
194
+ return result["error"], None, None
195
+ else:
196
+ return result.get("prompt", ""), result.get("validation", {}), result.get("stats", {})
197
+
198
  # --- Main Interface ---
199
  def build_interface():
200
  with gr.Blocks(title="Flux Pro Generator", theme=gr.themes.Soft()) as app:
201
+ # Header
202
+ gr.Markdown("# 🎨 Flux Pro Prompt Generator")
203
+ gr.Markdown("Generate optimized design prompts from images using Google's Gemini")
204
+
205
  # Security Section
206
  api_key = gr.Textbox(
207
  label="πŸ”‘ Gemini API Key",
 
226
  )
227
  adv_controls = create_advanced_controls()
228
  gen_btn = gr.Button("✨ Generate Prompt", variant="primary")
229
+ status_msg = gr.Textbox(label="Status", visible=True)
230
 
231
  with gr.Column(scale=2):
232
  prompt_output = gr.Textbox(
 
236
  )
237
  with gr.Row():
238
  copy_btn = gr.Button("πŸ“‹ Copy")
 
239
  quality_report = gr.JSON(
240
  label="πŸ” Quality Report",
241
  visible=True
 
245
  visible=True
246
  )
247
 
 
 
 
248
  # Event Handling
249
  gen_btn.click(
250
+ lambda *args: format_generation_response(generate_prompt(*args)),
251
  inputs=[img_input, api_key, style] + adv_controls,
252
+ outputs=[prompt_output, quality_report, token_stats],
253
+ api_name="generate"
254
  )
255
 
256
+ if pyperclip:
257
+ copy_btn.click(
258
+ lambda x: pyperclip.copy(x) if x else None,
259
+ inputs=prompt_output,
260
+ outputs=None
261
+ )
262
+ else:
263
+ copy_btn.click(
264
+ lambda: "Copy functionality not available (pyperclip not installed)",
265
+ inputs=None,
266
+ outputs=status_msg
267
+ )
268
 
269
  return app
270
 
271
  # --- Production Launch ---
272
  if __name__ == "__main__":
273
  app = build_interface()
274
+ app.launch(server_name="0.0.0.0", server_port=DEFAULT_PORT, share=False)