haepa_mac commited on
Commit
a1eb89d
ยท
1 Parent(s): a98acac

๐Ÿ”ง ์ฃผ์š” ์˜ค๋ฅ˜ ํ•ด๊ฒฐ ๋ฐ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜ ๊ฐœ์„  - JSON ๋Œ€ํ™” ์˜ค๋ฅ˜ ํ•ด๊ฒฐ, ์„ฑ๊ฒฉ ์„ค๋ช… ์ค‘๋ณต ์ œ๊ฑฐ, ๋งค๋ ฅ์  ๊ฒฐํ•จ ๊ฐœ์„ , ๋กœ๋“œ ์‹œ AI ์ธ์‚ฌ๋ง ์ ์šฉ

Browse files
Files changed (2) hide show
  1. app.py +64 -30
  2. modules/persona_generator.py +31 -20
app.py CHANGED
@@ -516,12 +516,10 @@ def adjust_persona_traits(persona, warmth, competence, extraversion, humor_style
516
  adjustment_message = f"""
517
  ### ๐ŸŽญ {persona_name}์˜ ์„ฑ๊ฒฉ์ด ์กฐ์ •๋˜์—ˆ์Šต๋‹ˆ๋‹ค!
518
 
519
- {personality_preview}
520
-
521
  โœจ **์กฐ์ •๋œ ์„ฑ๊ฒฉ (3๊ฐ€์ง€ ํ•ต์‹ฌ ์ง€ํ‘œ):**
522
- โ€ข ์˜จ๊ธฐ: {warmth}/100
523
- โ€ข ๋Šฅ๋ ฅ: {competence}/100
524
- โ€ข ์™ธํ–ฅ์„ฑ: {extraversion}/100
525
  โ€ข ์œ ๋จธ๊ฐ๊ฐ: 75/100 (๊ณ ์ • - ๋ชจ๋“  ํŽ˜๋ฅด์†Œ๋‚˜๊ฐ€ ์œ ๋จธ๋Ÿฌ์Šค!)
526
  โ€ข ์œ ๋จธ์Šคํƒ€์ผ: {humor_style}
527
 
@@ -567,13 +565,28 @@ def finalize_persona(persona):
567
  # ์œ ๋จธ ๋งคํŠธ๋ฆญ์Šค ์ฐจํŠธ ์ƒ์„ฑ
568
  humor_chart = plot_humor_matrix(persona.get("์œ ๋จธ๋งคํŠธ๋ฆญ์Šค", {}))
569
 
570
- # ๋งค๋ ฅ์  ๊ฒฐํ•จ์„ DataFrame ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜
571
  flaws = persona.get("๋งค๋ ฅ์ ๊ฒฐํ•จ", [])
572
- flaws_df = [[flaw, "๋งค๋ ฅ์ ์ธ ๊ฐœ์„ฑ"] for flaw in flaws]
 
 
 
 
 
 
 
573
 
574
- # ๋ชจ์ˆœ์  ํŠน์„ฑ์„ DataFrame ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜
575
  contradictions = persona.get("๋ชจ์ˆœ์ ํŠน์„ฑ", [])
576
- contradictions_df = [[contradiction, "๋ณตํ•ฉ์  ๋งค๋ ฅ"] for contradiction in contradictions]
 
 
 
 
 
 
 
 
577
 
578
  # 127๊ฐœ ์„ฑ๊ฒฉ ๋ณ€์ˆ˜๋ฅผ DataFrame ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜
579
  variables = persona.get("์„ฑ๊ฒฉ๋ณ€์ˆ˜127", {})
@@ -832,8 +845,15 @@ def chat_with_loaded_persona(persona, user_message, chat_history=None):
832
  # ํƒ€์ž…๋ณ„ ์•ˆ์ „ํ•œ ์ฒ˜๋ฆฌ
833
  if chat_turn is None:
834
  continue
 
 
 
 
 
 
 
835
  elif isinstance(chat_turn, (list, tuple)) and len(chat_turn) >= 2:
836
- # Gradio 4.x ํ˜•์‹: [user_message, bot_response]
837
  user_msg = chat_turn[0]
838
  bot_msg = chat_turn[1]
839
 
@@ -841,14 +861,6 @@ def chat_with_loaded_persona(persona, user_message, chat_history=None):
841
  conversation_history.append({"role": "user", "content": str(user_msg)})
842
  if bot_msg is not None and str(bot_msg).strip():
843
  conversation_history.append({"role": "assistant", "content": str(bot_msg)})
844
-
845
- elif isinstance(chat_turn, dict):
846
- # ํ˜น์‹œ dict ํ˜•์‹์ด ๋“ค์–ด์˜จ ๊ฒฝ์šฐ ์•ˆ์ „ํ•˜๊ฒŒ ์ฒ˜๋ฆฌ
847
- role = chat_turn.get("role") if hasattr(chat_turn, 'get') else None
848
- content = chat_turn.get("content") if hasattr(chat_turn, 'get') else None
849
-
850
- if role and content:
851
- conversation_history.append({"role": str(role), "content": str(content)})
852
  else:
853
  # ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ํ˜•์‹์€ ๋ฌด์‹œ
854
  print(f"โš ๏ธ ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์ฑ„ํŒ… ํ˜•์‹ ๋ฌด์‹œ: {type(chat_turn)}")
@@ -880,8 +892,13 @@ def chat_with_loaded_persona(persona, user_message, chat_history=None):
880
  if not isinstance(response, str):
881
  response = str(response) if response else "์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค. ์‘๋‹ต์„ ์ƒ์„ฑํ•  ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค."
882
 
883
- # Gradio 4.x ํ˜•์‹์œผ๋กœ ์•ˆ์ „ํ•˜๊ฒŒ ์ถ”๊ฐ€
884
- chat_history.append([user_message, response])
 
 
 
 
 
885
 
886
  return chat_history, ""
887
 
@@ -904,11 +921,17 @@ def chat_with_loaded_persona(persona, user_message, chat_history=None):
904
  else:
905
  friendly_error = f"์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค. ์ผ์‹œ์ ์ธ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์–ด์š”. ๐Ÿ˜…\n\n๐Ÿ” ๊ธฐ์ˆ  ์ •๋ณด: {str(e)}"
906
 
907
- # ์•ˆ์ „ํ•˜๊ฒŒ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€ ์ถ”๊ฐ€
908
  try:
909
- chat_history.append([user_message, friendly_error])
 
 
 
910
  except Exception:
911
- chat_history = [[user_message, friendly_error]]
 
 
 
912
 
913
  return chat_history, ""
914
 
@@ -942,11 +965,21 @@ def import_persona_from_json(json_file):
942
  persona_name = basic_info.get("์ด๋ฆ„", "Unknown")
943
  personality_traits = persona_data.get("์„ฑ๊ฒฉํŠน์„ฑ", {})
944
 
945
- # ์„ฑ๊ฒฉ์ด ๋“œ๋Ÿฌ๋‚˜๋Š” ์ธ์‚ฌ๋ง ์ƒ์„ฑ (์‚ฌ๋ฌผ ํŠน์„ฑ ๋ฐ˜์˜)
946
- object_info = basic_info
947
- personality_preview = generate_personality_preview(persona_name, personality_traits, object_info)
948
-
949
- greeting = f"### ๐Ÿค– JSON์—์„œ ๊นจ์–ด๋‚œ ์นœ๊ตฌ\n\n{personality_preview}\n\n๐Ÿ’พ *\"JSON์—์„œ ๋‹ค์‹œ ๊นจ์–ด๋‚ฌ์–ด! ๋‚ด ์„ฑ๊ฒฉ ๊ธฐ์–ต๋‚˜?\"*"
 
 
 
 
 
 
 
 
 
 
950
 
951
  return (persona_data, f"โœ… {persona_name} ํŽ˜๋ฅด์†Œ๋‚˜๋ฅผ JSON์—์„œ ๋ถˆ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค!",
952
  greeting, basic_info)
@@ -1609,16 +1642,17 @@ def create_main_interface():
1609
  outputs=[chatbot, message_input]
1610
  )
1611
 
1612
- # ๋Œ€ํ™” ์ดˆ๊ธฐํ™”
1613
  clear_btn.click(
1614
  fn=lambda: [],
1615
  outputs=[chatbot]
1616
  )
1617
 
1618
- # ์˜ˆ์‹œ ๋ฉ”์‹œ์ง€ ๋ฒ„ํŠผ๋“ค - API ์„ค์ • ์ •๋ณด ํฌํ•จ
1619
  def handle_example_message(persona, message):
1620
  if not persona:
1621
  return [], ""
 
1622
  chat_result, _ = chat_with_loaded_persona(persona, message, [])
1623
  return chat_result, ""
1624
 
 
516
  adjustment_message = f"""
517
  ### ๐ŸŽญ {persona_name}์˜ ์„ฑ๊ฒฉ์ด ์กฐ์ •๋˜์—ˆ์Šต๋‹ˆ๋‹ค!
518
 
 
 
519
  โœจ **์กฐ์ •๋œ ์„ฑ๊ฒฉ (3๊ฐ€์ง€ ํ•ต์‹ฌ ์ง€ํ‘œ):**
520
+ โ€ข ์˜จ๊ธฐ: {warmth}/100 {'(๋”ฐ๋œปํ•จ)' if warmth >= 60 else '(์ฐจ๊ฐ€์›€)' if warmth <= 40 else '(๋ณดํ†ต)'}
521
+ โ€ข ๋Šฅ๋ ฅ: {competence}/100 {'(์œ ๋Šฅํ•จ)' if competence >= 60 else '(์„œํˆผ)' if competence <= 40 else '(๋ณดํ†ต)'}
522
+ โ€ข ์™ธํ–ฅ์„ฑ: {extraversion}/100 {'(ํ™œ๋ฐœํ•จ)' if extraversion >= 60 else '(์กฐ์šฉํ•จ)' if extraversion <= 40 else '(๋ณดํ†ต)'}
523
  โ€ข ์œ ๋จธ๊ฐ๊ฐ: 75/100 (๊ณ ์ • - ๋ชจ๋“  ํŽ˜๋ฅด์†Œ๋‚˜๊ฐ€ ์œ ๋จธ๋Ÿฌ์Šค!)
524
  โ€ข ์œ ๋จธ์Šคํƒ€์ผ: {humor_style}
525
 
 
565
  # ์œ ๋จธ ๋งคํŠธ๋ฆญ์Šค ์ฐจํŠธ ์ƒ์„ฑ
566
  humor_chart = plot_humor_matrix(persona.get("์œ ๋จธ๋งคํŠธ๋ฆญ์Šค", {}))
567
 
568
+ # ๋งค๋ ฅ์  ๊ฒฐํ•จ์„ ๋” ์ƒ์„ธํ•œ DataFrame์œผ๋กœ ๋ณ€ํ™˜
569
  flaws = persona.get("๋งค๋ ฅ์ ๊ฒฐํ•จ", [])
570
+ flaws_df = []
571
+ for i, flaw in enumerate(flaws, 1):
572
+ # ์‚ฌ๋ฌผ ํŠน์„ฑ vs ์„ฑ๊ฒฉ์  ํŠน์„ฑ ๊ตฌ๋ถ„
573
+ if any(keyword in flaw for keyword in ["๋จผ์ง€", "ํ–‡๋ณ•", "์ƒ‰์ด", "์ถฉ๊ฒฉ", "์Šต๋„", "๋ƒ„์ƒˆ", "๋ชจ์„œ๋ฆฌ", "๋ฌด๊ฒŒ", "ํฌ๊ธฐ"]):
574
+ flaw_type = "์‚ฌ๋ฌผ ํŠน์„ฑ ๊ธฐ๋ฐ˜"
575
+ else:
576
+ flaw_type = "์„ฑ๊ฒฉ์  ํŠน์„ฑ"
577
+ flaws_df.append([f"{i}. {flaw}", flaw_type])
578
 
579
+ # ๋ชจ์ˆœ์  ํŠน์„ฑ์„ ๋” ์ƒ์„ธํ•œ DataFrame์œผ๋กœ ๋ณ€ํ™˜
580
  contradictions = persona.get("๋ชจ์ˆœ์ ํŠน์„ฑ", [])
581
+ contradictions_df = []
582
+ for i, contradiction in enumerate(contradictions, 1):
583
+ contradictions_df.append([f"{i}. {contradiction}", "๋ณตํ•ฉ์  ๋งค๋ ฅ"])
584
+
585
+ # ์‚ฌ๋ฌผ ๊ณ ์œ  ํŠน์„ฑ๋„ ์ถ”๊ฐ€
586
+ object_type = persona.get("๊ธฐ๋ณธ์ •๋ณด", {}).get("์œ ํ˜•", "")
587
+ purpose = persona.get("๊ธฐ๋ณธ์ •๋ณด", {}).get("์šฉ๋„", "")
588
+ if purpose:
589
+ contradictions_df.append([f"๐ŸŽฏ {purpose}์„ ๋‹ด๋‹นํ•˜๋Š” {object_type}์˜ ๋…ํŠนํ•œ ๊ฐœ์„ฑ", "์‚ฌ๋ฌผ ์—ญํ•  ํŠน์„ฑ"])
590
 
591
  # 127๊ฐœ ์„ฑ๊ฒฉ ๋ณ€์ˆ˜๋ฅผ DataFrame ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜
592
  variables = persona.get("์„ฑ๊ฒฉ๋ณ€์ˆ˜127", {})
 
845
  # ํƒ€์ž…๋ณ„ ์•ˆ์ „ํ•œ ์ฒ˜๋ฆฌ
846
  if chat_turn is None:
847
  continue
848
+ elif isinstance(chat_turn, dict):
849
+ # Messages format: {"role": "user/assistant", "content": "message"}
850
+ role = chat_turn.get("role")
851
+ content = chat_turn.get("content")
852
+
853
+ if role and content and role in ["user", "assistant"]:
854
+ conversation_history.append({"role": str(role), "content": str(content)})
855
  elif isinstance(chat_turn, (list, tuple)) and len(chat_turn) >= 2:
856
+ # ๊ตฌ Gradio ํ˜•์‹: [user_message, bot_response] (ํ˜ธํ™˜์„ฑ)
857
  user_msg = chat_turn[0]
858
  bot_msg = chat_turn[1]
859
 
 
861
  conversation_history.append({"role": "user", "content": str(user_msg)})
862
  if bot_msg is not None and str(bot_msg).strip():
863
  conversation_history.append({"role": "assistant", "content": str(bot_msg)})
 
 
 
 
 
 
 
 
864
  else:
865
  # ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ํ˜•์‹์€ ๋ฌด์‹œ
866
  print(f"โš ๏ธ ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์ฑ„ํŒ… ํ˜•์‹ ๋ฌด์‹œ: {type(chat_turn)}")
 
892
  if not isinstance(response, str):
893
  response = str(response) if response else "์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค. ์‘๋‹ต์„ ์ƒ์„ฑํ•  ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค."
894
 
895
+ # Gradio 4.x messages format์œผ๋กœ ์•ˆ์ „ํ•˜๊ฒŒ ์ถ”๊ฐ€
896
+ if not isinstance(chat_history, list):
897
+ chat_history = []
898
+
899
+ # Messages format: {"role": "user", "content": "message"}
900
+ chat_history.append({"role": "user", "content": user_message})
901
+ chat_history.append({"role": "assistant", "content": response})
902
 
903
  return chat_history, ""
904
 
 
921
  else:
922
  friendly_error = f"์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค. ์ผ์‹œ์ ์ธ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์–ด์š”. ๐Ÿ˜…\n\n๐Ÿ” ๊ธฐ์ˆ  ์ •๋ณด: {str(e)}"
923
 
924
+ # ์•ˆ์ „ํ•˜๊ฒŒ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€ ์ถ”๊ฐ€ (messages format)
925
  try:
926
+ if not isinstance(chat_history, list):
927
+ chat_history = []
928
+ chat_history.append({"role": "user", "content": user_message})
929
+ chat_history.append({"role": "assistant", "content": friendly_error})
930
  except Exception:
931
+ chat_history = [
932
+ {"role": "user", "content": user_message},
933
+ {"role": "assistant", "content": friendly_error}
934
+ ]
935
 
936
  return chat_history, ""
937
 
 
965
  persona_name = basic_info.get("์ด๋ฆ„", "Unknown")
966
  personality_traits = persona_data.get("์„ฑ๊ฒฉํŠน์„ฑ", {})
967
 
968
+ # AI ๊ธฐ๋ฐ˜ ์ธ์‚ฌ๋ง ์ƒ์„ฑ (๋กœ๋“œ ์‹œ์—๋„ ์กฐ์ •๋œ ์„ฑ๊ฒฉ ๋ฐ˜์˜)
969
+ global persona_generator
970
+ try:
971
+ if persona_generator:
972
+ ai_greeting = persona_generator.generate_ai_based_greeting(persona_data, personality_traits)
973
+ greeting = f"### ๐Ÿค– JSON์—์„œ ๊นจ์–ด๋‚œ ์นœ๊ตฌ\n\n{ai_greeting}\n\n๐Ÿ’พ *\"JSON์—์„œ ๋‹ค์‹œ ๊นจ์–ด๋‚ฌ์–ด! ๋‚ด ์„ฑ๊ฒฉ ๊ธฐ์–ต๋‚˜?\"*"
974
+ else:
975
+ # ํด๋ฐฑ: ๊ธฐ์กด ๋ฐฉ์‹
976
+ personality_preview = generate_personality_preview(persona_name, personality_traits, basic_info)
977
+ greeting = f"### ๐Ÿค– JSON์—์„œ ๊นจ์–ด๋‚œ ์นœ๊ตฌ\n\n{personality_preview}\n\n๐Ÿ’พ *\"JSON์—์„œ ๋‹ค์‹œ ๊นจ์–ด๋‚ฌ์–ด! ๋‚ด ์„ฑ๊ฒฉ ๊ธฐ์–ต๋‚˜?\"*"
978
+ except Exception as e:
979
+ print(f"โš ๏ธ JSON ๋กœ๋“œ ์‹œ AI ์ธ์‚ฌ๋ง ์ƒ์„ฑ ์‹คํŒจ: {e}")
980
+ # ํด๋ฐฑ: ๊ธฐ์กด ๋ฐฉ์‹
981
+ personality_preview = generate_personality_preview(persona_name, personality_traits, basic_info)
982
+ greeting = f"### ๐Ÿค– JSON์—์„œ ๊นจ์–ด๋‚œ ์นœ๊ตฌ\n\n{personality_preview}\n\n๐Ÿ’พ *\"JSON์—์„œ ๋‹ค์‹œ ๊นจ์–ด๋‚ฌ์–ด! ๋‚ด ์„ฑ๊ฒฉ ๊ธฐ์–ต๋‚˜?\"*"
983
 
984
  return (persona_data, f"โœ… {persona_name} ํŽ˜๋ฅด์†Œ๋‚˜๋ฅผ JSON์—์„œ ๋ถˆ๋Ÿฌ์™”์Šต๋‹ˆ๋‹ค!",
985
  greeting, basic_info)
 
1642
  outputs=[chatbot, message_input]
1643
  )
