openfree commited on
Commit
36ec0c3
ยท
verified ยท
1 Parent(s): b5d380e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +153 -143
app.py CHANGED
@@ -15,13 +15,13 @@ BRAVE_API_KEY = os.getenv('BRAVE_API_KEY', '') # Add Brave API key
15
 
16
  def search_design_trends(product_type):
17
  """
18
- Use Brave Search API to find current design trends and technologies
19
  """
20
  if not BRAVE_API_KEY:
21
- return "No search results available (API key not set)"
22
 
23
  try:
24
- # Construct search query for product design
25
  query = f"{product_type} design trends 2024 2025 materials technology innovation"
26
 
27
  url = "https://api.search.brave.com/res/v1/web/search"
@@ -47,84 +47,88 @@ def search_design_trends(product_type):
47
  if results:
48
  return "\n".join(results)
49
  else:
50
- return "Limited search results available"
51
  else:
52
- return "Search unavailable at the moment"
53
 
54
  except Exception as e:
55
- print(f"Brave search error: {str(e)}")
56
- return "Search results unavailable"
57
 
58
  def enhance_prompt_with_team(user_input):
59
  """
60
- Enhanced prompt generation using team collaboration with real web search
61
  """
62
  if not FIREWORKS_API_KEY:
63
- # Fallback to basic enhancement
64
- return create_basic_design_prompt(user_input)
65
 
66
  try:
67
- # First, get real search results for the engineer
68
  search_results = search_design_trends(user_input)
69
 
70
  url = "https://api.fireworks.ai/inference/v1/chat/completions"
71
 
72
- # Enhanced system prompt with search integration
73
- system_prompt = """You are a product design team with three specialized roles:
74
 
75
- ## TEAM ROLES:
76
 
77
- ### 1. DIRECTOR (Creative Vision Leader)
78
- - Analyzes user requirements and market positioning
79
- - Sets design philosophy and constraints
80
- - Makes final decisions on features
81
 
82
- ### 2. ENGINEER (Technical Expert with Research Data)
83
- - Uses provided search results to inform decisions
84
- - Evaluates manufacturing feasibility
85
- - Recommends materials and technologies
86
- - Suggests innovative features based on trends
87
 
88
- ### 3. DESIGNER (Visual Specialist)
89
- - Creates detailed visual specifications
90
- - Specifies exact materials, finishes, colors
91
- - Defines rendering style and atmosphere
92
- - MUST include text labels and annotations in the design
93
 
94
- ## OUTPUT FORMAT:
95
 
96
- **DIRECTOR'S VISION:**
97
- [Brief vision statement - 2-3 sentences]
98
 
99
- **ENGINEER'S TECHNICAL ASSESSMENT:**
100
- [Based on search data, provide 3-4 technical recommendations]
101
 
102
- **DESIGNER'S FINAL PROMPT:**
103
- [Detailed visual description INCLUDING text labels and annotations. MUST specify:
104
- - Product name/model as title text
105
- - Key feature callouts with arrow annotations
106
- - Technical specifications as overlay text
107
- - Material/component labels
108
- Example: "with text overlay showing 'MODEL X-500' at top, feature callouts pointing to 'Titanium Frame', 'OLED Display', '5000mAh Battery' with arrows"]
109
 
110
- Keep responses concise but specific. Focus on PHYSICAL PRODUCTS only with TEXT ANNOTATIONS."""
 
 
 
111
 
112
- # Create collaborative prompt with search results
113
- user_prompt = f"""Product concept: {user_input}
114
 
115
- ENGINEER'S RESEARCH DATA:
116
  {search_results}
117
 
118
- Based on this input and research, execute the team collaboration:
119
- 1. Director establishes vision (brief)
120
- 2. Engineer uses the research data above to recommend features
121
- 3. Designer creates a detailed visual prompt WITH TEXT LABELS AND ANNOTATIONS
 
122
 
123
- Focus on creating a manufacturable, innovative product design with clear text overlays showing key features, specifications, and component labels."""
124
 
