haepa_mac commited on
Commit
b2bd8b0
Β·
1 Parent(s): 67cb297

🎯 Fix API integration for persona generation + improve UI organization

Browse files
Files changed (1) hide show
  1. app.py +57 -29
app.py CHANGED
@@ -198,14 +198,27 @@ HUMOR_STYLE_MAPPING = {
198
  "Self-deprecating": "self_deprecating"
199
  }
200
 
201
- def create_persona_from_image(image, name, location, time_spent, object_type, progress=gr.Progress()):
202
  """페λ₯΄μ†Œλ‚˜ 생성 ν•¨μˆ˜ - API μ„€μ • 적용"""
203
  global persona_generator
204
 
205
  if image is None:
206
  return None, "이미지λ₯Ό μ—…λ‘œλ“œν•΄μ£Όμ„Έμš”.", "", {}, None, [], [], [], "", None, gr.update(visible=False)
207
 
208
- progress(0.1, desc="이미지 뢄석 쀑...")
 
 
 
 
 
 
 
 
 
 
 
 
 
209
 
210
  user_context = {
211
  "name": name,
@@ -229,20 +242,22 @@ def create_persona_from_image(image, name, location, time_spent, object_type, pr
229
  if image.format in ['AVIF', 'WEBP'] or image.mode not in ['RGB', 'RGBA']:
230
  image = image.convert('RGB')
231
 
232
- # κΈ€λ‘œλ²Œ persona_generator μ‚¬μš© (API 섀정이 적용된 μƒνƒœ)
233
- if persona_generator is None:
234
- persona_generator = PersonaGenerator()
235
 
236
  progress(0.3, desc="이미지 뢄석 쀑...")
237
  # 이미지 처리 방식 μˆ˜μ • - PIL Image 객체λ₯Ό 직접 전달
238
- image_analysis = persona_generator.analyze_image(image)
239
 
240
  progress(0.5, desc="페λ₯΄μ†Œλ‚˜ 생성 쀑...")
241
  # ν”„λ‘ νŠΈμ—”λ“œ 페λ₯΄μ†Œλ‚˜ 생성
242
- frontend_persona = persona_generator.create_frontend_persona(image_analysis, user_context)
243
 
244
  # λ°±μ—”λ“œ 페λ₯΄μ†Œλ‚˜ 생성 (κ΅¬μ‘°ν™”λœ ν”„λ‘¬ν”„νŠΈ 포함)
245
- backend_persona = persona_generator.create_backend_persona(frontend_persona, image_analysis)
 
 
 
246
 
247
  # 페λ₯΄μ†Œλ‚˜ 정보 ν¬λ§·νŒ…
248
  persona_name = backend_persona["기본정보"]["이름"]
@@ -274,7 +289,7 @@ def create_persona_from_image(image, name, location, time_spent, object_type, pr
274
 
275
  return (
276
  backend_persona, # current_persona
277
- f"βœ… {persona_name} 페λ₯΄μ†Œλ‚˜κ°€ μƒμ„±λ˜μ—ˆμŠ΅λ‹ˆλ‹€!", # status_output
278
  summary_display, # persona_summary_display
279
  backend_persona["μ„±κ²©νŠΉμ„±"], # personality_traits_output (hidden)
280
  humor_chart, # humor_chart_output
@@ -289,7 +304,7 @@ def create_persona_from_image(image, name, location, time_spent, object_type, pr
289
  except Exception as e:
290
  import traceback
291
  traceback.print_exc()
292
- return None, f"❌ 페λ₯΄μ†Œλ‚˜ 생성 쀑 였λ₯˜ λ°œμƒ: {str(e)}", "", {}, None, [], [], [], "", None, gr.update(visible=False)
293
 
294
  def generate_personality_preview(persona_name, personality_traits):
295
  """성격 νŠΉμ„±μ„ 기반으둜 ν•œ λ¬Έμž₯ 미리보기 생성"""
@@ -418,23 +433,29 @@ def adjust_persona_traits(persona, warmth, competence, extraversion, humor_style
418
  traceback.print_exc()
419
  return persona, f"μ‘°μ • 쀑 였λ₯˜ λ°œμƒ: {str(e)}", {}
420
 
421
- def finalize_persona(persona):
422
  """페λ₯΄μ†Œλ‚˜ μ΅œμ’… ν™•μ • - API μ„€μ • 적용"""
423
  global persona_generator
424
 
425
  if not persona:
426
  return None, "페λ₯΄μ†Œλ‚˜κ°€ μ—†μŠ΅λ‹ˆλ‹€.", "", {}, None, [], [], [], "", None
427
 
 
 
 
 
428
  try:
429
- # κΈ€λ‘œλ²Œ persona_generator μ‚¬μš© (API 섀정이 적용된 μƒνƒœ)
430
- if persona_generator is None:
431
- persona_generator = PersonaGenerator()
432
 
433
  # 이미 λ°±μ—”λ“œ 페λ₯΄μ†Œλ‚˜μΈ κ²½μš°μ™€ ν”„λ‘ νŠΈμ—”λ“œ 페λ₯΄μ†Œλ‚˜μΈ 경우 ꡬ뢄
434
  if "κ΅¬μ‘°ν™”ν”„λ‘¬ν”„νŠΈ" not in persona:
435
  # ν”„λ‘ νŠΈμ—”λ“œ 페λ₯΄μ†Œλ‚˜μΈ 경우 λ°±μ—”λ“œ 페λ₯΄μ†Œλ‚˜λ‘œ λ³€ν™˜
436
  image_analysis = {"object_type": persona.get("기본정보", {}).get("μœ ν˜•", "μ•Œ 수 μ—†λŠ” 사물")}
437
- persona = persona_generator.create_backend_persona(persona, image_analysis)
 
 
 
438
 
439
  persona_name = persona["기본정보"]["이름"]
440
 
@@ -469,7 +490,7 @@ def finalize_persona(persona):
469
 
470
  return (
471
  persona, # current_persona
472
- f"βœ… {persona_name} μ™„μ„±!", # status_output
473
  summary_display, # persona_summary_display
474
  persona["μ„±κ²©νŠΉμ„±"], # personality_traits_output
475
  humor_chart, # humor_chart_output
@@ -483,7 +504,7 @@ def finalize_persona(persona):
483
  except Exception as e:
484
  import traceback
485
  traceback.print_exc()
486
- return None, f"❌ 페λ₯΄μ†Œλ‚˜ ν™•μ • 쀑 였λ₯˜ λ°œμƒ: {str(e)}", "", {}, None, [], [], [], "", None
487
 
488
  def plot_humor_matrix(humor_data):
489
  """유머 맀트릭슀 μ‹œκ°ν™” - μ˜μ–΄ λ ˆμ΄λΈ” μ‚¬μš©"""
@@ -1253,6 +1274,13 @@ def create_main_interface():
1253
  gr.Markdown("### πŸ€– ν˜„μž¬ 페λ₯΄μ†Œλ‚˜")
1254
  chat_persona_greeting = gr.Markdown("", elem_classes=["persona-greeting"])
1255
  current_persona_info = gr.JSON(label="ν˜„μž¬ 페λ₯΄μ†Œλ‚˜ 정보", visible=False)
 
 
 
 
 
 
 
1256
 
1257
  with gr.Column(scale=1):
1258
  gr.Markdown("### πŸ’¬ λŒ€ν™”")
@@ -1275,16 +1303,15 @@ def create_main_interface():
1275
 
1276
  # 🧠 λŒ€ν™” 뢄석 νƒ­ μΆ”κ°€
1277
  with gr.Tab("🧠 λŒ€ν™” 뢄석"):
1278
- gr.Markdown("### πŸ“Š λŒ€ν™” 기둝 관리 및 뢄석")
1279
 
1280
  with gr.Row():
1281
  with gr.Column():
1282
- gr.Markdown("#### πŸ’Ύ λŒ€ν™” 기둝 μ €μž₯/뢈러였기")
1283
- conversation_export_btn = gr.Button("πŸ“₯ λŒ€ν™” 기둝 JSON λ‹€μš΄λ‘œλ“œ", variant="secondary")
1284
- conversation_download_file = gr.File(label="λ‹€μš΄λ‘œλ“œ", visible=False)
1285
 
1286
  import_file = gr.File(label="πŸ“€ λŒ€ν™” 기둝 JSON μ—…λ‘œλ“œ", file_types=[".json"])
1287
- import_result = gr.Textbox(label="κ°€μ Έμ˜€κΈ° κ²°κ³Ό", lines=3, interactive=False)
1288
 
1289
  with gr.Column():
1290
  gr.Markdown("#### πŸ” μ‹€μ‹œκ°„ ν‚€μ›Œλ“œ 뢄석")
@@ -1302,7 +1329,7 @@ def create_main_interface():
1302
  # 이벀트 ν•Έλ“€λŸ¬
1303
  create_btn.click(
1304
  fn=create_persona_from_image,
1305
- inputs=[image_input, name_input, location_input, time_spent_input, object_type_input],
1306
  outputs=[
1307
  current_persona, status_output, persona_summary_display, personality_traits_output,
1308
  humor_chart_output, attractive_flaws_output, contradictions_output,
@@ -1330,7 +1357,7 @@ def create_main_interface():
1330
  # 페λ₯΄μ†Œλ‚˜ μ΅œμ’… ν™•μ •
1331
  finalize_btn.click(
1332
  fn=finalize_persona,
1333
- inputs=[current_persona],
1334
  outputs=[
1335
  current_persona, status_output, persona_summary_display, personality_traits_output,
1336
  humor_chart_output, attractive_flaws_output, contradictions_output,
@@ -1433,16 +1460,17 @@ def create_main_interface():
1433
  outputs=[personas_list]
1434
  )
1435
 
1436
- # 이벀트 μ—°κ²°
1437
- conversation_export_btn.click(
1438
  export_conversation_history,
1439
- outputs=[conversation_download_file]
1440
  ).then(
1441
  lambda x: gr.update(visible=True) if x else gr.update(visible=False),
1442
- inputs=[conversation_download_file],
1443
- outputs=[conversation_download_file]
1444
  )
1445
 
 
1446
  import_file.upload(
1447
  import_conversation_history,
1448
  inputs=[import_file],
 
198
  "Self-deprecating": "self_deprecating"
199
  }
200
 
201
+ def create_persona_from_image(image, name, location, time_spent, object_type, api_provider="gemini", api_key=None, progress=gr.Progress()):
202
  """페λ₯΄μ†Œλ‚˜ 생성 ν•¨μˆ˜ - API μ„€μ • 적용"""
203
  global persona_generator
204
 
205
  if image is None:
206
  return None, "이미지λ₯Ό μ—…λ‘œλ“œν•΄μ£Όμ„Έμš”.", "", {}, None, [], [], [], "", None, gr.update(visible=False)
207
 
208
+ progress(0.1, desc="μ„€μ • 확인 쀑...")
209
+
210
+ # API ν‚€ 검증
211
+ if not api_key or not api_key.strip():
212
+ return None, "❌ **API ν‚€κ°€ ν•„μš”ν•©λ‹ˆλ‹€!** μƒλ‹¨μ˜ 'API μ„€μ •' μ„Ήμ…˜μ—μ„œ λ¨Όμ € API ν‚€λ₯Ό μ„€μ •ν•΄μ£Όμ„Έμš”.", "", {}, None, [], [], [], "", None, gr.update(visible=False)
213
+
214
+ # API ν‚€ ν˜•μ‹ 검증
215
+ api_key = api_key.strip()
216
+ if api_provider == "gemini" and not api_key.startswith("AI"):
217
+ return None, "❌ **Gemini API ν‚€ ν˜•μ‹μ΄ μ˜¬λ°”λ₯΄μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.** 'AIza...' ν˜•νƒœμ—¬μ•Ό ν•©λ‹ˆλ‹€.", "", {}, None, [], [], [], "", None, gr.update(visible=False)
218
+ elif api_provider == "openai" and not api_key.startswith("sk-"):
219
+ return None, "❌ **OpenAI API ν‚€ ν˜•μ‹μ΄ μ˜¬λ°”λ₯΄μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.** 'sk-...' ν˜•νƒœμ—¬μ•Ό ν•©λ‹ˆλ‹€.", "", {}, None, [], [], [], "", None, gr.update(visible=False)
220
+
221
+ progress(0.2, desc="API μ—°κ²° 확인 쀑...")
222
 
223
  user_context = {
224
  "name": name,
 
242
  if image.format in ['AVIF', 'WEBP'] or image.mode not in ['RGB', 'RGBA']:
243
  image = image.convert('RGB')
244
 
245
+ # PersonaGenerator μΈμŠ€ν„΄μŠ€ 생성 (API ν‚€ 포함)
246
+ generator = PersonaGenerator(api_provider=api_provider, api_key=api_key)
 
247
 
248
  progress(0.3, desc="이미지 뢄석 쀑...")
249
  # 이미지 처리 방식 μˆ˜μ • - PIL Image 객체λ₯Ό 직접 전달
250
+ image_analysis = generator.analyze_image(image)
251
 
252
  progress(0.5, desc="페λ₯΄μ†Œλ‚˜ 생성 쀑...")
253
  # ν”„λ‘ νŠΈμ—”λ“œ 페λ₯΄μ†Œλ‚˜ 생성
254
+ frontend_persona = generator.create_frontend_persona(image_analysis, user_context)
255
 
256
  # λ°±μ—”λ“œ 페λ₯΄μ†Œλ‚˜ 생성 (κ΅¬μ‘°ν™”λœ ν”„λ‘¬ν”„νŠΈ 포함)
257
+ backend_persona = generator.create_backend_persona(frontend_persona, image_analysis)
258
+
259
+ # κΈ€λ‘œλ²Œ μΈμŠ€ν„΄μŠ€ μ—…λ°μ΄νŠΈ (μ„±κ³΅ν•œ κ²½μš°μ—λ§Œ)
260
+ persona_generator = generator
261
 
262
  # 페λ₯΄μ†Œλ‚˜ 정보 ν¬λ§·νŒ…
263
  persona_name = backend_persona["기본정보"]["이름"]
 
289
 
290
  return (
291
  backend_persona, # current_persona
292
+ f"βœ… {persona_name} 페λ₯΄μ†Œλ‚˜κ°€ μƒμ„±λ˜μ—ˆμŠ΅λ‹ˆλ‹€! (API: {api_provider})", # status_output
293
  summary_display, # persona_summary_display
294
  backend_persona["μ„±κ²©νŠΉμ„±"], # personality_traits_output (hidden)
295
  humor_chart, # humor_chart_output
 
304
  except Exception as e:
305
  import traceback
306
  traceback.print_exc()
307
+ return None, f"❌ 페λ₯΄μ†Œλ‚˜ 생성 쀑 였λ₯˜ λ°œμƒ: {str(e)}\n\nπŸ’‘ **해결방법**: API ν‚€κ°€ μ˜¬λ°”λ₯Έμ§€ ν™•μΈν•˜κ³  인터넷 연결을 ν™•μΈν•΄λ³΄μ„Έμš”.", "", {}, None, [], [], [], "", None, gr.update(visible=False)
308
 
309
  def generate_personality_preview(persona_name, personality_traits):
310
  """성격 νŠΉμ„±μ„ 기반으둜 ν•œ λ¬Έμž₯ 미리보기 생성"""
 
433
  traceback.print_exc()
434
  return persona, f"μ‘°μ • 쀑 였λ₯˜ λ°œμƒ: {str(e)}", {}
435
 
436
+ def finalize_persona(persona, api_provider="gemini", api_key=None):
437
  """페λ₯΄μ†Œλ‚˜ μ΅œμ’… ν™•μ • - API μ„€μ • 적용"""
438
  global persona_generator
439
 
440
  if not persona:
441
  return None, "페λ₯΄μ†Œλ‚˜κ°€ μ—†μŠ΅λ‹ˆλ‹€.", "", {}, None, [], [], [], "", None
442
 
443
+ # API ν‚€ 검증
444
+ if not api_key or not api_key.strip():
445
+ return None, "❌ **API ν‚€κ°€ ν•„μš”ν•©λ‹ˆλ‹€!** μƒλ‹¨μ˜ 'API μ„€μ •' μ„Ήμ…˜μ—μ„œ λ¨Όμ € API ν‚€λ₯Ό μ„€μ •ν•΄μ£Όμ„Έμš”.", "", {}, None, [], [], [], "", None
446
+
447
  try:
448
+ # PersonaGenerator μΈμŠ€ν„΄μŠ€ 생성 (API ν‚€ 포함)
449
+ generator = PersonaGenerator(api_provider=api_provider, api_key=api_key.strip())
 
450
 
451
  # 이미 λ°±μ—”λ“œ 페λ₯΄μ†Œλ‚˜μΈ κ²½μš°μ™€ ν”„λ‘ νŠΈμ—”λ“œ 페λ₯΄μ†Œλ‚˜μΈ 경우 ꡬ뢄
452
  if "κ΅¬μ‘°ν™”ν”„λ‘¬ν”„νŠΈ" not in persona:
453
  # ν”„λ‘ νŠΈμ—”λ“œ 페λ₯΄μ†Œλ‚˜μΈ 경우 λ°±μ—”λ“œ 페λ₯΄μ†Œλ‚˜λ‘œ λ³€ν™˜
454
  image_analysis = {"object_type": persona.get("기본정보", {}).get("μœ ν˜•", "μ•Œ 수 μ—†λŠ” 사물")}
455
+ persona = generator.create_backend_persona(persona, image_analysis)
456
+
457
+ # κΈ€λ‘œλ²Œ μΈμŠ€ν„΄μŠ€ μ—…λ°μ΄νŠΈ (μ„±κ³΅ν•œ κ²½μš°μ—λ§Œ)
458
+ persona_generator = generator
459
 
460
  persona_name = persona["기본정보"]["이름"]
461
 
 
490
 
491
  return (
492
  persona, # current_persona
493
+ f"βœ… {persona_name} μ™„μ„±! (API: {api_provider})", # status_output
494
  summary_display, # persona_summary_display
495
  persona["μ„±κ²©νŠΉμ„±"], # personality_traits_output
496
  humor_chart, # humor_chart_output
 
504
  except Exception as e:
505
  import traceback
506
  traceback.print_exc()
507
+ return None, f"❌ 페λ₯΄μ†Œλ‚˜ ν™•μ • 쀑 였λ₯˜ λ°œμƒ: {str(e)}\n\nπŸ’‘ **해결방법**: API ν‚€κ°€ μ˜¬λ°”λ₯Έμ§€ ν™•μΈν•˜κ³  인터넷 연결을 ν™•μΈν•΄λ³΄μ„Έμš”.", "", {}, None, [], [], [], "", None
508
 
509
  def plot_humor_matrix(humor_data):
510
  """유머 맀트릭슀 μ‹œκ°ν™” - μ˜μ–΄ λ ˆμ΄λΈ” μ‚¬μš©"""
 
1274
  gr.Markdown("### πŸ€– ν˜„μž¬ 페λ₯΄μ†Œλ‚˜")
1275
  chat_persona_greeting = gr.Markdown("", elem_classes=["persona-greeting"])
1276
  current_persona_info = gr.JSON(label="ν˜„μž¬ 페λ₯΄μ†Œλ‚˜ 정보", visible=False)
1277
+
1278
+ # λŒ€ν™” 기둝 관리
1279
+ with gr.Group():
1280
+ gr.Markdown("### πŸ’Ύ λŒ€ν™” 기둝 관리")
1281
+ gr.Markdown("ν˜„μž¬ λŒ€ν™”λ₯Ό JSON 파일둜 λ‹€μš΄λ‘œλ“œν•˜μ—¬ λ³΄κ΄€ν•˜μ„Έμš”.")
1282
+ chat_export_btn = gr.Button("πŸ“₯ ν˜„μž¬ λŒ€ν™” 기둝 λ‹€μš΄λ‘œλ“œ", variant="secondary")
1283
+ chat_download_file = gr.File(label="λ‹€μš΄λ‘œλ“œ", visible=False)
1284
 
1285
  with gr.Column(scale=1):
1286
  gr.Markdown("### πŸ’¬ λŒ€ν™”")
 
1303
 
1304
  # 🧠 λŒ€ν™” 뢄석 νƒ­ μΆ”κ°€
1305
  with gr.Tab("🧠 λŒ€ν™” 뢄석"):
1306
+ gr.Markdown("### πŸ“Š λŒ€ν™” 기둝 뢄석 및 ν‚€μ›Œλ“œ μΆ”μΆœ")
1307
 
1308
  with gr.Row():
1309
  with gr.Column():
1310
+ gr.Markdown("#### πŸ“€ λŒ€ν™” 기둝 λΆ„μ„ν•˜κΈ°")
1311
+ gr.Markdown("μ €μž₯된 λŒ€ν™” 기둝 JSON νŒŒμΌμ„ μ—…λ‘œλ“œν•˜μ—¬ λΆ„μ„ν•΄λ³΄μ„Έμš”.")
 
1312
 
1313
  import_file = gr.File(label="πŸ“€ λŒ€ν™” 기둝 JSON μ—…λ‘œλ“œ", file_types=[".json"])
1314
+ import_result = gr.Textbox(label="μ—…λ‘œλ“œ κ²°κ³Ό", lines=3, interactive=False)
1315
 
1316
  with gr.Column():
1317
  gr.Markdown("#### πŸ” μ‹€μ‹œκ°„ ν‚€μ›Œλ“œ 뢄석")
 
1329
  # 이벀트 ν•Έλ“€λŸ¬
1330
  create_btn.click(
1331
  fn=create_persona_from_image,
1332
+ inputs=[image_input, name_input, location_input, time_spent_input, object_type_input, api_provider, api_key_input],
1333
  outputs=[
1334
  current_persona, status_output, persona_summary_display, personality_traits_output,
1335
  humor_chart_output, attractive_flaws_output, contradictions_output,
 
1357
  # 페λ₯΄μ†Œλ‚˜ μ΅œμ’… ν™•μ •
1358
  finalize_btn.click(
1359
  fn=finalize_persona,
1360
+ inputs=[current_persona, api_provider, api_key_input],
1361
  outputs=[
1362
  current_persona, status_output, persona_summary_display, personality_traits_output,
1363
  humor_chart_output, attractive_flaws_output, contradictions_output,
 
1460
  outputs=[personas_list]
1461
  )
1462
 
1463
+ # λŒ€ν™”ν•˜κΈ° νƒ­μ˜ λŒ€ν™” 기둝 λ‹€μš΄λ‘œλ“œ 이벀트
1464
+ chat_export_btn.click(
1465
  export_conversation_history,
1466
+ outputs=[chat_download_file]
1467
  ).then(
1468
  lambda x: gr.update(visible=True) if x else gr.update(visible=False),
1469
+ inputs=[chat_download_file],
1470
+ outputs=[chat_download_file]
1471
  )
1472
 
1473
+ # λŒ€ν™” 뢄석 νƒ­μ˜ μ—…λ‘œλ“œ 이벀트
1474
  import_file.upload(
1475
  import_conversation_history,
1476
  inputs=[import_file],