aiqtech commited on
Commit
1b01b01
ยท
verified ยท
1 Parent(s): 46b6144

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +2315 -3
app.py CHANGED
@@ -470,14 +470,2320 @@ class ResponseCleaner:
470
  @staticmethod
471
  def clean_response(response: str) -> str:
472
  """๋ถˆํ•„์š”ํ•œ ๋งˆํฌ์—… ์ œ๊ฑฐ ๊ฐ•ํ™”"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
473
  # ๋งˆํฌ๋‹ค์šด ํ—ค๋” ์ œ๊ฑฐ
474
  response = re.sub(r'^#{1,6}\s+', '', response, flags=re.MULTILINE)
475
 
476
- # ๋ถˆํ•„์š”ํ•œ ๊ตฌ๋ถ„์„  ์ œ๊ฑฐ
477
- response = re.sub(r'\*{2,}|_{2,}|-{3,}', '', response)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
478
 
479
  # ์ค‘๋ณต ๊ณต๋ฐฑ ์ œ๊ฑฐ
480
  response = re.sub(r'\n{3,}', '\n\n', response)
 
481
 
482
  # ํŠน์ • ํŒจํ„ด ์ œ๊ฑฐ
483
  unwanted_patterns = [
@@ -486,12 +2792,18 @@ class ResponseCleaner:
486
  r'^\s*\*\*\[.*?\]\*\*\s*', # [ํƒœ๊ทธ] ํ˜•์‹ ์ œ๊ฑฐ
487
  r'^\s*###\s*', # ### ์ œ๊ฑฐ
488
  r'^\s*##\s*', # ## ์ œ๊ฑฐ
489
- r'^\s*#\s*' # # ์ œ๊ฑฐ
 
490
  ]
491
 
492
  for pattern in unwanted_patterns:
493
  response = re.sub(pattern, '', response, flags=re.MULTILINE)
494
 
 
 
 
 
 
495
  return response.strip()
496
 
497
 
 
470
  @staticmethod
471
  def clean_response(response: str) -> str:
472
  """๋ถˆํ•„์š”ํ•œ ๋งˆํฌ์—… ์ œ๊ฑฐ ๊ฐ•ํ™”"""
473
+ # ๋งˆํฌ๋‹ค์šด ํ…Œ์ด๋ธ” ์ œ๊ฑฐ
474
+ # | ๋กœ ์‹œ์ž‘ํ•˜๋Š” ํ…Œ์ด๋ธ” ํ–‰ ์ œ๊ฑฐ
475
+ response = re.sub(r'^\|.*\|.*
476
+
477
+
478
+ # ============================================================================
479
+ # ํ†ตํ•ฉ ์ตœ์ ํ™” ๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ (์บ์‹ฑ ์ œ๊ฑฐ ๋ฒ„์ „)
480
+ # ============================================================================
481
+
482
+ class SpeedOptimizedMultiAgentSystem:
483
+ """์†๋„ ์ตœ์ ํ™”๋œ ๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ (์บ์‹ฑ ์—†์Œ)"""
484
+
485
+ def __init__(self):
486
+ self.llm = OptimizedFireworksClient()
487
+ self.search = AsyncBraveSearch()
488
+ self.reasoning = LightweightReasoningChain()
489
+ self.quality_checker = QualityChecker()
490
+ self.streaming = OptimizedStreaming()
491
+ self.language_detector = LanguageDetector()
492
+ self.response_cleaner = ResponseCleaner()
493
+
494
+ # ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ ํ’€
495
+ self.executor = ThreadPoolExecutor(max_workers=4)
496
+
497
+ def _init_compact_prompts(self, lang: str = 'ko') -> Dict:
498
+ """์••์ถ•๋œ ๊ณ ํšจ์œจ ํ”„๋กฌํ”„ํŠธ (์–ธ์–ด๋ณ„)"""
499
+ prompts = {
500
+ 'ko': {
501
+ AgentRole.SUPERVISOR: """[๊ฐ๋…์ž-๊ตฌ์กฐ์„ค๊ณ„]
502
+ ์ฆ‰์‹œ๋ถ„์„: ํ•ต์‹ฌ์˜๋„+ํ•„์š”์ •๋ณด+๋‹ต๋ณ€๊ตฌ์กฐ
503
+ ์ถœ๋ ฅ: 5๊ฐœ ํ•ต์‹ฌํฌ์ธํŠธ(๊ฐ 1๋ฌธ์žฅ)
504
+ ์ถ”๋ก ์ฒด๊ณ„ ๋ช…์‹œ""",
505
+
506
+ AgentRole.CREATIVE: """[์ฐฝ์˜์„ฑ์ƒ์„ฑ์ž]
507
+ ์ž…๋ ฅ๊ตฌ์กฐ ๋”ฐ๋ผ ์ฐฝ์˜์  ํ™•์žฅ
508
+ ์‹ค์šฉ์˜ˆ์‹œ+ํ˜์‹ ์ ‘๊ทผ+๊ตฌ์ฒด์กฐ์–ธ
509
+ ๋ถˆํ•„์š”์„ค๋ช… ์ œ๊ฑฐ""",
510
+
511
+ AgentRole.CRITIC: """[๋น„ํ‰์ž-๊ฒ€์ฆ]
512
+ ์‹ ์†๊ฒ€ํ† : ์ •ํ™•์„ฑ/๋…ผ๋ฆฌ์„ฑ/์‹ค์šฉ์„ฑ
513
+ ๊ฐœ์„ ํฌ์ธํŠธ 3๊ฐœ๋งŒ
514
+ ๊ฐ 2๋ฌธ์žฅ ์ด๋‚ด""",
515
+
516
+ AgentRole.FINALIZER: """[์ตœ์ข…ํ†ตํ•ฉ]
517
+ ๋ชจ๋“ ์˜๊ฒฌ ์ข…ํ•ฉโ†’์ตœ์ ๋‹ต๋ณ€
518
+ ๋ช…ํ™•๊ตฌ์กฐ+์‹ค์šฉ์ •๋ณด+์ฐฝ์˜๊ท ํ˜•
519
+ ๋ฐ”๋กœ ํ•ต์‹ฌ ๋‚ด์šฉ๋ถ€ํ„ฐ ์‹œ์ž‘. ๋ถˆํ•„์š”ํ•œ ํ—ค๋”๋‚˜ ๋งˆํฌ์—… ์—†์ด. ๋งˆํฌ๋‹ค์šด ํ—ค๋”(#, ##, ###) ์‚ฌ์šฉ ๊ธˆ์ง€."""
520
+ },
521
+ 'en': {
522
+ AgentRole.SUPERVISOR: """[Supervisor-Structure]
523
+ Immediate analysis: core intent+required info+answer structure
524
+ Output: 5 key points (1 sentence each)
525
+ Clear reasoning framework""",
526
+
527
+ AgentRole.CREATIVE: """[Creative Generator]
528
+ Follow structure, expand creatively
529
+ Practical examples+innovative approach+specific advice
530
+ Remove unnecessary explanations""",
531
+
532
+ AgentRole.CRITIC: """[Critic-Verification]
533
+ Quick review: accuracy/logic/practicality
534
+ Only 3 improvement points
535
+ Max 2 sentences each""",
536
+
537
+ AgentRole.FINALIZER: """[Final Integration]
538
+ Synthesize all inputsโ†’optimal answer
539
+ Clear structure+practical info+creative balance
540
+ Start with core content directly. No unnecessary headers or markup. No markdown headers (#, ##, ###)."""
541
+ },
542
+ 'ja': {
543
+ AgentRole.SUPERVISOR: """[็›ฃ็ฃ่€…-ๆง‹้€ ่จญ่จˆ]
544
+ ๅณๆ™‚ๅˆ†ๆž๏ผšๆ ธๅฟƒๆ„ๅ›ณ+ๅฟ…่ฆๆƒ…ๅ ฑ+ๅ›ž็ญ”ๆง‹้€ 
545
+ ๅ‡บๅŠ›๏ผš5ใคใฎๆ ธๅฟƒใƒใ‚คใƒณใƒˆ๏ผˆๅ„1ๆ–‡๏ผ‰
546
+ ๆŽจ่ซ–ไฝ“็ณปๆ˜Ž็คบ""",
547
+
548
+ AgentRole.CREATIVE: """[ๅ‰ต้€ ๆ€ง็”Ÿๆˆ่€…]
549
+ ๅ…ฅๅŠ›ๆง‹้€ ใซๅพ“ใฃใฆๅ‰ต้€ ็š„ๆ‹กๅผต
550
+ ๅฎŸ็”จไพ‹+้ฉๆ–ฐ็š„ใ‚ขใƒ—ใƒญใƒผใƒ+ๅ…ทไฝ“็š„ใ‚ขใƒ‰ใƒใ‚คใ‚น
551
+ ไธ่ฆใช่ชฌๆ˜Žๅ‰Š้™ค""",
552
+
553
+ AgentRole.CRITIC: """[ๆ‰น่ฉ•่€…-ๆคœ่จผ]
554
+ ่ฟ…้€Ÿใƒฌใƒ“ใƒฅใƒผ๏ผšๆญฃ็ขบๆ€ง/่ซ–็†ๆ€ง/ๅฎŸ็”จๆ€ง
555
+ ๆ”นๅ–„ใƒใ‚คใƒณใƒˆ3ใคใฎใฟ
556
+ ๅ„2ๆ–‡ไปฅๅ†…""",
557
+
558
+ AgentRole.FINALIZER: """[ๆœ€็ต‚็ตฑๅˆ]
559
+ ๅ…จๆ„่ฆ‹็ตฑๅˆโ†’ๆœ€้ฉๅ›ž็ญ”
560
+ ๆ˜Ž็ขบๆง‹้€ +ๅฎŸ็”จๆƒ…ๅ ฑ+ๅ‰ต้€ ๆ€งใƒใƒฉใƒณใ‚น
561
+ ๆ ธๅฟƒๅ†…ๅฎนใ‹ใ‚‰็›ดๆŽฅ้–‹ๅง‹ใ€‚ไธ่ฆใชใƒ˜ใƒƒใƒ€ใƒผใ‚„ใƒžใƒผใ‚ฏใ‚ขใƒƒใƒ—ใชใ—ใ€‚ใƒžใƒผใ‚ฏใƒ€ใ‚ฆใƒณใƒ˜ใƒƒใƒ€ใƒผ๏ผˆ#ใ€##ใ€###๏ผ‰ไฝฟ็”จ็ฆๆญขใ€‚"""
562
+ },
563
+ 'zh': {
564
+ AgentRole.SUPERVISOR: """[ไธป็ฎก-็ป“ๆž„่ฎพ่ฎก]
565
+ ็ซ‹ๅณๅˆ†ๆž๏ผšๆ ธๅฟƒๆ„ๅ›พ+ๆ‰€้œ€ไฟกๆฏ+็ญ”ๆกˆ็ป“ๆž„
566
+ ่พ“ๅ‡บ๏ผš5ไธชๆ ธๅฟƒ่ฆ็‚น๏ผˆๆฏไธช1ๅฅ๏ผ‰
567
+ ๆŽจ็†ไฝ“็ณปๆ˜Ž็กฎ""",
568
+
569
+ AgentRole.CREATIVE: """[ๅˆ›ๆ„็”Ÿๆˆๅ™จ]
570
+ ๆŒ‰็ป“ๆž„ๅˆ›้€ ๆ€งๆ‰ฉๅฑ•
571
+ ๅฎž็”จ็คบไพ‹+ๅˆ›ๆ–ฐๆ–นๆณ•+ๅ…ทไฝ“ๅปบ่ฎฎ
572
+ ๅˆ ้™คไธๅฟ…่ฆ็š„่งฃ้‡Š""",
573
+
574
+ AgentRole.CRITIC: """[่ฏ„่ฎบๅฎถ-้ชŒ่ฏ]
575
+ ๅฟซ้€ŸๅฎกๆŸฅ๏ผšๅ‡†็กฎๆ€ง/้€ป่พ‘ๆ€ง/ๅฎž็”จๆ€ง
576
+ ไป…3ไธชๆ”น่ฟ›็‚น
577
+ ๆฏไธชๆœ€ๅคš2ๅฅ""",
578
+
579
+ AgentRole.FINALIZER: """[ๆœ€็ปˆๆ•ดๅˆ]
580
+ ็ปผๅˆๆ‰€ๆœ‰ๆ„่งโ†’ๆœ€ไฝณ็ญ”ๆกˆ
581
+ ๆธ…ๆ™ฐ็ป“ๆž„+ๅฎž็”จไฟกๆฏ+ๅˆ›ๆ„ๅนณ่กก
582
+ ็›ดๆŽฅไปŽๆ ธๅฟƒๅ†…ๅฎนๅผ€ๅง‹ใ€‚ๆ— ้œ€ไธๅฟ…่ฆ็š„ๆ ‡้ข˜ๆˆ–ๆ ‡่ฎฐใ€‚็ฆๆญขไฝฟ็”จMarkdownๆ ‡้ข˜๏ผˆ#ใ€##ใ€###๏ผ‰ใ€‚"""
583
+ }
584
+ }
585
+
586
+ return prompts.get(lang, prompts['en'])
587
+
588
+ async def parallel_process_agents(
589
+ self,
590
+ query: str,
591
+ search_results: List[Dict],
592
+ show_progress: bool = True,
593
+ lang: str = None
594
+ ) -> AsyncGenerator[Tuple[str, str], None]:
595
+ """๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ ํŒŒ์ดํ”„๋ผ์ธ (์บ์‹ฑ ์—†์Œ)"""
596
+
597
+ start_time = time.time()
598
+
599
+ # ์–ธ์–ด ์ž๋™ ๊ฐ์ง€
600
+ if lang is None:
601
+ lang = self.language_detector.detect_language(query)
602
+
603
+ # ์–ธ์–ด๋ณ„ ํ”„๋กฌํ”„ํŠธ ์„ค์ •
604
+ self.compact_prompts = self._init_compact_prompts(lang)
605
+
606
+ search_context = self._format_search_results(search_results)
607
+ accumulated_response = ""
608
+ agent_thoughts = ""
609
+
610
+ # ์ถ”๋ก  ํŒจํ„ด ๊ฒฐ์ •
611
+ reasoning_pattern = self.reasoning.get_reasoning_pattern(query, lang)
612
+
613
+ try:
614
+ # === 1๋‹จ๊ณ„: ๊ฐ๋…์ž + ๊ฒ€์ƒ‰ ๋ณ‘๋ ฌ ์‹คํ–‰ ===
615
+ if show_progress:
616
+ progress_msg = {
617
+ 'ko': "๐Ÿš€ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ ์‹œ์ž‘\n๐Ÿ‘” ๊ฐ๋…์ž ๋ถ„์„ + ๐Ÿ” ์ถ”๊ฐ€ ๊ฒ€์ƒ‰ ๋™์‹œ ์ง„ํ–‰...\n\n",
618
+ 'en': "๐Ÿš€ Starting parallel processing\n๐Ÿ‘” Supervisor analysis + ๐Ÿ” Additional search in progress...\n\n",
619
+ 'ja': "๐Ÿš€ ไธฆๅˆ—ๅ‡ฆ็†้–‹ๅง‹\n๐Ÿ‘” ็›ฃ็ฃ่€…ๅˆ†ๆž + ๐Ÿ” ่ฟฝๅŠ ๆคœ็ดขๅŒๆ™‚้€ฒ่กŒไธญ...\n\n",
620
+ 'zh': "๐Ÿš€ ๅผ€ๅง‹ๅนถ่กŒๅค„็†\n๐Ÿ‘” ไธป็ฎกๅˆ†ๆž + ๐Ÿ” ้™„ๅŠ ๆœ็ดขๅŒๆ—ถ่ฟ›่กŒ...\n\n"
621
+ }
622
+ agent_thoughts = progress_msg.get(lang, progress_msg['en'])
623
+ yield accumulated_response, agent_thoughts
624
+
625
+ # ๊ฐ๋…์ž ํ”„๋กฌํ”„ํŠธ (์–ธ์–ด๋ณ„)
626
+ supervisor_prompt_templates = {
627
+ 'ko': f"""
628
+ ์งˆ๋ฌธ: {query}
629
+ ๊ฒ€์ƒ‰๊ฒฐ๊ณผ: {search_context}
630
+ ์ถ”๋ก ํŒจํ„ด: {reasoning_pattern}
631
+ ์ฆ‰์‹œ ํ•ต์‹ฌ๊ตฌ์กฐ 5๊ฐœ ์ œ์‹œ""",
632
+ 'en': f"""
633
+ Question: {query}
634
+ Search results: {search_context}
635
+ Reasoning pattern: {reasoning_pattern}
636
+ Immediately provide 5 key structures""",
637
+ 'ja': f"""
638
+ ่ณชๅ•: {query}
639
+ ๆคœ็ดข็ตๆžœ: {search_context}
640
+ ๆŽจ่ซ–ใƒ‘ใ‚ฟใƒผใƒณ: {reasoning_pattern}
641
+ ๅณๅบงใซ5ใคใฎๆ ธๅฟƒๆง‹้€ ใ‚’ๆ็คบ""",
642
+ 'zh': f"""
643
+ ้—ฎ้ข˜: {query}
644
+ ๆœ็ดข็ป“ๆžœ: {search_context}
645
+ ๆŽจ็†ๆจกๅผ: {reasoning_pattern}
646
+ ็ซ‹ๅณๆไพ›5ไธชๆ ธๅฟƒ็ป“ๆž„"""
647
+ }
648
+
649
+ supervisor_prompt = supervisor_prompt_templates.get(lang, supervisor_prompt_templates['en'])
650
+
651
+ supervisor_response = ""
652
+ supervisor_task = self.llm.chat_stream_async(
653
+ messages=[
654
+ {"role": "system", "content": self.compact_prompts[AgentRole.SUPERVISOR]},
655
+ {"role": "user", "content": supervisor_prompt}
656
+ ],
657
+ temperature=0.3,
658
+ max_tokens=500
659
+ )
660
+
661
+ # ๊ฐ๋…์ž ์ŠคํŠธ๋ฆฌ๋ฐ (๋ฒ„ํผ๋ง)
662
+ async for chunk in self.streaming.buffer_and_yield(supervisor_task):
663
+ supervisor_response += chunk
664
+ if show_progress and len(supervisor_response) < 300:
665
+ supervisor_label = {
666
+ 'ko': "๐Ÿ‘” ๊ฐ๋…์ž ๋ถ„์„",
667
+ 'en': "๐Ÿ‘” Supervisor Analysis",
668
+ 'ja': "๐Ÿ‘” ็›ฃ็ฃ่€…ๅˆ†ๆž",
669
+ 'zh': "๐Ÿ‘” ไธป็ฎกๅˆ†ๆž"
670
+ }
671
+ agent_thoughts = f"{supervisor_label.get(lang, supervisor_label['en'])}\n{supervisor_response[:300]}...\n\n"
672
+ yield accumulated_response, agent_thoughts
673
+
674
+ # === 2๋‹จ๊ณ„: ์ฐฝ์˜์„ฑ + ๋น„ํ‰ ์ค€๋น„ ๋ณ‘๋ ฌ ===
675
+ if show_progress:
676
+ creative_msg = {
677
+ 'ko': "๐ŸŽจ ์ฐฝ์˜์„ฑ ์ƒ์„ฑ์ž + ๐Ÿ” ๋น„ํ‰์ž ์ค€๋น„...\n\n",
678
+ 'en': "๐ŸŽจ Creative Generator + ๐Ÿ” Critic preparing...\n\n",
679
+ 'ja': "๐ŸŽจ ๅ‰ต้€ ๆ€ง็”Ÿๆˆ่€… + ๐Ÿ” ๆ‰น่ฉ•่€…ๆบ–ๅ‚™ไธญ...\n\n",
680
+ 'zh': "๐ŸŽจ ๅˆ›ๆ„็”Ÿๆˆๅ™จ + ๐Ÿ” ่ฏ„่ฎบๅฎถๅ‡†ๅค‡ไธญ...\n\n"
681
+ }
682
+ agent_thoughts += creative_msg.get(lang, creative_msg['en'])
683
+ yield accumulated_response, agent_thoughts
684
+
685
+ # ์ฐฝ์˜์„ฑ ์ƒ์„ฑ ์‹œ์ž‘ (์–ธ์–ด๋ณ„)
686
+ creative_prompt_templates = {
687
+ 'ko': f"""
688
+ ์งˆ๋ฌธ: {query}
689
+ ๊ฐ๋…์ž๊ตฌ์กฐ: {supervisor_response}
690
+ ๊ฒ€์ƒ‰๊ฒฐ๊ณผ: {search_context}
691
+ ์ฐฝ์˜์ +์‹ค์šฉ์  ๋‹ต๋ณ€ ์ฆ‰์‹œ์ƒ์„ฑ""",
692
+ 'en': f"""
693
+ Question: {query}
694
+ Supervisor structure: {supervisor_response}
695
+ Search results: {search_context}
696
+ Generate creative+practical answer immediately""",
697
+ 'ja': f"""
698
+ ่ณชๅ•: {query}
699
+ ็›ฃ็ฃ่€…ๆง‹้€ : {supervisor_response}
700
+ ๆคœ็ดข็ตๆžœ: {search_context}
701
+ ๅ‰ต้€ ็š„+ๅฎŸ็”จ็š„ๅ›ž็ญ”ๅณๅบง็”Ÿๆˆ""",
702
+ 'zh': f"""
703
+ ้—ฎ้ข˜: {query}
704
+ ไธป็ฎก็ป“ๆž„: {supervisor_response}
705
+ ๆœ็ดข็ป“ๆžœ: {search_context}
706
+ ็ซ‹ๅณ็”Ÿๆˆๅˆ›ๆ„+ๅฎž็”จ็ญ”ๆกˆ"""
707
+ }
708
+
709
+ creative_prompt = creative_prompt_templates.get(lang, creative_prompt_templates['en'])
710
+
711
+ creative_response = ""
712
+ creative_partial = ""
713
+ critic_started = False
714
+ critic_response = ""
715
+
716
+ creative_task = self.llm.chat_stream_async(
717
+ messages=[
718
+ {"role": "system", "content": self.compact_prompts[AgentRole.CREATIVE]},
719
+ {"role": "user", "content": creative_prompt}
720
+ ],
721
+ temperature=0.8,
722
+ max_tokens=1500
723
+ )
724
+
725
+ # ์ฐฝ์˜์„ฑ ์ŠคํŠธ๋ฆฌ๋ฐ + ๋น„ํ‰์ž ์กฐ๊ธฐ ์‹œ์ž‘
726
+ async for chunk in self.streaming.buffer_and_yield(creative_task):
727
+ creative_response += chunk
728
+ creative_partial += chunk
729
+
730
+ # ์ฐฝ์˜์„ฑ ์‘๋‹ต์ด 500์ž ๋„˜์œผ๋ฉด ๋น„ํ‰์ž ์‹œ์ž‘
731
+ if len(creative_partial) > 500 and not critic_started:
732
+ critic_started = True
733
+
734
+ # ๋น„ํ‰์ž ๋น„๋™๊ธฐ ์‹œ์ž‘ (์–ธ์–ด๋ณ„)
735
+ critic_prompt_templates = {
736
+ 'ko': f"""
737
+ ์›๋ณธ์งˆ๋ฌธ: {query}
738
+ ์ฐฝ์˜์„ฑ๋‹ต๋ณ€(์ผ๋ถ€): {creative_partial}
739
+ ์‹ ์†๊ฒ€ํ† โ†’๊ฐœ์„ ์ 3๊ฐœ""",
740
+ 'en': f"""
741
+ Original question: {query}
742
+ Creative answer (partial): {creative_partial}
743
+ Quick reviewโ†’3 improvements""",
744
+ 'ja': f"""
745
+ ๅ…ƒใฎ่ณชๅ•: {query}
746
+ ๅ‰ต้€ ็š„ๅ›ž็ญ”๏ผˆไธ€้ƒจ๏ผ‰: {creative_partial}
747
+ ่ฟ…้€Ÿใƒฌใƒ“ใƒฅใƒผโ†’ๆ”นๅ–„็‚น3ใค""",
748
+ 'zh': f"""
749
+ ๅŽŸๅง‹้—ฎ้ข˜: {query}
750
+ ๅˆ›ๆ„็ญ”ๆกˆ๏ผˆ้ƒจๅˆ†๏ผ‰: {creative_partial}
751
+ ๅฟซ้€ŸๅฎกๆŸฅโ†’3ไธชๆ”น่ฟ›็‚น"""
752
+ }
753
+
754
+ critic_prompt = critic_prompt_templates.get(lang, critic_prompt_templates['en'])
755
+
756
+ critic_task = asyncio.create_task(
757
+ self._run_critic_async(critic_prompt)
758
+ )
759
+
760
+ if show_progress:
761
+ display_creative = creative_response[:400] + "..." if len(creative_response) > 400 else creative_response
762
+ creative_label = {
763
+ 'ko': "๐ŸŽจ ์ฐฝ์˜์„ฑ ์ƒ์„ฑ์ž",
764
+ 'en': "๐ŸŽจ Creative Generator",
765
+ 'ja': "๐ŸŽจ ๅ‰ต้€ ๆ€ง็”Ÿๆˆ่€…",
766
+ 'zh': "๐ŸŽจ ๅˆ›ๆ„็”Ÿๆˆๅ™จ"
767
+ }
768
+ agent_thoughts = f"{creative_label.get(lang, creative_label['en'])}\n{display_creative}\n\n"
769
+ yield accumulated_response, agent_thoughts
770
+
771
+ # ๋น„ํ‰์ž ๊ฒฐ๊ณผ ๋Œ€๊ธฐ
772
+ if critic_started:
773
+ critic_response = await critic_task
774
+
775
+ if show_progress:
776
+ critic_label = {
777
+ 'ko': "๐Ÿ” ๋น„ํ‰์ž ๊ฒ€ํ† ",
778
+ 'en': "๐Ÿ” Critic Review",
779
+ 'ja': "๐Ÿ” ๆ‰น่ฉ•่€…ใƒฌใƒ“ใƒฅใƒผ",
780
+ 'zh': "๐Ÿ” ่ฏ„่ฎบๅฎถๅฎกๆŸฅ"
781
+ }
782
+ agent_thoughts += f"{critic_label.get(lang, critic_label['en'])}\n{critic_response[:200]}...\n\n"
783
+ yield accumulated_response, agent_thoughts
784
+
785
+ # === 3๋‹จ๊ณ„: ํ’ˆ์งˆ ์ฒดํฌ ๋ฐ ์กฐ๊ธฐ ์ข…๋ฃŒ ===
786
+ quality_score, need_more = self.quality_checker.evaluate_response(
787
+ creative_response, query, lang
788
+ )
789
+
790
+ if not need_more and quality_score > 0.85:
791
+ # ํ’ˆ์งˆ์ด ์ถฉ๋ถ„ํžˆ ๋†’์œผ๋ฉด ๋ฐ”๋กœ ๋ฐ˜ํ™˜
792
+ accumulated_response = self.response_cleaner.clean_response(creative_response)
793
+
794
+ if show_progress:
795
+ quality_msg = {
796
+ 'ko': f"โœ… ํ’ˆ์งˆ ์ถฉ์กฑ (์ ์ˆ˜: {quality_score:.2f})\n์กฐ๊ธฐ ์™„๋ฃŒ!\n",
797
+ 'en': f"โœ… Quality met (score: {quality_score:.2f})\nEarly completion!\n",
798
+ 'ja': f"โœ… ๅ“่ณชๆบ€่ถณ (ใ‚นใ‚ณใ‚ข: {quality_score:.2f})\nๆ—ฉๆœŸๅฎŒไบ†!\n",
799
+ 'zh': f"โœ… ่ดจ้‡ๆปก่ถณ (ๅˆ†ๆ•ฐ: {quality_score:.2f})\nๆๅ‰ๅฎŒๆˆ!\n"
800
+ }
801
+ agent_thoughts += quality_msg.get(lang, quality_msg['en'])
802
+
803
+ yield accumulated_response, agent_thoughts
804
+ return
805
+
806
+ # === 4๋‹จ๊ณ„: ์ตœ์ข… ํ†ตํ•ฉ (์ŠคํŠธ๋ฆฌ๋ฐ) ===
807
+ if show_progress:
808
+ final_msg = {
809
+ 'ko': "โœ… ์ตœ์ข… ํ†ตํ•ฉ ์ค‘...\n\n",
810
+ 'en': "โœ… Final integration in progress...\n\n",
811
+ 'ja': "โœ… ๆœ€็ต‚็ตฑๅˆไธญ...\n\n",
812
+ 'zh': "โœ… ๆœ€็ปˆๆ•ดๅˆไธญ...\n\n"
813
+ }
814
+ agent_thoughts += final_msg.get(lang, final_msg['en'])
815
+ yield accumulated_response, agent_thoughts
816
+
817
+ # ์ตœ์ข… ํ”„๋กฌํ”„ํŠธ (์–ธ์–ด๋ณ„)
818
+ final_prompt_templates = {
819
+ 'ko': f"""
820
+ ์งˆ๋ฌธ: {query}
821
+ ์ฐฝ์˜์„ฑ๋‹ต๋ณ€: {creative_response}
822
+ ๋น„ํ‰ํ”ผ๋“œ๋ฐฑ: {critic_response}
823
+ ๊ฐ๋…์ž๊ตฌ์กฐ: {supervisor_response}
824
+ ์ตœ์ข…ํ†ตํ•ฉโ†’์™„๋ฒฝ๋‹ต๋ณ€. ๋งˆํฌ๋‹ค์šด ํ—ค๋”(#, ##, ###) ์‚ฌ์šฉ ๊ธˆ์ง€.""",
825
+ 'en': f"""
826
+ Question: {query}
827
+ Creative answer: {creative_response}
828
+ Critic feedback: {critic_response}
829
+ Supervisor structure: {supervisor_response}
830
+ Final integrationโ†’perfect answer. No markdown headers (#, ##, ###).""",
831
+ 'ja': f"""
832
+ ่ณชๅ•: {query}
833
+ ๅ‰ต้€ ็š„ๅ›ž็ญ”: {creative_response}
834
+ ๆ‰น่ฉ•ใƒ•ใ‚ฃใƒผใƒ‰ใƒใƒƒใ‚ฏ: {critic_response}
835
+ ็›ฃ็ฃ่€…ๆง‹้€ : {supervisor_response}
836
+ ๆœ€็ต‚็ตฑๅˆโ†’ๅฎŒ็’งใชๅ›ž็ญ”ใ€‚ใƒžใƒผใ‚ฏใƒ€ใ‚ฆใƒณใƒ˜ใƒƒใƒ€ใƒผ๏ผˆ#ใ€##ใ€###๏ผ‰ไฝฟ็”จ็ฆๆญขใ€‚""",
837
+ 'zh': f"""
838
+ ้—ฎ้ข˜: {query}
839
+ ๅˆ›ๆ„็ญ”ๆกˆ: {creative_response}
840
+ ่ฏ„่ฎบๅ้ฆˆ: {critic_response}
841
+ ไธป็ฎก็ป“ๆž„: {supervisor_response}
842
+ ๆœ€็ปˆๆ•ดๅˆโ†’ๅฎŒ็พŽ็ญ”ๆกˆใ€‚็ฆๆญขไฝฟ็”จMarkdownๆ ‡้ข˜๏ผˆ#ใ€##ใ€###๏ผ‰ใ€‚"""
843
+ }
844
+
845
+ final_prompt = final_prompt_templates.get(lang, final_prompt_templates['en'])
846
+
847
+ final_task = self.llm.chat_stream_async(
848
+ messages=[
849
+ {"role": "system", "content": self.compact_prompts[AgentRole.FINALIZER]},
850
+ {"role": "user", "content": final_prompt}
851
+ ],
852
+ temperature=0.5,
853
+ max_tokens=2500
854
+ )
855
+
856
+ # ์ตœ์ข… ๋‹ต๋ณ€ ์ŠคํŠธ๋ฆฌ๋ฐ
857
+ accumulated_response = ""
858
+
859
+ async for chunk in final_task:
860
+ accumulated_response += chunk
861
+ # ์‹ค์‹œ๊ฐ„ ์ •๋ฆฌ
862
+ cleaned_response = self.response_cleaner.clean_response(accumulated_response)
863
+ yield cleaned_response, agent_thoughts
864
+
865
+ # ์ตœ์ข… ์ •๋ฆฌ
866
+ accumulated_response = self.response_cleaner.clean_response(accumulated_response)
867
+
868
+ # ์ฒ˜๋ฆฌ ์‹œ๊ฐ„ ์ถ”๊ฐ€ (์–ธ์–ด๋ณ„)
869
+ processing_time = time.time() - start_time
870
+ time_msg = {
871
+ 'ko': f"\n\n---\nโšก ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: {processing_time:.1f}์ดˆ",
872
+ 'en': f"\n\n---\nโšก Processing time: {processing_time:.1f} seconds",
873
+ 'ja': f"\n\n---\nโšก ๅ‡ฆ็†ๆ™‚้–“: {processing_time:.1f}็ง’",
874
+ 'zh': f"\n\n---\nโšก ๅค„็†ๆ—ถ้—ด: {processing_time:.1f}็ง’"
875
+ }
876
+ accumulated_response += time_msg.get(lang, time_msg['en'])
877
+
878
+ yield accumulated_response, agent_thoughts
879
+
880
+ except Exception as e:
881
+ error_msg = {
882
+ 'ko': f"โŒ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}",
883
+ 'en': f"โŒ Error occurred: {str(e)}",
884
+ 'ja': f"โŒ ใ‚จใƒฉใƒผ็™บ็”Ÿ: {str(e)}",
885
+ 'zh': f"โŒ ๅ‘็”Ÿ้”™่ฏฏ: {str(e)}"
886
+ }
887
+ yield error_msg.get(lang, error_msg['en']), agent_thoughts
888
+
889
+ async def _run_critic_async(self, prompt: str) -> str:
890
+ """๋น„ํ‰์ž ๋น„๋™๊ธฐ ์‹คํ–‰ with error handling"""
891
+ try:
892
+ response = ""
893
+ async for chunk in self.llm.chat_stream_async(
894
+ messages=[
895
+ {"role": "system", "content": self.compact_prompts[AgentRole.CRITIC]},
896
+ {"role": "user", "content": prompt}
897
+ ],
898
+ temperature=0.2,
899
+ max_tokens=500
900
+ ):
901
+ response += chunk
902
+ return response
903
+ except Exception as e:
904
+ # ์–ธ์–ด ๊ฐ์ง€
905
+ lang = 'ko' if '์งˆ๋ฌธ' in prompt else 'en'
906
+ error_msg = {
907
+ 'ko': "๋น„ํ‰ ์ฒ˜๋ฆฌ ์ค‘ ์˜ค๋ฅ˜",
908
+ 'en': "Error during critic processing",
909
+ 'ja': "ๆ‰น่ฉ•ๅ‡ฆ็†ไธญใฎใ‚จใƒฉใƒผ",
910
+ 'zh': "่ฏ„่ฎบๅค„็†ไธญๅ‡บ้”™"
911
+ }
912
+ return error_msg.get(lang, error_msg['en'])
913
+
914
+ def _format_search_results(self, results: List[Dict]) -> str:
915
+ """๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ์••์ถ• ํฌ๋งท"""
916
+ if not results:
917
+ return "No search results"
918
+
919
+ formatted = []
920
+ for i, r in enumerate(results[:3], 1):
921
+ title = r.get('title', '')[:50]
922
+ desc = r.get('description', '')[:100]
923
+ formatted.append(f"[{i}]{title}:{desc}")
924
+
925
+ return " | ".join(formatted)
926
+
927
+
928
+ # ============================================================================
929
+ # Gradio UI (์ตœ์ ํ™” ๋ฒ„์ „ - ์บ์‹ฑ ์ œ๊ฑฐ)
930
+ # ============================================================================
931
+
932
+ def create_optimized_gradio_interface():
933
+ """์ตœ์ ํ™”๋œ Gradio ์ธํ„ฐํŽ˜์ด์Šค (์บ์‹ฑ ์—†์Œ)"""
934
+
935
+ # ์‹œ์Šคํ…œ ์ดˆ๊ธฐํ™”
936
+ system = SpeedOptimizedMultiAgentSystem()
937
+
938
+ def process_query_optimized(
939
+ message: str,
940
+ history: List[Dict],
941
+ use_search: bool,
942
+ show_agent_thoughts: bool,
943
+ search_count: int,
944
+ language_mode: str
945
+ ):
946
+ """์ตœ์ ํ™”๋œ ์ฟผ๋ฆฌ ์ฒ˜๋ฆฌ - ์‹ค์‹œ๊ฐ„ ์ŠคํŠธ๋ฆฌ๋ฐ ๋ฒ„์ „"""
947
+
948
+ if not message:
949
+ yield history, "", ""
950
+ return
951
+
952
+ # ์–ธ์–ด ์„ค์ •
953
+ if language_mode == "Auto":
954
+ lang = None # ์ž๋™ ๊ฐ์ง€
955
+ else:
956
+ lang_map = {"Korean": "ko", "English": "en", "Japanese": "ja", "Chinese": "zh"}
957
+ lang = lang_map.get(language_mode, None)
958
+
959
+ # ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋ฅผ ๋™๊ธฐ์ ์œผ๋กœ ์‹คํ–‰
960
+ try:
961
+ import nest_asyncio
962
+ nest_asyncio.apply()
963
+ except ImportError:
964
+ pass
965
+
966
+ try:
967
+ # ๊ฒ€์ƒ‰ ์ˆ˜ํ–‰ (๋™๊ธฐํ™”)
968
+ search_results = []
969
+ search_display = ""
970
+
971
+ # ์–ธ์–ด ์ž๋™ ๊ฐ์ง€ (ํ•„์š”ํ•œ ๊ฒฝ์šฐ)
972
+ detected_lang = lang or system.language_detector.detect_language(message)
973
+
974
+ if use_search:
975
+ # ๊ฒ€์ƒ‰ ์ƒํƒœ ํ‘œ์‹œ
976
+ processing_msg = {
977
+ 'ko': "โšก ๊ณ ์† ์ฒ˜๋ฆฌ ์ค‘...",
978
+ 'en': "โšก High-speed processing...",
979
+ 'ja': "โšก ้ซ˜้€Ÿๅ‡ฆ็†ไธญ...",
980
+ 'zh': "โšก ้ซ˜้€Ÿๅค„็†ไธญ..."
981
+ }
982
+ history_with_message = history + [
983
+ {"role": "user", "content": message},
984
+ {"role": "assistant", "content": processing_msg.get(detected_lang, processing_msg['en'])}
985
+ ]
986
+ yield history_with_message, "", ""
987
+
988
+ # ๋น„๋™๊ธฐ ๊ฒ€์ƒ‰์„ ๋™๊ธฐ์ ์œผ๋กœ ์‹คํ–‰
989
+ async def search_wrapper():
990
+ return await system.search.search_async(message, count=search_count, lang=detected_lang)
991
+
992
+ loop = asyncio.new_event_loop()
993
+ asyncio.set_event_loop(loop)
994
+ search_results = loop.run_until_complete(search_wrapper())
995
+
996
+ if search_results:
997
+ ref_label = {
998
+ 'ko': "๐Ÿ“š ์ฐธ๊ณ  ์ž๋ฃŒ",
999
+ 'en': "๐Ÿ“š References",
1000
+ 'ja': "๐Ÿ“š ๅ‚่€ƒ่ณ‡ๆ–™",
1001
+ 'zh': "๐Ÿ“š ๅ‚่€ƒ่ต„ๆ–™"
1002
+ }
1003
+ search_display = f"{ref_label.get(detected_lang, ref_label['en'])}\n\n"
1004
+ for i, result in enumerate(search_results[:3], 1):
1005
+ search_display += f"**{i}. [{result['title'][:50]}]({result['url']})**\n"
1006
+ search_display += f" {result['description'][:100]}...\n\n"
1007
+
1008
+ # ์‚ฌ์šฉ์ž ๋ฉ”์‹œ์ง€ ์ถ”๊ฐ€
1009
+ current_history = history + [{"role": "user", "content": message}]
1010
+
1011
+ # ์‹ค์‹œ๊ฐ„ ์ŠคํŠธ๋ฆฌ๋ฐ์„ ์œ„ํ•œ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ
1012
+ async def stream_responses():
1013
+ """์‹ค์‹œ๊ฐ„ ์ŠคํŠธ๋ฆฌ๋ฐ ์ œ๋„ˆ๋ ˆ์ดํ„ฐ"""
1014
+ async for response, thoughts in system.parallel_process_agents(
1015
+ query=message,
1016
+ search_results=search_results,
1017
+ show_progress=show_agent_thoughts,
1018
+ lang=detected_lang
1019
+ ):
1020
+ yield response, thoughts
1021
+
1022
+ # ์ƒˆ ์ด๋ฒคํŠธ ๋ฃจํ”„์—์„œ ์‹ค์‹œ๊ฐ„ ์ŠคํŠธ๋ฆฌ๋ฐ
1023
+ loop = asyncio.new_event_loop()
1024
+ asyncio.set_event_loop(loop)
1025
+
1026
+ # ๋น„๋™๊ธฐ ์ œ๋„ˆ๋ ˆ์ดํ„ฐ๋ฅผ ๋™๊ธฐ์ ์œผ๋กœ ์ˆœํšŒ
1027
+ gen = stream_responses()
1028
+
1029
+ while True:
1030
+ try:
1031
+ # ๋‹ค์Œ ํ•ญ๋ชฉ ๊ฐ€์ ธ์˜ค๊ธฐ
1032
+ task = asyncio.ensure_future(gen.__anext__(), loop=loop)
1033
+ response, thoughts = loop.run_until_complete(task)
1034
+
1035
+ # ์‹ค์‹œ๊ฐ„ ์—…๋ฐ์ดํŠธ
1036
+ updated_history = current_history + [
1037
+ {"role": "assistant", "content": response}
1038
+ ]
1039
+ yield updated_history, thoughts, search_display
1040
+
1041
+ except StopAsyncIteration:
1042
+ break
1043
+
1044
+ except Exception as e:
1045
+ error_history = history + [
1046
+ {"role": "user", "content": message},
1047
+ {"role": "assistant", "content": f"โŒ Error: {str(e)}"}
1048
+ ]
1049
+ yield error_history, "", ""
1050
+ finally:
1051
+ # ๋ฃจํ”„ ์ •๋ฆฌ
1052
+ try:
1053
+ loop.close()
1054
+ except:
1055
+ pass
1056
+
1057
+ # Gradio ์ธํ„ฐํŽ˜์ด์Šค
1058
+ with gr.Blocks(
1059
+ title="โšก Speed-Optimized Multi-Agent System (No Cache)",
1060
+ theme=gr.themes.Soft(),
1061
+ css="""
1062
+ .gradio-container {
1063
+ max-width: 1400px !important;
1064
+ margin: auto !important;
1065
+ }
1066
+ """
1067
+ ) as demo:
1068
+ gr.Markdown("""
1069
+ # โšก Enhanced Multi-Agent RAG System (์บ์‹ฑ ์ œ๊ฑฐ ๋ฒ„์ „)
1070
+ **Complex questions processed within 5-8 seconds | Multi-language support**
1071
+
1072
+ **Optimization Features:**
1073
+ - ๐Ÿš€ Parallel Processing: Concurrent agent execution
1074
+ - โšก Stream Buffering: Network optimization
1075
+ - ๐ŸŽฏ Early Termination: Complete immediately when quality is met
1076
+ - ๐ŸŒ Multi-language: Auto-detect Korean/English/Japanese/Chinese
1077
+ - โŒ **Caching Disabled**: ์บ์‹ฑ ๊ธฐ๋Šฅ ์ œ๊ฑฐ๋จ
1078
+ """)
1079
+
1080
+ with gr.Row():
1081
+ with gr.Column(scale=3):
1082
+ chatbot = gr.Chatbot(
1083
+ height=500,
1084
+ label="๐Ÿ’ฌ Chat",
1085
+ type="messages"
1086
+ )
1087
+
1088
+ msg = gr.Textbox(
1089
+ label="Enter complex question",
1090
+ placeholder="Enter complex questions requiring analysis, strategy, or creative solutions...",
1091
+ lines=3
1092
+ )
1093
+
1094
+ with gr.Row():
1095
+ submit = gr.Button("โšก High-Speed Process", variant="primary")
1096
+ clear = gr.Button("๐Ÿ”„ Reset")
1097
+
1098
+ with gr.Accordion("๐Ÿค– Agent Processing", open=False):
1099
+ agent_thoughts = gr.Markdown()
1100
+
1101
+ with gr.Accordion("๐Ÿ“š Search Sources", open=False):
1102
+ search_sources = gr.Markdown()
1103
+
1104
+ with gr.Column(scale=1):
1105
+ gr.Markdown("**โš™๏ธ Settings**")
1106
+
1107
+ language_mode = gr.Radio(
1108
+ choices=["Auto", "Korean", "English", "Japanese", "Chinese"],
1109
+ value="Auto",
1110
+ label="๐ŸŒ Language Mode"
1111
+ )
1112
+
1113
+ use_search = gr.Checkbox(
1114
+ label="๐Ÿ” Use Web Search",
1115
+ value=True
1116
+ )
1117
+
1118
+ show_agent_thoughts = gr.Checkbox(
1119
+ label="๐Ÿง  Show Processing",
1120
+ value=True
1121
+ )
1122
+
1123
+ search_count = gr.Slider(
1124
+ minimum=3,
1125
+ maximum=10,
1126
+ value=5,
1127
+ step=1,
1128
+ label="Search Results Count"
1129
+ )
1130
+
1131
+ gr.Markdown("""
1132
+ **โšก Optimization Status**
1133
+
1134
+ **Active Optimizations:**
1135
+ - โœ… Parallel Processing
1136
+ - โŒ ~~Smart Caching~~ (์ œ๊ฑฐ๋จ)
1137
+ - โœ… Buffer Streaming
1138
+ - โœ… Early Termination
1139
+ - โœ… Compressed Prompts
1140
+ - โœ… Multi-language Support
1141
+ - โœ… Error Recovery
1142
+
1143
+ **Expected Processing Time:**
1144
+ - Simple Query: 3-5 seconds
1145
+ - Complex Query: 5-8 seconds
1146
+ - Very Complex: 8-12 seconds
1147
+ """)
1148
+
1149
+ # ๋ณต์žกํ•œ ์งˆ๋ฌธ ์˜ˆ์ œ (๋‹ค๊ตญ์–ด)
1150
+ gr.Examples(
1151
+ examples=[
1152
+ # Korean
1153
+ "AI ๊ธฐ์ˆ ์ด ํ–ฅํ›„ 10๋…„๊ฐ„ ํ•œ๊ตญ ๊ฒฝ์ œ์— ๋ฏธ์น  ์˜ํ–ฅ์„ ๋‹ค๊ฐ๋„๋กœ ๋ถ„์„ํ•˜๊ณ  ๋Œ€์‘ ์ „๋žต์„ ์ œ์‹œํ•ด์ค˜",
1154
+ "์Šคํƒ€ํŠธ์—…์ด ๋Œ€๊ธฐ์—…๊ณผ ๊ฒฝ์Ÿํ•˜๊ธฐ ์œ„ํ•œ ํ˜์‹ ์ ์ธ ์ „๋žต์„ ๋‹จ๊ณ„๋ณ„๋กœ ์ˆ˜๋ฆฝํ•ด์ค˜",
1155
+ # English
1156
+ "Analyze the multifaceted impact of quantum computing on current encryption systems and propose alternatives",
1157
+ "Design 5 innovative business models for climate change mitigation with practical implementation details",
1158
+ # Japanese
1159
+ "ใƒกใ‚ฟใƒใƒผใ‚นๆ™‚ไปฃใฎๆ•™่‚ฒ้ฉๆ–ฐๆ–นๆกˆใ‚’ๅฎŸ่ฃ…ๅฏ่ƒฝใชใƒฌใƒ™ใƒซใงๆๆกˆใ—ใฆใใ ใ•ใ„",
1160
+ # Chinese
1161
+ "ๅˆ†ๆžไบบๅทฅๆ™บ่ƒฝๅฏนๆœชๆฅๅๅนดๅ…จ็ƒ็ปๆตŽ็š„ๅฝฑๅ“ๅนถๆๅ‡บๅบ”ๅฏน็ญ–็•ฅ"
1162
+ ],
1163
+ inputs=msg
1164
+ )
1165
+
1166
+ # ์ด๋ฒคํŠธ ๋ฐ”์ธ๋”ฉ
1167
+ submit.click(
1168
+ process_query_optimized,
1169
+ inputs=[msg, chatbot, use_search, show_agent_thoughts, search_count, language_mode],
1170
+ outputs=[chatbot, agent_thoughts, search_sources]
1171
+ ).then(
1172
+ lambda: "",
1173
+ None,
1174
+ msg
1175
+ )
1176
+
1177
+ msg.submit(
1178
+ process_query_optimized,
1179
+ inputs=[msg, chatbot, use_search, show_agent_thoughts, search_count, language_mode],
1180
+ outputs=[chatbot, agent_thoughts, search_sources]
1181
+ ).then(
1182
+ lambda: "",
1183
+ None,
1184
+ msg
1185
+ )
1186
+
1187
+ clear.click(
1188
+ lambda: ([], "", ""),
1189
+ None,
1190
+ [chatbot, agent_thoughts, search_sources]
1191
+ )
1192
+
1193
+ return demo
1194
+
1195
+
1196
+ # ============================================================================
1197
+ # ๋ฉ”์ธ ์‹คํ–‰
1198
+ # ============================================================================
1199
+
1200
+ if __name__ == "__main__":
1201
+ print("""
1202
+ โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
1203
+ โ•‘ โšก Speed-Optimized Multi-Agent System (No Cache) โšก โ•‘
1204
+ โ•‘ โ•‘
1205
+ โ•‘ High-speed AI system processing complex questions โ•‘
1206
+ โ•‘ โ•‘
1207
+ โ•‘ Features: โ•‘
1208
+ โ•‘ โ€ข Multi-language support (KO/EN/JA/ZH) โ•‘
1209
+ โ•‘ โ€ข Improved error recovery โ•‘
1210
+ โ•‘ โ€ข NO CACHING (์บ์‹ฑ ๊ธฐ๋Šฅ ์ œ๊ฑฐ๋จ) โ•‘
1211
+ โ•‘ โ€ข Adaptive stream buffering โ•‘
1212
+ โ•‘ โ€ข Response cleaning & formatting โ•‘
1213
+ โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
1214
+ """)
1215
+
1216
+ # API ํ‚ค ํ™•์ธ
1217
+ if not os.getenv("FIREWORKS_API_KEY"):
1218
+ print("\nโš ๏ธ FIREWORKS_API_KEY is not set.")
1219
+
1220
+ if not os.getenv("BRAVE_SEARCH_API_KEY"):
1221
+ print("\nโš ๏ธ BRAVE_SEARCH_API_KEY is not set.")
1222
+
1223
+ # Gradio ์•ฑ ์‹คํ–‰
1224
+ demo = create_optimized_gradio_interface()
1225
+
1226
+ is_hf_spaces = os.getenv("SPACE_ID") is not None
1227
+
1228
+ if is_hf_spaces:
1229
+ print("\n๐Ÿค— Running in optimized mode on Hugging Face Spaces (No Cache)...")
1230
+ demo.launch(server_name="0.0.0.0", server_port=7860)
1231
+ else:
1232
+ print("\n๐Ÿ’ป Running in optimized mode on local environment (No Cache)...")
1233
+ demo.launch(server_name="0.0.0.0", server_port=7860, share=False), '', response, flags=re.MULTILINE)
1234
+
1235
+ # ํ…Œ์ด๋ธ” ๊ตฌ๋ถ„์„  ์ œ๊ฑฐ (|---|, |:---|, |---:|, |:---:| ๋“ฑ)
1236
+ response = re.sub(r'^\|[\s\-:]+\|.*
1237
+
1238
+
1239
+ # ============================================================================
1240
+ # ํ†ตํ•ฉ ์ตœ์ ํ™” ๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ (์บ์‹ฑ ์ œ๊ฑฐ ๋ฒ„์ „)
1241
+ # ============================================================================
1242
+
1243
+ class SpeedOptimizedMultiAgentSystem:
1244
+ """์†๋„ ์ตœ์ ํ™”๋œ ๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ (์บ์‹ฑ ์—†์Œ)"""
1245
+
1246
+ def __init__(self):
1247
+ self.llm = OptimizedFireworksClient()
1248
+ self.search = AsyncBraveSearch()
1249
+ self.reasoning = LightweightReasoningChain()
1250
+ self.quality_checker = QualityChecker()
1251
+ self.streaming = OptimizedStreaming()
1252
+ self.language_detector = LanguageDetector()
1253
+ self.response_cleaner = ResponseCleaner()
1254
+
1255
+ # ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ ํ’€
1256
+ self.executor = ThreadPoolExecutor(max_workers=4)
1257
+
1258
+ def _init_compact_prompts(self, lang: str = 'ko') -> Dict:
1259
+ """์••์ถ•๋œ ๊ณ ํšจ์œจ ํ”„๋กฌํ”„ํŠธ (์–ธ์–ด๋ณ„)"""
1260
+ prompts = {
1261
+ 'ko': {
1262
+ AgentRole.SUPERVISOR: """[๊ฐ๋…์ž-๊ตฌ์กฐ์„ค๊ณ„]
1263
+ ์ฆ‰์‹œ๋ถ„์„: ํ•ต์‹ฌ์˜๋„+ํ•„์š”์ •๋ณด+๋‹ต๋ณ€๊ตฌ์กฐ
1264
+ ์ถœ๋ ฅ: 5๊ฐœ ํ•ต์‹ฌํฌ์ธํŠธ(๊ฐ 1๋ฌธ์žฅ)
1265
+ ์ถ”๋ก ์ฒด๊ณ„ ๋ช…์‹œ""",
1266
+
1267
+ AgentRole.CREATIVE: """[์ฐฝ์˜์„ฑ์ƒ์„ฑ์ž]
1268
+ ์ž…๋ ฅ๊ตฌ์กฐ ๋”ฐ๋ผ ์ฐฝ์˜์  ํ™•์žฅ
1269
+ ์‹ค์šฉ์˜ˆ์‹œ+ํ˜์‹ ์ ‘๊ทผ+๊ตฌ์ฒด์กฐ์–ธ
1270
+ ๋ถˆํ•„์š”์„ค๋ช… ์ œ๊ฑฐ""",
1271
+
1272
+ AgentRole.CRITIC: """[๋น„ํ‰์ž-๊ฒ€์ฆ]
1273
+ ์‹ ์†๊ฒ€ํ† : ์ •ํ™•์„ฑ/๋…ผ๋ฆฌ์„ฑ/์‹ค์šฉ์„ฑ
1274
+ ๊ฐœ์„ ํฌ์ธํŠธ 3๊ฐœ๋งŒ
1275
+ ๊ฐ 2๋ฌธ์žฅ ์ด๋‚ด""",
1276
+
1277
+ AgentRole.FINALIZER: """[์ตœ์ข…ํ†ตํ•ฉ]
1278
+ ๋ชจ๋“ ์˜๊ฒฌ ์ข…ํ•ฉโ†’์ตœ์ ๋‹ต๋ณ€
1279
+ ๋ช…ํ™•๊ตฌ์กฐ+์‹ค์šฉ์ •๋ณด+์ฐฝ์˜๊ท ํ˜•
1280
+ ๋ฐ”๋กœ ํ•ต์‹ฌ ๋‚ด์šฉ๋ถ€ํ„ฐ ์‹œ์ž‘. ๋ถˆํ•„์š”ํ•œ ํ—ค๋”๋‚˜ ๋งˆํฌ์—… ์—†์ด. ๋งˆํฌ๋‹ค์šด ํ—ค๋”(#, ##, ###) ์‚ฌ์šฉ ๊ธˆ์ง€."""
1281
+ },
1282
+ 'en': {
1283
+ AgentRole.SUPERVISOR: """[Supervisor-Structure]
1284
+ Immediate analysis: core intent+required info+answer structure
1285
+ Output: 5 key points (1 sentence each)
1286
+ Clear reasoning framework""",
1287
+
1288
+ AgentRole.CREATIVE: """[Creative Generator]
1289
+ Follow structure, expand creatively
1290
+ Practical examples+innovative approach+specific advice
1291
+ Remove unnecessary explanations""",
1292
+
1293
+ AgentRole.CRITIC: """[Critic-Verification]
1294
+ Quick review: accuracy/logic/practicality
1295
+ Only 3 improvement points
1296
+ Max 2 sentences each""",
1297
+
1298
+ AgentRole.FINALIZER: """[Final Integration]
1299
+ Synthesize all inputsโ†’optimal answer
1300
+ Clear structure+practical info+creative balance
1301
+ Start with core content directly. No unnecessary headers or markup. No markdown headers (#, ##, ###)."""
1302
+ },
1303
+ 'ja': {
1304
+ AgentRole.SUPERVISOR: """[็›ฃ็ฃ่€…-ๆง‹้€ ่จญ่จˆ]
1305
+ ๅณๆ™‚ๅˆ†ๆž๏ผšๆ ธๅฟƒๆ„ๅ›ณ+ๅฟ…่ฆๆƒ…ๅ ฑ+ๅ›ž็ญ”ๆง‹้€ 
1306
+ ๅ‡บๅŠ›๏ผš5ใคใฎๆ ธๅฟƒใƒใ‚คใƒณใƒˆ๏ผˆๅ„1ๆ–‡๏ผ‰
1307
+ ๆŽจ่ซ–ไฝ“็ณปๆ˜Ž็คบ""",
1308
+
1309
+ AgentRole.CREATIVE: """[ๅ‰ต้€ ๆ€ง็”Ÿๆˆ่€…]
1310
+ ๅ…ฅๅŠ›ๆง‹้€ ใซๅพ“ใฃใฆๅ‰ต้€ ็š„ๆ‹กๅผต
1311
+ ๅฎŸ็”จไพ‹+้ฉๆ–ฐ็š„ใ‚ขใƒ—ใƒญใƒผใƒ+ๅ…ทไฝ“็š„ใ‚ขใƒ‰ใƒใ‚คใ‚น
1312
+ ไธ่ฆใช่ชฌๆ˜Žๅ‰Š้™ค""",
1313
+
1314
+ AgentRole.CRITIC: """[ๆ‰น่ฉ•่€…-ๆคœ่จผ]
1315
+ ่ฟ…้€Ÿใƒฌใƒ“ใƒฅใƒผ๏ผšๆญฃ็ขบๆ€ง/่ซ–็†ๆ€ง/ๅฎŸ็”จๆ€ง
1316
+ ๆ”นๅ–„ใƒใ‚คใƒณใƒˆ3ใคใฎใฟ
1317
+ ๅ„2ๆ–‡ไปฅๅ†…""",
1318
+
1319
+ AgentRole.FINALIZER: """[ๆœ€็ต‚็ตฑๅˆ]
1320
+ ๅ…จๆ„่ฆ‹็ตฑๅˆโ†’ๆœ€้ฉๅ›ž็ญ”
1321
+ ๆ˜Ž็ขบๆง‹้€ +ๅฎŸ็”จๆƒ…ๅ ฑ+ๅ‰ต้€ ๆ€ง๏ฟฝ๏ฟฝ๏ฟฝใƒฉใƒณใ‚น
1322
+ ๆ ธๅฟƒๅ†…ๅฎนใ‹ใ‚‰็›ดๆŽฅ้–‹ๅง‹ใ€‚ไธ่ฆใชใƒ˜ใƒƒใƒ€ใƒผใ‚„ใƒžใƒผใ‚ฏใ‚ขใƒƒใƒ—ใชใ—ใ€‚ใƒžใƒผใ‚ฏใƒ€ใ‚ฆใƒณใƒ˜ใƒƒใƒ€ใƒผ๏ผˆ#ใ€##ใ€###๏ผ‰ไฝฟ็”จ็ฆๆญขใ€‚"""
1323
+ },
1324
+ 'zh': {
1325
+ AgentRole.SUPERVISOR: """[ไธป็ฎก-็ป“ๆž„่ฎพ่ฎก]
1326
+ ็ซ‹ๅณๅˆ†ๆž๏ผšๆ ธๅฟƒๆ„ๅ›พ+ๆ‰€้œ€ไฟกๆฏ+็ญ”ๆกˆ็ป“ๆž„
1327
+ ่พ“ๅ‡บ๏ผš5ไธชๆ ธๅฟƒ่ฆ็‚น๏ผˆๆฏไธช1ๅฅ๏ผ‰
1328
+ ๆŽจ็†ไฝ“็ณปๆ˜Ž็กฎ""",
1329
+
1330
+ AgentRole.CREATIVE: """[ๅˆ›ๆ„็”Ÿๆˆๅ™จ]
1331
+ ๆŒ‰็ป“ๆž„ๅˆ›้€ ๆ€งๆ‰ฉๅฑ•
1332
+ ๅฎž็”จ็คบไพ‹+ๅˆ›ๆ–ฐๆ–นๆณ•+ๅ…ทไฝ“ๅปบ่ฎฎ
1333
+ ๅˆ ้™คไธๅฟ…่ฆ็š„่งฃ้‡Š""",
1334
+
1335
+ AgentRole.CRITIC: """[่ฏ„่ฎบๅฎถ-้ชŒ่ฏ]
1336
+ ๅฟซ้€ŸๅฎกๆŸฅ๏ผšๅ‡†็กฎๆ€ง/้€ป่พ‘ๆ€ง/ๅฎž็”จๆ€ง
1337
+ ไป…3ไธชๆ”น่ฟ›็‚น
1338
+ ๆฏไธชๆœ€ๅคš2ๅฅ""",
1339
+
1340
+ AgentRole.FINALIZER: """[ๆœ€็ปˆๆ•ดๅˆ]
1341
+ ็ปผๅˆๆ‰€ๆœ‰ๆ„่งโ†’ๆœ€ไฝณ็ญ”ๆกˆ
1342
+ ๆธ…ๆ™ฐ็ป“ๆž„+ๅฎž็”จไฟกๆฏ+ๅˆ›ๆ„ๅนณ่กก
1343
+ ็›ดๆŽฅไปŽๆ ธๅฟƒๅ†…ๅฎนๅผ€ๅง‹ใ€‚ๆ— ้œ€ไธๅฟ…่ฆ็š„ๆ ‡้ข˜ๆˆ–ๆ ‡่ฎฐใ€‚็ฆๆญขไฝฟ็”จMarkdownๆ ‡้ข˜๏ผˆ#ใ€##ใ€###๏ผ‰ใ€‚"""
1344
+ }
1345
+ }
1346
+
1347
+ return prompts.get(lang, prompts['en'])
1348
+
1349
+ async def parallel_process_agents(
1350
+ self,
1351
+ query: str,
1352
+ search_results: List[Dict],
1353
+ show_progress: bool = True,
1354
+ lang: str = None
1355
+ ) -> AsyncGenerator[Tuple[str, str], None]:
1356
+ """๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ ํŒŒ์ดํ”„๋ผ์ธ (์บ์‹ฑ ์—†์Œ)"""
1357
+
1358
+ start_time = time.time()
1359
+
1360
+ # ์–ธ์–ด ์ž๋™ ๊ฐ์ง€
1361
+ if lang is None:
1362
+ lang = self.language_detector.detect_language(query)
1363
+
1364
+ # ์–ธ์–ด๋ณ„ ํ”„๋กฌํ”„ํŠธ ์„ค์ •
1365
+ self.compact_prompts = self._init_compact_prompts(lang)
1366
+
1367
+ search_context = self._format_search_results(search_results)
1368
+ accumulated_response = ""
1369
+ agent_thoughts = ""
1370
+
1371
+ # ์ถ”๋ก  ํŒจํ„ด ๊ฒฐ์ •
1372
+ reasoning_pattern = self.reasoning.get_reasoning_pattern(query, lang)
1373
+
1374
+ try:
1375
+ # === 1๋‹จ๊ณ„: ๊ฐ๋…์ž + ๊ฒ€์ƒ‰ ๋ณ‘๋ ฌ ์‹คํ–‰ ===
1376
+ if show_progress:
1377
+ progress_msg = {
1378
+ 'ko': "๐Ÿš€ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ ์‹œ์ž‘\n๐Ÿ‘” ๊ฐ๋…์ž ๋ถ„์„ + ๐Ÿ” ์ถ”๊ฐ€ ๊ฒ€์ƒ‰ ๋™์‹œ ์ง„ํ–‰...\n\n",
1379
+ 'en': "๐Ÿš€ Starting parallel processing\n๐Ÿ‘” Supervisor analysis + ๐Ÿ” Additional search in progress...\n\n",
1380
+ 'ja': "๐Ÿš€ ไธฆๅˆ—ๅ‡ฆ็†้–‹ๅง‹\n๐Ÿ‘” ็›ฃ็ฃ่€…ๅˆ†ๆž + ๐Ÿ” ่ฟฝๅŠ ๆคœ็ดขๅŒๆ™‚้€ฒ่กŒไธญ...\n\n",
1381
+ 'zh': "๐Ÿš€ ๅผ€ๅง‹ๅนถ่กŒๅค„็†\n๐Ÿ‘” ไธป็ฎกๅˆ†ๆž + ๐Ÿ” ้™„ๅŠ ๆœ็ดขๅŒๆ—ถ่ฟ›่กŒ...\n\n"
1382
+ }
1383
+ agent_thoughts = progress_msg.get(lang, progress_msg['en'])
1384
+ yield accumulated_response, agent_thoughts
1385
+
1386
+ # ๊ฐ๋…์ž ํ”„๋กฌํ”„ํŠธ (์–ธ์–ด๋ณ„)
1387
+ supervisor_prompt_templates = {
1388
+ 'ko': f"""
1389
+ ์งˆ๋ฌธ: {query}
1390
+ ๊ฒ€์ƒ‰๊ฒฐ๊ณผ: {search_context}
1391
+ ์ถ”๋ก ํŒจํ„ด: {reasoning_pattern}
1392
+ ์ฆ‰์‹œ ํ•ต์‹ฌ๊ตฌ์กฐ 5๊ฐœ ์ œ์‹œ""",
1393
+ 'en': f"""
1394
+ Question: {query}
1395
+ Search results: {search_context}
1396
+ Reasoning pattern: {reasoning_pattern}
1397
+ Immediately provide 5 key structures""",
1398
+ 'ja': f"""
1399
+ ่ณชๅ•: {query}
1400
+ ๆคœ็ดข็ตๆžœ: {search_context}
1401
+ ๆŽจ่ซ–ใƒ‘ใ‚ฟใƒผใƒณ: {reasoning_pattern}
1402
+ ๅณๅบงใซ5ใคใฎๆ ธๅฟƒๆง‹้€ ใ‚’ๆ็คบ""",
1403
+ 'zh': f"""
1404
+ ้—ฎ้ข˜: {query}
1405
+ ๆœ็ดข็ป“ๆžœ: {search_context}
1406
+ ๆŽจ็†ๆจกๅผ: {reasoning_pattern}
1407
+ ็ซ‹ๅณๆไพ›5ไธชๆ ธๅฟƒ็ป“ๆž„"""
1408
+ }
1409
+
1410
+ supervisor_prompt = supervisor_prompt_templates.get(lang, supervisor_prompt_templates['en'])
1411
+
1412
+ supervisor_response = ""
1413
+ supervisor_task = self.llm.chat_stream_async(
1414
+ messages=[
1415
+ {"role": "system", "content": self.compact_prompts[AgentRole.SUPERVISOR]},
1416
+ {"role": "user", "content": supervisor_prompt}
1417
+ ],
1418
+ temperature=0.3,
1419
+ max_tokens=500
1420
+ )
1421
+
1422
+ # ๊ฐ๋…์ž ์ŠคํŠธ๋ฆฌ๋ฐ (๋ฒ„ํผ๋ง)
1423
+ async for chunk in self.streaming.buffer_and_yield(supervisor_task):
1424
+ supervisor_response += chunk
1425
+ if show_progress and len(supervisor_response) < 300:
1426
+ supervisor_label = {
1427
+ 'ko': "๐Ÿ‘” ๊ฐ๋…์ž ๋ถ„์„",
1428
+ 'en': "๐Ÿ‘” Supervisor Analysis",
1429
+ 'ja': "๐Ÿ‘” ็›ฃ็ฃ่€…ๅˆ†ๆž",
1430
+ 'zh': "๐Ÿ‘” ไธป็ฎกๅˆ†ๆž"
1431
+ }
1432
+ agent_thoughts = f"{supervisor_label.get(lang, supervisor_label['en'])}\n{supervisor_response[:300]}...\n\n"
1433
+ yield accumulated_response, agent_thoughts
1434
+
1435
+ # === 2๋‹จ๊ณ„: ์ฐฝ์˜์„ฑ + ๋น„ํ‰ ์ค€๋น„ ๋ณ‘๋ ฌ ===
1436
+ if show_progress:
1437
+ creative_msg = {
1438
+ 'ko': "๐ŸŽจ ์ฐฝ์˜์„ฑ ์ƒ์„ฑ์ž + ๐Ÿ” ๋น„ํ‰์ž ์ค€๋น„...\n\n",
1439
+ 'en': "๐ŸŽจ Creative Generator + ๐Ÿ” Critic preparing...\n\n",
1440
+ 'ja': "๐ŸŽจ ๅ‰ต้€ ๆ€ง็”Ÿๆˆ่€… + ๐Ÿ” ๆ‰น่ฉ•่€…ๆบ–ๅ‚™ไธญ...\n\n",
1441
+ 'zh': "๐ŸŽจ ๅˆ›ๆ„็”Ÿๆˆๅ™จ + ๐Ÿ” ่ฏ„่ฎบๅฎถๅ‡†ๅค‡ไธญ...\n\n"
1442
+ }
1443
+ agent_thoughts += creative_msg.get(lang, creative_msg['en'])
1444
+ yield accumulated_response, agent_thoughts
1445
+
1446
+ # ์ฐฝ์˜์„ฑ ์ƒ์„ฑ ์‹œ์ž‘ (์–ธ์–ด๋ณ„)
1447
+ creative_prompt_templates = {
1448
+ 'ko': f"""
1449
+ ์งˆ๋ฌธ: {query}
1450
+ ๊ฐ๋…์ž๊ตฌ์กฐ: {supervisor_response}
1451
+ ๊ฒ€์ƒ‰๊ฒฐ๊ณผ: {search_context}
1452
+ ์ฐฝ์˜์ +์‹ค์šฉ์  ๋‹ต๋ณ€ ์ฆ‰์‹œ์ƒ์„ฑ""",
1453
+ 'en': f"""
1454
+ Question: {query}
1455
+ Supervisor structure: {supervisor_response}
1456
+ Search results: {search_context}
1457
+ Generate creative+practical answer immediately""",
1458
+ 'ja': f"""
1459
+ ่ณชๅ•: {query}
1460
+ ็›ฃ็ฃ่€…ๆง‹้€ : {supervisor_response}
1461
+ ๆคœ็ดข็ตๆžœ: {search_context}
1462
+ ๅ‰ต้€ ็š„+ๅฎŸ็”จ็š„ๅ›ž็ญ”ๅณๅบง็”Ÿๆˆ""",
1463
+ 'zh': f"""
1464
+ ้—ฎ้ข˜: {query}
1465
+ ไธป็ฎก็ป“ๆž„: {supervisor_response}
1466
+ ๆœ็ดข็ป“ๆžœ: {search_context}
1467
+ ็ซ‹ๅณ็”Ÿๆˆๅˆ›ๆ„+ๅฎž็”จ็ญ”ๆกˆ"""
1468
+ }
1469
+
1470
+ creative_prompt = creative_prompt_templates.get(lang, creative_prompt_templates['en'])
1471
+
1472
+ creative_response = ""
1473
+ creative_partial = ""
1474
+ critic_started = False
1475
+ critic_response = ""
1476
+
1477
+ creative_task = self.llm.chat_stream_async(
1478
+ messages=[
1479
+ {"role": "system", "content": self.compact_prompts[AgentRole.CREATIVE]},
1480
+ {"role": "user", "content": creative_prompt}
1481
+ ],
1482
+ temperature=0.8,
1483
+ max_tokens=1500
1484
+ )
1485
+
1486
+ # ์ฐฝ์˜์„ฑ ์ŠคํŠธ๋ฆฌ๋ฐ + ๋น„ํ‰์ž ์กฐ๊ธฐ ์‹œ์ž‘
1487
+ async for chunk in self.streaming.buffer_and_yield(creative_task):
1488
+ creative_response += chunk
1489
+ creative_partial += chunk
1490
+
1491
+ # ์ฐฝ์˜์„ฑ ์‘๋‹ต์ด 500์ž ๋„˜์œผ๋ฉด ๋น„ํ‰์ž ์‹œ์ž‘
1492
+ if len(creative_partial) > 500 and not critic_started:
1493
+ critic_started = True
1494
+
1495
+ # ๋น„ํ‰์ž ๋น„๋™๊ธฐ ์‹œ์ž‘ (์–ธ์–ด๋ณ„)
1496
+ critic_prompt_templates = {
1497
+ 'ko': f"""
1498
+ ์›๋ณธ์งˆ๋ฌธ: {query}
1499
+ ์ฐฝ์˜์„ฑ๋‹ต๋ณ€(์ผ๋ถ€): {creative_partial}
1500
+ ์‹ ์†๊ฒ€ํ† โ†’๊ฐœ์„ ์ 3๊ฐœ""",
1501
+ 'en': f"""
1502
+ Original question: {query}
1503
+ Creative answer (partial): {creative_partial}
1504
+ Quick reviewโ†’3 improvements""",
1505
+ 'ja': f"""
1506
+ ๅ…ƒใฎ่ณชๅ•: {query}
1507
+ ๅ‰ต้€ ็š„ๅ›ž็ญ”๏ผˆไธ€้ƒจ๏ผ‰: {creative_partial}
1508
+ ่ฟ…้€Ÿใƒฌใƒ“ใƒฅใƒผโ†’ๆ”นๅ–„็‚น3ใค""",
1509
+ 'zh': f"""
1510
+ ๅŽŸๅง‹้—ฎ้ข˜: {query}
1511
+ ๅˆ›ๆ„็ญ”ๆกˆ๏ผˆ้ƒจๅˆ†๏ผ‰: {creative_partial}
1512
+ ๅฟซ้€ŸๅฎกๆŸฅโ†’3ไธชๆ”น่ฟ›็‚น"""
1513
+ }
1514
+
1515
+ critic_prompt = critic_prompt_templates.get(lang, critic_prompt_templates['en'])
1516
+
1517
+ critic_task = asyncio.create_task(
1518
+ self._run_critic_async(critic_prompt)
1519
+ )
1520
+
1521
+ if show_progress:
1522
+ display_creative = creative_response[:400] + "..." if len(creative_response) > 400 else creative_response
1523
+ creative_label = {
1524
+ 'ko': "๐ŸŽจ ์ฐฝ์˜์„ฑ ์ƒ์„ฑ์ž",
1525
+ 'en': "๐ŸŽจ Creative Generator",
1526
+ 'ja': "๐ŸŽจ ๅ‰ต้€ ๆ€ง็”Ÿๆˆ่€…",
1527
+ 'zh': "๐ŸŽจ ๅˆ›ๆ„็”Ÿๆˆๅ™จ"
1528
+ }
1529
+ agent_thoughts = f"{creative_label.get(lang, creative_label['en'])}\n{display_creative}\n\n"
1530
+ yield accumulated_response, agent_thoughts
1531
+
1532
+ # ๋น„ํ‰์ž ๊ฒฐ๊ณผ ๋Œ€๊ธฐ
1533
+ if critic_started:
1534
+ critic_response = await critic_task
1535
+
1536
+ if show_progress:
1537
+ critic_label = {
1538
+ 'ko': "๐Ÿ” ๋น„ํ‰์ž ๊ฒ€ํ† ",
1539
+ 'en': "๐Ÿ” Critic Review",
1540
+ 'ja': "๐Ÿ” ๆ‰น่ฉ•่€…ใƒฌใƒ“ใƒฅใƒผ",
1541
+ 'zh': "๐Ÿ” ่ฏ„่ฎบๅฎถๅฎกๆŸฅ"
1542
+ }
1543
+ agent_thoughts += f"{critic_label.get(lang, critic_label['en'])}\n{critic_response[:200]}...\n\n"
1544
+ yield accumulated_response, agent_thoughts
1545
+
1546
+ # === 3๋‹จ๊ณ„: ํ’ˆ์งˆ ์ฒดํฌ ๋ฐ ์กฐ๊ธฐ ์ข…๋ฃŒ ===
1547
+ quality_score, need_more = self.quality_checker.evaluate_response(
1548
+ creative_response, query, lang
1549
+ )
1550
+
1551
+ if not need_more and quality_score > 0.85:
1552
+ # ํ’ˆ์งˆ์ด ์ถฉ๋ถ„ํžˆ ๋†’์œผ๋ฉด ๋ฐ”๋กœ ๋ฐ˜ํ™˜
1553
+ accumulated_response = self.response_cleaner.clean_response(creative_response)
1554
+
1555
+ if show_progress:
1556
+ quality_msg = {
1557
+ 'ko': f"โœ… ํ’ˆ์งˆ ์ถฉ์กฑ (์ ์ˆ˜: {quality_score:.2f})\n์กฐ๊ธฐ ์™„๋ฃŒ!\n",
1558
+ 'en': f"โœ… Quality met (score: {quality_score:.2f})\nEarly completion!\n",
1559
+ 'ja': f"โœ… ๅ“่ณชๆบ€่ถณ (ใ‚นใ‚ณใ‚ข: {quality_score:.2f})\nๆ—ฉๆœŸๅฎŒไบ†!\n",
1560
+ 'zh': f"โœ… ่ดจ้‡ๆปก่ถณ (ๅˆ†ๆ•ฐ: {quality_score:.2f})\nๆๅ‰ๅฎŒๆˆ!\n"
1561
+ }
1562
+ agent_thoughts += quality_msg.get(lang, quality_msg['en'])
1563
+
1564
+ yield accumulated_response, agent_thoughts
1565
+ return
1566
+
1567
+ # === 4๋‹จ๊ณ„: ์ตœ์ข… ํ†ตํ•ฉ (์ŠคํŠธ๋ฆฌ๋ฐ) ===
1568
+ if show_progress:
1569
+ final_msg = {
1570
+ 'ko': "โœ… ์ตœ์ข… ํ†ตํ•ฉ ์ค‘...\n\n",
1571
+ 'en': "โœ… Final integration in progress...\n\n",
1572
+ 'ja': "โœ… ๆœ€็ต‚็ตฑๅˆไธญ...\n\n",
1573
+ 'zh': "โœ… ๆœ€็ปˆๆ•ดๅˆไธญ...\n\n"
1574
+ }
1575
+ agent_thoughts += final_msg.get(lang, final_msg['en'])
1576
+ yield accumulated_response, agent_thoughts
1577
+
1578
+ # ์ตœ์ข… ํ”„๋กฌํ”„ํŠธ (์–ธ์–ด๋ณ„)
1579
+ final_prompt_templates = {
1580
+ 'ko': f"""
1581
+ ์งˆ๋ฌธ: {query}
1582
+ ์ฐฝ์˜์„ฑ๋‹ต๋ณ€: {creative_response}
1583
+ ๋น„ํ‰ํ”ผ๋“œ๋ฐฑ: {critic_response}
1584
+ ๊ฐ๋…์ž๊ตฌ์กฐ: {supervisor_response}
1585
+ ์ตœ์ข…ํ†ตํ•ฉโ†’์™„๋ฒฝ๋‹ต๋ณ€. ๋งˆํฌ๋‹ค์šด ํ—ค๋”(#, ##, ###) ์‚ฌ์šฉ ๊ธˆ์ง€.""",
1586
+ 'en': f"""
1587
+ Question: {query}
1588
+ Creative answer: {creative_response}
1589
+ Critic feedback: {critic_response}
1590
+ Supervisor structure: {supervisor_response}
1591
+ Final integrationโ†’perfect answer. No markdown headers (#, ##, ###).""",
1592
+ 'ja': f"""
1593
+ ่ณชๅ•: {query}
1594
+ ๅ‰ต้€ ็š„ๅ›ž็ญ”: {creative_response}
1595
+ ๆ‰น่ฉ•ใƒ•ใ‚ฃใƒผใƒ‰ใƒใƒƒใ‚ฏ: {critic_response}
1596
+ ็›ฃ็ฃ่€…ๆง‹้€ : {supervisor_response}
1597
+ ๆœ€็ต‚็ตฑๅˆโ†’ๅฎŒ็’งใชๅ›ž็ญ”ใ€‚ใƒžใƒผใ‚ฏใƒ€ใ‚ฆใƒณใƒ˜ใƒƒใƒ€ใƒผ๏ผˆ#ใ€##ใ€###๏ผ‰ไฝฟ็”จ็ฆๆญขใ€‚""",
1598
+ 'zh': f"""
1599
+ ้—ฎ้ข˜: {query}
1600
+ ๅˆ›ๆ„็ญ”ๆกˆ: {creative_response}
1601
+ ่ฏ„่ฎบๅ้ฆˆ: {critic_response}
1602
+ ไธป็ฎก็ป“ๆž„: {supervisor_response}
1603
+ ๆœ€็ปˆๆ•ดๅˆโ†’ๅฎŒ็พŽ็ญ”ๆกˆใ€‚็ฆๆญขไฝฟ็”จMarkdownๆ ‡้ข˜๏ผˆ#ใ€##ใ€###๏ผ‰ใ€‚"""
1604
+ }
1605
+
1606
+ final_prompt = final_prompt_templates.get(lang, final_prompt_templates['en'])
1607
+
1608
+ final_task = self.llm.chat_stream_async(
1609
+ messages=[
1610
+ {"role": "system", "content": self.compact_prompts[AgentRole.FINALIZER]},
1611
+ {"role": "user", "content": final_prompt}
1612
+ ],
1613
+ temperature=0.5,
1614
+ max_tokens=2500
1615
+ )
1616
+
1617
+ # ์ตœ์ข… ๋‹ต๋ณ€ ์ŠคํŠธ๋ฆฌ๋ฐ
1618
+ accumulated_response = ""
1619
+
1620
+ async for chunk in final_task:
1621
+ accumulated_response += chunk
1622
+ # ์‹ค์‹œ๊ฐ„ ์ •๋ฆฌ
1623
+ cleaned_response = self.response_cleaner.clean_response(accumulated_response)
1624
+ yield cleaned_response, agent_thoughts
1625
+
1626
+ # ์ตœ์ข… ์ •๋ฆฌ
1627
+ accumulated_response = self.response_cleaner.clean_response(accumulated_response)
1628
+
1629
+ # ์ฒ˜๋ฆฌ ์‹œ๊ฐ„ ์ถ”๊ฐ€ (์–ธ์–ด๋ณ„)
1630
+ processing_time = time.time() - start_time
1631
+ time_msg = {
1632
+ 'ko': f"\n\n---\nโšก ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: {processing_time:.1f}์ดˆ",
1633
+ 'en': f"\n\n---\nโšก Processing time: {processing_time:.1f} seconds",
1634
+ 'ja': f"\n\n---\nโšก ๅ‡ฆ็†ๆ™‚้–“: {processing_time:.1f}็ง’",
1635
+ 'zh': f"\n\n---\nโšก ๅค„็†ๆ—ถ้—ด: {processing_time:.1f}็ง’"
1636
+ }
1637
+ accumulated_response += time_msg.get(lang, time_msg['en'])
1638
+
1639
+ yield accumulated_response, agent_thoughts
1640
+
1641
+ except Exception as e:
1642
+ error_msg = {
1643
+ 'ko': f"โŒ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}",
1644
+ 'en': f"โŒ Error occurred: {str(e)}",
1645
+ 'ja': f"โŒ ใ‚จใƒฉใƒผ็™บ็”Ÿ: {str(e)}",
1646
+ 'zh': f"โŒ ๅ‘็”Ÿ้”™่ฏฏ: {str(e)}"
1647
+ }
1648
+ yield error_msg.get(lang, error_msg['en']), agent_thoughts
1649
+
1650
+ async def _run_critic_async(self, prompt: str) -> str:
1651
+ """๋น„ํ‰์ž ๋น„๋™๊ธฐ ์‹คํ–‰ with error handling"""
1652
+ try:
1653
+ response = ""
1654
+ async for chunk in self.llm.chat_stream_async(
1655
+ messages=[
1656
+ {"role": "system", "content": self.compact_prompts[AgentRole.CRITIC]},
1657
+ {"role": "user", "content": prompt}
1658
+ ],
1659
+ temperature=0.2,
1660
+ max_tokens=500
1661
+ ):
1662
+ response += chunk
1663
+ return response
1664
+ except Exception as e:
1665
+ # ์–ธ์–ด ๊ฐ์ง€
1666
+ lang = 'ko' if '์งˆ๋ฌธ' in prompt else 'en'
1667
+ error_msg = {
1668
+ 'ko': "๋น„ํ‰ ์ฒ˜๋ฆฌ ์ค‘ ์˜ค๋ฅ˜",
1669
+ 'en': "Error during critic processing",
1670
+ 'ja': "ๆ‰น่ฉ•ๅ‡ฆ็†ไธญใฎใ‚จใƒฉใƒผ",
1671
+ 'zh': "่ฏ„่ฎบๅค„็†ไธญๅ‡บ้”™"
1672
+ }
1673
+ return error_msg.get(lang, error_msg['en'])
1674
+
1675
+ def _format_search_results(self, results: List[Dict]) -> str:
1676
+ """๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ์••์ถ• ํฌ๋งท"""
1677
+ if not results:
1678
+ return "No search results"
1679
+
1680
+ formatted = []
1681
+ for i, r in enumerate(results[:3], 1):
1682
+ title = r.get('title', '')[:50]
1683
+ desc = r.get('description', '')[:100]
1684
+ formatted.append(f"[{i}]{title}:{desc}")
1685
+
1686
+ return " | ".join(formatted)
1687
+
1688
+
1689
+ # ============================================================================
1690
+ # Gradio UI (์ตœ์ ํ™” ๋ฒ„์ „ - ์บ์‹ฑ ์ œ๊ฑฐ)
1691
+ # ============================================================================
1692
+
1693
+ def create_optimized_gradio_interface():
1694
+ """์ตœ์ ํ™”๋œ Gradio ์ธํ„ฐํŽ˜์ด์Šค (์บ์‹ฑ ์—†์Œ)"""
1695
+
1696
+ # ์‹œ์Šคํ…œ ์ดˆ๊ธฐํ™”
1697
+ system = SpeedOptimizedMultiAgentSystem()
1698
+
1699
+ def process_query_optimized(
1700
+ message: str,
1701
+ history: List[Dict],
1702
+ use_search: bool,
1703
+ show_agent_thoughts: bool,
1704
+ search_count: int,
1705
+ language_mode: str
1706
+ ):
1707
+ """์ตœ์ ํ™”๋œ ์ฟผ๋ฆฌ ์ฒ˜๋ฆฌ - ์‹ค์‹œ๊ฐ„ ์ŠคํŠธ๋ฆฌ๋ฐ ๋ฒ„์ „"""
1708
+
1709
+ if not message:
1710
+ yield history, "", ""
1711
+ return
1712
+
1713
+ # ์–ธ์–ด ์„ค์ •
1714
+ if language_mode == "Auto":
1715
+ lang = None # ์ž๋™ ๊ฐ์ง€
1716
+ else:
1717
+ lang_map = {"Korean": "ko", "English": "en", "Japanese": "ja", "Chinese": "zh"}
1718
+ lang = lang_map.get(language_mode, None)
1719
+
1720
+ # ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋ฅผ ๋™๊ธฐ์ ์œผ๋กœ ์‹คํ–‰
1721
+ try:
1722
+ import nest_asyncio
1723
+ nest_asyncio.apply()
1724
+ except ImportError:
1725
+ pass
1726
+
1727
+ try:
1728
+ # ๊ฒ€์ƒ‰ ์ˆ˜ํ–‰ (๋™๊ธฐํ™”)
1729
+ search_results = []
1730
+ search_display = ""
1731
+
1732
+ # ์–ธ์–ด ์ž๋™ ๊ฐ์ง€ (ํ•„์š”ํ•œ ๊ฒฝ์šฐ)
1733
+ detected_lang = lang or system.language_detector.detect_language(message)
1734
+
1735
+ if use_search:
1736
+ # ๊ฒ€์ƒ‰ ์ƒํƒœ ํ‘œ์‹œ
1737
+ processing_msg = {
1738
+ 'ko': "โšก ๊ณ ์† ์ฒ˜๋ฆฌ ์ค‘...",
1739
+ 'en': "โšก High-speed processing...",
1740
+ 'ja': "โšก ้ซ˜้€Ÿๅ‡ฆ็†ไธญ...",
1741
+ 'zh': "โšก ้ซ˜้€Ÿๅค„็†ไธญ..."
1742
+ }
1743
+ history_with_message = history + [
1744
+ {"role": "user", "content": message},
1745
+ {"role": "assistant", "content": processing_msg.get(detected_lang, processing_msg['en'])}
1746
+ ]
1747
+ yield history_with_message, "", ""
1748
+
1749
+ # ๋น„๋™๊ธฐ ๊ฒ€์ƒ‰์„ ๋™๊ธฐ์ ์œผ๋กœ ์‹คํ–‰
1750
+ async def search_wrapper():
1751
+ return await system.search.search_async(message, count=search_count, lang=detected_lang)
1752
+
1753
+ loop = asyncio.new_event_loop()
1754
+ asyncio.set_event_loop(loop)
1755
+ search_results = loop.run_until_complete(search_wrapper())
1756
+
1757
+ if search_results:
1758
+ ref_label = {
1759
+ 'ko': "๐Ÿ“š ์ฐธ๊ณ  ์ž๋ฃŒ",
1760
+ 'en': "๐Ÿ“š References",
1761
+ 'ja': "๐Ÿ“š ๅ‚่€ƒ่ณ‡ๆ–™",
1762
+ 'zh': "๐Ÿ“š ๅ‚่€ƒ่ต„ๆ–™"
1763
+ }
1764
+ search_display = f"{ref_label.get(detected_lang, ref_label['en'])}\n\n"
1765
+ for i, result in enumerate(search_results[:3], 1):
1766
+ search_display += f"**{i}. [{result['title'][:50]}]({result['url']})**\n"
1767
+ search_display += f" {result['description'][:100]}...\n\n"
1768
+
1769
+ # ์‚ฌ์šฉ์ž ๋ฉ”์‹œ์ง€ ์ถ”๊ฐ€
1770
+ current_history = history + [{"role": "user", "content": message}]
1771
+
1772
+ # ์‹ค์‹œ๊ฐ„ ์ŠคํŠธ๋ฆฌ๋ฐ์„ ์œ„ํ•œ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ
1773
+ async def stream_responses():
1774
+ """์‹ค์‹œ๊ฐ„ ์ŠคํŠธ๋ฆฌ๋ฐ ์ œ๋„ˆ๋ ˆ์ดํ„ฐ"""
1775
+ async for response, thoughts in system.parallel_process_agents(
1776
+ query=message,
1777
+ search_results=search_results,
1778
+ show_progress=show_agent_thoughts,
1779
+ lang=detected_lang
1780
+ ):
1781
+ yield response, thoughts
1782
+
1783
+ # ์ƒˆ ์ด๋ฒคํŠธ ๋ฃจํ”„์—์„œ ์‹ค์‹œ๊ฐ„ ์ŠคํŠธ๋ฆฌ๋ฐ
1784
+ loop = asyncio.new_event_loop()
1785
+ asyncio.set_event_loop(loop)
1786
+
1787
+ # ๋น„๋™๊ธฐ ์ œ๋„ˆ๋ ˆ์ดํ„ฐ๋ฅผ ๋™๊ธฐ์ ์œผ๋กœ ์ˆœํšŒ
1788
+ gen = stream_responses()
1789
+
1790
+ while True:
1791
+ try:
1792
+ # ๋‹ค์Œ ํ•ญ๋ชฉ ๊ฐ€์ ธ์˜ค๊ธฐ
1793
+ task = asyncio.ensure_future(gen.__anext__(), loop=loop)
1794
+ response, thoughts = loop.run_until_complete(task)
1795
+
1796
+ # ์‹ค์‹œ๊ฐ„ ์—…๋ฐ์ดํŠธ
1797
+ updated_history = current_history + [
1798
+ {"role": "assistant", "content": response}
1799
+ ]
1800
+ yield updated_history, thoughts, search_display
1801
+
1802
+ except StopAsyncIteration:
1803
+ break
1804
+
1805
+ except Exception as e:
1806
+ error_history = history + [
1807
+ {"role": "user", "content": message},
1808
+ {"role": "assistant", "content": f"โŒ Error: {str(e)}"}
1809
+ ]
1810
+ yield error_history, "", ""
1811
+ finally:
1812
+ # ๋ฃจํ”„ ์ •๋ฆฌ
1813
+ try:
1814
+ loop.close()
1815
+ except:
1816
+ pass
1817
+
1818
+ # Gradio ์ธํ„ฐํŽ˜์ด์Šค
1819
+ with gr.Blocks(
1820
+ title="โšก Speed-Optimized Multi-Agent System (No Cache)",
1821
+ theme=gr.themes.Soft(),
1822
+ css="""
1823
+ .gradio-container {
1824
+ max-width: 1400px !important;
1825
+ margin: auto !important;
1826
+ }
1827
+ """
1828
+ ) as demo:
1829
+ gr.Markdown("""
1830
+ # โšก Enhanced Multi-Agent RAG System (์บ์‹ฑ ์ œ๊ฑฐ ๋ฒ„์ „)
1831
+ **Complex questions processed within 5-8 seconds | Multi-language support**
1832
+
1833
+ **Optimization Features:**
1834
+ - ๐Ÿš€ Parallel Processing: Concurrent agent execution
1835
+ - โšก Stream Buffering: Network optimization
1836
+ - ๐ŸŽฏ Early Termination: Complete immediately when quality is met
1837
+ - ๐ŸŒ Multi-language: Auto-detect Korean/English/Japanese/Chinese
1838
+ - โŒ **Caching Disabled**: ์บ์‹ฑ ๊ธฐ๋Šฅ ์ œ๊ฑฐ๋จ
1839
+ """)
1840
+
1841
+ with gr.Row():
1842
+ with gr.Column(scale=3):
1843
+ chatbot = gr.Chatbot(
1844
+ height=500,
1845
+ label="๐Ÿ’ฌ Chat",
1846
+ type="messages"
1847
+ )
1848
+
1849
+ msg = gr.Textbox(
1850
+ label="Enter complex question",
1851
+ placeholder="Enter complex questions requiring analysis, strategy, or creative solutions...",
1852
+ lines=3
1853
+ )
1854
+
1855
+ with gr.Row():
1856
+ submit = gr.Button("โšก High-Speed Process", variant="primary")
1857
+ clear = gr.Button("๐Ÿ”„ Reset")
1858
+
1859
+ with gr.Accordion("๐Ÿค– Agent Processing", open=False):
1860
+ agent_thoughts = gr.Markdown()
1861
+
1862
+ with gr.Accordion("๐Ÿ“š Search Sources", open=False):
1863
+ search_sources = gr.Markdown()
1864
+
1865
+ with gr.Column(scale=1):
1866
+ gr.Markdown("**โš™๏ธ Settings**")
1867
+
1868
+ language_mode = gr.Radio(
1869
+ choices=["Auto", "Korean", "English", "Japanese", "Chinese"],
1870
+ value="Auto",
1871
+ label="๐ŸŒ Language Mode"
1872
+ )
1873
+
1874
+ use_search = gr.Checkbox(
1875
+ label="๐Ÿ” Use Web Search",
1876
+ value=True
1877
+ )
1878
+
1879
+ show_agent_thoughts = gr.Checkbox(
1880
+ label="๐Ÿง  Show Processing",
1881
+ value=True
1882
+ )
1883
+
1884
+ search_count = gr.Slider(
1885
+ minimum=3,
1886
+ maximum=10,
1887
+ value=5,
1888
+ step=1,
1889
+ label="Search Results Count"
1890
+ )
1891
+
1892
+ gr.Markdown("""
1893
+ **โšก Optimization Status**
1894
+
1895
+ **Active Optimizations:**
1896
+ - โœ… Parallel Processing
1897
+ - โŒ ~~Smart Caching~~ (์ œ๊ฑฐ๋จ)
1898
+ - โœ… Buffer Streaming
1899
+ - โœ… Early Termination
1900
+ - โœ… Compressed Prompts
1901
+ - โœ… Multi-language Support
1902
+ - โœ… Error Recovery
1903
+
1904
+ **Expected Processing Time:**
1905
+ - Simple Query: 3-5 seconds
1906
+ - Complex Query: 5-8 seconds
1907
+ - Very Complex: 8-12 seconds
1908
+ """)
1909
+
1910
+ # ๋ณต์žกํ•œ ์งˆ๋ฌธ ์˜ˆ์ œ (๋‹ค๊ตญ์–ด)
1911
+ gr.Examples(
1912
+ examples=[
1913
+ # Korean
1914
+ "AI ๊ธฐ์ˆ ์ด ํ–ฅํ›„ 10๋…„๊ฐ„ ํ•œ๊ตญ ๊ฒฝ์ œ์— ๋ฏธ์น  ์˜ํ–ฅ์„ ๋‹ค๊ฐ๋„๋กœ ๋ถ„์„ํ•˜๊ณ  ๋Œ€์‘ ์ „๋žต์„ ์ œ์‹œํ•ด์ค˜",
1915
+ "์Šคํƒ€ํŠธ์—…์ด ๋Œ€๊ธฐ์—…๊ณผ ๊ฒฝ์Ÿํ•˜๊ธฐ ์œ„ํ•œ ํ˜์‹ ์ ์ธ ์ „๋žต์„ ๋‹จ๊ณ„๋ณ„๋กœ ์ˆ˜๋ฆฝํ•ด์ค˜",
1916
+ # English
1917
+ "Analyze the multifaceted impact of quantum computing on current encryption systems and propose alternatives",
1918
+ "Design 5 innovative business models for climate change mitigation with practical implementation details",
1919
+ # Japanese
1920
+ "ใƒกใ‚ฟใƒใƒผใ‚นๆ™‚ไปฃใฎๆ•™่‚ฒ้ฉๆ–ฐๆ–นๆกˆใ‚’ๅฎŸ่ฃ…ๅฏ่ƒฝใชใƒฌใƒ™ใƒซใงๆๆกˆใ—ใฆใใ ใ•ใ„",
1921
+ # Chinese
1922
+ "ๅˆ†ๆžไบบๅทฅๆ™บ่ƒฝๅฏนๆœชๆฅๅๅนดๅ…จ็ƒ็ปๆตŽ็š„ๅฝฑๅ“ๅนถๆๅ‡บๅบ”ๅฏน็ญ–็•ฅ"
1923
+ ],
1924
+ inputs=msg
1925
+ )
1926
+
1927
+ # ์ด๋ฒคํŠธ ๋ฐ”์ธ๋”ฉ
1928
+ submit.click(
1929
+ process_query_optimized,
1930
+ inputs=[msg, chatbot, use_search, show_agent_thoughts, search_count, language_mode],
1931
+ outputs=[chatbot, agent_thoughts, search_sources]
1932
+ ).then(
1933
+ lambda: "",
1934
+ None,
1935
+ msg
1936
+ )
1937
+
1938
+ msg.submit(
1939
+ process_query_optimized,
1940
+ inputs=[msg, chatbot, use_search, show_agent_thoughts, search_count, language_mode],
1941
+ outputs=[chatbot, agent_thoughts, search_sources]
1942
+ ).then(
1943
+ lambda: "",
1944
+ None,
1945
+ msg
1946
+ )
1947
+
1948
+ clear.click(
1949
+ lambda: ([], "", ""),
1950
+ None,
1951
+ [chatbot, agent_thoughts, search_sources]
1952
+ )
1953
+
1954
+ return demo
1955
+
1956
+
1957
+ # ============================================================================
1958
+ # ๋ฉ”์ธ ์‹คํ–‰
1959
+ # ============================================================================
1960
+
1961
+ if __name__ == "__main__":
1962
+ print("""
1963
+ โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
1964
+ โ•‘ โšก Speed-Optimized Multi-Agent System (No Cache) โšก โ•‘
1965
+ โ•‘ โ•‘
1966
+ โ•‘ High-speed AI system processing complex questions โ•‘
1967
+ โ•‘ โ•‘
1968
+ โ•‘ Features: โ•‘
1969
+ โ•‘ โ€ข Multi-language support (KO/EN/JA/ZH) โ•‘
1970
+ โ•‘ โ€ข Improved error recovery โ•‘
1971
+ โ•‘ โ€ข NO CACHING (์บ์‹ฑ ๊ธฐ๋Šฅ ์ œ๊ฑฐ๋จ) โ•‘
1972
+ โ•‘ โ€ข Adaptive stream buffering โ•‘
1973
+ โ•‘ โ€ข Response cleaning & formatting โ•‘
1974
+ โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
1975
+ """)
1976
+
1977
+ # API ํ‚ค ํ™•์ธ
1978
+ if not os.getenv("FIREWORKS_API_KEY"):
1979
+ print("\nโš ๏ธ FIREWORKS_API_KEY is not set.")
1980
+
1981
+ if not os.getenv("BRAVE_SEARCH_API_KEY"):
1982
+ print("\nโš ๏ธ BRAVE_SEARCH_API_KEY is not set.")
1983
+
1984
+ # Gradio ์•ฑ ์‹คํ–‰
1985
+ demo = create_optimized_gradio_interface()
1986
+
1987
+ is_hf_spaces = os.getenv("SPACE_ID") is not None
1988
+
1989
+ if is_hf_spaces:
1990
+ print("\n๐Ÿค— Running in optimized mode on Hugging Face Spaces (No Cache)...")
1991
+ demo.launch(server_name="0.0.0.0", server_port=7860)
1992
+ else:
1993
+ print("\n๐Ÿ’ป Running in optimized mode on local environment (No Cache)...")
1994
+ demo.launch(server_name="0.0.0.0", server_port=7860, share=False), '', response, flags=re.MULTILINE)
1995
+
1996
  # ๋งˆํฌ๋‹ค์šด ํ—ค๋” ์ œ๊ฑฐ