1644
 
1645
+ # ๋Œ€ํ™” ์ดˆ๊ธฐํ™” (messages format)
1646
  clear_btn.click(
1647
  fn=lambda: [],
1648
  outputs=[chatbot]
1649
  )
1650
 
1651
+ # ์˜ˆ์‹œ ๋ฉ”์‹œ์ง€ ๋ฒ„ํŠผ๋“ค - messages format ํ˜ธํ™˜
1652
  def handle_example_message(persona, message):
1653
  if not persona:
1654
  return [], ""
1655
+ # ๋นˆ messages format ๋ฐฐ์—ด๋กœ ์‹œ์ž‘
1656
  chat_result, _ = chat_with_loaded_persona(persona, message, [])
1657
  return chat_result, ""
1658
 
modules/persona_generator.py CHANGED
@@ -608,29 +608,40 @@ class PersonalityProfile:
608
  return self
609
 
610
  def generate_attractive_flaws(self):
611
- """๋งค๋ ฅ์  ๊ฒฐํ•จ 3๊ฐœ ์ƒ์„ฑ (ํ”„๋žซํด ํšจ๊ณผ ๊ธฐ๋ฐ˜)"""
612
  flaw_vars = {k: v for k, v in self.variables.items() if k.startswith("F")}
613
- top_flaws = sorted(flaw_vars.items(), key=lambda x: x[1], reverse=True)[:3]
 
 
 
 
 
 
 
 
 
 
 
 
614
 