125
  payload = {
126
  "model": "accounts/fireworks/models/qwen3-235b-a22b-instruct-2507", # Original model maintained
127
- "max_tokens": 500,
128
  "top_p": 0.9,
129
  "temperature": 0.7,
130
  "messages": [
@@ -151,51 +155,52 @@ Focus on creating a manufacturable, innovative product design with clear text ov
151
  result = response.json()
152
  enhanced = result.get('choices', [{}])[0].get('message', {}).get('content', '')
153
  if enhanced:
154
- # Extract designer's final prompt
155
- if "DESIGNER'S FINAL PROMPT:" in enhanced:
156
- parts = enhanced.split("DESIGNER'S FINAL PROMPT:")
157
  if len(parts) > 1:
158
- # Return both the final prompt and the full discussion
159
- return parts[1].strip(), enhanced
 
160
  return enhanced, enhanced
161
 
162
- # Fallback if API fails
163
- return create_basic_design_prompt(user_input), "Team collaboration unavailable - using basic prompt"
164
 
165
  except requests.exceptions.Timeout:
166
- print("Fireworks API timeout - using fallback")
167
- return create_basic_design_prompt(user_input), "API timeout - using fallback prompt generation"
168
  except Exception as e:
169
- print(f"Team collaboration error: {str(e)}")
170
- return create_basic_design_prompt(user_input), f"Error: {str(e)[:100]}"
171
 
172
  def create_basic_design_prompt(user_input):
173
  """
174
- Fallback function for basic design prompt generation with text annotations
175
  """
176
  product_name = user_input.upper().replace(" ", "-")
177
- return f"""A professional product design concept for {user_input} with detailed text annotations:
178
- - Product title text overlay: "{product_name} PRO 2025" in bold modern font at top
179
- - Feature callout labels with arrows pointing to key components:
180
- * "Premium Materials" โ†’ body
181
- * "Ergonomic Design" โ†’ form factor
182
- * "Smart Integration" โ†’ control panel
183
- * "Sustainable Manufacturing" โ†’ eco-friendly elements
184
- - Technical specifications text overlay in corner:
185
- * Dimensions, weight, power specs
186
- - Clean industrial design with annotations
187
- - Photorealistic rendering with studio lighting
188
- - Professional product photography style with infographic elements
189
- - Text labels in clean sans-serif font (Helvetica/Arial style)
190
- - High contrast text for readability
191
- - Shown from 3/4 perspective with all labels clearly visible"""
192
 
193
  def upload_image_to_hosting(image):
194
  """
195
- Upload image to hosting service
196
  """
197
  try:
198
- # Try imgbb first
199
  buffered = BytesIO()
200
  image.save(buffered, format="PNG")
201
  buffered.seek(0)
@@ -217,7 +222,7 @@ def upload_image_to_hosting(image):
217
  except:
218
  pass
219
 
220
- # Fallback to base64
221
  buffered = BytesIO()
222
  image.save(buffered, format="PNG")
223
  buffered.seek(0)
@@ -226,34 +231,34 @@ def upload_image_to_hosting(image):
226
 
227
  def process_product_design(prompt, enhance_prompt_flag, image1, image2=None):
228
  """
229
- Process product design with team collaboration
230
  """
231
  if not os.getenv('REPLICATE_API_TOKEN'):
232
- return None, prompt, "โš ๏ธ Please set REPLICATE_API_TOKEN", ""
233
 
234
  try:
235
  team_discussion = ""
236
  final_prompt = prompt
237
 
238
- # Apply team collaboration if enabled
239
  if enhance_prompt_flag:
240
  result = enhance_prompt_with_team(prompt)
241
  if isinstance(result, tuple):
242
  final_prompt, team_discussion = result
243
  else:
244
  final_prompt = result
245
- team_discussion = "Team collaboration completed"
246
 
247
- # Format team discussion for display
248
- if "DIRECTOR'S VISION:" in team_discussion:
249
- team_discussion = f"### ๐ŸŽฌ Team Collaboration Process\n\n{team_discussion}"
250
 
251
- # Prepare model input
252
  model_input = {
253
  "prompt": final_prompt
254
  }
255
 
256
- # Add reference images if provided
257
  if image1 or image2:
258
  image_urls = []
259
 
@@ -266,13 +271,13 @@ def process_product_design(prompt, enhance_prompt_flag, image1, image2=None):
266
  image_urls.append(url2)
267
 
268
  model_input["image_input"] = image_urls
269
- status_msg = "โœ… Product design generated with style references!"
270
  else:
271
- status_msg = "โœ… Product design generated successfully!"
272
 
273
- # Generate image with Replicate
274
  try:
275
- # Add text annotation emphasis to the prompt
276
  annotated_prompt = f"{final_prompt}. Include clear text labels, feature callouts with arrows, product name/model as title, technical specifications overlay, component annotations in clean modern typography"
277
 
278
  output = replicate.run(
@@ -286,7 +291,7 @@ def process_product_design(prompt, enhance_prompt_flag, image1, image2=None):
286
  }
287
  )
288
  except:
289
- # Fallback to original model with text annotations
290
  annotated_prompt = f"{final_prompt}. With text overlays showing product name, key features with arrow callouts, specifications, and component labels in professional typography"
291
 
292
  output = replicate.run(
@@ -301,9 +306,9 @@ def process_product_design(prompt, enhance_prompt_flag, image1, image2=None):
301
  )
302
 
303
  if output is None:
304
- return None, final_prompt, "โŒ No output received from model", team_discussion
305
 
306
- # Process output
307
  output_url = None
308
  if isinstance(output, str):
309
  output_url = output
@@ -318,17 +323,17 @@ def process_product_design(prompt, enhance_prompt_flag, image1, image2=None):
318
  img = Image.open(BytesIO(response.content))
319
  return img, final_prompt, status_msg, team_discussion
320
 
321
- return None, final_prompt, "โŒ Could not process output", team_discussion
322
 
323
  except Exception as e:
324
  error_msg = str(e)
325
- return None, prompt, f"โŒ Error: {error_msg[:200]}", ""
326
 
327
- # Professional Product Design CSS
328
  css = """
329
  .gradio-container {
330
  background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
331
- font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
332
  min-height: 100vh;
333
  }
334
  .header-container {
@@ -365,7 +370,7 @@ css = """
365
  text-align: center;
366
  font-weight: 500;
367
  color: #ffd700;
368
- max-width: 500px;
369
  font-size: 0.9rem;
370
  }
371
  .main-content {
@@ -409,11 +414,12 @@ css = """
409
  padding: 1.2rem;
410
  margin-top: 1rem;
411
  border: 1px solid #dee2e6;
412
- font-family: 'Courier New', monospace;
413
  font-size: 0.85rem;
414
- max-height: 300px;
415
  overflow-y: auto;
416
  white-space: pre-wrap;
 
417
  }
418
  .enhanced-prompt-box {
419
  background: #f0f0f0;
@@ -444,83 +450,83 @@ footer {
444
  }
445
  """
446
 
447
- # Create Gradio interface
448
  with gr.Blocks(css=css, theme=gr.themes.Base()) as demo:
449
  with gr.Column(elem_classes="header-container"):
450
  gr.HTML("""
451
- <h1 class="logo-text">๐Ÿญ PRODUCT DESIGN STUDIO</h1>
452
- <p class="subtitle">AI-Powered Industrial Design with Annotated Feature Guides</p>
453
  <div class="mode-indicator">
454
- ๐Ÿ‘ฅ Director โ†’ ๐Ÿ” Engineer (Research) โ†’ ๐ŸŽจ Designer (with Text Annotations)
455
  </div>
456
  """)
457
 
458
  with gr.Column(elem_classes="main-content"):
459
  gr.HTML("""
460
  <div class="info-box">
461
- <strong>๐ŸŽฏ Professional Product Design Process with Annotations:</strong><br>
462
- โ€ข <b>Director:</b> Establishes vision and requirements<br>
463
- โ€ข <b>Engineer:</b> Searches current trends & technologies via Brave API<br>
464
- โ€ข <b>Designer:</b> Creates visual specs with <b>text labels & feature callouts</b><br>
465
- โ€ข <b>Output:</b> Annotated product designs with key features highlighted<br>
466
- โ€ข <b>Focus:</b> Physical products with infographic-style annotations
467
  </div>
468
  """)
469
 
470
  with gr.Row(equal_height=True):
471
  with gr.Column(scale=1):
472
  prompt = gr.Textbox(
473
- label="๐Ÿ“ Product Concept",
474
- placeholder="Enter product type: 'ergonomic keyboard', 'smart watch', 'office chair', 'coffee maker'...",
475
  lines=2,
476
- value="wireless earbuds",
477
  elem_classes="prompt-input"
478
  )
479
 
480
  enhance_prompt_checkbox = gr.Checkbox(
481
- label="๐Ÿš€ Enable Team Collaboration with Web Research",
482
  value=True,
483
- info="Activates Director + Engineer (Brave Search) + Designer process"
484
  )
485
 
486
  with gr.Row():
487
  image1 = gr.Image(
488
- label="Style Reference 1 (Optional)",
489
  type="pil",
490
  height=180
491
  )
492
  image2 = gr.Image(
493
- label="Style Reference 2 (Optional)",
494
  type="pil",
495
  height=180
496
  )
497
 
498
  generate_btn = gr.Button(
499
- "๐ŸŽจ Generate Product Design",
500
  variant="primary",
501
  size="lg"
502
  )
503
 
504
  with gr.Column(scale=1):
505
  output_image = gr.Image(
506
- label="Generated Product Design",
507
  type="pil",
508
  height=400,
509
  elem_classes="image-container"
510
  )
511
 
512
  enhanced_prompt_display = gr.Textbox(
513
- label="๐Ÿ“‹ Final Design Specifications",
514
  interactive=False,
515
  lines=3,
516
  elem_classes="enhanced-prompt-box"
517
  )
518
 
519
  status = gr.Textbox(
520
- label="Status",
521
  interactive=False,
522
  elem_classes="status-text",
523
- value="Ready to design..."
524
  )
525
 
526
  with gr.Row():
@@ -529,42 +535,46 @@ with gr.Blocks(css=css, theme=gr.themes.Base()) as demo:
529
  elem_classes="team-discussion"
530
  )