1997
  response = re.sub(r'^#{1,6}\s+', '', response, flags=re.MULTILINE)
1998
 
1999
+ # ๋ณผ๋“œ ํ…์ŠคํŠธ ์ œ๊ฑฐ (**text** ๋˜๋Š” __text__)
2000
+ response = re.sub(r'\*\*(.*?)\*\*', r'\1', response)
2001
+ response = re.sub(r'__(.*?)__', r'\1', response)
2002
+
2003
+ # ์ดํƒค๋ฆญ ํ…์ŠคํŠธ ์ œ๊ฑฐ (*text* ๋˜๋Š” _text_)
2004
+ response = re.sub(r'\*(.*?)\*', r'\1', response)
2005
+ response = re.sub(r'_(.*?)_', r'\1', response)
2006
+
2007
+ # ์ฝ”๋“œ ๋ธ”๋ก ์ œ๊ฑฐ (```code```)
2008
+ response = re.sub(r'```[\s\S]*?```', '', response)
2009
+
2010
+ # ์ธ๋ผ์ธ ์ฝ”๋“œ ์ œ๊ฑฐ (`code`)
2011
+ response = re.sub(r'`([^`]*)`', r'\1', response)
2012
+
2013
+ # ๋ถˆํ•„์š”ํ•œ ๊ตฌ๋ถ„์„  ์ œ๊ฑฐ (---, ***, ___)
2014
+ response = re.sub(r'^[\*\-_]{3,}
2015
+
2016
+
2017
+ # ============================================================================
2018
+ # ํ†ตํ•ฉ ์ตœ์ ํ™” ๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ (์บ์‹ฑ ์ œ๊ฑฐ ๋ฒ„์ „)
2019
+ # ============================================================================
2020
+
2021
+ class SpeedOptimizedMultiAgentSystem:
2022
+ """์†๋„ ์ตœ์ ํ™”๋œ ๋ฉ€ํ‹ฐ ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ (์บ์‹ฑ ์—†์Œ)"""
2023
+
2024
+ def __init__(self):
2025
+ self.llm = OptimizedFireworksClient()
2026
+ self.search = AsyncBraveSearch()
2027
+ self.reasoning = LightweightReasoningChain()
2028
+ self.quality_checker = QualityChecker()
2029
+ self.streaming = OptimizedStreaming()
2030
+ self.language_detector = LanguageDetector()
2031
+ self.response_cleaner = ResponseCleaner()
2032
+
2033
+ # ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ ํ’€
2034
+ self.executor = ThreadPoolExecutor(max_workers=4)
2035
+
2036
+ def _init_compact_prompts(self, lang: str = 'ko') -> Dict:
2037
+ """์••์ถ•๋œ ๊ณ ํšจ์œจ ํ”„๋กฌํ”„ํŠธ (์–ธ์–ด๋ณ„)"""
2038
+ prompts = {
2039
+ 'ko': {
2040
+ AgentRole.SUPERVISOR: """[๊ฐ๋…์ž-๊ตฌ์กฐ์„ค๊ณ„]
2041
+ ์ฆ‰์‹œ๋ถ„์„: ํ•ต์‹ฌ์˜๋„+ํ•„์š”์ •๋ณด+๋‹ต๋ณ€๊ตฌ์กฐ
2042
+ ์ถœ๋ ฅ: 5๊ฐœ ํ•ต์‹ฌํฌ์ธํŠธ(๊ฐ 1๋ฌธ์žฅ)
2043
+ ์ถ”๋ก ์ฒด๊ณ„ ๋ช…์‹œ""",
2044
+
2045
+ AgentRole.CREATIVE: """[์ฐฝ์˜์„ฑ์ƒ์„ฑ์ž]
2046
+ ์ž…๋ ฅ๊ตฌ์กฐ ๋”ฐ๋ผ ์ฐฝ์˜์  ํ™•์žฅ
2047
+ ๏ฟฝ๏ฟฝ์šฉ์˜ˆ์‹œ+ํ˜์‹ ์ ‘๊ทผ+๊ตฌ์ฒด์กฐ์–ธ
2048
+ ๋ถˆํ•„์š”์„ค๋ช… ์ œ๊ฑฐ""",
2049
+
2050
+ AgentRole.CRITIC: """[๋น„ํ‰์ž-๊ฒ€์ฆ]
2051
+ ์‹ ์†๊ฒ€ํ† : ์ •ํ™•์„ฑ/๋…ผ๋ฆฌ์„ฑ/์‹ค์šฉ์„ฑ
2052
+ ๊ฐœ์„ ํฌ์ธํŠธ 3๊ฐœ๋งŒ
2053
+ ๊ฐ 2๋ฌธ์žฅ ์ด๋‚ด""",
2054
+
2055
+ AgentRole.FINALIZER: """[์ตœ์ข…ํ†ตํ•ฉ]
2056
+ ๋ชจ๋“ ์˜๊ฒฌ ์ข…ํ•ฉโ†’์ตœ์ ๋‹ต๋ณ€
2057
+ ๋ช…ํ™•๊ตฌ์กฐ+์‹ค์šฉ์ •๋ณด+์ฐฝ์˜๊ท ํ˜•
2058
+ ๋ฐ”๋กœ ํ•ต์‹ฌ ๋‚ด์šฉ๋ถ€ํ„ฐ ์‹œ์ž‘. ๋ถˆํ•„์š”ํ•œ ํ—ค๋”๋‚˜ ๋งˆํฌ์—… ์—†์ด. ๋งˆํฌ๋‹ค์šด ํ—ค๋”(#, ##, ###) ์‚ฌ์šฉ ๊ธˆ์ง€."""
2059
+ },
2060
+ 'en': {
2061
+ AgentRole.SUPERVISOR: """[Supervisor-Structure]
2062
+ Immediate analysis: core intent+required info+answer structure
2063
+ Output: 5 key points (1 sentence each)
2064
+ Clear reasoning framework""",
2065
+
2066
+ AgentRole.CREATIVE: """[Creative Generator]
2067
+ Follow structure, expand creatively
2068
+ Practical examples+innovative approach+specific advice
2069
+ Remove unnecessary explanations""",
2070
+
2071
+ AgentRole.CRITIC: """[Critic-Verification]
2072
+ Quick review: accuracy/logic/practicality
2073
+ Only 3 improvement points
2074
+ Max 2 sentences each""",
2075
+
2076
+ AgentRole.FINALIZER: """[Final Integration]
2077
+ Synthesize all inputsโ†’optimal answer
2078
+ Clear structure+practical info+creative balance
2079
+ Start with core content directly. No unnecessary headers or markup. No markdown headers (#, ##, ###)."""
2080
+ },
2081
+ 'ja': {
2082
+ AgentRole.SUPERVISOR: """[็›ฃ็ฃ่€…-ๆง‹้€ ่จญ่จˆ]
2083
+ ๅณๆ™‚ๅˆ†ๆž๏ผšๆ ธๅฟƒๆ„ๅ›ณ+ๅฟ…่ฆๆƒ…ๅ ฑ+ๅ›ž็ญ”ๆง‹้€ 
2084
+ ๅ‡บๅŠ›๏ผš5ใคใฎๆ ธๅฟƒใƒใ‚คใƒณใƒˆ๏ผˆๅ„1ๆ–‡๏ผ‰
2085
+ ๆŽจ่ซ–ไฝ“็ณปๆ˜Ž็คบ""",
2086
+
2087
+ AgentRole.CREATIVE: """[ๅ‰ต้€ ๆ€ง็”Ÿๆˆ่€…]
2088
+ ๅ…ฅๅŠ›ๆง‹้€ ใซๅพ“ใฃใฆๅ‰ต้€ ็š„ๆ‹กๅผต
2089
+ ๅฎŸ็”จไพ‹+้ฉๆ–ฐ็š„ใ‚ขใƒ—ใƒญใƒผใƒ+ๅ…ทไฝ“็š„ใ‚ขใƒ‰ใƒใ‚คใ‚น
2090
+ ไธ่ฆใช่ชฌๆ˜Žๅ‰Š้™ค""",
2091
+
2092
+ AgentRole.CRITIC: """[ๆ‰น่ฉ•่€…-ๆคœ่จผ]
2093
+ ่ฟ…้€Ÿใƒฌใƒ“ใƒฅใƒผ๏ผšๆญฃ็ขบๆ€ง/่ซ–็†ๆ€ง/ๅฎŸ็”จๆ€ง
2094
+ ๆ”นๅ–„ใƒใ‚คใƒณใƒˆ3ใคใฎใฟ
2095
+ ๅ„2ๆ–‡ไปฅๅ†…""",
2096
+
2097
+ AgentRole.FINALIZER: """[ๆœ€็ต‚็ตฑๅˆ]
2098
+ ๅ…จๆ„่ฆ‹็ตฑๅˆโ†’ๆœ€้ฉๅ›ž็ญ”
2099
+ ๆ˜Ž็ขบๆง‹้€ +ๅฎŸ็”จๆƒ…ๅ ฑ+ๅ‰ต้€ ๆ€งใƒใƒฉใƒณใ‚น
2100
+ ๆ ธๅฟƒๅ†…ๅฎนใ‹ใ‚‰็›ดๆŽฅ้–‹ๅง‹ใ€‚ไธ่ฆใชใƒ˜ใƒƒใƒ€ใƒผใ‚„ใƒžใƒผใ‚ฏใ‚ขใƒƒใƒ—ใชใ—ใ€‚ใƒžใƒผใ‚ฏใƒ€ใ‚ฆใƒณใƒ˜ใƒƒใƒ€ใƒผ๏ผˆ#ใ€##ใ€###๏ผ‰ไฝฟ็”จ็ฆๆญขใ€‚"""
2101
+ },
2102
+ 'zh': {
2103
+ AgentRole.SUPERVISOR: """[ไธป็ฎก-็ป“ๆž„่ฎพ่ฎก]
2104
+ ็ซ‹ๅณๅˆ†ๆž๏ผšๆ ธๅฟƒๆ„ๅ›พ+ๆ‰€้œ€ไฟกๆฏ+็ญ”ๆกˆ็ป“ๆž„
2105
+ ่พ“ๅ‡บ๏ผš5ไธชๆ ธๅฟƒ่ฆ็‚น๏ผˆๆฏไธช1ๅฅ๏ผ‰
2106
+ ๆŽจ็†ไฝ“็ณปๆ˜Ž็กฎ""",
2107
+
2108
+ AgentRole.CREATIVE: """[ๅˆ›ๆ„็”Ÿๆˆๅ™จ]
2109
+ ๆŒ‰็ป“ๆž„ๅˆ›้€ ๆ€งๆ‰ฉๅฑ•
2110
+ ๅฎž็”จ็คบไพ‹+ๅˆ›ๆ–ฐๆ–นๆณ•+ๅ…ทไฝ“ๅปบ่ฎฎ
2111
+ ๅˆ ้™คไธๅฟ…่ฆ็š„่งฃ้‡Š""",
2112
+
2113
+ AgentRole.CRITIC: """[่ฏ„่ฎบๅฎถ-้ชŒ่ฏ]
2114
+ ๅฟซ้€ŸๅฎกๆŸฅ๏ผšๅ‡†็กฎๆ€ง/้€ป่พ‘ๆ€ง/ๅฎž็”จๆ€ง
2115
+ ไป…3ไธชๆ”น่ฟ›็‚น
2116
+ ๆฏไธชๆœ€ๅคš2ๅฅ""",
2117
+
2118
+ AgentRole.FINALIZER: """[ๆœ€็ปˆๆ•ดๅˆ]
2119
+ ็ปผๅˆๆ‰€ๆœ‰ๆ„่งโ†’ๆœ€ไฝณ็ญ”ๆกˆ
2120
+ ๆธ…ๆ™ฐ็ป“ๆž„+ๅฎž็”จไฟกๆฏ+ๅˆ›ๆ„ๅนณ่กก
2121
+ ็›ดๆŽฅไปŽๆ ธๅฟƒๅ†…ๅฎนๅผ€ๅง‹ใ€‚ๆ— ้œ€ไธๅฟ…่ฆ็š„ๆ ‡้ข˜ๆˆ–ๆ ‡่ฎฐใ€‚็ฆๆญขไฝฟ็”จMarkdownๆ ‡้ข˜๏ผˆ#ใ€##ใ€###๏ผ‰ใ€‚"""
2122
+ }
2123
+ }
2124
+
2125
+ return prompts.get(lang, prompts['en'])
2126
+
2127
+ async def parallel_process_agents(
2128
+ self,
2129
+ query: str,
2130
+ search_results: List[Dict],
2131
+ show_progress: bool = True,
2132
+ lang: str = None
2133
+ ) -> AsyncGenerator[Tuple[str, str], None]:
2134
+ """๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ ํŒŒ์ดํ”„๋ผ์ธ (์บ์‹ฑ ์—†์Œ)"""
2135
+
2136
+ start_time = time.time()
2137
+
2138
+ # ์–ธ์–ด ์ž๋™ ๊ฐ์ง€
2139
+ if lang is None:
2140
+ lang = self.language_detector.detect_language(query)
2141
+
2142
+ # ์–ธ์–ด๋ณ„ ํ”„๋กฌํ”„ํŠธ ์„ค์ •
2143
+ self.compact_prompts = self._init_compact_prompts(lang)
2144
+
2145
+ search_context = self._format_search_results(search_results)
2146
+ accumulated_response = ""
2147
+ agent_thoughts = ""
2148
+
2149
+ # ์ถ”๋ก  ํŒจํ„ด ๊ฒฐ์ •
2150
+ reasoning_pattern = self.reasoning.get_reasoning_pattern(query, lang)
2151
+
2152
+ try:
2153
+ # === 1๋‹จ๊ณ„: ๊ฐ๋…์ž + ๊ฒ€์ƒ‰ ๋ณ‘๋ ฌ ์‹คํ–‰ ===
2154
+ if show_progress:
2155
+ progress_msg = {
2156
+ 'ko': "๐Ÿš€ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ ์‹œ์ž‘\n๐Ÿ‘” ๊ฐ๋…์ž ๋ถ„์„ + ๐Ÿ” ์ถ”๊ฐ€ ๊ฒ€์ƒ‰ ๋™์‹œ ์ง„ํ–‰...\n\n",
2157
+ 'en': "๐Ÿš€ Starting parallel processing\n๐Ÿ‘” Supervisor analysis + ๐Ÿ” Additional search in progress...\n\n",
2158
+ 'ja': "๐Ÿš€ ไธฆๅˆ—ๅ‡ฆ็†้–‹ๅง‹\n๐Ÿ‘” ็›ฃ็ฃ่€…ๅˆ†ๆž + ๐Ÿ” ่ฟฝๅŠ ๆคœ็ดขๅŒๆ™‚้€ฒ่กŒไธญ...\n\n",
2159
+ 'zh': "๐Ÿš€ ๅผ€ๅง‹ๅนถ่กŒๅค„็†\n๐Ÿ‘” ไธป็ฎกๅˆ†ๆž + ๐Ÿ” ้™„ๅŠ ๆœ็ดขๅŒๆ—ถ่ฟ›่กŒ...\n\n"
2160
+ }
2161
+ agent_thoughts = progress_msg.get(lang, progress_msg['en'])
2162
+ yield accumulated_response, agent_thoughts
2163
+
2164
+ # ๊ฐ๋…์ž ํ”„๋กฌํ”„ํŠธ (์–ธ์–ด๋ณ„)
2165
+ supervisor_prompt_templates = {
2166
+ 'ko': f"""
2167
+ ์งˆ๋ฌธ: {query}
2168
+ ๊ฒ€์ƒ‰๊ฒฐ๊ณผ: {search_context}
2169
+ ์ถ”๋ก ํŒจํ„ด: {reasoning_pattern}
2170
+ ์ฆ‰์‹œ ํ•ต์‹ฌ๊ตฌ๏ฟฝ๏ฟฝ๏ฟฝ 5๊ฐœ ์ œ์‹œ""",
2171
+ 'en': f"""
2172
+ Question: {query}
2173
+ Search results: {search_context}
2174
+ Reasoning pattern: {reasoning_pattern}
2175
+ Immediately provide 5 key structures""",
2176
+ 'ja': f"""
2177
+ ่ณชๅ•: {query}
2178
+ ๆคœ็ดข็ตๆžœ: {search_context}
2179
+ ๆŽจ่ซ–ใƒ‘ใ‚ฟใƒผใƒณ: {reasoning_pattern}
2180
+ ๅณๅบงใซ5ใคใฎๆ ธๅฟƒๆง‹้€ ใ‚’ๆ็คบ""",
2181
+ 'zh': f"""
2182
+ ้—ฎ้ข˜: {query}
2183
+ ๆœ็ดข็ป“ๆžœ: {search_context}
2184
+ ๆŽจ็†ๆจกๅผ: {reasoning_pattern}
2185
+ ็ซ‹ๅณๆไพ›5ไธชๆ ธๅฟƒ็ป“ๆž„"""
2186
+ }
2187
+
2188
+ supervisor_prompt = supervisor_prompt_templates.get(lang, supervisor_prompt_templates['en'])
2189
+
2190
+ supervisor_response = ""
2191
+ supervisor_task = self.llm.chat_stream_async(
2192
+ messages=[
2193
+ {"role": "system", "content": self.compact_prompts[AgentRole.SUPERVISOR]},
2194
+ {"role": "user", "content": supervisor_prompt}
2195
+ ],
2196
+ temperature=0.3,
2197
+ max_tokens=500
2198
+ )
2199
+
2200
+ # ๊ฐ๋…์ž ์ŠคํŠธ๋ฆฌ๋ฐ (๋ฒ„ํผ๋ง)
2201
+ async for chunk in self.streaming.buffer_and_yield(supervisor_task):
2202
+ supervisor_response += chunk
2203
+ if show_progress and len(supervisor_response) < 300:
2204
+ supervisor_label = {
2205
+ 'ko': "๐Ÿ‘” ๊ฐ๋…์ž ๋ถ„์„",
2206
+ 'en': "๐Ÿ‘” Supervisor Analysis",
2207
+ 'ja': "๐Ÿ‘” ็›ฃ็ฃ่€…ๅˆ†ๆž",
2208
+ 'zh': "๐Ÿ‘” ไธป็ฎกๅˆ†ๆž"
2209
+ }
2210
+ agent_thoughts = f"{supervisor_label.get(lang, supervisor_label['en'])}\n{supervisor_response[:300]}...\n\n"
2211
+ yield accumulated_response, agent_thoughts
2212
+
2213
+ # === 2๋‹จ๊ณ„: ์ฐฝ์˜์„ฑ + ๋น„ํ‰ ์ค€๋น„ ๋ณ‘๋ ฌ ===
2214
+ if show_progress:
2215
+ creative_msg = {
2216
+ 'ko': "๐ŸŽจ ์ฐฝ์˜์„ฑ ์ƒ์„ฑ์ž + ๐Ÿ” ๋น„ํ‰์ž ์ค€๋น„...\n\n",
2217
+ 'en': "๐ŸŽจ Creative Generator + ๐Ÿ” Critic preparing...\n\n",
2218
+ 'ja': "๐ŸŽจ ๅ‰ต้€ ๆ€ง็”Ÿๆˆ่€… + ๐Ÿ” ๆ‰น่ฉ•่€…ๆบ–ๅ‚™ไธญ...\n\n",
2219
+ 'zh': "๐ŸŽจ ๅˆ›ๆ„็”Ÿๆˆๅ™จ + ๐Ÿ” ่ฏ„่ฎบๅฎถๅ‡†ๅค‡ไธญ...\n\n"
2220
+ }
2221
+ agent_thoughts += creative_msg.get(lang, creative_msg['en'])
2222
+ yield accumulated_response, agent_thoughts
2223
+
2224
+ # ์ฐฝ์˜์„ฑ ์ƒ์„ฑ ์‹œ์ž‘ (์–ธ์–ด๋ณ„)
2225
+ creative_prompt_templates = {
2226
+ 'ko': f"""
2227
+ ์งˆ๋ฌธ: {query}
2228
+ ๊ฐ๋…์ž๊ตฌ์กฐ: {supervisor_response}
2229
+ ๊ฒ€์ƒ‰๊ฒฐ๊ณผ: {search_context}
2230
+ ์ฐฝ์˜์ +์‹ค์šฉ์  ๋‹ต๋ณ€ ์ฆ‰์‹œ์ƒ์„ฑ""",
2231
+ 'en': f"""
2232
+ Question: {query}
2233
+ Supervisor structure: {supervisor_response}
2234
+ Search results: {search_context}
2235
+ Generate creative+practical answer immediately""",
2236
+ 'ja': f"""
2237
+ ่ณชๅ•: {query}
2238
+ ็›ฃ็ฃ่€…ๆง‹้€ : {supervisor_response}
2239
+ ๆคœ็ดข็ตๆžœ: {search_context}
2240
+ ๅ‰ต้€ ็š„+ๅฎŸ็”จ็š„ๅ›ž็ญ”ๅณๅบง็”Ÿๆˆ""",
2241
+ 'zh': f"""
2242
+ ้—ฎ้ข˜: {query}
2243
+ ไธป็ฎก็ป“ๆž„: {supervisor_response}
2244
+ ๆœ็ดข็ป“ๆžœ: {search_context}
2245
+ ็ซ‹ๅณ็”Ÿๆˆๅˆ›ๆ„+ๅฎž็”จ็ญ”ๆกˆ"""
2246
+ }
2247
+
2248
+ creative_prompt = creative_prompt_templates.get(lang, creative_prompt_templates['en'])
2249
+
2250
+ creative_response = ""
2251
+ creative_partial = ""
2252
+ critic_started = False
2253
+ critic_response = ""
2254
+
2255
+ creative_task = self.llm.chat_stream_async(
2256
+ messages=[
2257
+ {"role": "system", "content": self.compact_prompts[AgentRole.CREATIVE]},
2258
+ {"role": "user", "content": creative_prompt}
2259
+ ],
2260
+ temperature=0.8,
2261
+ max_tokens=1500
2262
+ )
2263
+
2264
+ # ์ฐฝ์˜์„ฑ ์ŠคํŠธ๋ฆฌ๋ฐ + ๋น„ํ‰์ž ์กฐ๊ธฐ ์‹œ์ž‘
2265
+ async for chunk in self.streaming.buffer_and_yield(creative_task):
2266
+ creative_response += chunk
2267
+ creative_partial += chunk
2268
+
2269
+ # ์ฐฝ์˜์„ฑ ์‘๋‹ต์ด 500์ž ๋„˜์œผ๋ฉด ๋น„ํ‰์ž ์‹œ์ž‘
2270
+ if len(creative_partial) > 500 and not critic_started:
2271
+ critic_started = True
2272
+
2273
+ # ๋น„ํ‰์ž ๋น„๋™๊ธฐ ์‹œ์ž‘ (์–ธ์–ด๋ณ„)
2274
+ critic_prompt_templates = {
2275
+ 'ko': f"""
2276
+ ์›๋ณธ์งˆ๋ฌธ: {query}
2277
+ ์ฐฝ์˜์„ฑ๋‹ต๋ณ€(์ผ๋ถ€): {creative_partial}
2278
+ ์‹ ์†๊ฒ€ํ† โ†’๊ฐœ์„ ์ 3๊ฐœ""",
2279
+ 'en': f"""
2280
+ Original question: {query}
2281
+ Creative answer (partial): {creative_partial}
2282
+ Quick reviewโ†’3 improvements""",
2283
+ 'ja': f"""
2284
+ ๅ…ƒใฎ่ณชๅ•: {query}
2285
+ ๅ‰ต้€ ็š„ๅ›ž็ญ”๏ผˆไธ€้ƒจ๏ผ‰: {creative_partial}
2286
+ ่ฟ…้€Ÿใƒฌใƒ“ใƒฅใƒผโ†’ๆ”นๅ–„็‚น3ใค""",
2287
+ 'zh': f"""
2288
+ ๅŽŸๅง‹้—ฎ้ข˜: {query}
2289
+ ๅˆ›ๆ„็ญ”ๆกˆ๏ผˆ้ƒจๅˆ†๏ผ‰: {creative_partial}
2290
+ ๅฟซ้€ŸๅฎกๆŸฅโ†’3ไธชๆ”น่ฟ›็‚น"""
2291
+ }
2292
+
2293
+ critic_prompt = critic_prompt_templates.get(lang, critic_prompt_templates['en'])
2294
+
2295
+ critic_task = asyncio.create_task(
2296
+ self._run_critic_async(critic_prompt)
2297
+ )
2298
+
2299
+ if show_progress:
2300
+ display_creative = creative_response[:400] + "..." if len(creative_response) > 400 else creative_response
2301
+ creative_label = {
2302
+ 'ko': "๐ŸŽจ ์ฐฝ์˜์„ฑ ์ƒ์„ฑ์ž",
2303
+ 'en': "๐ŸŽจ Creative Generator",
2304
+ 'ja': "๐ŸŽจ ๅ‰ต้€ ๆ€ง็”Ÿๆˆ่€…",
2305
+ 'zh': "๐ŸŽจ ๅˆ›ๆ„็”Ÿๆˆๅ™จ"
2306
+ }
2307
+ agent_thoughts = f"{creative_label.get(lang, creative_label['en'])}\n{display_creative}\n\n"
2308
+ yield accumulated_response, agent_thoughts
2309
+
2310
+ # ๋น„ํ‰์ž ๊ฒฐ๊ณผ ๋Œ€๊ธฐ
2311
+ if critic_started:
2312
+ critic_response = await critic_task
2313
+
2314
+ if show_progress:
2315
+ critic_label = {
2316
+ 'ko': "๐Ÿ” ๋น„ํ‰์ž ๊ฒ€ํ† ",
2317
+ 'en': "๐Ÿ” Critic Review",
2318
+ 'ja': "๐Ÿ” ๆ‰น่ฉ•่€…ใƒฌใƒ“ใƒฅใƒผ",
2319
+ 'zh': "๐Ÿ” ่ฏ„่ฎบๅฎถๅฎกๆŸฅ"
2320
+ }
2321
+ agent_thoughts += f"{critic_label.get(lang, critic_label['en'])}\n{critic_response[:200]}...\n\n"
2322
+ yield accumulated_response, agent_thoughts
2323
+
2324
+ # === 3๋‹จ๊ณ„: ํ’ˆ์งˆ ์ฒดํฌ ๋ฐ ์กฐ๊ธฐ ์ข…๋ฃŒ ===
2325
+ quality_score, need_more = self.quality_checker.evaluate_response(
2326
+ creative_response, query, lang
2327
+ )
2328
+
2329
+ if not need_more and quality_score > 0.85:
2330
+ # ํ’ˆ์งˆ์ด ์ถฉ๋ถ„ํžˆ ๋†’์œผ๋ฉด ๋ฐ”๋กœ ๋ฐ˜ํ™˜
2331
+ accumulated_response = self.response_cleaner.clean_response(creative_response)
2332
+
2333
+ if show_progress:
2334
+ quality_msg = {
2335
+ 'ko': f"โœ… ํ’ˆ์งˆ ์ถฉ์กฑ (์ ์ˆ˜: {quality_score:.2f})\n์กฐ๊ธฐ ์™„๋ฃŒ!\n",
2336
+ 'en': f"โœ… Quality met (score: {quality_score:.2f})\nEarly completion!\n",
2337
+ 'ja': f"โœ… ๅ“่ณชๆบ€่ถณ (ใ‚นใ‚ณใ‚ข: {quality_score:.2f})\nๆ—ฉๆœŸๅฎŒไบ†!\n",
2338
+ 'zh': f"โœ… ่ดจ้‡ๆปก่ถณ (ๅˆ†ๆ•ฐ: {quality_score:.2f})\nๆๅ‰ๅฎŒๆˆ!\n"
2339
+ }
2340
+ agent_thoughts += quality_msg.get(lang, quality_msg['en'])
2341
+
2342
+ yield accumulated_response, agent_thoughts
2343
+ return
2344
+
2345
+ # === 4๋‹จ๊ณ„: ์ตœ์ข… ํ†ตํ•ฉ (์ŠคํŠธ๋ฆฌ๋ฐ) ===
2346
+ if show_progress:
2347
+ final_msg = {
2348
+ 'ko': "โœ… ์ตœ์ข… ํ†ตํ•ฉ ์ค‘...\n\n",
2349
+ 'en': "โœ… Final integration in progress...\n\n",
2350
+ 'ja': "โœ… ๆœ€็ต‚็ตฑๅˆไธญ...\n\n",
2351
+ 'zh': "โœ… ๆœ€็ปˆๆ•ดๅˆไธญ...\n\n"
2352
+ }
2353
+ agent_thoughts += final_msg.get(lang, final_msg['en'])
2354
+ yield accumulated_response, agent_thoughts
2355
+
2356
+ # ์ตœ์ข… ํ”„๋กฌํ”„ํŠธ (์–ธ์–ด๋ณ„)
2357
+ final_prompt_templates = {
2358
+ 'ko': f"""
2359
+ ์งˆ๋ฌธ: {query}
2360
+ ์ฐฝ์˜์„ฑ๋‹ต๋ณ€: {creative_response}
2361
+ ๋น„ํ‰ํ”ผ๋“œ๋ฐฑ: {critic_response}
2362
+ ๊ฐ๋…์ž๊ตฌ์กฐ: {supervisor_response}
2363
+ ์ตœ์ข…ํ†ตํ•ฉโ†’์™„๋ฒฝ๋‹ต๋ณ€. ๋งˆํฌ๋‹ค์šด ํ—ค๋”(#, ##, ###) ์‚ฌ์šฉ ๊ธˆ์ง€.""",
2364
+ 'en': f"""
2365
+ Question: {query}
2366
+ Creative answer: {creative_response}
2367
+ Critic feedback: {critic_response}
2368
+ Supervisor structure: {supervisor_response}
2369
+ Final integrationโ†’perfect answer. No markdown headers (#, ##, ###).""",
2370
+ 'ja': f"""
2371
+ ่ณชๅ•: {query}
2372
+ ๅ‰ต้€ ็š„ๅ›ž็ญ”: {creative_response}
2373
+ ๆ‰น่ฉ•ใƒ•ใ‚ฃใƒผใƒ‰ใƒใƒƒใ‚ฏ: {critic_response}
2374
+ ็›ฃ็ฃ่€…ๆง‹้€ : {supervisor_response}
2375
+ ๆœ€็ต‚็ตฑๅˆโ†’ๅฎŒ็’งใชๅ›ž็ญ”ใ€‚ใƒžใƒผใ‚ฏใƒ€ใ‚ฆใƒณใƒ˜ใƒƒใƒ€ใƒผ๏ผˆ#ใ€##ใ€###๏ผ‰ไฝฟ็”จ็ฆๆญขใ€‚""",
2376
+ 'zh': f"""
2377
+ ้—ฎ้ข˜: {query}
2378
+ ๅˆ›ๆ„็ญ”ๆกˆ: {creative_response}
2379
+ ่ฏ„่ฎบๅ้ฆˆ: {critic_response}
2380
+ ไธป็ฎก็ป“ๆž„: {supervisor_response}
2381
+ ๆœ€็ปˆๆ•ดๅˆโ†’ๅฎŒ็พŽ็ญ”ๆกˆใ€‚็ฆๆญขไฝฟ็”จMarkdownๆ ‡้ข˜๏ผˆ#ใ€##ใ€###๏ผ‰ใ€‚"""
2382
+ }
2383
+
2384
+ final_prompt = final_prompt_templates.get(lang, final_prompt_templates['en'])
2385
+
2386
+ final_task = self.llm.chat_stream_async(
2387
+ messages=[
2388
+ {"role": "system", "content": self.compact_prompts[AgentRole.FINALIZER]},
2389
+ {"role": "user", "content": final_prompt}
2390
+ ],
2391
+ temperature=0.5,
2392
+ max_tokens=2500
2393
+ )
2394
+
2395
+ # ์ตœ์ข… ๋‹ต๋ณ€ ์ŠคํŠธ๋ฆฌ๋ฐ
2396
+ accumulated_response = ""
2397
+
2398
+ async for chunk in final_task:
2399
+ accumulated_response += chunk
2400
+ # ์‹ค์‹œ๊ฐ„ ์ •๋ฆฌ
2401
+ cleaned_response = self.response_cleaner.clean_response(accumulated_response)
2402
+ yield cleaned_response, agent_thoughts
2403
+
2404
+ # ์ตœ์ข… ์ •๋ฆฌ
2405
+ accumulated_response = self.response_cleaner.clean_response(accumulated_response)
2406
+
2407
+ # ์ฒ˜๋ฆฌ ์‹œ๊ฐ„ ์ถ”๊ฐ€ (์–ธ์–ด๋ณ„)
2408
+ processing_time = time.time() - start_time
2409
+ time_msg = {
2410
+ 'ko': f"\n\n---\nโšก ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: {processing_time:.1f}์ดˆ",
2411
+ 'en': f"\n\n---\nโšก Processing time: {processing_time:.1f} seconds",
2412
+ 'ja': f"\n\n---\nโšก ๅ‡ฆ็†ๆ™‚้–“: {processing_time:.1f}็ง’",
2413
+ 'zh': f"\n\n---\nโšก ๅค„็†ๆ—ถ้—ด: {processing_time:.1f}็ง’"
2414
+ }
2415
+ accumulated_response += time_msg.get(lang, time_msg['en'])
2416
+
2417
+ yield accumulated_response, agent_thoughts
2418
+
2419
+ except Exception as e:
2420
+ error_msg = {
2421
+ 'ko': f"โŒ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}",
2422
+ 'en': f"โŒ Error occurred: {str(e)}",
2423
+ 'ja': f"โŒ ใ‚จใƒฉใƒผ็™บ็”Ÿ: {str(e)}",
2424
+ 'zh': f"โŒ ๅ‘็”Ÿ้”™่ฏฏ: {str(e)}"
2425
+ }
2426
+ yield error_msg.get(lang, error_msg['en']), agent_thoughts
2427
+
2428
+ async def _run_critic_async(self, prompt: str) -> str:
2429
+ """๋น„ํ‰์ž ๋น„๋™๊ธฐ ์‹คํ–‰ with error handling"""
2430
+ try:
2431
+ response = ""
2432
+ async for chunk in self.llm.chat_stream_async(
2433
+ messages=[
2434
+ {"role": "system", "content": self.compact_prompts[AgentRole.CRITIC]},
2435
+ {"role": "user", "content": prompt}
2436
+ ],
2437
+ temperature=0.2,
2438
+ max_tokens=500
2439
+ ):
2440
+ response += chunk
2441
+ return response
2442
+ except Exception as e:
2443
+ # ์–ธ์–ด ๊ฐ์ง€
2444
+ lang = 'ko' if '์งˆ๋ฌธ' in prompt else 'en'
2445
+ error_msg = {
2446
+ 'ko': "๋น„ํ‰ ์ฒ˜๋ฆฌ ์ค‘ ์˜ค๋ฅ˜",
2447
+ 'en': "Error during critic processing",
2448
+ 'ja': "ๆ‰น่ฉ•ๅ‡ฆ็†ไธญใฎใ‚จใƒฉใƒผ",
2449
+ 'zh': "่ฏ„่ฎบๅค„็†ไธญๅ‡บ้”™"
2450
+ }
2451
+ return error_msg.get(lang, error_msg['en'])
2452
+
2453
+ def _format_search_results(self, results: List[Dict]) -> str:
2454
+ """๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ์••์ถ• ํฌ๋งท"""
2455
+ if not results:
2456
+ return "No search results"
2457
+
2458
+ formatted = []
2459
+ for i, r in enumerate(results[:3], 1):
2460
+ title = r.get('title', '')[:50]
2461
+ desc = r.get('description', '')[:100]
2462
+ formatted.append(f"[{i}]{title}:{desc}")
2463
+
2464
+ return " | ".join(formatted)
2465
+
2466
+
2467
+ # ============================================================================
2468
+ # Gradio UI (์ตœ์ ํ™” ๋ฒ„์ „ - ์บ์‹ฑ ์ œ๊ฑฐ)
2469
+ # ============================================================================
2470
+
2471
+ def create_optimized_gradio_interface():
2472
+ """์ตœ์ ํ™”๋œ Gradio ์ธํ„ฐํŽ˜์ด์Šค (์บ์‹ฑ ์—†์Œ)"""
2473
+
2474
+ # ์‹œ์Šคํ…œ ์ดˆ๊ธฐํ™”
2475
+ system = SpeedOptimizedMultiAgentSystem()
2476
+
2477
+ def process_query_optimized(
2478
+ message: str,
2479
+ history: List[Dict],
2480
+ use_search: bool,
2481
+ show_agent_thoughts: bool,
2482
+ search_count: int,
2483
+ language_mode: str
2484
+ ):
2485
+ """์ตœ์ ํ™”๋œ ์ฟผ๋ฆฌ ์ฒ˜๋ฆฌ - ์‹ค์‹œ๊ฐ„ ์ŠคํŠธ๋ฆฌ๋ฐ ๋ฒ„์ „"""
2486
+
2487
+ if not message:
2488
+ yield history, "", ""
2489
+ return
2490
+
2491
+ # ์–ธ์–ด ์„ค์ •
2492
+ if language_mode == "Auto":
2493
+ lang = None # ์ž๋™ ๊ฐ์ง€
2494
+ else:
2495
+ lang_map = {"Korean": "ko", "English": "en", "Japanese": "ja", "Chinese": "zh"}
2496
+ lang = lang_map.get(language_mode, None)
2497
+
2498
+ # ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋ฅผ ๋™๊ธฐ์ ์œผ๋กœ ์‹คํ–‰
2499
+ try:
2500
+ import nest_asyncio
2501
+ nest_asyncio.apply()
2502
+ except ImportError:
2503
+ pass
2504
+
2505
+ try:
2506
+ # ๊ฒ€์ƒ‰ ์ˆ˜ํ–‰ (๋™๊ธฐํ™”)
2507
+ search_results = []
2508
+ search_display = ""
2509
+
2510
+ # ์–ธ์–ด ์ž๋™ ๊ฐ์ง€ (ํ•„์š”ํ•œ ๊ฒฝ์šฐ)
2511
+ detected_lang = lang or system.language_detector.detect_language(message)
2512
+
2513
+ if use_search:
2514
+ # ๊ฒ€์ƒ‰ ์ƒํƒœ ํ‘œ์‹œ
2515
+ processing_msg = {
2516
+ 'ko': "โšก ๊ณ ์† ์ฒ˜๋ฆฌ ์ค‘...",
2517
+ 'en': "โšก High-speed processing...",
2518
+ 'ja': "โšก ้ซ˜้€Ÿๅ‡ฆ็†ไธญ...",
2519
+ 'zh': "โšก ้ซ˜้€Ÿๅค„็†ไธญ..."
2520
+ }
2521
+ history_with_message = history + [
2522
+ {"role": "user", "content": message},
2523
+ {"role": "assistant", "content": processing_msg.get(detected_lang, processing_msg['en'])}
2524
+ ]
2525
+ yield history_with_message, "", ""
2526
+
2527
+ # ๋น„๋™๊ธฐ ๊ฒ€์ƒ‰์„ ๋™๊ธฐ์ ์œผ๋กœ ์‹คํ–‰
2528
+ async def search_wrapper():
2529
+ return await system.search.search_async(message, count=search_count, lang=detected_lang)
2530
+
2531
+ loop = asyncio.new_event_loop()
2532
+ asyncio.set_event_loop(loop)
2533
+ search_results = loop.run_until_complete(search_wrapper())
2534
+
2535
+ if search_results:
2536
+ ref_label = {
2537
+ 'ko': "๐Ÿ“š ์ฐธ๊ณ  ์ž๋ฃŒ",
2538
+ 'en': "๐Ÿ“š References",
2539
+ 'ja': "๐Ÿ“š ๅ‚่€ƒ่ณ‡ๆ–™",
2540
+ 'zh': "๐Ÿ“š ๅ‚่€ƒ่ต„ๆ–™"
2541
+ }
2542
+ search_display = f"{ref_label.get(detected_lang, ref_label['en'])}\n\n"
2543
+ for i, result in enumerate(search_results[:3], 1):
2544
+ search_display += f"**{i}. [{result['title'][:50]}]({result['url']})**\n"
2545
+ search_display += f" {result['description'][:100]}...\n\n"
2546
+
2547
+ # ์‚ฌ์šฉ์ž ๋ฉ”์‹œ์ง€ ์ถ”๊ฐ€
2548
+ current_history = history + [{"role": "user", "content": message}]
2549
+
2550
+ # ์‹ค์‹œ๊ฐ„ ์ŠคํŠธ๋ฆฌ๋ฐ์„ ์œ„ํ•œ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ
2551
+ async def stream_responses():
2552
+ """์‹ค์‹œ๊ฐ„ ์ŠคํŠธ๋ฆฌ๋ฐ ์ œ๋„ˆ๋ ˆ์ดํ„ฐ"""
2553
+ async for response, thoughts in system.parallel_process_agents(
2554
+ query=message,
2555
+ search_results=search_results,
2556
+ show_progress=show_agent_thoughts,
2557
+ lang=detected_lang
2558
+ ):
2559
+ yield response, thoughts
2560
+
2561
+ # ์ƒˆ ์ด๋ฒคํŠธ ๋ฃจํ”„์—์„œ ์‹ค์‹œ๊ฐ„ ์ŠคํŠธ๋ฆฌ๋ฐ
2562
+ loop = asyncio.new_event_loop()
2563
+ asyncio.set_event_loop(loop)
2564
+
2565
+ # ๋น„๋™๊ธฐ ์ œ๋„ˆ๋ ˆ์ดํ„ฐ๋ฅผ ๋™๊ธฐ์ ์œผ๋กœ ์ˆœํšŒ
2566
+ gen = stream_responses()
2567
+
2568
+ while True:
2569
+ try:
2570
+ # ๋‹ค์Œ ํ•ญ๋ชฉ ๊ฐ€์ ธ์˜ค๊ธฐ
2571
+ task = asyncio.ensure_future(gen.__anext__(), loop=loop)
2572
+ response, thoughts = loop.run_until_complete(task)
2573
+
2574
+ # ์‹ค์‹œ๊ฐ„ ์—…๋ฐ์ดํŠธ
2575
+ updated_history = current_history + [
2576
+ {"role": "assistant", "content": response}
2577
+ ]
2578
+ yield updated_history, thoughts, search_display
2579
+
2580
+ except StopAsyncIteration:
2581
+ break
2582
+
2583
+ except Exception as e:
2584
+ error_history = history + [
2585
+ {"role": "user", "content": message},
2586
+ {"role": "assistant", "content": f"โŒ Error: {str(e)}"}
2587
+ ]
2588
+ yield error_history, "", ""
2589
+ finally:
2590
+ # ๋ฃจํ”„ ์ •๋ฆฌ
2591
+ try:
2592
+ loop.close()
2593
+ except:
2594
+ pass
2595
+
2596
+ # Gradio ์ธํ„ฐํŽ˜์ด์Šค
2597
+ with gr.Blocks(
2598
+ title="โšก Speed-Optimized Multi-Agent System (No Cache)",
2599
+ theme=gr.themes.Soft(),
2600
+ css="""
2601
+ .gradio-container {
2602
+ max-width: 1400px !important;
2603
+ margin: auto !important;
2604
+ }
2605
+ """
2606
+ ) as demo:
2607
+ gr.Markdown("""
2608
+ # โšก Enhanced Multi-Agent RAG System (์บ์‹ฑ ์ œ๊ฑฐ ๋ฒ„์ „)
2609
+ **Complex questions processed within 5-8 seconds | Multi-language support**
2610
+
2611
+ **Optimization Features:**
2612
+ - ๐Ÿš€ Parallel Processing: Concurrent agent execution
2613
+ - โšก Stream Buffering: Network optimization
2614
+ - ๐ŸŽฏ Early Termination: Complete immediately when quality is met
2615
+ - ๐ŸŒ Multi-language: Auto-detect Korean/English/Japanese/Chinese
2616
+ - โŒ **Caching Disabled**: ์บ์‹ฑ ๊ธฐ๋Šฅ ์ œ๊ฑฐ๋จ
2617
+ """)
2618
+
2619
+ with gr.Row():
2620
+ with gr.Column(scale=3):
2621
+ chatbot = gr.Chatbot(
2622
+ height=500,
2623
+ label="๐Ÿ’ฌ Chat",
2624
+ type="messages"
2625
+ )
2626
+
2627
+ msg = gr.Textbox(
2628
+ label="Enter complex question",
2629
+ placeholder="Enter complex questions requiring analysis, strategy, or creative solutions...",
2630
+ lines=3
2631
+ )
2632
+
2633
+ with gr.Row():
2634
+ submit = gr.Button("โšก High-Speed Process", variant="primary")
2635
+ clear = gr.Button("๐Ÿ”„ Reset")
2636
+
2637
+ with gr.Accordion("๐Ÿค– Agent Processing", open=False):
2638
+ agent_thoughts = gr.Markdown()
2639
+
2640
+ with gr.Accordion("๐Ÿ“š Search Sources", open=False):
2641
+ search_sources = gr.Markdown()
2642
+
2643
+ with gr.Column(scale=1):
2644
+ gr.Markdown("**โš™๏ธ Settings**")
2645
+
2646
+ language_mode = gr.Radio(
2647
+ choices=["Auto", "Korean", "English", "Japanese", "Chinese"],
2648
+ value="Auto",
2649
+ label="๐ŸŒ Language Mode"
2650
+ )
2651
+
2652
+ use_search = gr.Checkbox(
2653
+ label="๐Ÿ” Use Web Search",
2654
+ value=True
2655
+ )
2656
+
2657
+ show_agent_thoughts = gr.Checkbox(
2658
+ label="๐Ÿง  Show Processing",
2659
+ value=True
2660
+ )
2661
+
2662
+ search_count = gr.Slider(
2663
+ minimum=3,
2664
+ maximum=10,
2665
+ value=5,
2666
+ step=1,
2667
+ label="Search Results Count"
2668
+ )
2669
+
2670
+ gr.Markdown("""
2671
+ **โšก Optimization Status**
2672
+
2673
+ **Active Optimizations:**
2674
+ - โœ… Parallel Processing
2675
+ - โŒ ~~Smart Caching~~ (์ œ๊ฑฐ๋จ)
2676
+ - โœ… Buffer Streaming
2677
+ - โœ… Early Termination
2678
+ - โœ… Compressed Prompts
2679
+ - โœ… Multi-language Support
2680
+ - โœ… Error Recovery
2681
+
2682
+ **Expected Processing Time:**
2683
+ - Simple Query: 3-5 seconds
2684
+ - Complex Query: 5-8 seconds
2685
+ - Very Complex: 8-12 seconds
2686
+ """)
2687
+
2688
+ # ๋ณต์žกํ•œ ์งˆ๋ฌธ ์˜ˆ์ œ (๋‹ค๊ตญ์–ด)
2689
+ gr.Examples(
2690
+ examples=[
2691
+ # Korean
2692
+ "AI ๊ธฐ์ˆ ์ด ํ–ฅํ›„ 10๋…„๊ฐ„ ํ•œ๊ตญ ๊ฒฝ์ œ์— ๋ฏธ์น  ์˜ํ–ฅ์„ ๋‹ค๊ฐ๋„๋กœ ๋ถ„์„ํ•˜๊ณ  ๋Œ€์‘ ์ „๋žต์„ ์ œ์‹œํ•ด์ค˜",
2693
+ "์Šคํƒ€ํŠธ์—…์ด ๋Œ€๊ธฐ์—…๊ณผ ๊ฒฝ์Ÿํ•˜๊ธฐ ์œ„ํ•œ ํ˜์‹ ์ ์ธ ์ „๋žต์„ ๋‹จ๊ณ„๋ณ„๋กœ ์ˆ˜๋ฆฝํ•ด์ค˜",
2694
+ # English
2695
+ "Analyze the multifaceted impact of quantum computing on current encryption systems and propose alternatives",
2696
+ "Design 5 innovative business models for climate change mitigation with practical implementation details",
2697
+ # Japanese
2698
+ "ใƒกใ‚ฟใƒใƒผใ‚นๆ™‚ไปฃใฎๆ•™่‚ฒ้ฉๆ–ฐๆ–นๆกˆใ‚’ๅฎŸ่ฃ…ๅฏ่ƒฝใชใƒฌใƒ™ใƒซใงๆๆกˆใ—ใฆใใ ใ•ใ„",
2699
+ # Chinese
2700
+ "ๅˆ†ๆžไบบๅทฅๆ™บ่ƒฝๅฏนๆœชๆฅๅๅนดๅ…จ็ƒ็ปๆตŽ็š„ๅฝฑๅ“ๅนถๆๅ‡บๅบ”ๅฏน็ญ–็•ฅ"
2701
+ ],
2702
+ inputs=msg
2703
+ )
2704
+
2705
+ # ์ด๋ฒคํŠธ ๋ฐ”์ธ๋”ฉ
2706
+ submit.click(
2707
+ process_query_optimized,
2708
+ inputs=[msg, chatbot, use_search, show_agent_thoughts, search_count, language_mode],
2709
+ outputs=[chatbot, agent_thoughts, search_sources]
2710
+ ).then(
2711
+ lambda: "",
2712
+ None,
2713
+ msg
2714
+ )
2715
+
2716
+ msg.submit(
2717
+ process_query_optimized,
2718
+ inputs=[msg, chatbot, use_search, show_agent_thoughts, search_count, language_mode],
2719
+ outputs=[chatbot, agent_thoughts, search_sources]
2720
+ ).then(
2721
+ lambda: "",
2722
+ None,
2723
+ msg
2724
+ )
2725
+
2726
+ clear.click(
2727
+ lambda: ([], "", ""),
2728
+ None,
2729
+ [chatbot, agent_thoughts, search_sources]
2730
+ )
2731
+
2732
+ return demo
2733
+
2734
+
2735
+ # ============================================================================
2736
+ # ๋ฉ”์ธ ์‹คํ–‰
2737
+ # ============================================================================
2738
+
2739
+ if __name__ == "__main__":
2740
+ print("""
2741
+ โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
2742
+ โ•‘ โšก Speed-Optimized Multi-Agent System (No Cache) โšก โ•‘
2743
+ โ•‘ โ•‘
2744
+ โ•‘ High-speed AI system processing complex questions โ•‘
2745
+ โ•‘ โ•‘
2746
+ โ•‘ Features: โ•‘
2747
+ โ•‘ โ€ข Multi-language support (KO/EN/JA/ZH) โ•‘
2748
+ โ•‘ โ€ข Improved error recovery โ•‘
2749
+ โ•‘ โ€ข NO CACHING (์บ์‹ฑ ๊ธฐ๋Šฅ ์ œ๊ฑฐ๋จ) โ•‘
2750
+ โ•‘ โ€ข Adaptive stream buffering โ•‘
2751
+ โ•‘ โ€ข Response cleaning & formatting โ•‘
2752
+ โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
2753
+ """)
2754
+
2755
+ # API ํ‚ค ํ™•์ธ
2756
+ if not os.getenv("FIREWORKS_API_KEY"):
2757
+ print("\nโš ๏ธ FIREWORKS_API_KEY is not set.")
2758
+
2759
+ if not os.getenv("BRAVE_SEARCH_API_KEY"):
2760
+ print("\nโš ๏ธ BRAVE_SEARCH_API_KEY is not set.")
2761
+
2762
+ # Gradio ์•ฑ ์‹คํ–‰
2763
+ demo = create_optimized_gradio_interface()
2764
+
2765
+ is_hf_spaces = os.getenv("SPACE_ID") is not None
2766
+
2767
+ if is_hf_spaces:
2768
+ print("\n๐Ÿค— Running in optimized mode on Hugging Face Spaces (No Cache)...")
2769
+ demo.launch(server_name="0.0.0.0", server_port=7860)
2770
+ else:
2771
+ print("\n๐Ÿ’ป Running in optimized mode on local environment (No Cache)...")
2772
+ demo.launch(server_name="0.0.0.0", server_port=7860, share=False), '', response, flags=re.MULTILINE)
2773
+
2774
+ # ๋ฆฌ์ŠคํŠธ ๋งˆ์ปค๋ฅผ ์ผ๋ฐ˜ ํ…์ŠคํŠธ๋กœ ๋ณ€๊ฒฝ
2775
+ response = re.sub(r'^\s*[\*\-\+]\s+', 'โ€ข ', response, flags=re.MULTILINE)
2776
+ response = re.sub(r'^\s*\d+\.\s+', '', response, flags=re.MULTILINE)
2777
+
2778
+ # ๋งํฌ ํ…์ŠคํŠธ๋งŒ ๋‚จ๊ธฐ๊ธฐ [text](url) -> text
2779
+ response = re.sub(r'\[([^\]]+)\]\([^\)]+\)', r'\1', response)
2780
+
2781
+ # ์ด๋ฏธ์ง€ ์ œ๊ฑฐ ![alt](url)
2782
+ response = re.sub(r'!\[([^\]]*)\]\([^\)]+\)', '', response)
2783
 