615
- flaw_descriptions = {
616
- "F01_์™„๋ฒฝ์ฃผ์˜๋ถˆ์•ˆ": "์™„๋ฒฝํ•˜์ง€ ๋ชปํ•  ๋•Œ ๋ถˆ์•ˆํ•ดํ•˜๋Š” ๊ฒฝํ–ฅ",
617
- "F02_๋ฐฉํ–ฅ๊ฐ๊ฐ๋ถ€์กฑ": "๊ฐ€๋” ๋ฐฉํ–ฅ์„ ์ž˜ ์ฐพ์ง€ ๋ชปํ•จ",
618
- "F03_๊ธฐ์ˆ ์น˜์Œ": "์ƒˆ๋กœ์šด ๊ธฐ์ˆ ์— ์ ์‘ํ•˜๋Š” ๋ฐ ์–ด๋ ค์›€์„ ๊ฒช์Œ",
619
- "F04_์šฐ์œ ๋ถ€๋‹จํ•จ": "๊ฒฐ์ •์„ ๋‚ด๋ฆฌ๊ธฐ ์–ด๋ ค์›Œํ•˜๋Š” ์„ฑํ–ฅ",
620
- "F05_๊ณผ๋„ํ•œ๊ฑฑ์ •": "์‚ฌ์†Œํ•œ ์ผ์—๋„ ์ง€๋‚˜์น˜๊ฒŒ ๊ฑฑ์ •ํ•จ",
621
- "F06_๊ฐ์ •๊ธฐ๋ณต": "๊ฐ์ •์˜ ๋ณ€ํ™”๊ฐ€ ํฐ ํŽธ",
622
- "F07_์‚ฐ๋งŒํ•จ": "์ง‘์ค‘๋ ฅ์ด ๋ถ€์กฑํ•˜๊ณ  ์‰ฝ๊ฒŒ ์‚ฐ๋งŒํ•ด์ง",
623
- "F08_๊ณ ์ง‘์Šค๋Ÿฌ์›€": "์ž์‹ ์˜ ๋ฐฉ์‹์„ ๊ณ ์ˆ˜ํ•˜๋Š” ๊ฒฝํ–ฅ",
624
- "F09_์˜ˆ๋ฏผํ•จ": "์ž‘์€ ์ผ์—๋„ ๋ฏผ๊ฐํ•˜๊ฒŒ ๋ฐ˜์‘ํ•จ",
625
- "F10_๋А๋ฆผ": "ํ–‰๋™์ด๋‚˜ ๋ฐ˜์‘์ด ๋А๋ฆฐ ํŽธ",
626
- "F11_์†Œ์‹ฌํ•จ": "๋‚ด์„ฑ์ ์ด๊ณ  ์กฐ์‹ฌ์Šค๋Ÿฌ์šด ์„ฑํ–ฅ",
627
- "F12_์ž˜๋ชป๋œ์ž์‹ ๊ฐ": "๊ฐ€๋” ์ž์‹ ์˜ ๋Šฅ๋ ฅ์„ ๊ณผ๋Œ€ํ‰๊ฐ€ํ•จ",
628
- "F13_๊ณผ๊ฑฐ์ง‘์ฐฉ": "๊ณผ๊ฑฐ์˜ ์ผ์— ์ž์ฃผ ๋จธ๋ฌด๋Š” ๊ฒฝํ–ฅ",
629
- "F14_๋ณ€ํ™”๊ฑฐ๋ถ€": "์ƒˆ๋กœ์šด ๋ณ€ํ™”๋ฅผ ๊บผ๋ฆฌ๋Š” ์„ฑํ–ฅ",
630
- "F15_ํ‘œํ˜„์„œํˆผ": "๊ฐ์ • ํ‘œํ˜„์ด ์„œํˆฐ ํŽธ"
631
- }
632
 