531
 
532
- # Connect event handler
533
  generate_btn.click(
534
  fn=process_product_design,
535
  inputs=[prompt, enhance_prompt_checkbox, image1, image2],
536
  outputs=[output_image, enhanced_prompt_display, status, team_discussion_display]
537
  )
538
 
539
- # Product examples
540
  gr.Examples(
541
  examples=[
542
- ["wireless earbuds", True, None, None],
543
- ["ergonomic office chair", True, None, None],
544
- ["smart home speaker", True, None, None],
545
- ["electric toothbrush", True, None, None],
546
- ["portable coffee maker", True, None, None],
547
- ["gaming keyboard", True, None, None],
548
- ["fitness tracker", True, None, None],
549
- ["desk lamp", True, None, None],
 
 
 
 
550
  ],
551
  inputs=[prompt, enhance_prompt_checkbox, image1, image2],
552
- label="๐Ÿ’ก Product Design Examples"
553
  )
554
 
555
- # Launch settings
556
  if __name__ == "__main__":
557
- # Check for required API keys
558
  if not os.getenv('REPLICATE_API_TOKEN'):
559
- print("โš ๏ธ Warning: REPLICATE_API_TOKEN not set")
560
  if not os.getenv('FIREWORKS_API_KEY'):
561
- print("โš ๏ธ Warning: FIREWORKS_API_KEY not set - will use fallback prompts")
562
  if not os.getenv('BRAVE_API_KEY'):
563
- print("โš ๏ธ Warning: BRAVE_API_KEY not set - web search unavailable")
564
 
565
  demo.launch(
566
- share=False, # Set to False for Hugging Face Spaces
567
  server_name="0.0.0.0",
568
  server_port=7860,
569
- ssr_mode=False # Disable SSR to avoid warning
570
  )
 
15
 
16
  def search_design_trends(product_type):
17
  """
18
+ Brave Search API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ตœ์‹  ๋””์ž์ธ ํŠธ๋ Œ๋“œ์™€ ๊ธฐ์ˆ  ๊ฒ€์ƒ‰
19
  """
20
  if not BRAVE_API_KEY:
21
+ return "๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ์—†์Œ (API ํ‚ค ๋ฏธ์„ค์ •)"
22
 
23
  try:
24
+ # ์ œํ’ˆ ๋””์ž์ธ์„ ์œ„ํ•œ ๊ฒ€์ƒ‰ ์ฟผ๋ฆฌ ๊ตฌ์„ฑ
25
  query = f"{product_type} design trends 2024 2025 materials technology innovation"
26
 
27
  url = "https://api.search.brave.com/res/v1/web/search"
 
47
  if results:
48
  return "\n".join(results)
49
  else:
50
+ return "์ œํ•œ๋œ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ"
51
  else:
52
+ return "ํ˜„์žฌ ๊ฒ€์ƒ‰ ๋ถˆ๊ฐ€"
53
 
54
  except Exception as e:
55
+ print(f"Brave ๊ฒ€์ƒ‰ ์˜ค๋ฅ˜: {str(e)}")
56
+ return "๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ์ด์šฉ ๋ถˆ๊ฐ€"
57
 
58
  def enhance_prompt_with_team(user_input):
59
  """
60
+ ์‹ค์ œ ์›น ๊ฒ€์ƒ‰์„ ํ†ตํ•œ ํŒ€ ํ˜‘์—… ๋ฐฉ์‹์˜ ํ–ฅ์ƒ๋œ ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ
61
  """
62
  if not FIREWORKS_API_KEY:
63
+ # ๊ธฐ๋ณธ ํ–ฅ์ƒ์œผ๋กœ ํด๋ฐฑ
64
+ return create_basic_design_prompt(user_input), "API ํ‚ค๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์Œ"
65
 
66
  try:
67
+ # ๋จผ์ € ์—”์ง€๋‹ˆ์–ด๋ฅผ ์œ„ํ•œ ์‹ค์ œ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ํš๋“
68
  search_results = search_design_trends(user_input)
69
 
70
  url = "https://api.fireworks.ai/inference/v1/chat/completions"
71
 
