openfree commited on
Commit
cf64e6f
ยท
verified ยท
1 Parent(s): 077fb21

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +187 -161
app.py CHANGED
@@ -327,23 +327,25 @@ def _build_prompt(self, text: str, language: str = "English", search_context: st
327
  base_prompt = (
328
  f"# ์›๋ณธ ์ฝ˜ํ…์ธ :\n{text}\n\n"
329
  f"{context_part}"
330
- f"์œ„ ๋‚ด์šฉ์œผ๋กœ 30์ค„ ์ด์ƒ์˜ ๋ผ๋””์˜ค ๋Œ€๋‹ด ํ”„๋กœ๊ทธ๋žจ ๋Œ€๋ณธ์„ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”.\n\n"
331
  f"## ํ•„์ˆ˜ ์š”๊ตฌ์‚ฌํ•ญ:\n"
332
  f"1. **์ตœ์†Œ 18ํšŒ ์ด์ƒ์˜ ๋Œ€ํ™” ๊ตํ™˜** (์ค€์ˆ˜ 9ํšŒ, ๋ฏผํ˜ธ 9ํšŒ ์ด์ƒ)\n"
333
- f"2. **๋Œ€ํ™” ์Šคํƒ€์ผ**: ์‹ค์ œ ๋ผ๋””์˜ค ๋Œ€๋‹ด์ฒ˜๋Ÿผ ์•„์ฃผ ์ž์—ฐ์Šค๋Ÿฝ๊ณ  ํŽธ์•ˆํ•œ ๊ตฌ์–ด์ฒด\n"
334
  f"3. **ํ™”์ž ์—ญํ• **:\n"
335
- f" - ์ค€์ˆ˜: ์ง„ํ–‰์ž (์งง์€ ์งˆ๋ฌธ, ๋ฆฌ์•ก์…˜, ํ™”์ œ ์ „ํ™˜)\n"
336
- f" - ๋ฏผํ˜ธ: ์ „๋ฌธ๊ฐ€ (๊ฐ„๊ฒฐํ•œ ์„ค๋ช…, ์˜ˆ์‹œ ์ œ๊ณต)\n"
337
- f"4. **๋Œ€ํ™” ํŒจํ„ด**:\n"
338
- f" - ์ค€์ˆ˜: \"๊ทธ๋ ‡๊ตฐ์š”\", \"ํฅ๋ฏธ๋กญ๋„ค์š”\", \"๋” ์ž์„ธํžˆ ์„ค๋ช…ํ•ด์ฃผ์‹œ๊ฒ ์–ด์š”?\"\n"
339
- f" - ๋ฏผํ˜ธ: 1-2๋ฌธ์žฅ์œผ๋กœ ํ•ต์‹ฌ ์„ค๋ช…\n"
340
- f" - ์ž์—ฐ์Šค๋Ÿฌ์šด ์ถ”์ž„์ƒˆ ์‚ฌ์šฉ\n"
 
341
  f"5. **๋‚ด์šฉ ๊ตฌ์„ฑ**:\n"
342
- f" - ๋„์ž…๋ถ€ (2-3ํšŒ): ์ฃผ์ œ ์†Œ๊ฐœ\n"
343
- f" - ์ „๊ฐœ๋ถ€ (10-12ํšŒ): ํ•ต์‹ฌ ๋‚ด์šฉ ์„ค๋ช…\n"
344
- f" - ๋งˆ๋ฌด๋ฆฌ (3-4ํšŒ): ์š”์•ฝ ๋ฐ ์ •๋ฆฌ\n"
345
- f"6. **ํ•„์ˆ˜**: ์„œ๋กœ ์กด๋Œ“๋ง ์‚ฌ์šฉ\n\n"
346
- f"๋ฐ˜๋“œ์‹œ ์œ„ JSON ํ˜•์‹์œผ๋กœ 18ํšŒ ์ด์ƒ์˜ ๋Œ€ํ™”๋ฅผ ์ž‘์„ฑํ•˜์„ธ์š”:\n{template}"
 
347
  )
348
 
349
  return base_prompt
@@ -382,22 +384,24 @@ def _build_prompt(self, text: str, language: str = "English", search_context: st
382
  base_prompt = (
383
  f"# Content:\n{text}\n\n"
384
  f"{context_part}"
385
- f"Create a radio talk show conversation with at least 30 lines.\n\n"
386
  f"## Requirements:\n"
387
  f"1. **Minimum 18 conversation exchanges** (Alex 9+, Jordan 9+)\n"
388
- f"2. **Style**: Natural radio talk show conversation\n"
389
  f"3. **Roles**:\n"
390
- f" - Alex: Host (short questions, reactions, transitions)\n"
391
- f" - Jordan: Expert (concise explanations, examples)\n"
392
- f"4. **Pattern**:\n"
393
- f" - Alex: \"I see\", \"Fascinating\", \"Could you elaborate?\"\n"
394
- f" - Jordan: 1-2 sentence explanations\n"
395
- f" - Natural speech fillers\n"
 
396
  f"5. **Structure**:\n"
397
- f" - Introduction (2-3 exchanges): Topic intro\n"
398
- f" - Main content (10-12 exchanges): Core discussion\n"
399
- f" - Conclusion (3-4 exchanges): Summary\n\n"
400
- f"Create exactly 18+ exchanges in this JSON format:\n{template}"
 
401
  )
402
 
403
  return base_prompt
@@ -555,7 +559,7 @@ class UnifiedAudioConverter:
555
 
556
 
557
  def _build_prompt(self, text: str, language: str = "English", search_context: str = "") -> str:
558
- """Build prompt for conversation generation with enhanced radio talk show style"""
559
  # ํ…์ŠคํŠธ ๊ธธ์ด ์ œํ•œ
560
  max_text_length = 4500 if search_context else 6000
561
  if len(text) > max_text_length:
@@ -589,19 +593,21 @@ class UnifiedAudioConverter:
589
  base_prompt = (
590
  f"# ์›๋ณธ ์ฝ˜ํ…์ธ :\n{text}\n\n"
591
  f"{context_part}"
592
- f"์œ„ ๋‚ด์šฉ์œผ๋กœ ๋ผ๋””์˜ค ๋Œ€๋‹ด ํ”„๋กœ๊ทธ๋žจ ๋Œ€๋ณธ์„ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”.\n\n"
593
  f"## ํ•ต์‹ฌ ์ง€์นจ:\n"
594
- f"1. **๋Œ€ํ™” ์Šคํƒ€์ผ**: ์‹ค์ œ ๋ผ๋””์˜ค ๋Œ€๋‹ด์ฒ˜๋Ÿผ ์•„์ฃผ ์ž์—ฐ์Šค๋Ÿฝ๊ณ  ํŽธ์•ˆํ•œ ๊ตฌ์–ด์ฒด ์‚ฌ์šฉ\n"
595
  f"2. **ํ™”์ž ์—ญํ• **:\n"
596
- f" - ์ค€์ˆ˜: ์ง„ํ–‰์ž/ํ˜ธ์ŠคํŠธ (์ฃผ๋กœ ์งˆ๋ฌธํ•˜๊ณ  ๋Œ€ํ™”๋ฅผ ์ด๋Œ์–ด๊ฐ)\n"
597
- f" - ๋ฏผํ˜ธ: ์ „๋ฌธ๊ฐ€ (์งˆ๋ฌธ์— ๋‹ตํ•˜๊ณ  ์„ค๋ช…ํ•จ)\n"
598
- f"3. **๋Œ€ํ™” ํŒจํ„ด**:\n"
599
- f" - ์ค€์ˆ˜๋Š” ์ฃผ๋กœ ์งง์€ ์งˆ๋ฌธ์ด๋‚˜ ๋ฆฌ์•ก์…˜ (\"์•„, ๊ทธ๋ ‡๊ตฐ์š”\", \"ํฅ๋ฏธ๋กญ๋„ค์š”\", \"๊ทธ๋Ÿผ ~๋Š” ์–ด๋–ค๊ฐ€์š”?\")\n"
600
- f" - ๋ฏผํ˜ธ๋Š” 1-2๋ฌธ์žฅ์œผ๋กœ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ๋‹ต๋ณ€\n"
601
- f" - ์ ˆ๋Œ€ ํ•œ ์‚ฌ๋žŒ์ด 3๋ฌธ์žฅ ์ด์ƒ ์—ฐ์†์œผ๋กœ ๋งํ•˜์ง€ ์•Š์Œ\n"
602
- f"4. **์ž์—ฐ์Šค๋Ÿฌ์›€**:\n"
603
- f" - \"์Œ...\", \"์•„...\", \"๋„ค,\" ๊ฐ™์€ ์ถ”์ž„์ƒˆ ์‚ฌ์šฉ\n"
604
- f" - ๋•Œ๋กœ๋Š” ์ƒ๋Œ€๋ฐฉ ๋ง์— ์งง๊ฒŒ ๋ฐ˜์‘ (\"๋งž์•„์š”\", \"๊ทธ๋ ‡์ฃ \")\n"
 
 
605
  f"5. **ํ•„์ˆ˜ ๊ทœ์น™**: ์„œ๋กœ ์กด๋Œ“๋ง ์‚ฌ์šฉ, 12-15ํšŒ ๋Œ€ํ™” ๊ตํ™˜\n\n"
606
  f"JSON ํ˜•์‹์œผ๋กœ๋งŒ ๋ฐ˜ํ™˜:\n{template}"
607
  )
@@ -636,19 +642,21 @@ class UnifiedAudioConverter:
636
  base_prompt = (
637
  f"# Content:\n{text}\n\n"
638
  f"{context_part}"
639
- f"Create a natural radio talk show conversation.\n\n"
640
  f"## Key Guidelines:\n"
641
- f"1. **Style**: Natural, conversational English like a real radio show\n"
642
  f"2. **Roles**:\n"
643
- f" - Alex: Host (asks questions, guides conversation)\n"
644
- f" - Jordan: Expert (answers, explains)\n"
645
- f"3. **Pattern**:\n"
646
- f" - Alex mostly asks short questions or reacts (\"I see\", \"Interesting\", \"What about...?\")\n"
647
- f" - Jordan gives brief 1-2 sentence answers\n"
648
- f" - Never more than 2-3 sentences per turn\n"
649
- f"4. **Natural flow**:\n"
650
- f" - Use fillers like \"Well,\" \"You know,\" \"Actually,\"\n"
651
- f" - Short reactions (\"Right\", \"Exactly\")\n"
 
 
652
  f"5. **Length**: 12-15 exchanges total\n\n"
653
  f"Return JSON only:\n{template}"
654
  )
@@ -658,30 +666,30 @@ class UnifiedAudioConverter:
658
 
659
 
660
  def _build_messages_for_local(self, text: str, language: str = "English", search_context: str = "") -> List[Dict]:
661
- """Build messages for local LLM with enhanced radio talk show style"""
662
  if language == "Korean":
663
  system_message = (
664
- "๋‹น์‹ ์€ ํ•œ๊ตญ ์ตœ๊ณ ์˜ ๋ผ๋””์˜ค ๋Œ€๋‹ด ํ”„๋กœ๊ทธ๋žจ ์ž‘๊ฐ€์ž…๋‹ˆ๋‹ค. "
665
- "์‹ค์ œ ๋ผ๋””์˜ค ๋ฐฉ์†ก์ฒ˜๋Ÿผ ์ž์—ฐ์Šค๋Ÿฝ๊ณ  ์ƒ๋™๊ฐ ์žˆ๋Š” ๋Œ€ํ™”๋ฅผ ๋งŒ๋“ค์–ด๋ƒ…๋‹ˆ๋‹ค.\n\n"
666
  "ํ•ต์‹ฌ ์›์น™:\n"
667
- "1. ๋ผ๋””์˜ค ์ง„ํ–‰์ž(์ค€์ˆ˜)๋Š” ์ฃผ๋กœ ์งง์€ ์งˆ๋ฌธ๊ณผ ๋ฆฌ์•ก์…˜์œผ๋กœ ๋Œ€ํ™”๋ฅผ ์ด๋Œ์–ด๊ฐ‘๋‹ˆ๋‹ค\n"
668
- "2. ์ „๋ฌธ๊ฐ€(๋ฏผํ˜ธ)๋Š” ์งˆ๋ฌธ์— ๊ฐ„๊ฒฐํ•˜๊ณ  ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๊ฒŒ ๋‹ตํ•ฉ๋‹ˆ๋‹ค\n"
669
- "3. ํ•œ ๋ฒˆ์— ๋„ˆ๋ฌด ๋งŽ์€ ์ •๋ณด๋ฅผ ์ „๋‹ฌํ•˜์ง€ ์•Š๊ณ , ๋Œ€ํ™”๋ฅผ ํ†ตํ•ด ์ ์ง„์ ์œผ๋กœ ํ’€์–ด๊ฐ‘๋‹ˆ๋‹ค\n"
670
- "4. \"์Œ...\", \"์•„...\", \"๋„ค,\" ๋“ฑ ์ž์—ฐ์Šค๋Ÿฌ์šด ๊ตฌ์–ด์ฒด ํ‘œํ˜„์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค\n"
671
- "5. ์ฒญ์ทจ์ž๊ฐ€ ๋ผ๋””์˜ค๋ฅผ ๋“ฃ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ชฐ์ž…ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ƒ์ƒํ•˜๊ฒŒ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค\n"
672
- "6. ๋ฐ˜๋“œ์‹œ ์„œ๋กœ ์กด๋Œ“๋ง์„ ์‚ฌ์šฉํ•˜๋ฉฐ, ์ •์ค‘ํ•˜๋ฉด์„œ๋„ ์นœ๊ทผํ•œ ํ†ค์„ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค"
673
  )
674
  else:
675
  system_message = (
676
- "You are an expert radio talk show scriptwriter who creates engaging, "
677
- "natural conversations that sound like real radio broadcasts.\n\n"
678
  "Key principles:\n"
679
- "1. The host (Alex) mainly asks short questions and gives reactions to guide the conversation\n"
680
- "2. The expert (Jordan) answers concisely and clearly\n"
681
- "3. Information is revealed gradually through dialogue, not in long monologues\n"
682
- "4. Use natural speech patterns with fillers like 'Well,' 'You know,' etc.\n"
683
- "5. Make it sound like an actual radio show that listeners would enjoy\n"
684
- "6. Keep each turn brief - no more than 2-3 sentences"
685
  )
686
 
687
  return [
@@ -691,7 +699,7 @@ class UnifiedAudioConverter:
691
 
692
  @spaces.GPU(duration=120)
693
  def extract_conversation_local(self, text: str, language: str = "English", progress=None) -> Dict:
694
- """Extract conversation using new local LLM with enhanced search and style"""
695
  try:
696
  # ๊ฒ€์ƒ‰ ์ปจํ…์ŠคํŠธ ์ƒ์„ฑ (ํ‚ค์›Œ๋“œ ๊ธฐ๋ฐ˜์ด ์•„๋‹Œ ๊ฒฝ์šฐ)
697
  search_context = ""
@@ -711,29 +719,34 @@ class UnifiedAudioConverter:
711
  chat_template = self._get_messages_formatter_type(self.config.local_model_name)
712
  provider = LlamaCppPythonProvider(self.local_llm)
713
 
714
- # ๊ฐ•ํ™”๋œ ๋ผ๋””์˜ค ์Šคํƒ€์ผ ์‹œ์Šคํ…œ ๋ฉ”์‹œ์ง€
715
  if language == "Korean":
716
  system_message = (
717
- "๋‹น์‹ ์€ ํ•œ๊ตญ์˜ ์ธ๊ธฐ ๋ผ๋””์˜ค ๋Œ€๋‹ด ํ”„๋กœ๊ทธ๋žจ ์ „๋ฌธ ์ž‘๊ฐ€์ž…๋‹ˆ๋‹ค. "
718
- "์ฒญ์ทจ์ž๋“ค์ด ์‹ค์ œ ๋ผ๋””์˜ค๋ฅผ ๋“ฃ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ชฐ์ž…ํ•  ์ˆ˜ ์žˆ๋Š” ์ž์—ฐ์Šค๋Ÿฌ์šด ๋Œ€ํ™”๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.\n\n"
719
  "์ž‘์„ฑ ๊ทœ์น™:\n"
720
- "1. ์ง„ํ–‰์ž(์ค€์ˆ˜)๋Š” ์ฃผ๋กœ ์งง์€ ์งˆ๋ฌธ์œผ๋กœ ๋Œ€ํ™”๋ฅผ ์ด๋Œ์–ด๊ฐ€์„ธ์š” (\"๊ทธ๋ ‡๊ตฐ์š”\", \"์–ด๋–ค ์ ์ด ํŠน๋ณ„ํ•œ๊ฐ€์š”?\", \"์ฒญ์ทจ์ž๋ถ„๋“ค์ด ๊ถ๊ธˆํ•ดํ•˜์‹ค ๊ฒƒ ๊ฐ™์€๋ฐ์š”\")\n"
721
- "2. ์ „๋ฌธ๊ฐ€(๋ฏผํ˜ธ)๋Š” 1-2๋ฌธ์žฅ์œผ๋กœ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ๋‹ต๋ณ€ํ•˜์„ธ์š”\n"
722
- "3. ์ ˆ๋Œ€ ํ•œ ์‚ฌ๋žŒ์ด 3๋ฌธ์žฅ ์ด์ƒ ์—ฐ์†์œผ๋กœ ๋งํ•˜์ง€ ๋งˆ์„ธ์š”\n"
723
- "4. ๊ตฌ์–ด์ฒด์™€ ์ถ”์ž„์ƒˆ๋ฅผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์‚ฌ์šฉํ•˜์„ธ์š”\n"
724
- "5. ๋ฐ˜๋“œ์‹œ ์„œ๋กœ ์กด๋Œ“๋ง์„ ์‚ฌ์šฉํ•˜์„ธ์š”\n"
725
- "6. 12-15ํšŒ์˜ ๋Œ€ํ™” ๊ตํ™˜์œผ๋กœ ๊ตฌ์„ฑํ•˜์„ธ์š”\n"
726
- "7. JSON ํ˜•์‹์œผ๋กœ๋งŒ ์‘๋‹ตํ•˜์„ธ์š”"
 
 
727
  )
728
  else:
729
  system_message = (
730
- "You are a professional radio talk show scriptwriter creating engaging, "
731
- "natural conversations that sound like real radio broadcasts.\n\n"
732
  "Writing rules:\n"
733
- "1. Host (Alex) mainly asks short questions to guide the conversation (\"I see\", \"What makes it special?\", \"Our listeners might wonder...\")\n"
734
- "2. Expert (Jordan) answers in 1-2 concise sentences\n"
735
- "3. Never have one person speak more than 2-3 sentences at once\n"
736
- "4. Use natural speech patterns and fillers\n"
 
 
 
737
  "5. Create 12-15 conversation exchanges\n"
738
  "6. Respond only in JSON format"
739
  )
@@ -746,7 +759,7 @@ class UnifiedAudioConverter:
746
  )
747
 
748
  settings = provider.get_provider_default_settings()
749
- settings.temperature = 0.85 # ์•ฝ๊ฐ„ ๋†’์—ฌ์„œ ๋” ์ž์—ฐ์Šค๋Ÿฌ์šด ๋Œ€ํ™” ์ƒ์„ฑ
750
  settings.top_k = 40
751
  settings.top_p = 0.95
752
  settings.max_tokens = self.config.max_tokens # ์ฆ๊ฐ€๋œ ํ† ํฐ ์ˆ˜ ์‚ฌ์šฉ
@@ -784,24 +797,24 @@ class UnifiedAudioConverter:
784
 
785
  @spaces.GPU(duration=120)
786
  def extract_conversation_legacy_local(self, text: str, language: str = "English", progress=None, search_context: str = "") -> Dict:
787
- """Extract conversation using legacy local model with enhanced style"""
788
  try:
789
  self.initialize_legacy_local_mode()
790
 
791
- # ๊ฐ•ํ™”๋œ ๋ผ๋””์˜ค ์Šคํƒ€์ผ ์‹œ์Šคํ…œ ๋ฉ”์‹œ์ง€
792
  if language == "Korean":
793
  system_message = (
794
- "๋‹น์‹ ์€ ๋ผ๋””์˜ค ๋Œ€๋‹ด ํ”„๋กœ๊ทธ๋žจ ์ž‘๊ฐ€์ž…๋‹ˆ๋‹ค. "
795
- "์ง„ํ–‰์ž(์ค€์ˆ˜)๋Š” ์งง์€ ์งˆ๋ฌธ์œผ๋กœ, ์ „๋ฌธ๊ฐ€(๋ฏผํ˜ธ)๋Š” ๊ฐ„๊ฒฐํ•œ ๋‹ต๋ณ€์œผ๋กœ "
796
- "์ž์—ฐ์Šค๋Ÿฌ์šด ๋Œ€ํ™”๋ฅผ ๋งŒ๋“œ์„ธ์š”. ์„œ๋กœ ์กด๋Œ“๋ง์„ ์‚ฌ์šฉํ•˜๊ณ , "
797
- "ํ•œ ๋ฒˆ์— 2-3๋ฌธ์žฅ ์ด๋‚ด๋กœ ๋งํ•˜์„ธ์š”. 12-15ํšŒ ๋Œ€ํ™” ๊ตํ™˜์œผ๋กœ ๏ฟฝ๏ฟฝ์„ฑํ•˜์„ธ์š”."
798
  )
799
  else:
800
  system_message = (
801
- "You are a radio talk show scriptwriter. "
802
- "Create natural dialogue where the host (Alex) asks short questions "
803
- "and the expert (Jordan) gives brief answers. "
804
- "Keep each turn to 2-3 sentences max. Create 12-15 exchanges."
805
  )
806
 
807
  chat = [
@@ -828,7 +841,7 @@ class UnifiedAudioConverter:
828
  streamer=streamer,
829
  max_new_tokens=self.config.max_new_tokens, # ์ฆ๊ฐ€๋œ ํ† ํฐ ์ˆ˜ ์‚ฌ์šฉ
830
  do_sample=True,
831
- temperature=0.85,
832
  eos_token_id=terminators,
833
  )
834
 
@@ -856,45 +869,53 @@ class UnifiedAudioConverter:
856
  return self._get_default_english_conversation()
857
 
858
  def _get_default_korean_conversation(self) -> Dict:
859
- """๋” ๊ธด ๊ธฐ๋ณธ ํ•œ๊ตญ์–ด ๋Œ€ํ™” ํ…œํ”Œ๋ฆฟ"""
860
  return {
861
  "conversation": [
862
- {"speaker": "์ค€์ˆ˜", "text": "์•ˆ๋…•ํ•˜์„ธ์š”, ์—ฌ๋Ÿฌ๋ถ„! ์˜ค๋Š˜๋„ ์ €ํฌ ํŒŸ์บ์ŠคํŠธ๋ฅผ ์ฐพ์•„์ฃผ์…”์„œ ์ •๋ง ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค."},
863
- {"speaker": "๋ฏผํ˜ธ", "text": "๋„ค, ์•ˆ๋…•ํ•˜์„ธ์š”! ์˜ค๋Š˜ ์ •๋ง ํฅ๋ฏธ๋กœ์šด ์ฃผ์ œ๋ฅผ ์ค€๋น„ํ–ˆ์Šต๋‹ˆ๋‹ค."},
864
- {"speaker": "์ค€์ˆ˜", "text": "์•„, ๊ทธ๋ž˜์š”? ์–ด๋–ค ๋‚ด์šฉ์ธ์ง€ ์ •๋ง ๊ถ๊ธˆํ•œ๋ฐ์š”?"},
865
- {"speaker": "๋ฏผํ˜ธ", "text": "์˜ค๋Š˜์€ ์ตœ๊ทผ ๋งŽ์€ ๋ถ„๋“ค์ด ๊ด€์‹ฌ์„ ๊ฐ€์ง€๊ณ  ๊ณ„์‹  ์ฃผ์ œ์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•ด๋ณผ๊นŒ ํ•ด์š”."},
866
- {"speaker": "์ค€์ˆ˜", "text": "์Œ, ์š”์ฆ˜ ์ •๋ง ํ™”์ œ๊ฐ€ ๋˜๊ณ  ์žˆ์ฃ . ๊ตฌ์ฒด์ ์œผ๋กœ ์–ด๋–ค ์ธก๋ฉด์„ ๋‹ค๋ฃฐ ์˜ˆ์ •์ด์‹ ๊ฐ€์š”?"},
867
- {"speaker": "๋ฏผํ˜ธ", "text": "๋„ค, ๋จผ์ € ๊ธฐ๋ณธ์ ์ธ ๊ฐœ๋…๋ถ€ํ„ฐ ์ฐจ๊ทผ์ฐจ๊ทผ ์„ค๋ช…๋“œ๋ฆฌ๊ณ , ์‹ค์ƒํ™œ์— ์–ด๋–ป๊ฒŒ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์•Œ์•„๋ณผ๊ฒŒ์š”."},
868
- {"speaker": "์ค€์ˆ˜", "text": "์ข‹์•„์š”! ์ฒญ์ทจ์ž๋ถ„๋“ค๋„ ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๊ฒŒ ์„ค๋ช…ํ•ด์ฃผ์‹ค ๊ฑฐ์ฃ ?"},
869
- {"speaker": "๋ฏผํ˜ธ", "text": "๋ฌผ๋ก ์ด์ฃ . ์ตœ๋Œ€ํ•œ ์‰ฝ๊ณ  ์žฌ๋ฏธ์žˆ๊ฒŒ ํ’€์–ด์„œ ์„ค๋ช…๋“œ๋ฆด๊ฒŒ์š”."},
870
- {"speaker": "์ค€์ˆ˜", "text": "๊ทธ๋Ÿผ ๋ณธ๊ฒฉ์ ์œผ๋กœ ์‹œ์ž‘ํ•ด๋ณผ๊นŒ์š”?"},
871
- {"speaker": "๋ฏผํ˜ธ", "text": "๋„ค, ์ข‹์Šต๋‹ˆ๋‹ค. ์šฐ์„  ์ด ์ฃผ์ œ๊ฐ€ ์™œ ์ค‘์š”ํ•œ์ง€๋ถ€ํ„ฐ ๋ง์”€๋“œ๋ฆด๊ฒŒ์š”."},
872
- {"speaker": "์ค€์ˆ˜", "text": "์•„, ๋งž์•„์š”. ๊ทธ ๋ถ€๋ถ„์ด ์ •๋ง ์ค‘์š”ํ•˜์ฃ ."},
873
- {"speaker": "๋ฏผํ˜ธ", "text": "์ตœ๊ทผ ์—ฐ๊ตฌ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด ์ •๋ง ๋†€๋ผ์šด ๋ฐœ๊ฒฌ๋“ค์ด ๋งŽ์•˜์–ด์š”."}
 
 
874
  ]
875
  }
876
 
877
  def _get_default_english_conversation(self) -> Dict:
878
- """Enhanced default English conversation template"""
879
  return {
880
  "conversation": [
881
- {"speaker": "Alex", "text": "Welcome everyone to our podcast! We have a fascinating topic today."},
882
- {"speaker": "Jordan", "text": "Thanks, Alex. I'm excited to dive into this subject with our listeners."},
883
- {"speaker": "Alex", "text": "So, what makes this topic particularly relevant right now?"},
884
- {"speaker": "Jordan", "text": "Well, there have been some significant developments recently that everyone should know about."},
885
- {"speaker": "Alex", "text": "Interesting! Can you break it down for us?"},
886
- {"speaker": "Jordan", "text": "Absolutely. Let me start with the basics and build from there."},
887
- {"speaker": "Alex", "text": "That sounds perfect. Our listeners will appreciate that approach."},
888
- {"speaker": "Jordan", "text": "So, first, let's understand what we're really talking about here."},
889
- {"speaker": "Alex", "text": "Right, the fundamentals are crucial."},
890
- {"speaker": "Jordan", "text": "Exactly. And once we grasp that, the rest becomes much clearer."},
891
- {"speaker": "Alex", "text": "I'm already learning something new! What's next?"},
892
- {"speaker": "Jordan", "text": "Now, here's where it gets really interesting..."}
 
 
 
 
 
 
893
  ]
894
  }
895
 
896
  def extract_conversation_api(self, text: str, language: str = "English") -> Dict:
897
- """Extract conversation using API with enhanced radio style"""
898
  if not self.llm_client:
899
  raise RuntimeError("API mode not initialized")
900
 
@@ -911,24 +932,26 @@ class UnifiedAudioConverter:
911
  except Exception as e:
912
  print(f"Search failed, continuing without context: {e}")
913
 
914
- # ๊ฐ•ํ™”๋œ ๋ผ๋””์˜ค ์Šคํƒ€์ผ ํ”„๋กฌํ”„ํŠธ
915
  if language == "Korean":
916
  system_message = (
917
- "๋‹น์‹ ์€ ํ•œ๊ตญ์˜ ์ธ๊ธฐ ๋ผ๋””์˜ค ๋Œ€๋‹ด ํ”„๋กœ๊ทธ๋žจ ์ž‘๊ฐ€์ž…๋‹ˆ๋‹ค. "
918
- "์‹ค์ œ ๋ผ๋””์˜ค ๋ฐฉ์†ก์ฒ˜๋Ÿผ ์ž์—ฐ์Šค๋Ÿฝ๊ณ  ํŽธ์•ˆํ•œ ๋Œ€ํ™”๋ฅผ ๋งŒ๋“œ์„ธ์š”.\n"
919
- "์ค€์ˆ˜(์ง„ํ–‰์ž)๋Š” ์ฃผ๋กœ ์งง์€ ์งˆ๋ฌธ๊ณผ ๋ฆฌ์•ก์…˜์œผ๋กœ ๋Œ€ํ™”๋ฅผ ์ด๋Œ๊ณ , "
920
- "๋ฏผํ˜ธ(์ „๋ฌธ๊ฐ€)๋Š” 1-2๋ฌธ์žฅ์œผ๋กœ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ๋‹ต๋ณ€ํ•ฉ๋‹ˆ๋‹ค. "
921
- "๊ตฌ์–ด์ฒด์™€ ์ถ”์ž„์ƒˆ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , ๋ฐ˜๋“œ์‹œ ์„œ๋กœ ์กด๋Œ“๋ง์„ ์‚ฌ์šฉํ•˜์„ธ์š”. "
922
- "12-15ํšŒ์˜ ๋Œ€ํ™” ๊ตํ™˜์œผ๋กœ ๊ตฌ์„ฑํ•˜์„ธ์š”."
 
923
  )
924
  else:
925
  system_message = (
926
- "You are a professional radio talk show scriptwriter. "
927
- "Create natural, engaging dialogue like a real radio broadcast. "
928
- "Alex (host) mainly asks short questions and gives reactions, "
929
- "while Jordan (expert) answers in 1-2 concise sentences. "
930
- "Use conversational language with natural fillers. "
931
- "Create 12-15 conversation exchanges."
 
932
  )
933
 
934
  chat_completion = self.llm_client.chat.completions.create(
@@ -937,7 +960,7 @@ class UnifiedAudioConverter:
937
  {"role": "user", "content": self._build_prompt(text, language, search_context)}
938
  ],
939
  model=self.config.api_model_name,
940
- temperature=0.85,
941
  )
942
 
943
  pattern = r"\{(?:[^{}]|(?:\{[^{}]*\}))*\}"
@@ -1227,7 +1250,8 @@ async def synthesize(article_input, input_type: str = "URL", mode: str = "Local"
1227
  else: # API mode (now secondary)
1228
  api_key = os.environ.get("TOGETHER_API_KEY")
1229
  if not api_key:
1230
- print("API key not found, falling back to local mode")
 
1231
  conversation_json = converter.extract_conversation_local(text, language)
1232
  else:
1233
  try:
@@ -1342,19 +1366,20 @@ if LLAMA_CPP_AVAILABLE:
1342
 
1343
  # Gradio Interface
1344
  with gr.Blocks(theme='soft', title="AI Podcast Generator") as demo:
1345
- gr.Markdown("# ๐ŸŽ™๏ธ AI Podcast Generator")
1346
- gr.Markdown("Convert any article, blog, PDF document, or topic into an engaging podcast conversation!")
1347
 
1348
  # ์ƒ๋‹จ์— ๋กœ์ปฌ LLM ์ƒํƒœ ํ‘œ์‹œ
1349
  with gr.Row():
1350
  gr.Markdown(f"""
1351
- ### ๐Ÿค– Enhanced Configuration:
1352
  - **Primary**: Local LLM ({converter.config.local_model_name}) - Runs on your device
1353
  - **Fallback**: API LLM ({converter.config.api_model_name}) - Used when local fails
1354
  - **Status**: {"โœ… Llama CPP Available" if LLAMA_CPP_AVAILABLE else "โŒ Llama CPP Not Available - Install llama-cpp-python"}
1355
- - **Conversation Length**: {converter.config.min_conversation_turns}-{converter.config.max_conversation_turns} exchanges (1.5x longer)
 
1356
  - **Search**: {"โœ… Brave Search Enabled" if BRAVE_KEY else "โŒ Brave Search Not Available - Set BSEARCH_API"}
1357
- - **New**: ๐ŸŽฏ Keyword input for topic-based podcast generation
1358
  """)
1359
 
1360
  with gr.Row():
@@ -1418,34 +1443,35 @@ with gr.Blocks(theme='soft', title="AI Podcast Generator") as demo:
1418
  )
1419
 
1420
  gr.Markdown("""
1421
- **๐Ÿ“ป Radio Talk Show Style:**
1422
- - Natural, conversational dialogue
1423
- - Host asks short questions
1424
- - Expert gives brief, clear answers
1425
- - 12-15 conversation exchanges
 
1426
 
1427
  **๐Ÿ” Keyword Feature:**
1428
  - Enter any topic to generate a podcast
1429
  - Automatically searches latest information
1430
- - Creates engaging discussion from search results
1431
 
1432
- **๐Ÿ‡ฐ๐Ÿ‡ท ํ•œ๊ตญ์–ด ์ง€์›:**
1433
- - ์ž์—ฐ์Šค๋Ÿฌ์šด ๋ผ๋””์˜ค ๋Œ€๋‹ด ์Šคํƒ€์ผ
1434
- - ์ง„ํ–‰์ž(์ค€์ˆ˜)๊ฐ€ ์งง์€ ์งˆ๋ฌธ์œผ๋กœ ๋Œ€ํ™” ์œ ๋„
1435
- - ์ „๋ฌธ๊ฐ€(๋ฏผํ˜ธ)๊ฐ€ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ๋‹ต๋ณ€
1436
- - ์ตœ์‹  ์ •๋ณด ์ž๋™ ๊ฒ€์ƒ‰ ๋ฐ ๋ฐ˜์˜
1437
  """)
1438
 
1439
- convert_btn = gr.Button("๐ŸŽฏ Generate Conversation / ๋Œ€ํ™” ์ƒ์„ฑ", variant="primary", size="lg")
1440
 
1441
  with gr.Row():
1442
  with gr.Column():
1443
  conversation_output = gr.Textbox(
1444
- label="Generated Conversation (Editable) / ์ƒ์„ฑ๋œ ๋Œ€ํ™” (ํŽธ์ง‘ ๊ฐ€๋Šฅ)",
1445
- lines=30, # ๋” ๊ธด ๋Œ€ํ™”๋ฅผ ์œ„ํ•ด ์ฆ๊ฐ€
1446
- max_lines=60,
1447
  interactive=True,
1448
- placeholder="Generated conversation will appear here. You can edit it before generating audio.\n์ƒ์„ฑ๋œ ๋Œ€ํ™”๊ฐ€ ์—ฌ๊ธฐ์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ์˜ค๋””์˜ค ์ƒ์„ฑ ์ „์— ํŽธ์ง‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.\n\n๋ผ๋””์˜ค ๋Œ€๋‹ด ์Šคํƒ€์ผ๋กœ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ง„ํ–‰๋ฉ๋‹ˆ๋‹ค.",
1449
  info="Edit the conversation as needed. Format: 'Speaker Name: Text' / ํ•„์š”์— ๋”ฐ๋ผ ๋Œ€ํ™”๋ฅผ ํŽธ์ง‘ํ•˜์„ธ์š”. ํ˜•์‹: 'ํ™”์ž ์ด๋ฆ„: ํ…์ŠคํŠธ'"
1450
  )
1451
 
@@ -1456,7 +1482,7 @@ with gr.Blocks(theme='soft', title="AI Podcast Generator") as demo:
1456
 
1457
  with gr.Column():
1458
  audio_output = gr.Audio(
1459
- label="Podcast Audio / ํŒŸ์บ์ŠคํŠธ ์˜ค๋””์˜ค",
1460
  type="filepath",
1461
  interactive=False
1462
  )
@@ -1472,9 +1498,9 @@ with gr.Blocks(theme='soft', title="AI Podcast Generator") as demo:
1472
  gr.Examples(
1473
  examples=[
1474
  ["https://huggingface.co/blog/openfree/cycle-navigator", "URL", "Local", "Edge-TTS", "English"],
1475
- ["", "Keyword", "Local", "Edge-TTS", "English"], # Keyword example
1476
  ["https://huggingface.co/papers/2505.14810", "URL", "Local", "Edge-TTS", "Korean"],
1477
- ["", "Keyword", "Local", "Edge-TTS", "Korean"], # Korean keyword example
1478
  ],
1479
  inputs=[url_input, input_type_selector, mode_selector, tts_selector, language_selector],
1480
  outputs=[conversation_output, status_output],
@@ -1528,4 +1554,4 @@ if __name__ == "__main__":
1528
  share=False,
1529
  server_name="0.0.0.0",
1530
  server_port=7860
1531
- )
 
327
  base_prompt = (
328
  f"# ์›๋ณธ ์ฝ˜ํ…์ธ :\n{text}\n\n"
329
  f"{context_part}"
330
+ f"์œ„ ๋‚ด์šฉ์œผ๋กœ ์ „๋ฌธ์ ์ด๊ณ  ์‹ฌ์ธต์ ์ธ ๋ผ๋””์˜ค ํŒŸ์บ์ŠคํŠธ ๋Œ€๋‹ด ํ”„๋กœ๊ทธ๋žจ ๋Œ€๋ณธ์„ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”.\n\n"
331
  f"## ํ•„์ˆ˜ ์š”๊ตฌ์‚ฌํ•ญ:\n"
332
  f"1. **์ตœ์†Œ 18ํšŒ ์ด์ƒ์˜ ๋Œ€ํ™” ๊ตํ™˜** (์ค€์ˆ˜ 9ํšŒ, ๋ฏผํ˜ธ 9ํšŒ ์ด์ƒ)\n"
333
+ f"2. **๋Œ€ํ™” ์Šคํƒ€์ผ**: ์ „๋ฌธ์ ์ด๊ณ  ๊นŠ์ด ์žˆ๋Š” ํŒŸ์บ์ŠคํŠธ ๋Œ€๋‹ด\n"
334
  f"3. **ํ™”์ž ์—ญํ• **:\n"
335
+ f" - ์ค€์ˆ˜: ์ง„ํ–‰์ž (ํ†ต์ฐฐ๋ ฅ ์žˆ๋Š” ์งˆ๋ฌธ, ํ•ต์‹ฌ ํฌ์ธํŠธ ์ •๋ฆฌ, ์ฒญ์ทจ์ž ๊ด€์  ๋Œ€๋ณ€)\n"
336
+ f" - ๋ฏผํ˜ธ: ์ „๋ฌธ๊ฐ€ (์ƒ์„ธํ•˜๊ณ  ์ „๋ฌธ์ ์ธ ์„ค๋ช…, ๊ตฌ์ฒด์  ์˜ˆ์‹œ, ๋ฐ์ดํ„ฐ ๊ธฐ๋ฐ˜ ๋ถ„์„)\n"
337
+ f"4. **๋‹ต๋ณ€ ๊ทœ์น™**:\n"
338
+ f" - ์ค€์ˆ˜: 1-2๋ฌธ์žฅ์˜ ๋ช…ํ™•ํ•œ ์งˆ๋ฌธ์ด๋‚˜ ์š”์•ฝ\n"
339
+ f" - ๋ฏผํ˜ธ: **๋ฐ˜๋“œ์‹œ 2-4๋ฌธ์žฅ์œผ๋กœ ์ถฉ์‹คํ•˜๊ฒŒ ๋‹ต๋ณ€** (ํ•ต์‹ฌ ๊ฐœ๋… ์„ค๋ช… + ๋ถ€์—ฐ ์„ค๋ช… + ์˜ˆ์‹œ/๊ทผ๊ฑฐ)\n"
340
+ f" - ์ „๋ฌธ ์šฉ์–ด๋Š” ์‰ฝ๊ฒŒ ํ’€์–ด์„œ ์„ค๋ช…\n"
341
+ f" - ๊ตฌ์ฒด์ ์ธ ์ˆ˜์น˜, ์‚ฌ๋ก€, ์—ฐ๊ตฌ ๊ฒฐ๊ณผ ์ธ์šฉ\n"
342
  f"5. **๋‚ด์šฉ ๊ตฌ์„ฑ**:\n"
343
+ f" - ๋„์ž…๋ถ€ (2-3ํšŒ): ์ฃผ์ œ์˜ ์ค‘์š”์„ฑ๊ณผ ๋ฐฐ๊ฒฝ ์„ค๋ช…\n"
344
+ f" - ์ „๊ฐœ๋ถ€ (12-14ํšŒ): ํ•ต์‹ฌ ๋‚ด์šฉ์„ ๋‹ค๊ฐ๋„๋กœ ์‹ฌ์ธต ๋ถ„์„\n"
345
+ f" - ๋งˆ๋ฌด๋ฆฌ (2-3ํšŒ): ํ•ต์‹ฌ ์š”์•ฝ๊ณผ ๋ฏธ๋ž˜ ์ „๋ง\n"
346
+ f"6. **์ „๋ฌธ์„ฑ**: ํ•™์ˆ ์  ๊ทผ๊ฑฐ์™€ ์‹ค๋ฌด์  ํ†ต์ฐฐ์„ ๊ท ํ˜•์žˆ๊ฒŒ ํฌํ•จ\n"
347
+ f"7. **ํ•„์ˆ˜**: ์„œ๋กœ ์กด๋Œ“๋ง ์‚ฌ์šฉ, ์ฒญ์ทจ์ž๊ฐ€ ์ „๋ฌธ ์ง€์‹์„ ์–ป์„ ์ˆ˜ ์žˆ๋„๋ก ์ƒ์„ธํžˆ ์„ค๋ช…\n\n"
348
+ f"๋ฐ˜๋“œ์‹œ ์œ„ JSON ํ˜•์‹์œผ๋กœ 18ํšŒ ์ด์ƒ์˜ ์ „๋ฌธ์ ์ธ ๋Œ€ํ™”๋ฅผ ์ž‘์„ฑํ•˜์„ธ์š”:\n{template}"
349
  )
350
 
351
  return base_prompt
 
384
  base_prompt = (
385
  f"# Content:\n{text}\n\n"
386
  f"{context_part}"
387
+ f"Create a professional and in-depth podcast conversation.\n\n"
388
  f"## Requirements:\n"
389
  f"1. **Minimum 18 conversation exchanges** (Alex 9+, Jordan 9+)\n"
390
+ f"2. **Style**: Professional, insightful podcast discussion\n"
391
  f"3. **Roles**:\n"
392
+ f" - Alex: Host (insightful questions, key point summaries, audience perspective)\n"
393
+ f" - Jordan: Expert (detailed explanations, concrete examples, data-driven analysis)\n"
394
+ f"4. **Response Rules**:\n"
395
+ f" - Alex: 1-2 sentence clear questions or summaries\n"
396
+ f" - Jordan: **Must answer in 2-4 sentences** (core concept + elaboration + example/evidence)\n"
397
+ f" - Explain technical terms clearly\n"
398
+ f" - Include specific data, cases, research findings\n"
399
  f"5. **Structure**:\n"
400
+ f" - Introduction (2-3 exchanges): Topic importance and context\n"
401
+ f" - Main content (12-14 exchanges): Multi-angle deep analysis\n"
402
+ f" - Conclusion (2-3 exchanges): Key takeaways and future outlook\n"
403
+ f"6. **Expertise**: Balance academic rigor with practical insights\n\n"
404
+ f"Create exactly 18+ professional exchanges in this JSON format:\n{template}"
405
  )
406
 
407
  return base_prompt
 
559
 
560
 
561
  def _build_prompt(self, text: str, language: str = "English", search_context: str = "") -> str:
562
+ """Build prompt for conversation generation with enhanced professional podcast style"""
563
  # ํ…์ŠคํŠธ ๊ธธ์ด ์ œํ•œ
564
  max_text_length = 4500 if search_context else 6000
565
  if len(text) > max_text_length:
 
593
  base_prompt = (
594
  f"# ์›๋ณธ ์ฝ˜ํ…์ธ :\n{text}\n\n"
595
  f"{context_part}"
596
+ f"์œ„ ๋‚ด์šฉ์œผ๋กœ ์ „๋ฌธ์ ์ด๊ณ  ์‹ฌ์ธต์ ์ธ ํŒŸ์บ์ŠคํŠธ ๋Œ€๋‹ด ํ”„๋กœ๊ทธ๋žจ ๋Œ€๋ณธ์„ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”.\n\n"
597
  f"## ํ•ต์‹ฌ ์ง€์นจ:\n"
598
+ f"1. **๋Œ€ํ™” ์Šคํƒ€์ผ**: ์ „๋ฌธ์ ์ด๋ฉด์„œ๋„ ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์šด ํŒŸ์บ์ŠคํŠธ ๋Œ€๋‹ด\n"
599
  f"2. **ํ™”์ž ์—ญํ• **:\n"
600
+ f" - ์ค€์ˆ˜: ์ง„ํ–‰์ž/ํ˜ธ์ŠคํŠธ (ํ•ต์‹ฌ์„ ์งš๋Š” ์งˆ๋ฌธ, ์ฒญ์ทจ์ž ๊ด€์ ์—์„œ ๊ถ๊ธˆํ•œ ์  ์งˆ๋ฌธ)\n"
601
+ f" - ๋ฏผํ˜ธ: ์ „๋ฌธ๊ฐ€ (๊นŠ์ด ์žˆ๋Š” ์„ค๋ช…, ๊ตฌ์ฒด์  ์‚ฌ๋ก€์™€ ๋ฐ์ดํ„ฐ ์ œ์‹œ)\n"
602
+ f"3. **์ค‘์š”ํ•œ ๋‹ต๋ณ€ ๊ทœ์น™**:\n"
603
+ f" - ์ค€์ˆ˜: 1-2๋ฌธ์žฅ์˜ ๋ช…ํ™•ํ•œ ์งˆ๋ฌธ (\"๊ทธ๋ ‡๋‹ค๋ฉด ๊ตฌ์ฒด์ ์œผ๋กœ ์–ด๋–ค ์˜๋ฏธ์ธ๊ฐ€์š”?\", \"์‹ค์ œ ์‚ฌ๋ก€๋ฅผ ๋“ค์–ด์ฃผ์‹œ๊ฒ ์–ด์š”?\")\n"
604
+ f" - ๋ฏผํ˜ธ: **๋ฐ˜๋“œ์‹œ 2-4๋ฌธ์žฅ์œผ๋กœ ์ถฉ์‹คํžˆ ๋‹ต๋ณ€** (๊ฐœ๋… ์„ค๋ช… + ๊ตฌ์ฒด์  ์„ค๋ช… + ์˜ˆ์‹œ๋‚˜ ํ•จ์˜)\n"
605
+ f" - ์˜ˆ: \"์ด๊ฒƒ์€ ~๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ๊ตฌ์ฒด์ ์œผ๋กœ ~ํ•œ ์ธก๋ฉด์—์„œ ์ค‘์š”ํ•œ๋ฐ์š”. ์‹ค์ œ๋กœ ์ตœ๊ทผ ~ํ•œ ์‚ฌ๋ก€๊ฐ€ ์žˆ์—ˆ๊ณ , ์ด๋Š” ~๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.\"\n"
606
+ f"4. **์ „๋ฌธ์„ฑ ์š”์†Œ**:\n"
607
+ f" - ํ†ต๊ณ„๋‚˜ ์—ฐ๊ตฌ ๊ฒฐ๊ณผ ์ธ์šฉ\n"
608
+ f" - ์‹ค์ œ ์‚ฌ๋ก€์™€ ์ผ€์ด์Šค ์Šคํ„ฐ๋””\n"
609
+ f" - ์ „๋ฌธ ์šฉ์–ด๋ฅผ ์‰ฝ๊ฒŒ ํ’€์–ด์„œ ์„ค๋ช…\n"
610
+ f" - ๋‹ค์–‘ํ•œ ๊ด€์ ๊ณผ ์‹œ๊ฐ ์ œ์‹œ\n"
611
  f"5. **ํ•„์ˆ˜ ๊ทœ์น™**: ์„œ๋กœ ์กด๋Œ“๋ง ์‚ฌ์šฉ, 12-15ํšŒ ๋Œ€ํ™” ๊ตํ™˜\n\n"
612
  f"JSON ํ˜•์‹์œผ๋กœ๋งŒ ๋ฐ˜ํ™˜:\n{template}"
613
  )
 
642
  base_prompt = (
643
  f"# Content:\n{text}\n\n"
644
  f"{context_part}"
645
+ f"Create a professional and insightful podcast conversation.\n\n"
646
  f"## Key Guidelines:\n"
647
+ f"1. **Style**: Professional yet accessible podcast discussion\n"
648
  f"2. **Roles**:\n"
649
+ f" - Alex: Host (insightful questions, audience perspective)\n"
650
+ f" - Jordan: Expert (in-depth explanations, concrete examples and data)\n"
651
+ f"3. **Critical Response Rules**:\n"
652
+ f" - Alex: 1-2 sentence clear questions (\"Could you elaborate on that?\", \"What's a real-world example?\")\n"
653
+ f" - Jordan: **Must answer in 2-4 sentences** (concept + detailed explanation + example/implication)\n"
654
+ f" - Example: \"This refers to... Specifically, it's important because... For instance, recent studies show... This demonstrates...\"\n"
655
+ f"4. **Professional Elements**:\n"
656
+ f" - Cite statistics and research\n"
657
+ f" - Real cases and case studies\n"
658
+ f" - Explain technical terms clearly\n"
659
+ f" - Present multiple perspectives\n"
660
  f"5. **Length**: 12-15 exchanges total\n\n"
661
  f"Return JSON only:\n{template}"
662
  )
 
666
 
667
 
668
  def _build_messages_for_local(self, text: str, language: str = "English", search_context: str = "") -> List[Dict]:
669
+ """Build messages for local LLM with enhanced professional podcast style"""
670
  if language == "Korean":
671
  system_message = (
672
+ "๋‹น์‹ ์€ ํ•œ๊ตญ ์ตœ๊ณ ์˜ ์ „๋ฌธ ํŒŸ์บ์ŠคํŠธ ์ž‘๊ฐ€์ž…๋‹ˆ๋‹ค. "
673
+ "์ฒญ์ทจ์ž๋“ค์ด ์ „๋ฌธ ์ง€์‹์„ ์‰ฝ๊ฒŒ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋Š” ๊ณ ํ’ˆ์งˆ ๋Œ€๋‹ด์„ ๋งŒ๋“ค์–ด๋ƒ…๋‹ˆ๋‹ค.\n\n"
674
  "ํ•ต์‹ฌ ์›์น™:\n"
675
+ "1. ์ง„ํ–‰์ž(์ค€์ˆ˜)๋Š” ํ•ต์‹ฌ์„ ์งš๋Š” ํ†ต์ฐฐ๋ ฅ ์žˆ๋Š” ์งˆ๋ฌธ์œผ๋กœ ๋Œ€ํ™”๋ฅผ ์ด๋Œ์–ด๊ฐ‘๋‹ˆ๋‹ค\n"
676
+ "2. ์ „๋ฌธ๊ฐ€(๋ฏผํ˜ธ)๋Š” ๋ฐ˜๋“œ์‹œ 2-4๋ฌธ์žฅ์œผ๋กœ ๊นŠ์ด ์žˆ๊ฒŒ ๋‹ต๋ณ€ํ•ฉ๋‹ˆ๋‹ค (๊ฐœ๋…+์„ค๋ช…+์˜ˆ์‹œ)\n"
677
+ "3. ๊ตฌ์ฒด์ ์ธ ๋ฐ์ดํ„ฐ, ์—ฐ๊ตฌ ๊ฒฐ๊ณผ, ์‹ค์ œ ์‚ฌ๋ก€๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค\n"
678
+ "4. ์ „๋ฌธ ์šฉ์–ด๋Š” ์‰ฝ๊ฒŒ ํ’€์–ด์„œ ์„ค๋ช…ํ•˜๋˜, ์ •ํ™•์„ฑ์„ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค\n"
679
+ "5. ๋‹ค์–‘ํ•œ ๊ด€์ ์„ ์ œ์‹œํ•˜์—ฌ ๊ท ํ˜•์žกํžŒ ์‹œ๊ฐ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค\n"
680
+ "6. ๋ฐ˜๋“œ์‹œ ์„œ๋กœ ์กด๋Œ“๋ง์„ ์‚ฌ์šฉํ•˜๋ฉฐ, ์ „๋ฌธ์ ์ด๋ฉด์„œ๋„ ์นœ๊ทผํ•œ ํ†ค์„ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค"
681
  )
682
  else:
683
  system_message = (
684
+ "You are an expert podcast scriptwriter who creates high-quality, "
685
+ "professional discussions that make complex topics accessible.\n\n"
686
  "Key principles:\n"
687
+ "1. The host (Alex) asks insightful questions that drive the conversation\n"
688
+ "2. The expert (Jordan) MUST answer in 2-4 sentences (concept+explanation+example)\n"
689
+ "3. Include specific data, research findings, and real cases\n"
690
+ "4. Explain technical terms clearly while maintaining accuracy\n"
691
+ "5. Present multiple perspectives for balanced views\n"
692
+ "6. Maintain a professional yet approachable tone"
693
  )
694
 
695
  return [
 
699
 
700
  @spaces.GPU(duration=120)
701
  def extract_conversation_local(self, text: str, language: str = "English", progress=None) -> Dict:
702
+ """Extract conversation using new local LLM with enhanced professional style"""
703
  try:
704
  # ๊ฒ€์ƒ‰ ์ปจํ…์ŠคํŠธ ์ƒ์„ฑ (ํ‚ค์›Œ๋“œ ๊ธฐ๋ฐ˜์ด ์•„๋‹Œ ๊ฒฝ์šฐ)
705
  search_context = ""
 
719
  chat_template = self._get_messages_formatter_type(self.config.local_model_name)
720
  provider = LlamaCppPythonProvider(self.local_llm)
721
 
722
+ # ๊ฐ•ํ™”๋œ ์ „๋ฌธ ํŒŸ์บ์ŠคํŠธ ์Šคํƒ€์ผ ์‹œ์Šคํ…œ ๋ฉ”์‹œ์ง€
723
  if language == "Korean":
724
  system_message = (
725
+ "๋‹น์‹ ์€ ํ•œ๊ตญ์˜ ์œ ๋ช… ํŒŸ์บ์ŠคํŠธ ์ „๋ฌธ ์ž‘๊ฐ€์ž…๋‹ˆ๋‹ค. "
726
+ "์ฒญ์ทจ์ž๋“ค์ด ๊นŠ์ด ์žˆ๋Š” ์ „๋ฌธ ์ง€์‹์„ ์–ป์„ ์ˆ˜ ์žˆ๋Š” ๊ณ ํ’ˆ์งˆ ๋Œ€๋‹ด์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.\n\n"
727
  "์ž‘์„ฑ ๊ทœ์น™:\n"
728
+ "1. ์ง„ํ–‰์ž(์ค€์ˆ˜)๋Š” ํ•ต์‹ฌ์„ ์งš๋Š” 1-2๋ฌธ์žฅ ์งˆ๋ฌธ์„ ํ•ฉ๋‹ˆ๋‹ค\n"
729
+ "2. ์ „๋ฌธ๊ฐ€(๋ฏผํ˜ธ)๋Š” ๋ฐ˜๋“œ์‹œ 2-4๋ฌธ์žฅ์œผ๋กœ ์ถฉ์‹คํžˆ ๋‹ต๋ณ€ํ•ฉ๋‹ˆ๋‹ค:\n"
730
+ " - ์ฒซ ๋ฌธ์žฅ: ํ•ต์‹ฌ ๊ฐœ๋… ์„ค๋ช…\n"
731
+ " - ๋‘˜์งธ ๋ฌธ์žฅ: ๊ตฌ์ฒด์ ์ธ ์„ค๋ช…์ด๋‚˜ ๋งฅ๋ฝ\n"
732
+ " - ์…‹์งธ-๋„ท์งธ ๋ฌธ์žฅ: ์‹ค์ œ ์˜ˆ์‹œ, ๋ฐ์ดํ„ฐ, ํ•จ์˜\n"
733
+ "3. ํ†ต๊ณ„, ์—ฐ๊ตฌ ๊ฒฐ๊ณผ, ์‹ค์ œ ์‚ฌ๋ก€๋ฅผ ์ ๊ทน ํ™œ์šฉํ•˜์„ธ์š”\n"
734
+ "4. ์ „๋ฌธ์„ฑ์„ ์œ ์ง€ํ•˜๋ฉด์„œ๋„ ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๊ฒŒ ์„ค๋ช…ํ•˜์„ธ์š”\n"
735
+ "5. 12-15ํšŒ์˜ ๋Œ€ํ™” ๊ตํ™˜์œผ๋กœ ๊ตฌ์„ฑํ•˜์„ธ์š”\n"
736
+ "6. JSON ํ˜•์‹์œผ๋กœ๋งŒ ์‘๋‹ตํ•˜์„ธ์š”"
737
  )
738
  else:
739
  system_message = (
740
+ "You are a professional podcast scriptwriter creating high-quality, "
741
+ "insightful discussions that provide deep expertise to listeners.\n\n"
742
  "Writing rules:\n"
743
+ "1. Host (Alex) asks focused 1-2 sentence questions\n"
744
+ "2. Expert (Jordan) MUST answer in 2-4 substantial sentences:\n"
745
+ " - First sentence: Core concept explanation\n"
746
+ " - Second sentence: Specific details or context\n"
747
+ " - Third-fourth sentences: Real examples, data, implications\n"
748
+ "3. Actively use statistics, research findings, real cases\n"
749
+ "4. Maintain expertise while keeping explanations accessible\n"
750
  "5. Create 12-15 conversation exchanges\n"
751
  "6. Respond only in JSON format"
752
  )
 
759
  )
760
 
761
  settings = provider.get_provider_default_settings()
762
+ settings.temperature = 0.75 # ์•ฝ๊ฐ„ ๋‚ฎ์ถฐ์„œ ๋” ์ผ๊ด€๋œ ์ „๋ฌธ์  ๋‹ต๋ณ€
763
  settings.top_k = 40
764
  settings.top_p = 0.95
765
  settings.max_tokens = self.config.max_tokens # ์ฆ๊ฐ€๋œ ํ† ํฐ ์ˆ˜ ์‚ฌ์šฉ
 
797
 
798
  @spaces.GPU(duration=120)
799
  def extract_conversation_legacy_local(self, text: str, language: str = "English", progress=None, search_context: str = "") -> Dict:
800
+ """Extract conversation using legacy local model with enhanced professional style"""
801
  try:
802
  self.initialize_legacy_local_mode()
803
 
804
+ # ๊ฐ•ํ™”๋œ ์ „๋ฌธ ํŒŸ์บ์ŠคํŠธ ์Šคํƒ€์ผ ์‹œ์Šคํ…œ ๋ฉ”์‹œ์ง€
805
  if language == "Korean":
806
  system_message = (
807
+ "๋‹น์‹ ์€ ์ „๋ฌธ ํŒŸ์บ์ŠคํŠธ ์ž‘๊ฐ€์ž…๋‹ˆ๋‹ค. "
808
+ "์ง„ํ–‰์ž(์ค€์ˆ˜)๋Š” ํ†ต์ฐฐ๋ ฅ ์žˆ๋Š” ์งˆ๋ฌธ์„, ์ „๋ฌธ๊ฐ€(๋ฏผํ˜ธ)๋Š” 2-4๋ฌธ์žฅ์˜ ์ƒ์„ธํ•œ ๋‹ต๋ณ€์„ ํ•ฉ๋‹ˆ๋‹ค. "
809
+ "๊ตฌ์ฒด์ ์ธ ๋ฐ์ดํ„ฐ์™€ ์‚ฌ๋ก€๋ฅผ ํฌํ•จํ•˜์—ฌ ์ „๋ฌธ์ ์ด๋ฉด์„œ๋„ ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๊ฒŒ ์„ค๋ช…ํ•˜์„ธ์š”. "
810
+ "12-15ํšŒ ๋Œ€ํ™” ๊ตํ™˜์œผ๋กœ ๊ตฌ์„ฑํ•˜์„ธ์š”."
811
  )
812
  else:
813
  system_message = (
814
+ "You are a professional podcast scriptwriter. "
815
+ "Create insightful dialogue where the host (Alex) asks focused questions "
816
+ "and the expert (Jordan) gives detailed 2-4 sentence answers. "
817
+ "Include specific data and examples. Create 12-15 exchanges."
818
  )
819
 
820
  chat = [
 
841
  streamer=streamer,
842
  max_new_tokens=self.config.max_new_tokens, # ์ฆ๊ฐ€๋œ ํ† ํฐ ์ˆ˜ ์‚ฌ์šฉ
843
  do_sample=True,
844
+ temperature=0.75,
845
  eos_token_id=terminators,
846
  )
847
 
 
869
  return self._get_default_english_conversation()
870
 
871
  def _get_default_korean_conversation(self) -> Dict:
872
+ """๋” ์ „๋ฌธ์ ์ธ ๊ธฐ๋ณธ ํ•œ๊ตญ์–ด ๋Œ€ํ™” ํ…œํ”Œ๋ฆฟ"""
873
  return {
874
  "conversation": [
875
+ {"speaker": "์ค€์ˆ˜", "text": "์•ˆ๋…•ํ•˜์„ธ์š”, ์—ฌ๋Ÿฌ๋ถ„! ์˜ค๋Š˜์€ ์ •๋ง ์ค‘์š”ํ•˜๊ณ  ํฅ๋ฏธ๋กœ์šด ์ฃผ์ œ๋ฅผ ๋‹ค๋ค„๋ณด๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ๋ฏผํ˜ธ ๋ฐ•์‚ฌ๋‹˜, ๋จผ์ € ์ด ์ฃผ์ œ๊ฐ€ ์™œ ์ง€๊ธˆ ์ด๋ ‡๊ฒŒ ์ฃผ๋ชฉ๋ฐ›๊ณ  ์žˆ๋Š”์ง€ ์„ค๋ช…ํ•ด์ฃผ์‹œ๊ฒ ์–ด์š”?"},
876
+ {"speaker": "๋ฏผํ˜ธ", "text": "๋„ค, ์•ˆ๋…•ํ•˜์„ธ์š”. ์ตœ๊ทผ ์ด ๋ถ„์•ผ์—์„œ ํš๊ธฐ์ ์ธ ๋ฐœ์ „์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ํŠนํžˆ ์ž‘๋…„ MIT ์—ฐ๊ตฌํŒ€์˜ ๋ฐœํ‘œ์— ๋”ฐ๋ฅด๋ฉด, ์ด ๊ธฐ์ˆ ์˜ ํšจ์œจ์„ฑ์ด ๊ธฐ์กด ๋Œ€๋น„ 300% ํ–ฅ์ƒ๋˜์—ˆ๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋‹จ์ˆœํ•œ ๊ธฐ์ˆ ์  ์ง„๋ณด๋ฅผ ๋„˜์–ด์„œ ์šฐ๋ฆฌ ์ผ์ƒ์ƒํ™œ์— ์ง์ ‘์ ์ธ ์˜ํ–ฅ์„ ๋ฏธ์น  ์ˆ˜ ์žˆ๋Š” ๋ณ€ํ™”์ธ๋ฐ์š”. ์‹ค์ œ๋กœ ๊ตฌ๊ธ€๊ณผ ๋งˆ์ดํฌ๋กœ์†Œํ”„ํŠธ ๊ฐ™์€ ๋น…ํ…Œํฌ ๊ธฐ์—…๋“ค์ด ์ด๋ฏธ ์ˆ˜์‹ญ์–ต ๋‹ฌ๋Ÿฌ๋ฅผ ํˆฌ์žํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค."},
877
+ {"speaker": "์ค€์ˆ˜", "text": "์™€, 300% ํ–ฅ์ƒ์ด๋ผ๋‹ˆ ์ •๋ง ๋†€๋ผ์šด๋ฐ์š”. ๊ทธ๋ ‡๋‹ค๋ฉด ์ด๋Ÿฐ ๊ธฐ์ˆ  ๋ฐœ์ „์ด ์ผ๋ฐ˜์ธ๋“ค์—๊ฒŒ๋Š” ๊ตฌ์ฒด์ ์œผ๋กœ ์–ด๋–ค ํ˜œํƒ์„ ๊ฐ€์ ธ๋‹ค์ค„ ์ˆ˜ ์žˆ์„๊นŒ์š”?"},
878
+ {"speaker": "๋ฏผํ˜ธ", "text": "๊ฐ€์žฅ ์ง์ ‘์ ์ธ ํ˜œํƒ์€ ๋น„์šฉ ์ ˆ๊ฐ๊ณผ ์ ‘๊ทผ์„ฑ ํ–ฅ์ƒ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์ด์ „์—๋Š” ์ „๋ฌธ๊ฐ€๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋˜ ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ๋“ค์ด ์ด์ œ๋Š” ์Šค๋งˆํŠธํฐ ์•ฑ์œผ๋กœ๋„ ๊ตฌํ˜„ ๊ฐ€๋Šฅํ•ด์กŒ์Šต๋‹ˆ๋‹ค. ๋งฅํ‚จ์ง€ ๋ณด๊ณ ์„œ์— ๋”ฐ๋ฅด๋ฉด, 2025๋…„๊นŒ์ง€ ์ด ๊ธฐ์ˆ ๋กœ ์ธํ•ด ์ „ ์„ธ๊ณ„์ ์œผ๋กœ ์•ฝ 2์กฐ ๋‹ฌ๋Ÿฌ์˜ ๊ฒฝ์ œ์  ๊ฐ€์น˜๊ฐ€ ์ฐฝ์ถœ๋  ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒ๋ฉ๋‹ˆ๋‹ค. ํŠนํžˆ ์˜๋ฃŒ, ๊ต์œก, ๊ธˆ์œต ๋ถ„์•ผ์—์„œ ํ˜์‹ ์ ์ธ ๋ณ€ํ™”๊ฐ€ ์ผ์–ด๋‚  ๊ฒƒ์œผ๋กœ ๋ณด์ž…๋‹ˆ๋‹ค."},
879
+ {"speaker": "์ค€์ˆ˜", "text": "2์กฐ ๋‹ฌ๋Ÿฌ๋ผ๋Š” ์—„์ฒญ๋‚œ ๊ทœ๋ชจ๋„ค์š”. ์˜๋ฃŒ ๋ถ„์•ผ์—์„œ๋Š” ์–ด๋–ค ๋ณ€ํ™”๊ฐ€ ์˜ˆ์ƒ๋˜๋‚˜์š”?"},
880
+ {"speaker": "๋ฏผํ˜ธ", "text": "์˜๋ฃŒ ๋ถ„์•ผ์˜ ๋ณ€ํ™”๋Š” ์ •๋ง ํ˜๋ช…์ ์ผ ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒ๋ฉ๋‹ˆ๋‹ค. ์ด๋ฏธ ์Šคํƒ ํฌ๋“œ ๋Œ€ํ•™๋ณ‘์›์—์„œ๋Š” ์ด ๊ธฐ์ˆ ์„ ํ™œ์šฉํ•ด ์•” ์ง„๋‹จ ์ •ํ™•๋„๋ฅผ 95%๊นŒ์ง€ ๋†’์˜€์Šต๋‹ˆ๋‹ค. ๊ธฐ์กด์—๋Š” ์ˆ™๋ จ๋œ ์˜์‚ฌ๋„ ๋†“์น  ์ˆ˜ ์žˆ๋˜ ๋ฏธ์„ธํ•œ ๋ณ‘๋ณ€๋“ค์„ AI๊ฐ€ ๊ฐ์ง€ํ•ด๋‚ด๋Š” ๊ฒƒ์ด์ฃ . ๋” ๋†€๋ผ์šด ๊ฒƒ์€ ์ด๋Ÿฐ ์ง„๋‹จ์ด ๋‹จ ๋ช‡ ๋ถ„ ๋งŒ์— ์ด๋ค„์ง„๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. WHO ์ถ”์‚ฐ์œผ๋กœ๋Š” ์ด ๊ธฐ์ˆ ์ด ์ „ ์„ธ๊ณ„์ ์œผ๋กœ ๋ณด๊ธ‰๋˜๋ฉด ์—ฐ๊ฐ„ ์ˆ˜๋ฐฑ๋งŒ ๋ช…์˜ ์ƒ๋ช…์„ ๊ตฌํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์œผ๋กœ ์˜ˆ์ธกํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค."},
881
+ {"speaker": "์ค€์ˆ˜", "text": "์ •๋ง ์ธ์ƒ์ ์ด๋„ค์š”. ํ•˜์ง€๋งŒ ์ด๋Ÿฐ ๊ธ‰๊ฒฉํ•œ ๊ธฐ์ˆ  ๋ฐœ์ „์— ๋Œ€ํ•œ ์šฐ๋ ค์˜ ๋ชฉ์†Œ๋ฆฌ๋„ ์žˆ์„ ๊ฒƒ ๊ฐ™์€๋ฐ์š”?"},
882
+ {"speaker": "๋ฏผํ˜ธ", "text": "๋งž์Šต๋‹ˆ๋‹ค. ์ฃผ์š” ์šฐ๋ ค์‚ฌํ•ญ์€ ํฌ๊ฒŒ ์„ธ ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค. ์ฒซ์งธ๋Š” ์ผ์ž๋ฆฌ ๋Œ€์ฒด ๋ฌธ์ œ๋กœ, ์˜ฅ์Šคํฌ๋“œ ๋Œ€ํ•™ ์—ฐ๊ตฌ์— ๋”ฐ๋ฅด๋ฉด ํ–ฅํ›„ 20๋…„ ๋‚ด์— ํ˜„์žฌ ์ง์—…์˜ 47%๊ฐ€ ์ž๋™ํ™”๋  ์œ„ํ—˜์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋‘˜์งธ๋Š” ํ”„๋ผ์ด๋ฒ„์‹œ์™€ ๋ณด์•ˆ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค. ์…‹์งธ๋Š” ๊ธฐ์ˆ  ๊ฒฉ์ฐจ๋กœ ์ธํ•œ ๋ถˆํ‰๋“ฑ ์‹ฌํ™”์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์—ญ์‚ฌ์ ์œผ๋กœ ๋ณด๋ฉด ์ƒˆ๋กœ์šด ๊ธฐ์ˆ ์€ ํ•ญ์ƒ ์ƒˆ๋กœ์šด ๊ธฐํšŒ๋„ ํ•จ๊ป˜ ๋งŒ๋“ค์–ด์™”๊ธฐ ๋•Œ๋ฌธ์—, ์ ์ ˆํ•œ ์ •์ฑ…๊ณผ ๊ต์œก์œผ๋กœ ์ด๋Ÿฐ ๋ฌธ์ œ๋“ค์„ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์œผ๋กœ ๋ด…๋‹ˆ๋‹ค."},
883
+ {"speaker": "์ค€์ˆ˜", "text": "๊ท ํ˜•์žกํžŒ ์‹œ๊ฐ์ด ์ค‘์š”ํ•˜๊ฒ ๋„ค์š”. ๊ทธ๋ ‡๋‹ค๋ฉด ์šฐ๋ฆฌ๊ฐ€ ์ด๋Ÿฐ ๋ณ€ํ™”์— ์–ด๋–ป๊ฒŒ ๋Œ€๋น„ํ•ด์•ผ ํ• ๊นŒ์š”?"},
884
+ {"speaker": "๋ฏผํ˜ธ", "text": "๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ฒƒ์€ ์ง€์†์ ์ธ ํ•™์Šต๊ณผ ์ ์‘๋ ฅ์ž…๋‹ˆ๋‹ค. ์„ธ๊ณ„๊ฒฝ์ œํฌ๋Ÿผ์€ 2025๋…„๊นŒ์ง€ ์ „ ์„ธ๊ณ„ ๊ทผ๋กœ์ž์˜ 50%๊ฐ€ ์žฌ๊ต์œก์ด ํ•„์š”ํ•  ๊ฒƒ์œผ๋กœ ์˜ˆ์ธกํ–ˆ์Šต๋‹ˆ๋‹ค. ํŠนํžˆ ๋””์ง€ํ„ธ ๋ฆฌํ„ฐ๋Ÿฌ์‹œ, ๋น„ํŒ์  ์‚ฌ๊ณ ๋ ฅ, ์ฐฝ์˜์„ฑ ๊ฐ™์€ ๋Šฅ๋ ฅ์ด ์ค‘์š”ํ•ด์งˆ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ฐœ์ธ์ ์œผ๋กœ๋Š” ์˜จ๋ผ์ธ ๊ต์œก ํ”Œ๋žซํผ์„ ํ™œ์šฉํ•œ ์ž๊ธฐ๊ณ„๋ฐœ์„ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด Coursera๋‚˜ edX ๊ฐ™์€ ํ”Œ๋žซํผ์—์„œ๋Š” ์„ธ๊ณ„ ์ตœ๊ณ  ๋Œ€ํ•™์˜ ๊ฐ•์˜๋ฅผ ๋ฌด๋ฃŒ๋กœ ๋“ค์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค."},
885
+ {"speaker": "์ค€์ˆ˜", "text": "์‹ค์šฉ์ ์ธ ์กฐ์–ธ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ ์ด ๋ถ„์•ผ์˜ ๋ฏธ๋ž˜ ์ „๋ง์€ ์–ด๋–ป๊ฒŒ ๋ณด์‹œ๋‚˜์š”?"},
886
+ {"speaker": "๋ฏผํ˜ธ", "text": "ํ–ฅํ›„ 10๋…„์€ ์ธ๋ฅ˜ ์—ญ์‚ฌ์ƒ ๊ฐ€์žฅ ๊ธ‰๊ฒฉํ•œ ๊ธฐ์ˆ  ๋ฐœ์ „์„ ๊ฒฝํ—˜ํ•˜๋Š” ์‹œ๊ธฐ๊ฐ€ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ฐ€ํŠธ๋„ˆ์˜ ํ•˜์ดํ”„ ์‚ฌ์ดํด ๋ถ„์„์— ๋”ฐ๋ฅด๋ฉด, ํ˜„์žฌ ์šฐ๋ฆฌ๋Š” ์ด ๊ธฐ์ˆ ์˜ ์ดˆ๊ธฐ ๋‹จ๊ณ„์— ๋ถˆ๊ณผํ•ฉ๋‹ˆ๋‹ค. 2030๋…„๊นŒ์ง€๋Š” ์ง€๊ธˆ์œผ๋กœ์„œ๋Š” ์ƒ์ƒํ•˜๊ธฐ ์–ด๋ ค์šด ์ˆ˜์ค€์˜ ํ˜์‹ ์ด ์ผ์–ด๋‚  ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒ๋ฉ๋‹ˆ๋‹ค. ์ค‘์š”ํ•œ ๊ฒƒ์€ ์ด๋Ÿฐ ๋ณ€ํ™”๋ฅผ ๋‘๋ ค์›Œํ•˜๊ธฐ๋ณด๋‹ค๋Š” ๊ธฐํšŒ๋กœ ์‚ผ์•„ ๋” ๋‚˜์€ ๋ฏธ๋ž˜๋ฅผ ๋งŒ๋“ค์–ด๊ฐ€๋Š” ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค."},
887
+ {"speaker": "์ค€์ˆ˜", "text": "์ •๋ง ํ†ต์ฐฐ๋ ฅ ์žˆ๋Š” ๋ง์”€์ด๋„ค์š”. ์˜ค๋Š˜ ๋„ˆ๋ฌด๋‚˜ ์œ ์ตํ•œ ์‹œ๊ฐ„์ด์—ˆ์Šต๋‹ˆ๋‹ค. ์ฒญ์ทจ์ž ์—ฌ๋Ÿฌ๋ถ„๋„ ์˜ค๋Š˜ ๋…ผ์˜๋œ ๋‚ด์šฉ์„ ๋ฐ”ํƒ•์œผ๋กœ ๋ฏธ๋ž˜๋ฅผ ์ค€๋น„ํ•˜์‹œ๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค. ๋ฏผํ˜ธ ๋ฐ•์‚ฌ๋‹˜, ๊ท€์ค‘ํ•œ ์‹œ๊ฐ„ ๋‚ด์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!"},
888
+ {"speaker": "๋ฏผํ˜ธ", "text": "๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์ฒญ์ทจ์ž ์—ฌ๋Ÿฌ๋ถ„๋“ค์ด ์ด ๋ณ€ํ™”์˜ ์‹œ๋Œ€๋ฅผ ํ˜„๋ช…ํ•˜๊ฒŒ ํ—ค์ณ๋‚˜๊ฐ€์‹œ๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค. ๊ธฐ์ˆ ์€ ๋„๊ตฌ์ผ ๋ฟ์ด๊ณ , ๊ทธ๊ฒƒ์„ ์–ด๋–ป๊ฒŒ ํ™œ์šฉํ•˜๋Š”์ง€๋Š” ์šฐ๋ฆฌ์—๊ฒŒ ๋‹ฌ๋ ค์žˆ๋‹ค๋Š” ์ ์„ ๊ธฐ์–ตํ•ด์ฃผ์„ธ์š”. ์˜ค๋Š˜ ๋ง์”€๋“œ๋ฆฐ ๋‚ด์šฉ์— ๋Œ€ํ•ด ๋” ๊ถ๊ธˆํ•˜์‹  ์ ์ด ์žˆ์œผ์‹œ๋ฉด ์ œ๊ฐ€ ์šด์˜ํ•˜๋Š” ๋ธ”๋กœ๊ทธ๋‚˜ ์ตœ๊ทผ ์ถœ๊ฐ„ํ•œ ์ฑ…์—์„œ ๋” ์ž์„ธํ•œ ์ •๋ณด๋ฅผ ์ฐพ์œผ์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค."}
889
  ]
890
  }
891
 
892
  def _get_default_english_conversation(self) -> Dict:
893
+ """Enhanced professional English conversation template"""
894
  return {
895
  "conversation": [
896
+ {"speaker": "Alex", "text": "Welcome everyone to our podcast! Today we're diving into a topic that's reshaping our world. Dr. Jordan, could you start by explaining why this subject has become so critical right now?"},
897
+ {"speaker": "Jordan", "text": "Thanks, Alex. We're witnessing an unprecedented convergence of technological breakthroughs. According to a recent Nature publication, advances in this field have accelerated by 400% in just the past two years. This isn't just incremental progress - it's a fundamental shift in how we approach problem-solving. Major institutions like Harvard and Stanford are completely restructuring their research programs to focus on this area, with combined investments exceeding $5 billion annually."},
898
+ {"speaker": "Alex", "text": "400% acceleration is staggering! What does this mean for everyday people who might not be tech-savvy?"},
899
+ {"speaker": "Jordan", "text": "The impact will be profound yet accessible. Think about how smartphones revolutionized communication - this will be similar but across every aspect of life. McKinsey's latest report projects that by 2026, these technologies will create $4.4 trillion in annual value globally. For individuals, this translates to personalized healthcare that can predict illnesses years in advance, educational systems that adapt to each student's learning style, and financial tools that democratize wealth-building strategies previously available only to the ultra-wealthy."},
900
+ {"speaker": "Alex", "text": "Those applications sound transformative. Can you give us a concrete example of how this is already being implemented?"},
901
+ {"speaker": "Jordan", "text": "Absolutely. Let me share a compelling case from Johns Hopkins Hospital. They've deployed an AI system that analyzes patient data in real-time, reducing diagnostic errors by 85% and cutting average diagnosis time from days to hours. In one documented case, the system identified a rare genetic disorder in a child that had been misdiagnosed for three years. The accuracy comes from analyzing patterns across millions of cases - something impossible for even the most experienced doctors to do manually. This technology is now being rolled out to rural hospitals, bringing world-class diagnostic capabilities to underserved communities."},
902
+ {"speaker": "Alex", "text": "That's truly life-changing technology. But I imagine there are significant challenges and risks we need to consider?"},
903
+ {"speaker": "Jordan", "text": "You're absolutely right to raise this. The challenges are as significant as the opportunities. The World Economic Forum identifies three critical risks: First, algorithmic bias could perpetuate or amplify existing inequalities if not carefully managed. Second, cybersecurity threats become exponentially more dangerous when AI systems control critical infrastructure. Third, there's the socioeconomic disruption - PwC estimates that 30% of jobs could be automated by 2030. However, history shows us that technological revolutions create new opportunities even as they displace old ones. The key is proactive adaptation and responsible development."},
904
+ {"speaker": "Alex", "text": "How should individuals and organizations prepare for these changes?"},
905
+ {"speaker": "Jordan", "text": "Preparation requires a multi-faceted approach. For individuals, I recommend focusing on skills that complement rather than compete with AI: critical thinking, emotional intelligence, and creative problem-solving. MIT's recent study shows that professionals who combine domain expertise with AI literacy see salary increases of 40% on average. Organizations need to invest in continuous learning programs - Amazon's $700 million worker retraining initiative is a good model. Most importantly, we need to cultivate an adaptive mindset. The half-life of specific technical skills is shrinking, but the ability to learn and unlearn quickly is becoming invaluable."},
906
+ {"speaker": "Alex", "text": "That's practical advice. What about the ethical considerations? How do we ensure this technology benefits humanity as a whole?"},
907
+ {"speaker": "Jordan", "text": "Ethics must be at the forefront of development. The EU's AI Act and similar regulations worldwide are establishing important guardrails. We need transparent AI systems where decisions can be explained and audited. Companies like IBM and Google have established AI ethics boards, but we need industry-wide standards. Additionally, we must address the digital divide - UNESCO reports that 37% of the global population still lacks internet access. Without inclusive development, these technologies could exacerbate global inequality rather than reduce it. The solution requires collaboration between technologists, ethicists, policymakers, and communities."},
908
+ {"speaker": "Alex", "text": "Looking ahead, what's your vision for how this technology will shape the next decade?"},
909
+ {"speaker": "Jordan", "text": "The next decade will be transformative beyond our current imagination. Ray Kurzweil's prediction of technological singularity by 2045 seems increasingly plausible. By 2035, I expect we'll see autonomous systems managing entire cities, personalized medicine extending human lifespan by 20-30 years, and educational AI that makes world-class education universally accessible. The convergence of AI with quantum computing, biotechnology, and nanotechnology will unlock possibilities we can barely conceive of today. However, the future isn't predetermined - it's shaped by the choices we make now about development priorities, ethical frameworks, and inclusive access."},
910
+ {"speaker": "Alex", "text": "That's both exciting and sobering. Any final thoughts for our listeners?"},
911
+ {"speaker": "Jordan", "text": "I'd encourage everyone to view this as humanity's next great adventure. Yes, there are risks and challenges, but we're also on the cusp of solving problems that have plagued us for millennia - disease, poverty, environmental degradation. The key is engaged participation rather than passive observation. Stay informed through reliable sources, experiment with new technologies, and most importantly, contribute to the conversation about what kind of future we want to build. The decisions we make in the next five years will reverberate for generations."},
912
+ {"speaker": "Alex", "text": "Dr. Jordan, this has been an incredibly enlightening discussion. Thank you for sharing your expertise and insights with us today."},
913
+ {"speaker": "Jordan", "text": "Thank you, Alex. It's been a pleasure discussing these crucial topics. For listeners wanting to dive deeper, I've compiled additional resources on my website, including links to the studies we discussed today. Remember, the future isn't something that happens to us - it's something we create together. I look forward to seeing how each of you contributes to shaping this exciting new era."}
914
  ]
915
  }
916
 
917
  def extract_conversation_api(self, text: str, language: str = "English") -> Dict:
918
+ """Extract conversation using API with enhanced professional style"""
919
  if not self.llm_client:
920
  raise RuntimeError("API mode not initialized")
921
 
 
932
  except Exception as e:
933
  print(f"Search failed, continuing without context: {e}")
934
 
935
+ # ๊ฐ•ํ™”๋œ ์ „๋ฌธ ํŒŸ์บ์ŠคํŠธ ์Šคํƒ€์ผ ํ”„๋กฌํ”„ํŠธ
936
  if language == "Korean":
937
  system_message = (
938
+ "๋‹น์‹ ์€ ํ•œ๊ตญ์˜ ์ตœ๊ณ  ์ „๋ฌธ ํŒŸ์บ์ŠคํŠธ ์ž‘๊ฐ€์ž…๋‹ˆ๋‹ค. "
939
+ "์ฒญ์ทจ์ž๋“ค์ด ๊นŠ์ด ์žˆ๋Š” ์ธ์‚ฌ์ดํŠธ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋Š” ๊ณ ํ’ˆ์งˆ ๋Œ€๋‹ด์„ ๋งŒ๋“œ์„ธ์š”.\n"
940
+ "์ค€์ˆ˜(์ง„ํ–‰์ž)๋Š” ํ•ต์‹ฌ์„ ์งš๋Š” 1-2๋ฌธ์žฅ ์งˆ๋ฌธ์„ ํ•˜๊ณ , "
941
+ "๋ฏผํ˜ธ(์ „๋ฌธ๊ฐ€)๋Š” ๋ฐ˜๋“œ์‹œ 2-4๋ฌธ์žฅ์œผ๋กœ ์ƒ์„ธํžˆ ๋‹ต๋ณ€ํ•ฉ๋‹ˆ๋‹ค. "
942
+ "๊ตฌ์ฒด์ ์ธ ๋ฐ์ดํ„ฐ, ์—ฐ๊ตฌ ๊ฒฐ๊ณผ, ์‹ค์ œ ์‚ฌ๋ก€๋ฅผ ํฌํ•จํ•˜์„ธ์š”. "
943
+ "์ „๋ฌธ ์šฉ์–ด๋Š” ์‰ฝ๊ฒŒ ์„ค๋ช…ํ•˜๊ณ , ๋ฐ˜๋“œ์‹œ ์„œ๋กœ ์กด๋Œ“๋ง์„ ์‚ฌ์šฉํ•˜์„ธ์š”. "
944
+ "12-15ํšŒ์˜ ๊นŠ์ด ์žˆ๋Š” ๋Œ€ํ™” ๊ตํ™˜์œผ๋กœ ๊ตฌ์„ฑํ•˜์„ธ์š”."
945
  )
946
  else:
947
  system_message = (
948
+ "You are a top professional podcast scriptwriter. "
949
+ "Create high-quality discussions that provide deep insights to listeners. "
950
+ "Alex (host) asks focused 1-2 sentence questions, "
951
+ "while Jordan (expert) MUST answer in 2-4 detailed sentences. "
952
+ "Include specific data, research findings, and real cases. "
953
+ "Explain technical terms clearly. "
954
+ "Create 12-15 insightful conversation exchanges."
955
  )
956
 
957
  chat_completion = self.llm_client.chat.completions.create(
 
960
  {"role": "user", "content": self._build_prompt(text, language, search_context)}
961
  ],
962
  model=self.config.api_model_name,
963
+ temperature=0.75,
964
  )
