mroccuper commited on
Commit
b33083d
ยท
verified ยท
1 Parent(s): 9270a80

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +147 -108
app.py CHANGED
@@ -6,166 +6,205 @@ import io
6
  import base64
7
  import json
8
  import time
 
9
  try:
10
  import pyperclip
11
  except ImportError:
12
- os.system('pip install pyperclip')
13
- import pyperclip
14
 
15
- # --- Security First Configuration ---
16
- GEMINI_KEY = os.environ.get("GEMINI_KEY", "") # Load from environment variable
 
17
 
18
- # --- Template Optimization System ---
19
- BASE_TEMPLATE = (
20
- "Describe this design as a single, cohesive, and concise prompt suitable for Flux 1.1 Pro. "
21
- "Focus on key elements such as text, symbols, layout, and overall style."
22
- )
 
23
 
24
  STYLE_INSTRUCTIONS = {
25
  "General": BASE_TEMPLATE,
26
- "Realistic": (
27
- f"{BASE_TEMPLATE} Focus on photorealistic details: textures, lighting, depth. "
28
- "Avoid illustrations/cartoon styles. Use technical photography terms."
29
- ),
30
- "Kawaii/Cartoon": (
31
- f"{BASE_TEMPLATE} Emphasize cute, rounded shapes, playful expressions, "
32
- "vibrant colors. Use anime/kawaii terminology."
33
- ),
34
- "Vector": (
35
- f"{BASE_TEMPLATE} Specify clean vector style with sharp lines, geometric shapes. "
36
- "Black/white only with gray gradients. Use design technical terms."
37
- ),
38
- "Silhouette": (
39
- f"{BASE_TEMPLATE} Use high-contrast black/white silhouettes. "
40
- "Focus on bold shapes and outlines. Eliminate interior details."
41
- ),
42
  }
43
 
44
- # --- Flux Configuration Engine ---
45
  FLUX_SPECS = {
46
- "aspect_ratios": ["1:1", "16:9", "4:3", "9:16", "Custom"],
47
- "output_formats": ["SVG", "PNG-300dpi", "PDF", "EPS"],
48
- "color_modes": ["B&W", "CMYK", "Spot Colors", "RGB"],
49
- "complexity_levels": ["Minimal", "Medium", "High", "Ultra"]
50
  }
51
 
52
- # --- Quality Control Systems ---
53
  class QualityValidator:
54
- VALIDATION_PROMPT = """Analyze this Flux prompt on:
55
- 1. Technical specificity (1-5)
56
- 2. Style adherence (1-5)
57
- 3. Flux compatibility (1-5)
58
- Respond ONLY as JSON: {"total": x/15, "issues": [list]}"""
59
 
60
  @classmethod
61
  def validate(cls, prompt, model):
62
  try:
63
- response = model.generate_content([cls.VALIDATION_PROMPT, prompt])
64
  return json.loads(response.text)
65
  except:
66
- return {"total": 0, "issues": ["Validation failed"]}
67
 
68
  # --- Image Processing Pipeline ---
69
  def preprocess_image(img):
70
- """Enhance image quality before analysis"""
71
- img = img.convert("RGB")
72
- img = ImageEnhance.Contrast(img).enhance(1.2)
73
- img = img.filter(ImageFilter.SHARPEN)
74
- return img
75
-
76
- # --- Core Application Logic ---
77
- def generate_prompt(image, api_key, style, creativity, neg_prompt, flux_specs):
78
- genai.configure(api_key=api_key or GEMINI_KEY)
79
- model = genai.GenerativeModel("gemini-1.5-pro", generation_config={
80
- "temperature": creativity,
81
- "top_p": 0.95
82
- })
83
-
84
- # Pre-process image
85
- img = preprocess_image(image)
86
- img_bytes = io.BytesIO()
87
- img.save(img_bytes, format="PNG")
88
- img_b64 = base64.b64encode(img_bytes.getvalue()).decode()
89
-
90
- # Build instruction
91
- instruction = f"{STYLE_INSTRUCTIONS[style]}\nAVOID: {neg_prompt}\nFLUX SPECS: {flux_specs}"
92
-
93
- # Generate initial prompt
94
- response = model.generate_content([instruction, {"mime_type": "image/png", "data": img_b64}])
95
- raw_prompt = response.text
96
-
97
- # Quality validation
98
- validation = QualityValidator.validate(raw_prompt, model)
99
- if validation["total"] < 10: # Regenerate if low quality
100
- response = model.generate_content([
101
- f"Improve this prompt addressing: {validation['issues']}\n\n{raw_prompt}"
102
- ])
 
 
 
 
 
 
 
 
103
  raw_prompt = response.text