72
+ # ๊ฒ€์ƒ‰ ํ†ตํ•ฉ๋œ ํ–ฅ์ƒ๋œ ์‹œ์Šคํ…œ ํ”„๋กฌํ”„ํŠธ
73
+ system_prompt = """๋‹น์‹ ์€ ์„ธ ๊ฐ€์ง€ ์ „๋ฌธ ์—ญํ• ๋กœ ๊ตฌ์„ฑ๋œ ์ œํ’ˆ ๋””์ž์ธ ํŒ€์ž…๋‹ˆ๋‹ค. ๋ชจ๋“  ์‘๋‹ต์€ ํ•œ๊ตญ์–ด๋กœ ์ž‘์„ฑํ•˜์„ธ์š”:
74
 
75
+ ## ํŒ€ ์—ญํ• :
76
 
77
+ ### 1. ๊ฐ๋… (ํฌ๋ฆฌ์—์ดํ‹ฐ๋ธŒ ๋น„์ „ ๋ฆฌ๋”)
78
+ - ์‚ฌ์šฉ์ž ์š”๊ตฌ์‚ฌํ•ญ๊ณผ ์‹œ์žฅ ํฌ์ง€์…”๋‹ ๋ถ„์„
79
+ - ๋””์ž์ธ ์ฒ ํ•™๊ณผ ์ œ์•ฝ ์กฐ๊ฑด ์„ค์ •
80
+ - ๊ธฐ๋Šฅ์— ๋Œ€ํ•œ ์ตœ์ข… ๊ฒฐ์ •
81
 
82
+ ### 2. ์—”์ง€๋‹ˆ์–ด (์—ฐ๊ตฌ ๋ฐ์ดํ„ฐ๋ฅผ ํ™œ์šฉํ•œ ๊ธฐ์ˆ  ์ „๋ฌธ๊ฐ€)
83
+ - ์ œ๊ณต๋œ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๋ฅผ ํ™œ์šฉํ•œ ์˜์‚ฌ๊ฒฐ์ •
84
+ - ์ œ์กฐ ๊ฐ€๋Šฅ์„ฑ ํ‰๊ฐ€
85
+ - ์žฌ๋ฃŒ์™€ ๊ธฐ์ˆ  ์ถ”์ฒœ
86
+ - ํŠธ๋ Œ๋“œ ๊ธฐ๋ฐ˜ ํ˜์‹  ๊ธฐ๋Šฅ ์ œ์•ˆ
87
 
88
+ ### 3. ๋””์ž์ด๋„ˆ (๋น„์ฃผ์–ผ ์ „๋ฌธ๊ฐ€)
89
+ - ์ƒ์„ธํ•œ ์‹œ๊ฐ์  ์‚ฌ์–‘ ์ž‘์„ฑ
90
+ - ์ •ํ™•ํ•œ ์žฌ๋ฃŒ, ๋งˆ๊ฐ, ์ƒ‰์ƒ ์ง€์ •
91
+ - ๋ Œ๋”๋ง ์Šคํƒ€์ผ๊ณผ ๋ถ„์œ„๊ธฐ ์ •์˜
92
+ - ํ…์ŠคํŠธ ๋ ˆ์ด๋ธ”๊ณผ ์ฃผ์„ ํฌํ•จ ํ•„์ˆ˜
93
 
94
+ ## ์ถœ๋ ฅ ํ˜•์‹:
95
 
96
+ **๊ฐ๋…์˜ ๋น„์ „:**
97
+ [๊ฐ„๋žตํ•œ ๋น„์ „ ์„ค๋ช… - 2-3๋ฌธ์žฅ]
98
 
99
+ **์—”์ง€๋‹ˆ์–ด์˜ ๊ธฐ์ˆ  ํ‰๊ฐ€:**
100
+ [๊ฒ€์ƒ‰ ๋ฐ์ดํ„ฐ ๊ธฐ๋ฐ˜ 3-4๊ฐœ ๊ธฐ์ˆ  ๊ถŒ์žฅ์‚ฌํ•ญ]
101
 
102
+ **๋””์ž์ด๋„ˆ์˜ ์ตœ์ข… ํ”„๋กฌํ”„ํŠธ:**
103
+ [ํ…์ŠคํŠธ ๋ ˆ์ด๋ธ”๊ณผ ์ฃผ์„์„ ํฌํ•จํ•œ ์ƒ์„ธํ•œ ์‹œ๊ฐ์  ์„ค๋ช…. ๋ฐ˜๋“œ์‹œ ํฌํ•จ:
104
+ - ์ œํ’ˆ๋ช…/๋ชจ๋ธ์„ ํƒ€์ดํ‹€ ํ…์ŠคํŠธ๋กœ
105
+ - ํ™”์‚ดํ‘œ ์ฃผ์„๊ณผ ํ•จ๊ป˜ ์ฃผ์š” ๊ธฐ๋Šฅ ์„ค๋ช…
106
+ - ์˜ค๋ฒ„๋ ˆ์ด ํ…์ŠคํŠธ๋กœ ๊ธฐ์ˆ  ์‚ฌ์–‘
107
+ - ์žฌ๋ฃŒ/๊ตฌ์„ฑ์š”์†Œ ๋ ˆ์ด๋ธ”
108
+ ์˜ˆ์‹œ: "์ƒ๋‹จ์— 'MODEL X-500' ํ…์ŠคํŠธ ์˜ค๋ฒ„๋ ˆ์ด, 'ํ‹ฐํƒ€๋Š„ ํ”„๋ ˆ์ž„', 'OLED ๋””์Šคํ”Œ๋ ˆ์ด', '5000mAh ๋ฐฐํ„ฐ๋ฆฌ'๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ํ™”์‚ดํ‘œ์™€ ๊ธฐ๋Šฅ ์„ค๋ช…"]
109
 
110
+ **์ตœ์ข… ๋””์ž์ธ ๋ณด๊ณ ์„œ:**
111
+ [ํ•œ๊ตญ์–ด๋กœ ์ž‘์„ฑ๋œ ์ œํ’ˆ์˜ ํ•ต์‹ฌ ํŠน์ง•, ํ˜์‹  ํฌ์ธํŠธ, ํƒ€๊ฒŸ ์‹œ์žฅ, ์˜ˆ์ƒ ์ œ์กฐ ๋น„์šฉ ๋“ฑ์„ ํฌํ•จํ•œ ์ข…ํ•ฉ ๋ณด๊ณ ์„œ - 3-4๋ฌธ์žฅ]
112
+
113
+ ๊ฐ„๊ฒฐํ•˜์ง€๋งŒ ๊ตฌ์ฒด์ ์œผ๋กœ ์ž‘์„ฑ. ๋ฌผ๋ฆฌ์  ์ œํ’ˆ์—๋งŒ ์ง‘์ค‘ํ•˜๋ฉฐ ํ…์ŠคํŠธ ์ฃผ์„ ํฌํ•จ."""
114
 