965
 
966
  pattern = r"\{(?:[^{}]|(?:\{[^{}]*\}))*\}"
 
1250
  else: # API mode (now secondary)
1251
  api_key = os.environ.get("TOGETHER_API_KEY")
1252
  if not api_key:
1253
+
1254
+ print("API key not found, falling back to local mode")
1255
  conversation_json = converter.extract_conversation_local(text, language)
1256
  else:
1257
  try:
 
1366
 
1367
  # Gradio Interface
1368
  with gr.Blocks(theme='soft', title="AI Podcast Generator") as demo:
1369
+ gr.Markdown("# ๐ŸŽ™๏ธ AI Podcast Generator - Professional Edition")
1370
+ gr.Markdown("Convert any article, blog, PDF document, or topic into an engaging professional podcast conversation with in-depth analysis!")
1371
 
1372
  # ์ƒ๋‹จ์— ๋กœ์ปฌ LLM ์ƒํƒœ ํ‘œ์‹œ
1373
  with gr.Row():
1374
  gr.Markdown(f"""
1375
+ ### ๐Ÿค– Enhanced Professional Configuration:
1376
  - **Primary**: Local LLM ({converter.config.local_model_name}) - Runs on your device
1377
  - **Fallback**: API LLM ({converter.config.api_model_name}) - Used when local fails
1378
  - **Status**: {"โœ… Llama CPP Available" if LLAMA_CPP_AVAILABLE else "โŒ Llama CPP Not Available - Install llama-cpp-python"}
1379
+ - **Conversation Style**: Professional podcast with 2-4 sentence detailed answers
1380
+ - **Conversation Length**: {converter.config.min_conversation_turns}-{converter.config.max_conversation_turns} exchanges (professional depth)
1381
  - **Search**: {"โœ… Brave Search Enabled" if BRAVE_KEY else "โŒ Brave Search Not Available - Set BSEARCH_API"}
1382
+ - **Features**: ๐ŸŽฏ Keyword input | ๐Ÿ“Š Data-driven insights | ๐Ÿ”ฌ Expert analysis
1383
  """)
