mroccuper commited on
Commit
19338e6
ยท
verified ยท
1 Parent(s): 83a7945

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +186 -86
app.py CHANGED
@@ -1,102 +1,202 @@
1
  import os
2
  import gradio as gr
3
  import google.generativeai as genai
4
- from PIL import Image
5
  import io
 
 
6
  import time
 
 
 
 
 
7
 
8
- # Hugging Face-safe configuration
9
- MAX_SIZE = 768
10
- TIMEOUT = 15
11
- CONCURRENCY = 2 # Reduced for HF stability
 
 
 
 
 
 
12
 
13
  STYLE_INSTRUCTIONS = {
14
- "General": "Describe this design concisely for Flux",
15
- "Vector": "Clean vector style with sharp lines",
16
- "Realistic": "Photorealistic details",
17
- "Kawaii": "Cute cartoon style with pastel colors"
 
 
 
 
 
 
 
 
 
18
  }
19
 
20
- def hf_safe_generate(image, api_key, style):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  try:
22
- start_time = time.time()
23
-
24
- # Convert and resize image
25
- img = image.convert("RGB")
26
- img.thumbnail((MAX_SIZE, MAX_SIZE))
27
- buffer = io.BytesIO()
28
- img.save(buffer, format="JPEG", quality=85)
29
-
30
- # Configure API
31
- genai.configure(api_key=api_key)
32
- model = genai.GenerativeModel('gemini-1.5-pro')
33
-
34
- # Timeout check
35
- if time.time() - start_time > 5:
36
- return "Error: Image processing too slow"
37
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  response = model.generate_content(
39
- [STYLE_INSTRUCTIONS[style],
40
- {"mime_type": "image/jpeg", "data": buffer.getvalue()},
41
- request_options={"timeout": TIMEOUT}
42
  )
 
 
 
 
 
 
 
 
 
 
 
43
 
44
- return response.text[:500] if response.text else "No response"
45
-
 
 
 
 
46
  except Exception as e:
47
- return f"Error: {str(e)}"
48
-
49
- # Enhanced interface with original features
50
- with gr.Blocks(title="Flux Pro HF", theme=gr.themes.Soft()) as app:
51
- gr.Markdown("## ๐Ÿš€ **Flux Prompt Generator**")
52
-
53
- with gr.Row():
54
- with gr.Column():
55
- api_key = gr.Textbox(
56
- label="๐Ÿ”‘ Gemini API Key",
57
- type="password",
58
- placeholder="Enter your API key..."
59
- )
60
- style = gr.Dropdown(
61
- list(STYLE_INSTRUCTIONS.keys()),
62
- value="General",
63
- label="๐ŸŽจ Design Style",
64
- interactive=True
65
- )
66
- image = gr.Image(
67
- label="๐Ÿ–ผ๏ธ Upload Design",
68
- type="pil",
69
- height=300
70
- )
71
-
72
- with gr.Row():
73
- generate_btn = gr.Button("โœจ Generate Prompt", variant="primary")
74
- copy_btn = gr.Button("๐Ÿ“‹ Copy")
75
-
76
- output = gr.Textbox(
77
- label="๐Ÿ“ Generated Prompt",
78
- lines=5,
79
- max_lines=8,
80
- interactive=False
81
- )
82
-
83
- # Event handlers
84
- generate_btn.click(
85
- hf_safe_generate,
86
- inputs=[image, api_key, style],
87
- outputs=output
88
- )
89
-
90
- copy_btn.click(
91
- lambda x: x,
92
- inputs=output,
93
- outputs=output,
94
- _js="(text) => navigator.clipboard.writeText(text)"
95
- )
96
-
97
- # Fixed queue configuration for Hugging Face
98
- app.queue(concurrency_count=CONCURRENCY).launch(
99
- debug=False,
100
- max_threads=1,
101
- show_error=True
102
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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:
13
+ pyperclip = None
14
 
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:
21
+ - Key visual elements
22
+ - Technical specifications
23
+ - Style consistency
24
+ - Functional requirements"""
25
 
26
  STYLE_INSTRUCTIONS = {
27
+ "General": BASE_TEMPLATE,
28
+ "Realistic": f"{BASE_TEMPLATE}\nPHOTOREALISTIC RULES: Use photography terms, texture details, accurate lighting",
29
+ "Kawaii": f"{BASE_TEMPLATE}\nKAWAII RULES: Rounded shapes, pastel colors, cute expressions",
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
+ # --- Quality Control System ---
43
+ class QualityValidator:
44
+ VALIDATION_TEMPLATE = """Analyze this Flux prompt:
45
+ 1. Score style adherence (1-5)
46
+ 2. List technical issues
47
+ 3. Suggest improvements
48
+ Respond ONLY as JSON: {"score": x/10, "issues": [], "suggestions": []}"""
49
+
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"""
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
+ 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")
90
+ img_b64 = base64.b64encode(img_bytes.getvalue()).decode()
91
+
92
+ # Build instruction
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
111
+ output_tokens = len(raw_prompt.split())
112
 
113
+ return {
114
+ "prompt": raw_prompt,
115
+ "validation": validation,
116
+ "stats": {"input": input_tokens, "output": output_tokens}
117
+ }
118
+
119
  except Exception as e:
120
+ traceback.print_exc()
121
+ return {"error": str(e)}
122
+
123
+ # --- UI Components ---
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()