115
+ # ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ์™€ ํ•จ๊ป˜ ํ˜‘์—… ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ
116
+ user_prompt = f"""์ œํ’ˆ ์ปจ์…‰: {user_input}
117
 
118
+ ์—”์ง€๋‹ˆ์–ด์˜ ์—ฐ๊ตฌ ๋ฐ์ดํ„ฐ:
119
  {search_results}
120
 
121
+ ์œ„ ์ž…๋ ฅ๊ณผ ์—ฐ๊ตฌ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ํŒ€ ํ˜‘์—… ์‹คํ–‰:
122
+ 1. ๊ฐ๋…์ด ๋น„์ „ ์ˆ˜๋ฆฝ (๊ฐ„๋žตํžˆ)
123
+ 2. ์—”์ง€๋‹ˆ์–ด๊ฐ€ ์œ„ ์—ฐ๊ตฌ ๋ฐ์ดํ„ฐ๋ฅผ ํ™œ์šฉํ•ด ๊ธฐ๋Šฅ ์ถ”์ฒœ
124
+ 3. ๋””์ž์ด๋„ˆ๊ฐ€ ํ…์ŠคํŠธ ๋ ˆ์ด๋ธ”๊ณผ ์ฃผ์„์ด ํฌํ•จ๋œ ์ƒ์„ธํ•œ ์‹œ๊ฐ์  ํ”„๋กฌํ”„ํŠธ ์ž‘์„ฑ
125
+ 4. ์ตœ์ข… ๋””์ž์ธ ๋ณด๊ณ ์„œ ์ž‘์„ฑ (ํ•œ๊ตญ์–ด)
126
 
127
+ ์ œ์กฐ ๊ฐ€๋Šฅํ•˜๊ณ  ํ˜์‹ ์ ์ธ ์ œํ’ˆ ๋””์ž์ธ ์ฐฝ์ถœ์— ์ง‘์ค‘ํ•˜๋ฉฐ, ๋ช…ํ™•ํ•œ ํ…์ŠคํŠธ ์˜ค๋ฒ„๋ ˆ์ด๋กœ ์ฃผ์š” ๊ธฐ๋Šฅ, ์‚ฌ์–‘, ๊ตฌ์„ฑ์š”์†Œ ๋ ˆ์ด๋ธ” ํ‘œ์‹œ."""
128
 
