mroccuper commited on
Commit
bc1dcdf
ยท
verified ยท
1 Parent(s): 70ebe1c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +65 -69
app.py CHANGED
@@ -37,7 +37,6 @@ FLUX_SPECS = {
37
 
38
  # --- Image Processing Pipeline ---
39
  def preprocess_image(img):
40
- """Convert and enhance uploaded images"""
41
  try:
42
  if isinstance(img, str): # Handle file paths
43
  img = Image.open(img)
@@ -46,44 +45,49 @@ def preprocess_image(img):
46
  img = img.filter(ImageFilter.SHARPEN)
47
  return img
48
  except Exception as e:
49
- raise ValueError(f"Image processing error: {str(e)}")
50
 
51
  # --- Core Generation Engine ---
52
  def generate_prompt(image, api_key, style, creativity, neg_prompt, aspect, color_mode, dpi):
53
  try:
54
- # Validate inputs
55
  if not image:
56
- return {"error": "Please upload an image"}
57
-
58
  api_key = api_key or GEMINI_KEY
59
  if not api_key:
60
- return {"error": "API key required - set in env (GEMINI_KEY) or input field"}
61
 
62
- # Import and configure Gemini only when needed
63
  try:
64
  import google.generativeai as genai
65
  genai.configure(api_key=api_key)
66
  model = genai.GenerativeModel("gemini-1.5-pro")
67
  except ImportError:
68
- return {"error": "Failed to import google.generativeai. Install with: pip install google-generativeai"}
69
  except Exception as e:
70
  if "authentication" in str(e).lower():
71
- return {"error": "Invalid API key or authentication error"}
72
  else:
73
- return {"error": f"API initialization error: {str(e)}"}
74
 
75
- # Process image with timeout protection
76
- start_time = time.time()
77
- img = preprocess_image(image)
78
- img_bytes = io.BytesIO()
79
- img.save(img_bytes, format="PNG")
80
- img_b64 = base64.b64encode(img_bytes.getvalue()).decode()
 
 
81
 
82
- # Build instruction
83
- instruction = f"{STYLE_INSTRUCTIONS[style]}\nAVOID: {neg_prompt}\n"
84
- instruction += f"ASPECT: {aspect}, COLORS: {color_mode}, DPI: {dpi}\n"
 
 
 
85
 
86
- # Generate prompt with timeout protection
87
  try:
88
  response = model.generate_content(
89
  contents=[instruction, {"mime_type": "image/png", "data": img_b64}],
@@ -91,121 +95,113 @@ def generate_prompt(image, api_key, style, creativity, neg_prompt, aspect, color
91
  )
92
  raw_prompt = response.text
93
  except Exception as e:
94
- return {"error": f"Generation failed: {str(e)}"}
95
 
96
- # Simple quality validation
97
  validation = {"score": 8, "issues": [], "suggestions": []}
98
-
99
- # Token tracking
100
- input_tokens = len(img_b64) // 4 # Approximate base64 token count
101
  output_tokens = len(raw_prompt.split())
102
-
103
  return {
104
  "prompt": raw_prompt,
105
  "validation": validation,
106
  "stats": {"input": input_tokens, "output": output_tokens}
107
- }
108
 
109
  except Exception as e:
110
  traceback.print_exc()
111
- return {"error": str(e)}
112
 
113
- # --- UI Response Formatting ---
114
- def format_generation_response(result):
115
- """Format the response from generate_prompt for the UI"""
116
- if "error" in result:
117
- return result["error"], None, None
118
- else:
119
- return result.get("prompt", ""), result.get("validation", {}), result.get("stats", {})
120
 
121
- # Modern copy function using Gradio's JavaScript API
122
  def copy_text(text):
123
- return gr.update(value=text), f"โœ“ Copied: '{text[:20]}...'", gr.Button.update(variant="secondary")
 
124
 
125
  # --- Main Interface ---
126
  def build_interface():
 
 
127
  with gr.Blocks(title="Flux Pro Generator", theme="soft") as app:
128
- # Header
129
  gr.Markdown("# ๐ŸŽจ Flux Pro Prompt Generator")
130
- gr.Markdown("Generate optimized design prompts from images using Google's Gemini")
131
-
132
- # Security Section
133
- api_key = gr.Textbox(
134
- label="๐Ÿ”‘ Gemini API Key",
135
- value=GEMINI_KEY,
136
- type="password",
137
- info="Set GEMINI_KEY environment variable for production"
138
- )
139
 
140
- # Main Workflow
141
  with gr.Row():
142
  with gr.Column(scale=1):
 
 
 
 
 
 
 
143
  img_input = gr.Image(
144
  label="๐Ÿ–ผ๏ธ Upload Design",
145
  type="pil",
146
  sources=["upload"],
147
  interactive=True
148
  )
 
149
  style = gr.Dropdown(
150
  list(STYLE_INSTRUCTIONS.keys()),
151
  value="General",
152
  label="๐ŸŽจ Target Style"
153
  )
154
-
155
- # Advanced Settings
156
  with gr.Accordion("โš™๏ธ Advanced Settings", open=False):
157
- creativity = gr.Slider(0.0, 1.0, 0.7, label="Creativity Level")
158
  neg_prompt = gr.Textbox(label="๐Ÿšซ Negative Prompts", placeholder="What to avoid")
159
  aspect = gr.Dropdown(FLUX_SPECS["aspect_ratios"], value="1:1", label="Aspect Ratio")
160
  color_mode = gr.Dropdown(FLUX_SPECS["color_modes"], value="RGB", label="Color Mode")
161
  dpi = gr.Dropdown([str(d) for d in FLUX_SPECS["dpi_options"]], value="300", label="Output DPI")
162
-
163
  gen_btn = gr.Button("โœจ Generate Prompt", variant="primary")
164
 
165
  with gr.Column(scale=2):
 
 
166
  prompt_output = gr.Textbox(
167
  label="๐Ÿ“ Optimized Prompt",
168
  lines=8,
169
  interactive=True,
170
- show_copy_button=True # Modern Gradio has built-in copy button
171
  )
172
- status_msg = gr.Textbox(label="Status", visible=True)
173
  with gr.Row():
174
  copy_btn = gr.Button("๐Ÿ“‹ Copy to Clipboard", variant="secondary")
175
-
176
- quality_report = gr.JSON(
177
- label="๐Ÿ” Quality Report",
178
- visible=True
179
- )
180
- token_stats = gr.JSON(
181
- label="๐Ÿงฎ Token Usage",
182
- visible=True
183
- )
184
-
185
  # Event Handling
186
  gen_btn.click(
187
  fn=generate_prompt,
188
  inputs=[
189
- img_input, api_key, style, creativity,
190
  neg_prompt, aspect, color_mode, dpi
191
  ],
192
  outputs=[prompt_output, quality_report, token_stats],
193
  api_name="generate"
194
  ).then(
195
- fn=lambda: gr.update(value="Generation complete!"),
196
  outputs=status_msg
197
  )
198
-
199
- # Modern copy implementation
200
  copy_btn.click(
201
  fn=copy_text,
202
  inputs=prompt_output,
203
  outputs=[prompt_output, status_msg, copy_btn],
204
- js="(text) => { if(text) { navigator.clipboard.writeText(text); } return [text]; }"
 
 
 
 
 
205
  )
206
 
207
  return app
208
 
 
209
  # --- Production Launch ---
210
  if __name__ == "__main__":
211
  app = build_interface()
 
37
 
38
  # --- Image Processing Pipeline ---
39
  def preprocess_image(img):
 
40
  try:
41
  if isinstance(img, str): # Handle file paths
42
  img = Image.open(img)
 
45
  img = img.filter(ImageFilter.SHARPEN)
46
  return img
47
  except Exception as e:
48
+ raise ValueError(f"๐Ÿ”ด Image processing failed: {str(e)}")
49
 
50
  # --- Core Generation Engine ---
51
  def generate_prompt(image, api_key, style, creativity, neg_prompt, aspect, color_mode, dpi):
52
  try:
53
+ # Step 1: Input Validation
54
  if not image:
55
+ return {"error": "โš ๏ธ Please upload an image."}, None, None
56
+
57
  api_key = api_key or GEMINI_KEY
58
  if not api_key:
59
+ return {"error": "๐Ÿ”‘ API key required - set in env (GEMINI_KEY) or input field."}, None, None
60
 
61
+ # Step 2: Gemini Setup
62
  try:
63
  import google.generativeai as genai
64
  genai.configure(api_key=api_key)
65
  model = genai.GenerativeModel("gemini-1.5-pro")
66
  except ImportError:
67
+ return {"error": "๐Ÿšซ Failed to import google.generativeai. Install with: pip install google-generativeai"}, None, None
68
  except Exception as e:
69
  if "authentication" in str(e).lower():
70
+ return {"error": "๐Ÿ” Invalid API key or authentication error"}, None, None
71
  else:
72
+ return {"error": f"โš™๏ธ API initialization error: {str(e)}"}, None, None
73
 
74
+ # Step 3: Preprocess Image
75
+ try:
76
+ img = preprocess_image(image)
77
+ img_bytes = io.BytesIO()
78
+ img.save(img_bytes, format="PNG")
79
+ img_b64 = base64.b64encode(img_bytes.getvalue()).decode()
80
+ except Exception as e:
81
+ return {"error": f"๐Ÿ–ผ๏ธ Image preparation failed: {str(e)}"}, None, None
82
 
83
+ # Step 4: Build Instruction Prompt
84
+ try:
85
+ instruction = f"{STYLE_INSTRUCTIONS[style]}\nAVOID: {neg_prompt}\n"
86
+ instruction += f"ASPECT: {aspect}, COLORS: {color_mode}, DPI: {dpi}\n"
87
+ except KeyError:
88
+ return {"error": "๐Ÿ› ๏ธ Invalid style selected. Please choose from available options."}, None, None
89
 
90
+ # Step 5: Call Gemini API
91
  try:
92
  response = model.generate_content(
93
  contents=[instruction, {"mime_type": "image/png", "data": img_b64}],
 
95
  )
96
  raw_prompt = response.text
97
  except Exception as e:
98
+ return {"error": f"๐Ÿค– Prompt generation failed: {str(e)}"}, None, None
99
 
100
+ # Step 6: Quality & Token Stats
101
  validation = {"score": 8, "issues": [], "suggestions": []}
102
+ input_tokens = len(img_b64) // 4
 
 
103
  output_tokens = len(raw_prompt.split())
104
+
105
  return {
106
  "prompt": raw_prompt,
107
  "validation": validation,
108
  "stats": {"input": input_tokens, "output": output_tokens}
109
+ }, validation, {"tokens": f"Input: {input_tokens}, Output: {output_tokens}"}
110
 
111
  except Exception as e:
112
  traceback.print_exc()
113
+ return {"error": f"๐Ÿ’ฅ Unexpected error: {str(e)}"}, None, None
114
 
 
 
 
 
 
 
 
115
 
116
+ # --- Modern Copy Function ---
117
  def copy_text(text):
118
+ return text, "โœ“ Copied to clipboard!", gr.Button.update(variant="secondary")
119
+
120
 
121
  # --- Main Interface ---
122
  def build_interface():
123
+ global STYLE_INSTRUCTIONS # Ensure access to global dict
124
+
125
  with gr.Blocks(title="Flux Pro Generator", theme="soft") as app:
 
126
  gr.Markdown("# ๐ŸŽจ Flux Pro Prompt Generator")
127
+ gr.Markdown("Generate optimized design prompts from images using Google's Gemini.")
 
 
 
 
 
 
 
 
128
 
 
129
  with gr.Row():
130
  with gr.Column(scale=1):
131
+ api_key = gr.Textbox(
132
+ label="๐Ÿ”‘ Gemini API Key",
133
+ value=GEMINI_KEY,
134
+ type="password",
135
+ info="Set GEMINI_KEY environment variable for production."
136
+ )
137
+
138
  img_input = gr.Image(
139
  label="๐Ÿ–ผ๏ธ Upload Design",
140
  type="pil",
141
  sources=["upload"],
142
  interactive=True
143
  )
144
+
145
  style = gr.Dropdown(
146
  list(STYLE_INSTRUCTIONS.keys()),
147
  value="General",
148
  label="๐ŸŽจ Target Style"
149
  )
150
+
 
151
  with gr.Accordion("โš™๏ธ Advanced Settings", open=False):
152
+ creativity = gr.Slider(0.0, 1.0, 0.7, label="๐Ÿง  Creativity Level")
153
  neg_prompt = gr.Textbox(label="๐Ÿšซ Negative Prompts", placeholder="What to avoid")
154
  aspect = gr.Dropdown(FLUX_SPECS["aspect_ratios"], value="1:1", label="Aspect Ratio")
155
  color_mode = gr.Dropdown(FLUX_SPECS["color_modes"], value="RGB", label="Color Mode")
156
  dpi = gr.Dropdown([str(d) for d in FLUX_SPECS["dpi_options"]], value="300", label="Output DPI")
157
+
158
  gen_btn = gr.Button("โœจ Generate Prompt", variant="primary")
159
 
160
  with gr.Column(scale=2):
161
+ status_msg = gr.Textbox(label="๐Ÿ“ข Status", interactive=False)
162
+
163
  prompt_output = gr.Textbox(
164
  label="๐Ÿ“ Optimized Prompt",
165
  lines=8,
166
  interactive=True,
167
+ show_copy_button=True
168
  )
169
+
170
  with gr.Row():
171
  copy_btn = gr.Button("๐Ÿ“‹ Copy to Clipboard", variant="secondary")
172
+
173
+ quality_report = gr.JSON(label="๐Ÿ” Quality Report")
174
+ token_stats = gr.JSON(label="๐Ÿงฎ Token Usage")
175
+
 
 
 
 
 
 
176
  # Event Handling
177
  gen_btn.click(
178
  fn=generate_prompt,
179
  inputs=[
180
+ img_input, api_key, style, creativity,
181
  neg_prompt, aspect, color_mode, dpi
182
  ],
183
  outputs=[prompt_output, quality_report, token_stats],
184
  api_name="generate"
185
  ).then(
186
+ fn=lambda: "โœ… Prompt generated successfully!",
187
  outputs=status_msg
188
  )
189
+
 
190
  copy_btn.click(
191
  fn=copy_text,
192
  inputs=prompt_output,
193
  outputs=[prompt_output, status_msg, copy_btn],
194
+ js="""
195
+ (text) => {
196
+ if(text) navigator.clipboard.writeText(text);
197
+ return [text, 'โœ“ Copied!', { variant: 'secondary' }];
198
+ }
199
+ """
200
  )
201
 
202
  return app
203
 
204
+
205
  # --- Production Launch ---
206
  if __name__ == "__main__":
207
  app = build_interface()