633
- return [flaw_descriptions.get(f[0], f[0]) for f in top_flaws]
 
 
 
 
 
634
 
635
  def generate_contradictions(self):
636
  """๋ชจ์ˆœ์  ํŠน์„ฑ 2๊ฐœ ์ƒ์„ฑ (๋ณต์žก์„ฑ๊ณผ ๊นŠ์ด ๋ถ€์—ฌ)"""
 
608
  return self
609
 
610
  def generate_attractive_flaws(self):
611
+ """๋งค๋ ฅ์  ๊ฒฐํ•จ 3-4๊ฐœ ์ƒ์„ฑ (์‚ฌ๋ฌผ ํŠน์„ฑ + ์„ฑ๊ฒฉ์  ํŠน์„ฑ ํ˜ผํ•ฉ)"""
612
  flaw_vars = {k: v for k, v in self.variables.items() if k.startswith("F")}
613
+ top_flaws = sorted(flaw_vars.items(), key=lambda x: x[1], reverse=True)[:4]
614
+
615
+ # ์‚ฌ๋ฌผ ํŠน์„ฑ ๊ธฐ๋ฐ˜ ๋งค๋ ฅ์  ๊ฒฐํ•จ
616
+ physical_flaws = [
617
+ "๋จผ์ง€๊ฐ€ ์Œ“์ด๋ฉด ์กฐ๊ธˆ ๊ธฐ๋ถ„์ด ์šฐ์šธํ•ด์ง",
618
+ "ํ–‡๋ณ•์— ๋„ˆ๋ฌด ์˜ค๋ž˜ ์žˆ์œผ๋ฉด ์ƒ‰์ด ๋ฐ”๋ž ๊นŒ ๋ด ๊ฑฑ์ •ํ•จ",
619
+ "๊ฐ‘์ž‘์Šค๋Ÿฌ์šด ์ถฉ๊ฒฉ์— ๋†€๋ผ๋ฉด ์˜ค๋žซ๋™์•ˆ ๋–จ๋ฆผ",
620
+ "์Šต๋„๊ฐ€ ๋†’์œผ๋ฉด ์ปจ๋””์…˜์ด ์กฐ๊ธˆ ๋‚˜๋น ์ง",
621
+ "์ƒˆ๋กœ์šด ๋ƒ„์ƒˆ์— ๋ฏผ๊ฐํ•˜๊ฒŒ ๋ฐ˜์‘ํ•จ",
622
+ "์™„๋ฒฝํ•œ ์ •๋ฆฌ์ •๋ˆ์„ ๊ฟˆ๊พธ์ง€๋งŒ ํ˜„์‹ค์€ ์–ด์ง€๋Ÿฌ์›€",
623
+ "์ž์‹ ์˜ ๋ชจ์„œ๋ฆฌ๋‚˜ ๋๋ถ€๋ถ„์ด ๋‹ณ๋Š” ๊ฒƒ์„ ์‹ ๊ฒฝ์”€",
624
+ "๊ฐ€๋” ์ž์‹ ์˜ ๋ฌด๊ฒŒ๋‚˜ ํฌ๊ธฐ ๋•Œ๋ฌธ์— ๋ฏธ์•ˆํ•ดํ•จ"
625
+ ]
626
 