129
  payload = {
130
  "model": "accounts/fireworks/models/qwen3-235b-a22b-instruct-2507", # Original model maintained
131
+ "max_tokens": 600,
132
  "top_p": 0.9,
133
  "temperature": 0.7,
134
  "messages": [
 
155
  result = response.json()
156
  enhanced = result.get('choices', [{}])[0].get('message', {}).get('content', '')
157
  if enhanced:
158
+ # ๋””์ž์ด๋„ˆ์˜ ์ตœ์ข… ํ”„๋กฌํ”„ํŠธ ์ถ”์ถœ
159
+ if "๋””์ž์ด๋„ˆ์˜ ์ตœ์ข… ํ”„๋กฌํ”„ํŠธ:" in enhanced or "DESIGNER'S FINAL PROMPT:" in enhanced:
160
+ parts = enhanced.split("๋””์ž์ด๋„ˆ์˜ ์ตœ์ข… ํ”„๋กฌํ”„ํŠธ:" if "๋””์ž์ด๋„ˆ์˜ ์ตœ์ข… ํ”„๋กฌํ”„ํŠธ:" in enhanced else "DESIGNER'S FINAL PROMPT:")
161
  if len(parts) > 1:
162
+ # ์ตœ์ข… ํ”„๋กฌํ”„ํŠธ์™€ ์ „์ฒด ํ† ๋ก  ๋ชจ๋‘ ๋ฐ˜ํ™˜
163
+ final_prompt = parts[1].split("**")[0].strip()
164
+ return final_prompt, enhanced
165
  return enhanced, enhanced
166
 
167
+ # API ์‹คํŒจ ์‹œ ํด๋ฐฑ
168
+ return create_basic_design_prompt(user_input), "ํŒ€ ํ˜‘์—… ๋ถˆ๊ฐ€ - ๊ธฐ๋ณธ ํ”„๋กฌํ”„ํŠธ ์‚ฌ์šฉ"
169
 
170
  except requests.exceptions.Timeout:
171
+ print("Fireworks API ํƒ€์ž„์•„์›ƒ - ํด๋ฐฑ ์‚ฌ์šฉ")
172
+ return create_basic_design_prompt(user_input), "API ํƒ€์ž„์•„์›ƒ - ํด๋ฐฑ ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ ์‚ฌ์šฉ"
173
  except Exception as e:
174
+ print(f"ํŒ€ ํ˜‘์—… ์˜ค๋ฅ˜: {str(e)}")
175
+ return create_basic_design_prompt(user_input), f"์˜ค๋ฅ˜: {str(e)[:100]}"
176
 
177
  def create_basic_design_prompt(user_input):
178
  """
179
+ ํ…์ŠคํŠธ ์ฃผ์„์ด ํฌํ•จ๋œ ๊ธฐ๋ณธ ๋””์ž์ธ ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ์„ ์œ„ํ•œ ํด๋ฐฑ ํ•จ์ˆ˜
180
  """
181
  product_name = user_input.upper().replace(" ", "-")
182
+ return f"""์ƒ์„ธํ•œ ํ…์ŠคํŠธ ์ฃผ์„์ด ํฌํ•จ๋œ {user_input}์˜ ์ „๋ฌธ ์ œํ’ˆ ๋””์ž์ธ ์ปจ์…‰:
183
+ - ์ƒ๋‹จ์— ๊ตต์€ ๋ชจ๋˜ ํฐํŠธ๋กœ ์ œํ’ˆ ํƒ€์ดํ‹€ ํ…์ŠคํŠธ ์˜ค๋ฒ„๋ ˆ์ด: "{product_name} PRO 2025"
184
+ - ์ฃผ์š” ๊ตฌ์„ฑ์š”์†Œ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ํ™”์‚ดํ‘œ์™€ ํ•จ๊ป˜ ๊ธฐ๋Šฅ ์„ค๋ช… ๋ ˆ์ด๋ธ”:
185
+ * "ํ”„๋ฆฌ๋ฏธ์—„ ์†Œ์žฌ" โ†’ ๋ณธ์ฒด
186
+ * "์ธ์ฒด๊ณตํ•™์  ๋””์ž์ธ" โ†’ ํผ ํŒฉํ„ฐ
187
+ * "์Šค๋งˆํŠธ ํ†ตํ•ฉ" โ†’ ์ œ์–ด ํŒจ๋„
188
+ * "์ง€์†๊ฐ€๋Šฅํ•œ ์ œ์กฐ" โ†’ ์นœํ™˜๊ฒฝ ์š”์†Œ
189
+ - ๋ชจ์„œ๋ฆฌ์— ๊ธฐ์ˆ  ์‚ฌ์–‘ ํ…์ŠคํŠธ ์˜ค๋ฒ„๋ ˆ์ด:
190
+ * ์น˜์ˆ˜, ๋ฌด๊ฒŒ, ์ „๋ ฅ ์‚ฌ์–‘
191
+ - ์ฃผ์„์ด ํฌํ•จ๋œ ๊น”๋”ํ•œ ์‚ฐ์—… ๋””์ž์ธ
192
+ - ์ŠคํŠœ๋””์˜ค ์กฐ๋ช…๊ณผ ํ•จ๊ป˜ ํฌํ† ๋ฆฌ์–ผ๋ฆฌ์Šคํ‹ฑ ๋ Œ๋”๋ง
193
+ - ์ธํฌ๊ทธ๋ž˜ํ”ฝ ์š”์†Œ๊ฐ€ ํฌํ•จ๋œ ์ „๋ฌธ ์ œํ’ˆ ์‚ฌ์ง„ ์Šคํƒ€์ผ
194
+ - ๊น”๋”ํ•œ ์‚ฐ์„ธ๋ฆฌํ”„ ํฐํŠธ(Helvetica/Arial ์Šคํƒ€์ผ)์˜ ํ…์ŠคํŠธ ๋ ˆ์ด๋ธ”
195
+ - ๊ฐ€๋…์„ฑ์„ ์œ„ํ•œ ๋†’์€ ๋Œ€๋น„ ํ…์ŠคํŠธ
196
+ - ๋ชจ๋“  ๋ ˆ์ด๋ธ”์ด ๋ช…ํ™•ํžˆ ๋ณด์ด๋Š” 3/4 ๊ด€์ ์—์„œ ํ‘œ์‹œ"""
197
 
198
  def upload_image_to_hosting(image):
199
  """
200
+ ํ˜ธ์ŠคํŒ… ์„œ๋น„์Šค์— ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ
201
  """
202
  try:
203
+ # imgbb ๋จผ์ € ์‹œ๋„
204
  buffered = BytesIO()
205
  image.save(buffered, format="PNG")
206
  buffered.seek(0)
 
222
  except:
223
  pass
224
 
225
+ # base64๋กœ ํด๋ฐฑ
226
  buffered = BytesIO()
227
  image.save(buffered, format="PNG")
228
  buffered.seek(0)
 
231
 
232
  def process_product_design(prompt, enhance_prompt_flag, image1, image2=None):
233
  """
234
+ ํŒ€ ํ˜‘์—…์„ ํ†ตํ•œ ์ œํ’ˆ ๋””์ž์ธ ์ฒ˜๋ฆฌ
235
  """
236
  if not os.getenv('REPLICATE_API_TOKEN'):
237
+ return None, prompt, "โš ๏ธ REPLICATE_API_TOKEN์„ ์„ค์ •ํ•˜์„ธ์š”", ""
238
 
239
  try:
240
  team_discussion = ""
241
  final_prompt = prompt
242
 
243
+ # ํ™œ์„ฑํ™”๋œ ๊ฒฝ์šฐ ํŒ€ ํ˜‘์—… ์ ์šฉ
244
  if enhance_prompt_flag:
245
  result = enhance_prompt_with_team(prompt)
246
  if isinstance(result, tuple):
247
  final_prompt, team_discussion = result
248
  else:
249
  final_prompt = result
250
+ team_discussion = "ํŒ€ ํ˜‘์—… ์™„๋ฃŒ"
251
 
252
+ # ํ‘œ์‹œ๋ฅผ ์œ„ํ•œ ํŒ€ ํ† ๋ก  ํ˜•์‹ํ™”
253
+ if "๊ฐ๋…์˜ ๋น„์ „:" in team_discussion or "DIRECTOR'S VISION:" in team_discussion:
254
+ team_discussion = f"### ๐ŸŽฌ ํŒ€ ํ˜‘์—… ํ”„๋กœ์„ธ์Šค\n\n{team_discussion}"
255
 
256
+ # ๋ชจ๋ธ ์ž…๋ ฅ ์ค€๋น„
257
  model_input = {
258
  "prompt": final_prompt
259
  }
260
 
261
+ # ์ œ๊ณต๋œ ๊ฒฝ์šฐ ์ฐธ์กฐ ์ด๋ฏธ์ง€ ์ถ”๊ฐ€
262
  if image1 or image2:
263
  image_urls = []
264
 
 
271
  image_urls.append(url2)
272
 
273
  model_input["image_input"] = image_urls
274
+ status_msg = "โœ… ์Šคํƒ€์ผ ์ฐธ์กฐ์™€ ํ•จ๊ป˜ ์ œํ’ˆ ๋””์ž์ธ ์ƒ์„ฑ ์™„๋ฃŒ!"
275
  else:
276
+ status_msg = "โœ… ์ œํ’ˆ ๋””์ž์ธ์ด ์„ฑ๊ณต์ ์œผ๋กœ ์ƒ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค!"
277
 
278
+ # Replicate๋กœ ์ด๋ฏธ์ง€ ์ƒ์„ฑ
279
  try:
280
+ # ํ”„๋กฌํ”„ํŠธ์— ํ…์ŠคํŠธ ์ฃผ์„ ๊ฐ•์กฐ ์ถ”๊ฐ€
281
  annotated_prompt = f"{final_prompt}. Include clear text labels, feature callouts with arrows, product name/model as title, technical specifications overlay, component annotations in clean modern typography"
282
 
283
  output = replicate.run(
 
291
  }
292
  )
293
  except:
294
+ # ํ…์ŠคํŠธ ์ฃผ์„๊ณผ ํ•จ๊ป˜ ์›๋ณธ ๋ชจ๋ธ๋กœ ํด๋ฐฑ
295
  annotated_prompt = f"{final_prompt}. With text overlays showing product name, key features with arrow callouts, specifications, and component labels in professional typography"
296
 
297
  output = replicate.run(
 
306
  )
307
 
308
  if output is None:
309
+ return None, final_prompt, "โŒ ๋ชจ๋ธ๋กœ๋ถ€ํ„ฐ ์ถœ๋ ฅ์„ ๋ฐ›์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค", team_discussion
310
 
311
+ # ์ถœ๋ ฅ ์ฒ˜๋ฆฌ
312
  output_url = None
313
  if isinstance(output, str):
314
  output_url = output
 
323
  img = Image.open(BytesIO(response.content))
324
  return img, final_prompt, status_msg, team_discussion
325
 
326
+ return None, final_prompt, "โŒ ์ถœ๋ ฅ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค", team_discussion
327
 
328
  except Exception as e:
329
  error_msg = str(e)
330
+ return None, prompt, f"โŒ ์˜ค๋ฅ˜: {error_msg[:200]}", ""
331
 
332
+ # ์ „๋ฌธ ์ œํ’ˆ ๋””์ž์ธ CSS
333
  css = """
334
  .gradio-container {
335
  background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
336
+ font-family: 'Pretendard', 'Noto Sans KR', -apple-system, BlinkMacSystemFont, sans-serif;
337
  min-height: 100vh;
338
  }
339
  .header-container {
 
370
  text-align: center;
371
  font-weight: 500;
372
  color: #ffd700;
373
+ max-width: 600px;
374
  font-size: 0.9rem;
375
  }
376
  .main-content {
 
414
  padding: 1.2rem;
415
  margin-top: 1rem;
416
  border: 1px solid #dee2e6;
417
+ font-family: 'Pretendard', 'Noto Sans KR', monospace;
418
  font-size: 0.85rem;
419
+ max-height: 400px;
420
  overflow-y: auto;
421
  white-space: pre-wrap;
422
+ line-height: 1.6;
423
  }
424
  .enhanced-prompt-box {
425
  background: #f0f0f0;
 
450
  }
451
  """
452
 
453
+ # Gradio ์ธํ„ฐํŽ˜์ด์Šค ์ƒ์„ฑ
454
  with gr.Blocks(css=css, theme=gr.themes.Base()) as demo:
455
  with gr.Column(elem_classes="header-container"):
456
  gr.HTML("""
457
+ <h1 class="logo-text">๐Ÿญ ์ œํ’ˆ ๋””์ž์ธ ์ŠคํŠœ๋””์˜ค</h1>
458
+ <p class="subtitle">AI ๊ธฐ๋ฐ˜ ์‚ฐ์—… ๋””์ž์ธ ์‹œ์Šคํ…œ - ์›น ๋ฆฌ์„œ์น˜์™€ ์ฃผ์„ ๊ธฐ๋Šฅ ํฌํ•จ</p>
459
  <div class="mode-indicator">
460
+ ๐Ÿ‘ฅ ๊ฐ๋… โ†’ ๐Ÿ” ์—”์ง€๋‹ˆ์–ด (Brave ๊ฒ€์ƒ‰) โ†’ ๐ŸŽจ ๋””์ž์ด๋„ˆ (ํ…์ŠคํŠธ ์ฃผ์„ ํฌํ•จ)
461
  </div>
462
  """)
463
 
464
  with gr.Column(elem_classes="main-content"):
465
  gr.HTML("""
466
  <div class="info-box">
467
+ <strong>๐ŸŽฏ ์ „๋ฌธ ์ œํ’ˆ ๋””์ž์ธ ํ”„๋กœ์„ธ์Šค (์ฃผ์„ ํฌํ•จ):</strong><br>
468
+ โ€ข <b>๊ฐ๋…:</b> ๋น„์ „๊ณผ ์š”๊ตฌ์‚ฌํ•ญ ์ˆ˜๋ฆฝ<br>
469
+ โ€ข <b>์—”์ง€๋‹ˆ์–ด:</b> Brave API๋กœ ์ตœ์‹  ํŠธ๋ Œ๋“œ์™€ ๊ธฐ์ˆ  ๊ฒ€์ƒ‰<br>
470
+ โ€ข <b>๋””์ž์ด๋„ˆ:</b> <b>ํ…์ŠคํŠธ ๋ ˆ์ด๋ธ”๊ณผ ๊ธฐ๋Šฅ ์„ค๋ช…</b>์ด ํฌํ•จ๋œ ์‹œ๊ฐ ์‚ฌ์–‘ ์ž‘์„ฑ<br>
471
+ โ€ข <b>๊ฒฐ๊ณผ๋ฌผ:</b> ์ฃผ์š” ๊ธฐ๋Šฅ์ด ๊ฐ•์กฐ๋œ ์ฃผ์„ ํฌํ•จ ์ œํ’ˆ ๋””์ž์ธ<br>
472
+ โ€ข <b>์ง‘์ค‘ ๋ถ„์•ผ:</b> ์ธํฌ๊ทธ๋ž˜ํ”ฝ ์Šคํƒ€์ผ ์ฃผ์„์ด ํฌํ•จ๋œ ๋ฌผ๋ฆฌ์  ์ œํ’ˆ
473
  </div>
474
  """)
475
 
476
  with gr.Row(equal_height=True):
477
  with gr.Column(scale=1):
478
  prompt = gr.Textbox(
479
+ label="๐Ÿ“ ์ œํ’ˆ ์ปจ์…‰",
480
+ placeholder="์ œํ’ˆ ์œ ํ˜• ์ž…๋ ฅ: '์Šค๋งˆํŠธ ์šด๋™ํ™”', '๋ฏธ๋ž˜ํ˜• ์ฃผ๋ฐฉ์šฉํ’ˆ', '์นœํ™˜๊ฒฝ ๊ฐ€๋ฐฉ', '๋ชจ๋“ˆํ˜• ๊ฐ€๊ตฌ'...",
481
  lines=2,
482
+ value="์ฐจ์„ธ๋Œ€ ๋ฌด์„  ์ด์–ดํฐ",
483
  elem_classes="prompt-input"
484
  )
485
 
486
  enhance_prompt_checkbox = gr.Checkbox(
487
+ label="๐Ÿš€ ์›น ๋ฆฌ์„œ์น˜๋ฅผ ํ†ตํ•œ ํŒ€ ํ˜‘์—… ํ™œ์„ฑํ™”",
488
  value=True,
489
+ info="๊ฐ๋… + ์—”์ง€๋‹ˆ์–ด(Brave ๊ฒ€์ƒ‰) + ๋””์ž์ด๋„ˆ ํ”„๋กœ์„ธ์Šค ํ™œ์„ฑํ™”"
490
  )
491
 
492
  with gr.Row():
493
  image1 = gr.Image(
494
+ label="์Šคํƒ€์ผ ์ฐธ์กฐ 1 (์„ ํƒ์‚ฌํ•ญ)",
495
  type="pil",
496
  height=180
497
  )
498
  image2 = gr.Image(
499
+ label="์Šคํƒ€์ผ ์ฐธ์กฐ 2 (์„ ํƒ์‚ฌํ•ญ)",
500
  type="pil",
501
  height=180
502
  )
503
 
504
  generate_btn = gr.Button(
505
+ "๐ŸŽจ ์ œํ’ˆ ๋””์ž์ธ ์ƒ์„ฑ",
506
  variant="primary",
507
  size="lg"
508
  )
509
 
510
  with gr.Column(scale=1):
511
  output_image = gr.Image(
512
+ label="์ƒ์„ฑ๋œ ์ œํ’ˆ ๋””์ž์ธ",
513
  type="pil",
514
  height=400,
515
  elem_classes="image-container"
516
  )
517
 
518
  enhanced_prompt_display = gr.Textbox(
519
+ label="๐Ÿ“‹ ์ตœ์ข… ๋””์ž์ธ ์‚ฌ์–‘",
520
  interactive=False,
521
  lines=3,
522
  elem_classes="enhanced-prompt-box"
523
  )
524
 
525
  status = gr.Textbox(
526
+ label="์ƒํƒœ",
527
  interactive=False,
528
  elem_classes="status-text",
529
+ value="๋””์ž์ธ ์ค€๋น„ ์ค‘..."
530
  )
531
 
532
  with gr.Row():
 
535
  elem_classes="team-discussion"
536
  )