104
 
105
- return raw_prompt, validation
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106
 
107
  # --- UI Components ---
108
- def create_advanced_params():
109
- with gr.Accordion("โš™๏ธ Advanced Parameters", open=False):
110
  with gr.Row():
111
- creativity = gr.Slider(0.0, 1.0, 0.7, label="Creativity")
112
- neg_prompt = gr.Textbox(label="๐Ÿšซ Avoid in Prompt", placeholder="e.g., no text, avoid gradients")
113
  with gr.Row():
114
- aspect = gr.Dropdown(FLUX_SPECS["aspect_ratios"], value="1:1", label="Aspect Ratio")
115
- fmt = gr.Dropdown(FLUX_SPECS["output_formats"], value="SVG", label="Output Format")
116
- color = gr.Dropdown(FLUX_SPECS["color_modes"], value="B&W", label="Color Mode")
117
- complexity = gr.Dropdown(FLUX_SPECS["complexity_levels"], value="Medium", label="Complexity")
118
- return [creativity, neg_prompt, aspect, fmt, color, complexity]
119
 
120
- # --- Gradio Interface ---
121
  def build_interface():
122
- with gr.Blocks(title="Flux Pro Generator") as app:
123
- # Security First
124
- api_key = gr.Textbox(label="๐Ÿ”‘ Gemini API Key", value=GEMINI_KEY, type="password",
125
- info="Set GEMINI_KEY environment variable for production")
 
 
 
 
126
 
127
  # Main Workflow
128
- with gr.Row():
129
  with gr.Column(scale=1):
130
- img_input = gr.Image(label="๐Ÿ–ผ๏ธ Upload Design", type="pil", sources=["upload", "clipboard"])
131
- style = gr.Dropdown(list(STYLE_INSTRUCTIONS), value="General", label="๐ŸŽจ Target Style")
132
- adv_params = create_advanced_params()
133
-
 
 
 
 
 
 
 
 
 
 
134
  with gr.Column(scale=2):
135
- prompt_output = gr.Textbox(label="๐Ÿ“ Optimized Prompt", lines=8, interactive=False)
 
 
 
 
136
  with gr.Row():
137
- gen_btn = gr.Button("โœจ Generate", variant="primary")
138
  copy_btn = gr.Button("๐Ÿ“‹ Copy")
139
- quality_report = gr.JSON(label="๐Ÿ” Quality Report")
140
-
141
- # Enterprise Features
142
- token_counter = gr.Textbox(label="๐Ÿงฎ Token Usage", interactive=False)
 
 
 
 
 
 
 
143
  history = gr.State([])
144
 
145
  # Event Handling
146
  gen_btn.click(
147
- generate_prompt,
148
- inputs=[img_input, api_key, style] + adv_params,
149
- outputs=[prompt_output, quality_report]
150
  )
151
-
152
  copy_btn.click(
153
- lambda x: (pyperclip.copy(x), x),
154
  inputs=prompt_output,
155
- outputs=prompt_output
156
  )
157
 
158
  return app
159
 
160
- # --- Production Deployment ---
161
  if __name__ == "__main__":
162
  app = build_interface()
163
  app.launch(
164
  server_name="0.0.0.0",
165
- server_port=int(os.getenv("PORT", 7860)),
166
  share=False,
167
  auth=(
168
- os.getenv("APP_USER", "admin"),
169
- os.getenv("APP_PWD", "admin")
170
- ) if os.getenv("ENV") == "prod" else None
171
  )
 
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(
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
  )