627
+ # ์„ฑ๊ฒฉ์  ๋งค๋ ฅ์  ๊ฒฐํ•จ
628
+ personality_flaws = [
629
+ "์™„๋ฒฝํ•ด ๋ณด์ด๋ ค๊ณ  ๋…ธ๋ ฅํ•˜์ง€๋งŒ ๊ฐ€๋” ์‹ค์ˆ˜๋ฅผ ํ•จ",
630
+ "์ƒ๊ฐ์ด ๋„ˆ๋ฌด ๋งŽ์•„์„œ ๊ฒฐ์ •์„ ๋‚ด๋ฆฌ๊ธฐ ์–ด๋ ค์›Œํ•จ",
631
+ "๋„ˆ๋ฌด ์†”์งํ•ด์„œ ๊ฐ€๋” ๋ˆˆ์น˜๊ฐ€ ์—†์Œ",
632
+ "์ง€๋‚˜์น˜๊ฒŒ ์—ด์ •์ ์ด์–ด์„œ ์‰ฌ๋Š” ๊ฒƒ์„ ์žŠ์„ ๋•Œ๊ฐ€ ์žˆ์Œ",
633
+ "์ƒˆ๋กœ์šด ์•„์ด๋””์–ด์— ๋„ˆ๋ฌด ์‰ฝ๊ฒŒ ํฅ๋ถ„ํ•จ",
634
+ "ํ˜ธ๊ธฐ์‹ฌ์ด ๋งŽ์•„ ์ง‘์ค‘๋ ฅ์ด ์•ฝ๊ฐ„ ๋ถ€์กฑํ•จ",
635
+ "๊ฐ์ • ํ‘œํ˜„์ด ์„œํˆด๋Ÿฌ์„œ ์˜คํ•ด๋ฐ›์„ ๋•Œ๊ฐ€ ์žˆ์Œ",
636
+ "๊ณผ๊ฑฐ์˜ ์ข‹์€ ๊ธฐ์–ต์— ์ž์ฃผ ๋น ์ ธ ํ˜„์‹ค์„ ๋†“์น  ๋•Œ๊ฐ€ ์žˆ์Œ"
637
+ ]
 
 
 
 
 
 
638
 
639
+ # ์‚ฌ๋ฌผ ํŠน์„ฑ 2๊ฐœ + ์„ฑ๊ฒฉ์  ํŠน์„ฑ 2๊ฐœ ์กฐํ•ฉ
640
+ selected_flaws = []
641
+ selected_flaws.extend(random.sample(physical_flaws, 2))
642
+ selected_flaws.extend(random.sample(personality_flaws, 2))
643
+
644
+ return selected_flaws
645
 
646
  def generate_contradictions(self):
647
  """๋ชจ์ˆœ์  ํŠน์„ฑ 2๊ฐœ ์ƒ์„ฑ (๋ณต์žก์„ฑ๊ณผ ๊นŠ์ด ๋ถ€์—ฌ)"""