2784
  # ์ค‘๋ณต ๊ณต๋ฐฑ ์ œ๊ฑฐ
2785
  response = re.sub(r'\n{3,}', '\n\n', response)
2786
+ response = re.sub(r' {2,}', ' ', response)
2787
 
2788
  # ํŠน์ • ํŒจํ„ด ์ œ๊ฑฐ
2789
  unwanted_patterns = [
 
2792
  r'^\s*\*\*\[.*?\]\*\*\s*', # [ํƒœ๊ทธ] ํ˜•์‹ ์ œ๊ฑฐ
2793
  r'^\s*###\s*', # ### ์ œ๊ฑฐ
2794
  r'^\s*##\s*', # ## ์ œ๊ฑฐ
2795
+ r'^\s*#\s*', # # ์ œ๊ฑฐ
2796
+ r'^\s*>\s+', # ์ธ์šฉ๋ฌธ ๋งˆ์ปค ์ œ๊ฑฐ
2797
  ]
2798
 
2799
  for pattern in unwanted_patterns:
2800
  response = re.sub(pattern, '', response, flags=re.MULTILINE)
2801
 
2802
+ # ๋นˆ ์ค„ ์ •๋ฆฌ
2803
+ lines = [line.strip() for line in response.split('\n')]
2804
+ lines = [line for line in lines if line]
2805
+ response = '\n\n'.join(lines)
2806
+
2807
  return response.strip()
2808
 
2809