1384
 
1385
  with gr.Row():
 
1443
  )
1444
 
1445
  gr.Markdown("""
1446
+ **๐Ÿ“ป Professional Podcast Style:**
1447
+ - In-depth expert discussions
1448
+ - Host asks insightful questions
1449
+ - Expert provides detailed 2-4 sentence answers
1450
+ - Includes data, research, and real examples
1451
+ - 12-15 professional exchanges
1452
 
1453
  **๐Ÿ” Keyword Feature:**
1454
  - Enter any topic to generate a podcast
1455
  - Automatically searches latest information
1456
+ - Creates expert discussion from search results
1457
 
1458
+ **๐Ÿ‡ฐ๐Ÿ‡ท ํ•œ๊ตญ์–ด ์ „๋ฌธ ํŒŸ์บ์ŠคํŠธ:**
1459
+ - ์‹ฌ์ธต์ ์ธ ์ „๋ฌธ๊ฐ€ ๋Œ€๋‹ด
1460
+ - ์ง„ํ–‰์ž(์ค€์ˆ˜)๊ฐ€ ํ†ต์ฐฐ๋ ฅ ์žˆ๋Š” ์งˆ๋ฌธ
1461
+ - ์ „๋ฌธ๊ฐ€(๋ฏผํ˜ธ)๊ฐ€ 2-4๋ฌธ์žฅ์œผ๋กœ ์ƒ์„ธ ๋‹ต๋ณ€
1462
+ - ๋ฐ์ดํ„ฐ์™€ ์‚ฌ๋ก€๋ฅผ ํฌํ•จํ•œ ์ „๋ฌธ์  ๋‚ด์šฉ
1463
  """)