537
 
538
+ # ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ์—ฐ๊ฒฐ
539
  generate_btn.click(
540
  fn=process_product_design,
541
  inputs=[prompt, enhance_prompt_checkbox, image1, image2],
542
  outputs=[output_image, enhanced_prompt_display, status, team_discussion_display]
543
  )
544
 
545
+ # ์ฐฝ์˜์ ์ธ ํ•œ๊ธ€ ์ œํ’ˆ ์˜ˆ์‹œ
546
  gr.Examples(
547
  examples=[
548
+ ["๊ณต์ค‘ ๋ถ€์–‘ ์Šคํ”ผ์ปค", True, None, None],
549
+ ["๋ณ€ํ˜• ๊ฐ€๋Šฅํ•œ ๋‹ค๋ชฉ์  ๊ฐ€๊ตฌ", True, None, None],
550
+ ["์ž๊ฐ€ ์ถฉ์ „ ์Šค๋งˆํŠธ ์‹ ๋ฐœ", True, None, None],
551
+ ["ํ™€๋กœ๊ทธ๋žจ ๋””์Šคํ”Œ๋ ˆ์ด ์‹œ๊ณ„", True, None, None],
552
+ ["์ ‘์ด์‹ ์ „๊ธฐ ์Šค์ฟ ํ„ฐ ํ—ฌ๋ฉง", True, None, None],
553
+ ["AI ์š”๋ฆฌ ๋„์šฐ๋ฏธ ๋กœ๋ด‡", True, None, None],
554
+ ["ํˆฌ๋ช… OLED ๋…ธํŠธ๋ถ", True, None, None],
555
+ ["์ƒ์ฒด์ธ์‹ ์Šค๋งˆํŠธ ๋„์–ด๋ฝ", True, None, None],
556
+ ["๋ชจ๋“ˆํ˜• ์บ ํ•‘ ์žฅ๋น„ ์‹œ์Šคํ…œ", True, None, None],
557
+ ["์›จ์–ด๋Ÿฌ๋ธ” ๊ณต๊ธฐ์ฒญ์ •๊ธฐ", True, None, None],
558
+ ["์ž๋™ ์˜จ๋„์กฐ์ ˆ ํ…€๋ธ”๋Ÿฌ", True, None, None],
559
+ ["๋ฏธ๋ž˜ํ˜• ๋ฐ˜๋ ค๋™๋ฌผ ์ผ€์–ด ์Šคํ…Œ์ด์…˜", True, None, None],
560
  ],
561
  inputs=[prompt, enhance_prompt_checkbox, image1, image2],
562
+ label="๐Ÿ’ก ์ฐฝ์˜์ ์ธ ์ œํ’ˆ ๋””์ž์ธ ์˜ˆ์‹œ"
563
  )
564
 
565
+ # ์‹คํ–‰ ์„ค์ •
566
  if __name__ == "__main__":
567
+ # ํ•„์š”ํ•œ API ํ‚ค ํ™•์ธ
568
  if not os.getenv('REPLICATE_API_TOKEN'):
569
+ print("โš ๏ธ ๊ฒฝ๊ณ : REPLICATE_API_TOKEN์ด ์„ค์ •๋˜์ง€ ์•Š์Œ")
570
  if not os.getenv('FIREWORKS_API_KEY'):
571
+ print("โš ๏ธ ๊ฒฝ๊ณ : FIREWORKS_API_KEY๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์Œ - ํด๋ฐฑ ํ”„๋กฌํ”„ํŠธ ์‚ฌ์šฉ")
572
  if not os.getenv('BRAVE_API_KEY'):
573
+ print("โš ๏ธ ๊ฒฝ๊ณ : BRAVE_API_KEY๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์Œ - ์›น ๊ฒ€์ƒ‰ ๋ถˆ๊ฐ€")
574
 
575
  demo.launch(
576
+ share=False, # Hugging Face Spaces์šฉ์œผ๋กœ False ์„ค์ •
577
  server_name="0.0.0.0",
578
  server_port=7860,
579
+ ssr_mode=False # ๊ฒฝ๊ณ  ๋ฐฉ์ง€๋ฅผ ์œ„ํ•ด SSR ๋น„ํ™œ์„ฑํ™”
580
  )