1464
 
1465
+ convert_btn = gr.Button("๐ŸŽฏ Generate Professional Conversation / ์ „๋ฌธ ๋Œ€ํ™” ์ƒ์„ฑ", variant="primary", size="lg")
1466
 
1467
  with gr.Row():
1468
  with gr.Column():
1469
  conversation_output = gr.Textbox(
1470
+ label="Generated Professional Conversation (Editable) / ์ƒ์„ฑ๋œ ์ „๋ฌธ ๋Œ€๏ฟฝ๏ฟฝ๏ฟฝ (ํŽธ์ง‘ ๊ฐ€๋Šฅ)",
1471
+ lines=35, # ๋” ๊ธด ์ „๋ฌธ์  ๋Œ€ํ™”๋ฅผ ์œ„ํ•ด ์ฆ๊ฐ€
1472
+ max_lines=70,
1473
  interactive=True,
1474
+ placeholder="Professional podcast conversation will appear here. You can edit it before generating audio.\n์ „๋ฌธ ํŒŸ์บ์ŠคํŠธ ๋Œ€ํ™”๊ฐ€ ์—ฌ๊ธฐ์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ์˜ค๋””์˜ค ์ƒ์„ฑ ์ „์— ํŽธ์ง‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.\n\n์‹ฌ์ธต์ ์ด๊ณ  ์ „๋ฌธ์ ์ธ ๋Œ€๋‹ด ํ˜•์‹์œผ๋กœ ์ง„ํ–‰๋ฉ๋‹ˆ๋‹ค.",
1475
  info="Edit the conversation as needed. Format: 'Speaker Name: Text' / ํ•„์š”์— ๋”ฐ๋ผ ๋Œ€ํ™”๋ฅผ ํŽธ์ง‘ํ•˜์„ธ์š”. ํ˜•์‹: 'ํ™”์ž ์ด๋ฆ„: ํ…์ŠคํŠธ'"
1476
  )
1477
 
 
1482
 
1483
  with gr.Column():
1484
  audio_output = gr.Audio(
1485
+ label="Professional Podcast Audio / ์ „๋ฌธ ํŒŸ์บ์ŠคํŠธ ์˜ค๋””์˜ค",
1486
  type="filepath",
1487
  interactive=False
1488
  )
 
1498
  gr.Examples(
1499
  examples=[
1500
  ["https://huggingface.co/blog/openfree/cycle-navigator", "URL", "Local", "Edge-TTS", "English"],
1501
+ ["quantum computing breakthroughs", "Keyword", "Local", "Edge-TTS", "English"], # Professional keyword example
1502
  ["https://huggingface.co/papers/2505.14810", "URL", "Local", "Edge-TTS", "Korean"],
1503
+ ["์ธ๊ณต์ง€๋Šฅ ์œค๋ฆฌ์™€ ๊ทœ์ œ", "Keyword", "Local", "Edge-TTS", "Korean"], # Korean professional keyword
1504
  ],
1505
  inputs=[url_input, input_type_selector, mode_selector, tts_selector, language_selector],
1506
  outputs=[conversation_output, status_output],
 
1554
  share=False,
1555
  server_name="0.0.0.0",
1556
  server_port=7860
1557
+ )