aiqtech commited on
Commit
bda65f2
·
verified ·
1 Parent(s): 2a02202

Update app-backup2.py

Browse files
Files changed (1) hide show
  1. app-backup2.py +992 -263
app-backup2.py CHANGED
@@ -12,9 +12,24 @@ import re
12
  logging.basicConfig(level=logging.INFO)
13
  logger = logging.getLogger(__name__)
14
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  # 환경 변수에서 토큰 가져오기
16
  FRIENDLI_TOKEN = os.getenv("FRIENDLI_TOKEN", "YOUR_FRIENDLI_TOKEN")
17
  BAPI_TOKEN = os.getenv("BAPI_TOKEN", "YOUR_BRAVE_API_TOKEN")
 
18
  API_URL = "https://api.friendli.ai/dedicated/v1/chat/completions"
19
  BRAVE_SEARCH_URL = "https://api.search.brave.com/res/v1/web/search"
20
  MODEL_ID = "dep89a2fld32mcm"
@@ -27,15 +42,31 @@ class LLMCollaborativeSystem:
27
  def __init__(self):
28
  self.token = FRIENDLI_TOKEN
29
  self.bapi_token = BAPI_TOKEN
 
30
  self.api_url = API_URL
31
  self.brave_url = BRAVE_SEARCH_URL
32
  self.model_id = MODEL_ID
33
  self.test_mode = TEST_MODE or (self.token == "YOUR_FRIENDLI_TOKEN")
 
 
34
 
35
  if self.test_mode:
36
  logger.warning("테스트 모드로 실행됩니다.")
37
  if self.bapi_token == "YOUR_BRAVE_API_TOKEN":
38
  logger.warning("Brave API 토큰이 설정되지 않았습니다.")
 
 
 
 
 
 
 
 
 
 
 
 
 
39
 
40
  def create_headers(self):
41
  """API 헤더 생성"""
@@ -69,12 +100,26 @@ class LLMCollaborativeSystem:
69
  def create_researcher_prompt(self, user_query: str, supervisor_guidance: str, search_results: Dict[str, List[Dict]]) -> str:
70
  """조사자 AI 프롬프트 생성"""
71
  search_summary = ""
 
 
72
  for keyword, results in search_results.items():
73
  search_summary += f"\n\n**{keyword}에 대한 검색 결과:**\n"
74
- for i, result in enumerate(results[:3], 1):
75
- search_summary += f"{i}. {result.get('title', 'N/A')}\n"
76
  search_summary += f" - {result.get('description', 'N/A')}\n"
77
  search_summary += f" - 출처: {result.get('url', 'N/A')}\n"
 
 
 
 
 
 
 
 
 
 
 
 
78
 
79
  return f"""당신은 정보를 조사하고 정리하는 조사자 AI입니다.
80
 
@@ -83,14 +128,17 @@ class LLMCollaborativeSystem:
83
  감독자 AI의 지침:
84
  {supervisor_guidance}
85
 
86
- 브레이브 검색 결과:
87
  {search_summary}
 
88
 
89
  위 검색 결과를 바탕으로:
90
  1. 각 키워드별로 중요한 정보를 정리하세요
91
- 2. 신뢰할 수 있는 출처를 명시하세요
92
- 3. 실행자 AI가 활용할있는 구체적인 데이터와 사실을 추출하세요
93
- 4. 최신 트렌드나 중요한 통계가 있다면 강조하세요"""
 
 
94
 
95
  def create_supervisor_execution_prompt(self, user_query: str, research_summary: str) -> str:
96
  """감독자 AI의 실행 지시 ���롬프트"""
@@ -147,6 +195,41 @@ class LLMCollaborativeSystem:
147
  4. 명확한 결론과 다음 단계를 제시하세요
148
  5. 전문적이고 완성도 높은 최종 보고서 형식으로 작성하세요"""
149
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
  def extract_keywords(self, supervisor_response: str) -> List[str]:
151
  """감독자 응답에서 키워드 추출"""
152
  keywords = []
@@ -163,32 +246,169 @@ class LLMCollaborativeSystem:
163
 
164
  return keywords[:7] # 최대 7개로 제한
165
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166
  def brave_search(self, query: str) -> List[Dict]:
167
  """Brave Search API 호출"""
168
  if self.test_mode or self.bapi_token == "YOUR_BRAVE_API_TOKEN":
169
  # 테스트 모드에서는 시뮬레이션된 결과 반환
170
- return [
171
- {
172
- "title": f"Best Practices for {query}",
173
- "description": f"Comprehensive guide on implementing {query} with proven methodologies and real-world examples.",
174
- "url": f"https://example.com/{query.replace(' ', '-')}"
175
- },
176
- {
177
- "title": f"Latest Trends in {query}",
178
- "description": f"Analysis of current trends and future directions in {query}, including market insights and expert opinions.",
179
- "url": f"https://trends.example.com/{query.replace(' ', '-')}"
180
- },
181
- {
182
- "title": f"{query}: Case Studies and Success Stories",
183
- "description": f"Real-world implementations of {query} across various industries with measurable results.",
184
- "url": f"https://casestudies.example.com/{query.replace(' ', '-')}"
185
- }
186
- ]
187
 
188
  try:
189
  params = {
190
  "q": query,
191
- "count": 5,
192
  "safesearch": "moderate",
193
  "freshness": "pw" # Past week for recent results
194
  }
@@ -203,12 +423,19 @@ class LLMCollaborativeSystem:
203
  if response.status_code == 200:
204
  data = response.json()
205
  results = []
206
- for item in data.get("web", {}).get("results", [])[:5]:
207
- results.append({
208
  "title": item.get("title", ""),
209
  "description": item.get("description", ""),
210
- "url": item.get("url", "")
211
- })
 
 
 
 
 
 
 
212
  return results
213
  else:
214
  logger.error(f"Brave API 오류: {response.status_code}")
@@ -226,9 +453,71 @@ class LLMCollaborativeSystem:
226
  yield chunk + " "
227
  time.sleep(0.05)
228
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
229
  def call_llm_streaming(self, messages: List[Dict[str, str]], role: str) -> Generator[str, None, None]:
230
  """스트리밍 LLM API 호출"""
231
 
 
 
 
 
 
232
  # 테스트 모드
233
  if self.test_mode:
234
  logger.info(f"테스트 모드 스트리밍 - Role: {role}")
@@ -254,25 +543,30 @@ class LLMCollaborativeSystem:
254
 
255
  "researcher": """조사 결과를 종합하여 다음과 같이 정리했습니다.
256
 
257
- **1. Machine Learning Optimization**
258
- - 최신 연구에 따르면 모델 최적화의 핵심은 아키텍처 설계와 훈련 전략의 균형입니다
259
- - AutoML 도구들이 하이퍼파라미터 튜닝을 자동화하여 효율성을 크게 향상시킵니다
260
- - 출처: ML Conference 2024, Google Research
261
-
262
- **2. Performance Improvement Strategies**
263
- - 데이터 품질 개선이 모델 성능 향상의 80%를 차지한다는 연구 결과
264
- - 앙상블 기법과 전이학습이 주요 성능 개선 방법으로 입증됨
265
- - 벤치마크: ImageNet에서 95% 이상의 정확도 달성 사례
266
-
267
- **3. Model Efficiency Techniques**
268
- - 모델 경량화(Pruning, Quantization)로 추론 속도 10배 향상 가능
269
- - Knowledge Distillation으로 모델 크기 90% 감소, 성능 유지
270
- - 최신 트렌드: Efficient Transformers, Neural Architecture Search
271
-
272
- **4. 실제 적용 사례**
273
- - Netflix: 추천 시스템 개선으로 사용자 만족도 35% 향상
274
- - Tesla: 실시간 객체 인식 속도 50% 개선
275
- - OpenAI: GPT 모델 효율성 개선으로 비용 70% 절감""",
 
 
 
 
 
276
 
277
  "supervisor_execution": """조사 내용을 바탕으로 실행자 AI에게 다음과 같이 구체적으로 지시합니다.
278
 
@@ -317,27 +611,7 @@ class LLMCollaborativeSystem:
317
  - Knowledge Distillation 구현
318
  * Teacher 모델: 현재 대규모 모델
319
  * Student 모델: 90% 작은 크기 목표 (조사 결과 기반)
320
- * 구현 프레임워크: PyTorch/TensorFlow
321
- - Pruning 및 Quantization 적용
322
- * 구조적 pruning으로 50% 파라미터 제거
323
- * INT8 quantization으로 추가 4배 속도 향상
324
- * Tesla 사례 참고: TensorRT 최적화 적용
325
-
326
- **4단계: 성과 검증 및 배포 (7-8주차)**
327
- - 성과 지표 측정
328
- * 추론 속도: 목표 10배 향상 (조사 결과 기반)
329
- * 정확도 손실: 최대 2% 이내 유지
330
- * 비용 절감: 70% 목표 (OpenAI 사례 참고)
331
- - 배포 전략
332
- * A/B 테스트: 10% 트래픽으로 시작
333
- * 모니터링: Prometheus + Grafana 대시보드
334
- * 롤백 계획: 성능 저하 시 자동 롤백
335
-
336
- **예상 결과물**
337
- - 최적화된 모델 (크기 90% 감소, 속도 10배 향상)
338
- - 상세 성능 벤치마크 보고서
339
- - 프로덕션 배포 가이드 및 모니터링 대시보드
340
- - 재현 가능한 최적화 파이프라인 코드""",
341
 
342
  "supervisor_review": """실행자 AI의 계획을 검토한 결과, 조사 내용이 잘 반영되었습니다. 다음과 같은 개선사항을 제안합니다.
343
 
@@ -354,53 +628,69 @@ class LLMCollaborativeSystem:
354
  2. **비용 분석 구체화**
355
  - OpenAI 사례의 70% 절감을 위한 구체적인 비용 계산
356
  - ROI 분석 및 투자 대비 효과 측정 방법
357
-
358
- 3. **팀 협업 체계화**
359
- - 데이터 과학자, ML 엔지니어, DevOps 간 역할 분담 명확화
360
- - 주간 진행 상황 공유 및 이슈 트래킹 프로세스
361
 
362
  **추가 권장사항**
363
  - 최신 연구 동향 모니터링 체계 구축
364
- - 경쟁사 벤치마킹을 위한 정기적인 조사 프로세스
365
- - 내부 지식 공유를 위한 문서화 및 세미나 계획
366
- - 실패 사례에서 배운 교훈을 축적하는 시스템 구축""",
367
 
368
  "executor_final": """감독자 AI의 피드백을 완전히 반영하여 최종 실행 보고서를 작성합니다.
369
 
370
  # 🎯 기계학습 모델 성능 향상 최종 실행 보고서
371
 
372
  ## 📋 Executive Summary
373
- 본 보고서는 웹 검색을 통해 수집된 최신 사례와 감독자 AI의 전략적 지침을 바탕으로, 8주간의 체계적인 모델 최적화 프로젝트를 제시합니다. 목표는 모델 크기 90% 감소, 추론 ���도 10배 향상, 운영 비용 70% 절감입니다.
 
 
 
 
 
 
 
 
 
 
374
 
375
  ## 📊 1단계: 현재 모델 진단 및 베이스라인 설정 (1주차)
376
 
377
  ### 실행 계획
 
378
  **월-화요일: 성능 메트릭 수집**
379
  - MLflow를 통한 현재 모델 전체 분석
380
- - Netflix 사례 기반 핵심 지표: 정확도(92%), 지연시간(45ms), 처리량(1,000 req/s)
381
- - 리소스 사용량: GPU 메모리 8GB, 추론 시 CPU 사용률 85%
 
 
 
382
 
383
  **수-목요일: AutoML 초기 탐색**
384
- - Optuna로 하이퍼파라미터 최적화 (200회 시도)
385
- - Ray Tune으로 분산 학습 환경 구축
386
- - 초기 개선 가능성: 15-20% 성능 향상 예상
387
-
388
- **금요일: 진단 보고서 및 리스크 분석**
389
- - 주요 병목: 모델 크기(2.5GB), 배치 처리 비효율성
390
- - 리스크: 데이터 드리프트, 하드웨어 제약
391
- - 백업 계획: 클라우드 GPU 인스턴스 확보
 
 
 
 
 
392
 
393
  ### 예상 산출물
394
- - 상세 성능 베이스라인 문서
395
- - 개선 기회 우선순위 매트릭스
396
- - 리스크 레지스터 및 대응 계획
397
 
398
  ## 📊 2단계: 데이터 품질 개선 (2-3주차)
399
 
400
  ### 실행 계획
401
- **2주차: 데이터 정제 파이프라인**
 
 
 
 
402
  ```python
403
- # data_quality_pipeline.py 주요 구성
404
  class DataQualityPipeline:
405
  def __init__(self):
406
  self.validators = [
@@ -411,125 +701,217 @@ class DataQualityPipeline:
411
  ]
412
 
413
  def process(self, data):
414
- # 80% 규칙 적용: 데이터 품질이 성능의 80% 결정
415
  for validator in self.validators:
416
  data = validator.transform(data)
417
  self.log_metrics(validator.get_stats())
418
  return data
419
  ```
420
 
421
- **3주차: 고급 데이터 증강**
422
- - MixUp: 15% 정확도 향상 예상
423
- - CutMix: 경계 검출 성능 20% 개선
424
- - AutoAugment: 자동 최적 증강 정책 탐색
425
- - A/B 테스트: 각 기법별 효과 측정
426
 
427
- ### 리스크 대응
428
- - 데이터 품질 저하 시: 롤백 메커니즘 구현
429
- - 증강 과적합 방지: 검증셋 분리 및 교차 검증
430
 
431
- ### 예상 산출물
432
- - 자동화된 데이터 품질 파이프라인
433
- - 데이터 품질 대시보드 (Grafana)
434
- - 15% 이상 성능 향상 검증 보고서
 
435
 
436
  ## 📊 3단계: 모델 최적화 구현 (4-6주차)
437
 
438
- ### 실행 계획
439
- **4-5주차: Knowledge Distillation**
 
440
  - Teacher 모델: 현재 2.5GB 모델
441
- - Student 모델 아키텍처:
442
- * 파라미터 수: 250M → 25M (90% 감소)
443
- * 레이어 수: 24 → 6
444
- * Hidden dimension: 1024 → 256
445
- - 훈련 전략:
446
- * Temperature: 5.0
447
- * Alpha (KD loss weight): 0.7
448
- * 훈련 에폭: 50
449
-
450
- **6주차: Pruning & Quantization**
451
- - 구조적 Pruning:
452
- * Magnitude 기반 50% 채널 제거
453
- * Fine-tuning: 10 에폭
454
- - INT8 Quantization:
455
- * Post-training quantization
456
- * Calibration dataset: 1,000 샘플
457
- - TensorRT 최적화 (Tesla 사례 적용):
458
- * FP16 추론 활성화
459
- * 동적 배치 최적화
460
-
461
- ### 팀 협업 체계
462
- - ML 엔지니어: 모델 아키텍처 및 훈련
463
- - DevOps: 인프라 및 배포 파이프라인
464
- - 데이터 과학자: 성능 분석 및 검증
465
- - 주간 스탠드업 미팅 및 Jira 이슈 트래킹
466
 
467
- ### 예상 산출물
468
- - 최적화된 모델 체크포인트
469
- - 성능 벤치마크 상세 보고서
470
- - 모델 변환 자동화 스크립트
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
471
 
472
  ## 📊 4단계: 성과 검증 및 프로덕션 배포 (7-8주차)
473
 
474
- ### 실행 계획
475
- **7주차: 종합 성능 검증**
476
- - 성능 지표 달성도:
477
- * 추론 속도: 45ms → 4.5ms (10배 향상) ✓
478
- * 모델 크기: 2.5GB → 250MB (90% 감소) ✓
479
- * 정확도 손실: 92% → 90.5% (1.5% 손실) ✓
480
- - 비용 분석:
481
- * GPU 인스턴스: $2,000/월 → $600/월
482
- * 처리량 증가로 인한 서버 수 감소: 10대 → 3대
483
- * 총 비용 절감: 70% 달성 ✓
484
-
485
- **8주차: 단계적 배포**
486
- - Canary 배포:
487
- * 1일차: 1% 트래픽
488
- * 3일차: 10% 트래픽
489
- * 7일차: 50% 트래픽
490
- * 14일차: 100% 전환
491
- - 모니터링 설정:
492
- * Prometheus + Grafana 대시보드
493
- * 알림 임계값: 지연시간 >10ms, 오류율 >0.1%
494
- - 롤백 계획:
495
- * 자동 롤백 트리거 설정
496
- * Blue-Green 배포로 즉시 전환 가능
497
-
498
- ### ROI 분석
499
- - 초기 투자: $50,000 (인건비 + 인프라)
500
- - 월간 절감액: $14,000
501
- - 투자 회수 기간: 3.6개월
502
- - 1년 순이익: $118,000
503
 
504
- ### 예상 산출물
505
- - 프로덕션 배포 완료
506
- - 실시간 모니터링 대시보드
507
- - ROI 분석 보고서
508
- - 운영 가이드 문서
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
509
 
510
  ## 📈 지속적 개선 계획
511
 
512
- ### 모니터링 및 유지보수
513
- - 월간 성능 리뷰 미팅
514
- - 분기별 재훈련 계획
515
- - 신기술 도입 검토 (Sparse Models, MoE)
516
 
517
- ### 지식 공유
518
- - 내부 기술 세미나 (월 1회)
519
- - 외부 컨퍼런스 발표 준비
520
- - 오픈소스 기여 계획
521
 
522
- ### 차기 프로젝트
523
- - 엣지 디바이스 배포 최적화
524
- - 연합 학습(Federated Learning) 도입
525
- - AutoML 플랫폼 구축
526
 
527
- ## 📝 결론
528
- 본 프로젝트는 최신 연구 결과와 업계 베스트 프랙티스를 적용하여, 8주 만에 모델 성능을 획기적으로 개선하고 운영 비용을 70% 절감하는 성과를 달성할 것으로 예상됩니다. 체계적인 접근과 리스크 관리, 그리고 지속적인 개선 계획을 통해 장기적인 경쟁력을 확보할 수 있습니다.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
529
 
530
  ---
531
  *작성일: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}*
532
- *작성자: 협력적 AI 시스템 (감독자, 조사자, 실행자 AI)*"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
533
  }
534
 
535
  # 프롬프트 내용에 따라 적절한 응답 선택
@@ -543,6 +925,8 @@ class DataQualityPipeline:
543
  response = test_responses["researcher"]
544
  elif role == "executor" and "최종 보고서" in messages[0]["content"]:
545
  response = test_responses["executor_final"]
 
 
546
  else:
547
  response = test_responses["executor"]
548
 
@@ -554,7 +938,8 @@ class DataQualityPipeline:
554
  system_prompts = {
555
  "supervisor": "당신은 거시적 관점에서 분석하고 지도하는 감독자 AI입니다.",
556
  "researcher": "당신은 정보를 조사하고 체계적으로 정리하는 조사자 AI입니다.",
557
- "executor": "당신은 세부적인 내용을 구현하는 실행자 AI입니다."
 
558
  }
559
 
560
  full_messages = [
@@ -565,7 +950,7 @@ class DataQualityPipeline:
565
  payload = {
566
  "model": self.model_id,
567
  "messages": full_messages,
568
- "max_tokens": 2048,
569
  "temperature": 0.7,
570
  "top_p": 0.8,
571
  "stream": True,
@@ -617,15 +1002,18 @@ llm_system = LLMCollaborativeSystem()
617
  # 내부 히스토리 관리 (UI에는 표시하지 않음)
618
  internal_history = []
619
 
620
- def process_query_streaming(user_query: str):
621
  """스트리밍을 지원하는 쿼리 처리"""
622
  global internal_history
623
 
624
  if not user_query:
625
- return "", "", "", "", "❌ 질문을 입력해주세요."
 
 
 
626
 
627
  conversation_log = []
628
- all_responses = {"supervisor": [], "researcher": [], "executor": []}
629
 
630
  try:
631
  # 1단계: 감독자 AI 초기 분석 및 키워드 추출
@@ -639,7 +1027,7 @@ def process_query_streaming(user_query: str):
639
  ):
640
  supervisor_initial_response += chunk
641
  supervisor_text = f"[초기 분석] - {datetime.now().strftime('%H:%M:%S')}\n{supervisor_initial_response}"
642
- yield supervisor_text, "", "", "", "🔄 감독자 AI가 분석 중..."
643
 
644
  all_responses["supervisor"].append(supervisor_initial_response)
645
 
@@ -649,15 +1037,50 @@ def process_query_streaming(user_query: str):
649
 
650
  # 2단계: 브레이브 검색 수행
651
  researcher_text = "[웹 검색] 🔍 검색 중...\n"
652
- yield supervisor_text, researcher_text, "", "", "🔍 웹 검색 수행 중..."
653
 
654
  search_results = {}
 
 
 
655
  for keyword in keywords:
656
  results = llm_system.brave_search(keyword)
657
  if results:
658
  search_results[keyword] = results
659
- researcher_text += f"✓ '{keyword}' 검색 완료\n"
660
- yield supervisor_text, researcher_text, "", "", f"🔍 '{keyword}' 검색 중..."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
661
 
662
  # 3단계: 조사자 AI가 검색 결과 정리
663
  researcher_prompt = llm_system.create_researcher_prompt(user_query, supervisor_initial_response, search_results)
@@ -670,12 +1093,57 @@ def process_query_streaming(user_query: str):
670
  ):
671
  researcher_response += chunk
672
  researcher_text = f"[조사 결과 정리] - {datetime.now().strftime('%H:%M:%S')}\n{researcher_response}"
673
- yield supervisor_text, researcher_text, "", "", "📝 조사자 AI가 정리 중..."
674
 
675
  all_responses["researcher"].append(researcher_response)
676
 
677
- # 4단계: 감독자 AI가 조사 내용 기반으로 실행 지시
678
- supervisor_execution_prompt = llm_system.create_supervisor_execution_prompt(user_query, researcher_response)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
679
  supervisor_execution_response = ""
680
 
681
  supervisor_text += "\n\n---\n\n[실행 지시] 🔄 생성 중...\n"
@@ -686,11 +1154,11 @@ def process_query_streaming(user_query: str):
686
  supervisor_execution_response += chunk
687
  temp_text = f"{all_responses['supervisor'][0]}\n\n---\n\n[실행 지시] - {datetime.now().strftime('%H:%M:%S')}\n{supervisor_execution_response}"
688
  supervisor_text = f"[초기 분석] - {datetime.now().strftime('%H:%M:%S')}\n{temp_text}"
689
- yield supervisor_text, researcher_text, "", "", "🎯 감독자 AI가 지시 중..."
690
 
691
  all_responses["supervisor"].append(supervisor_execution_response)
692
 
693
- # 5단계: 실행자 AI가 조사 내용과 지시를 기반으로 초기 구현
694
  executor_prompt = llm_system.create_executor_prompt(user_query, supervisor_execution_response, researcher_response)
695
  executor_response = ""
696
 
@@ -701,41 +1169,129 @@ def process_query_streaming(user_query: str):
701
  ):
702
  executor_response += chunk
703
  executor_text = f"[초기 구현] - {datetime.now().strftime('%H:%M:%S')}\n{executor_response}"
704
- yield supervisor_text, researcher_text, executor_text, "", "🔧 실행자 AI가 구현 중..."
705
 
706
  all_responses["executor"].append(executor_response)
707
 
708
- # 6단계: 감독자 AI 검토 피드백
709
- review_prompt = f"""당신은 거시적 관점에서 분석하고 지도하는 감독자 AI입니다.
710
 
711
  사용자 질문: {user_query}
712
 
713
- 실행자 AI의 답변:
714
  {executor_response}
715
 
716
- 답변을 검토하고 개선점과 추가 고려사항을 제시해주세요. 구체적이고 실행 가능한 개선 방안을 제시하세요."""
 
 
 
 
 
 
 
717
 
718
- review_response = ""
719
- supervisor_text = f"[초기 분석] - {datetime.now().strftime('%H:%M:%S')}\n{all_responses['supervisor'][0]}\n\n---\n\n[실행 지시] - {datetime.now().strftime('%H:%M:%S')}\n{all_responses['supervisor'][1]}\n\n---\n\n[검토 및 피드백] 🔄 생성 중...\n"
720
 
721
  for chunk in llm_system.call_llm_streaming(
722
- [{"role": "user", "content": review_prompt}],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
723
  "supervisor"
724
  ):
725
- review_response += chunk
726
- temp_text = f"{all_responses['supervisor'][0]}\n\n---\n\n[실행 지시] - {datetime.now().strftime('%H:%M:%S')}\n{all_responses['supervisor'][1]}\n\n---\n\n[검토 및 피드백] - {datetime.now().strftime('%H:%M:%S')}\n{review_response}"
727
  supervisor_text = f"[초기 분석] - {datetime.now().strftime('%H:%M:%S')}\n{temp_text}"
728
- yield supervisor_text, researcher_text, executor_text, "", "🔄 감독자 AI가 검토 중..."
729
 
730
- all_responses["supervisor"].append(review_response)
731
 
732
- # 7단계: 실행자 AI 최종 보고서 (피드백 반영)
733
- final_executor_prompt = llm_system.create_executor_final_prompt(
734
- user_query,
735
- executor_response,
736
- review_response,
737
- researcher_response
 
738
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
739
  final_executor_response = ""
740
 
741
  executor_text += "\n\n---\n\n[최종 보고서] 🔄 작성 중...\n"
@@ -746,58 +1302,63 @@ def process_query_streaming(user_query: str):
746
  final_executor_response += chunk
747
  temp_text = f"[초기 구현] - {datetime.now().strftime('%H:%M:%S')}\n{all_responses['executor'][0]}\n\n---\n\n[최종 보고서] - {datetime.now().strftime('%H:%M:%S')}\n{final_executor_response}"
748
  executor_text = temp_text
749
- yield supervisor_text, researcher_text, executor_text, "", "📄 최종 보고서 작성 중..."
750
 
751
  all_responses["executor"].append(final_executor_response)
752
 
753
  # 최종 결과 생성 (최종 보고서를 메인으로)
754
- final_summary = f"""## 🎯 최종 종합 보고서
755
 
756
- ### 📌 사용자 질문
757
- {user_query}
 
 
 
 
758
 
759
- ### 📄 최종 보고서 (실행자 AI - 피드백 반영)
760
  {final_executor_response}
761
 
762
  ---
763
 
764
- <details>
765
- <summary>📋 전체 협력 과정 보기</summary>
766
 
767
- #### 🔍 거시적 분석 (감독자 AI)
768
- {all_responses['supervisor'][0]}
769
 
770
- #### 📚 조사 결과 (조사자 AI)
771
- {researcher_response}
772
 
773
- #### 🎯 실행 지시 (감독자 AI)
774
- {all_responses['supervisor'][1]}
775
 
776
- #### 💡 초기 구현 (실행자 AI)
777
- {executor_response}
 
778
 
779
- #### 검토 및 개선사항 (감독자 AI)
780
- {review_response}
781
 
782
- </details>
 
 
 
 
 
783
 
784
  ---
785
- *이 보고서는 웹 검색을 통한 최신 정보와 AI들의 협력, 그리고 피드백 반영을 통해 작성되었습니다.*"""
 
786
 
787
  # 내부 히스토리 업데이트 (UI에는 표시하지 않음)
788
  internal_history.append((user_query, final_summary))
789
 
790
- yield supervisor_text, researcher_text, executor_text, final_summary, "✅ 최종 보고서 완성!"
791
 
792
  except Exception as e:
793
  error_msg = f"❌ 처리 중 오류: {str(e)}"
794
- yield "", "", "", error_msg, error_msg
795
 
796
  def clear_all():
797
  """모든 내용 초기화"""
798
  global internal_history
799
  internal_history = []
800
- return "", "", "", "", "🔄 초기화되었습니다."
801
 
802
  # Gradio 인터페이스
803
  css = """
@@ -807,22 +1368,176 @@ css = """
807
  .supervisor-box textarea {
808
  border-left: 4px solid #667eea !important;
809
  padding-left: 10px !important;
 
810
  }
811
  .researcher-box textarea {
812
  border-left: 4px solid #10b981 !important;
813
  padding-left: 10px !important;
 
814
  }
815
  .executor-box textarea {
816
  border-left: 4px solid #764ba2 !important;
817
  padding-left: 10px !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
818
  }
819
  """
820
 
821
- with gr.Blocks(title="협력적 LLM 시스템", theme=gr.themes.Soft(), css=css) as app:
 
 
 
 
 
 
 
 
 
 
 
 
 
822
 
823
  # 입력 섹션
824
  with gr.Row():
825
  with gr.Column():
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
826
  user_input = gr.Textbox(
827
  label="질문 입력",
828
  placeholder="예: 기계학습 모델의 성능을 향상시키는 방법은?",
@@ -837,60 +1552,74 @@ with gr.Blocks(title="협력적 LLM 시스템", theme=gr.themes.Soft(), css=css)
837
  label="상태",
838
  interactive=False,
839
  value="대기 중...",
840
- max_lines=1
841
  )
842
 
843
- # 최종 결과
844
  with gr.Row():
845
  with gr.Column():
846
- with gr.Accordion("📊 최종 종합 결과", open=True):
847
- final_output = gr.Markdown(
848
- value="*질문을 입력하면 결과가 여기에 표시됩니다.*"
849
- )
 
850
 
851
- # AI 출력들 - 줄에 나란히 배치
852
  with gr.Row():
853
- # 감독자 AI 출력
854
  with gr.Column():
855
  gr.Markdown("### 🧠 감독자 AI (거시적 분석)")
856
  supervisor_output = gr.Textbox(
857
  label="",
858
- lines=20,
859
- max_lines=25,
860
  interactive=False,
861
  elem_classes=["supervisor-box"]
862
  )
863
 
864
- # 조사자 AI 출력
865
  with gr.Column():
866
  gr.Markdown("### 🔍 조사자 AI (웹 검색 & 정리)")
867
  researcher_output = gr.Textbox(
868
  label="",
869
- lines=20,
870
- max_lines=25,
871
  interactive=False,
872
  elem_classes=["researcher-box"]
873
  )
874
-
875
- # 실행자 AI 출력
 
876
  with gr.Column():
877
  gr.Markdown("### 👁️ 실행자 AI (미시적 구현)")
878
  executor_output = gr.Textbox(
879
  label="",
880
- lines=20,
881
- max_lines=25,
882
  interactive=False,
883
  elem_classes=["executor-box"]
884
  )
 
 
 
 
 
 
 
 
 
 
885
 
886
  # 예제
887
  gr.Examples(
888
  examples=[
889
  "기계학습 모델의 성능을 향상시키는 최신 방법은?",
890
- "2024년 효과적인 프로젝트 관리 도구와 전략은?",
891
  "지속 가능한 비즈니스 모델의 최신 트렌드는?",
892
  "최신 데이터 시각화 도구와 기법은?",
893
- "원격 팀의 생산성을 높이는 검증된 방법은?"
 
 
 
894
  ],
895
  inputs=user_input,
896
  label="💡 예제 질문"
@@ -899,8 +1628,8 @@ with gr.Blocks(title="협력적 LLM 시스템", theme=gr.themes.Soft(), css=css)
899
  # 이벤트 핸들러
900
  submit_btn.click(
901
  fn=process_query_streaming,
902
- inputs=[user_input],
903
- outputs=[supervisor_output, researcher_output, executor_output, final_output, status_text]
904
  ).then(
905
  fn=lambda: "",
906
  outputs=[user_input]
@@ -908,8 +1637,8 @@ with gr.Blocks(title="협력적 LLM 시스템", theme=gr.themes.Soft(), css=css)
908
 
909
  user_input.submit(
910
  fn=process_query_streaming,
911
- inputs=[user_input],
912
- outputs=[supervisor_output, researcher_output, executor_output, final_output, status_text]
913
  ).then(
914
  fn=lambda: "",
915
  outputs=[user_input]
@@ -917,7 +1646,7 @@ with gr.Blocks(title="협력적 LLM 시스템", theme=gr.themes.Soft(), css=css)
917
 
918
  clear_btn.click(
919
  fn=clear_all,
920
- outputs=[supervisor_output, researcher_output, executor_output, final_output, status_text]
921
  )
922
 
923
 
 
12
  logging.basicConfig(level=logging.INFO)
13
  logger = logging.getLogger(__name__)
14
 
15
+ # 추가 임포트
16
+ from bs4 import BeautifulSoup
17
+ from urllib.parse import urlparse
18
+ import urllib.request
19
+
20
+ # Gemini API 임포트
21
+ try:
22
+ from google import genai
23
+ from google.genai import types
24
+ GEMINI_AVAILABLE = True
25
+ except ImportError:
26
+ GEMINI_AVAILABLE = False
27
+ logger.warning("Google Gemini API가 설치되지 않았습니다. pip install google-genai로 설치하세요.")
28
+
29
  # 환경 변수에서 토큰 가져오기
30
  FRIENDLI_TOKEN = os.getenv("FRIENDLI_TOKEN", "YOUR_FRIENDLI_TOKEN")
31
  BAPI_TOKEN = os.getenv("BAPI_TOKEN", "YOUR_BRAVE_API_TOKEN")
32
+ GEMINI_API_KEY = os.getenv("GEMINI_API_KEY", "YOUR_GEMINI_API_KEY")
33
  API_URL = "https://api.friendli.ai/dedicated/v1/chat/completions"
34
  BRAVE_SEARCH_URL = "https://api.search.brave.com/res/v1/web/search"
35
  MODEL_ID = "dep89a2fld32mcm"
 
42
  def __init__(self):
43
  self.token = FRIENDLI_TOKEN
44
  self.bapi_token = BAPI_TOKEN
45
+ self.gemini_api_key = GEMINI_API_KEY
46
  self.api_url = API_URL
47
  self.brave_url = BRAVE_SEARCH_URL
48
  self.model_id = MODEL_ID
49
  self.test_mode = TEST_MODE or (self.token == "YOUR_FRIENDLI_TOKEN")
50
+ self.use_gemini = False
51
+ self.gemini_client = None
52
 
53
  if self.test_mode:
54
  logger.warning("테스트 모드로 실행됩니다.")
55
  if self.bapi_token == "YOUR_BRAVE_API_TOKEN":
56
  logger.warning("Brave API 토큰이 설정되지 않았습니다.")
57
+ if self.gemini_api_key == "YOUR_GEMINI_API_KEY":
58
+ logger.warning("Gemini API 토큰이 설정되지 않았습니다.")
59
+
60
+ def set_llm_mode(self, mode: str):
61
+ """LLM 모드 설정 (default 또는 commercial)"""
62
+ if mode == "commercial" and GEMINI_AVAILABLE and self.gemini_api_key != "YOUR_GEMINI_API_KEY":
63
+ self.use_gemini = True
64
+ if not self.gemini_client:
65
+ self.gemini_client = genai.Client(api_key=self.gemini_api_key)
66
+ logger.info("Gemini 2.5 Pro 모드로 전환되었습니다.")
67
+ else:
68
+ self.use_gemini = False
69
+ logger.info("기본 LLM 모드로 전환되었습니다.")
70
 
71
  def create_headers(self):
72
  """API 헤더 생성"""
 
100
  def create_researcher_prompt(self, user_query: str, supervisor_guidance: str, search_results: Dict[str, List[Dict]]) -> str:
101
  """조사자 AI 프롬프트 생성"""
102
  search_summary = ""
103
+ all_results = []
104
+
105
  for keyword, results in search_results.items():
106
  search_summary += f"\n\n**{keyword}에 대한 검색 결과:**\n"
107
+ for i, result in enumerate(results[:10], 1): # 상위 10개만 표시
108
+ search_summary += f"{i}. {result.get('title', 'N/A')} (신뢰도: {result.get('credibility_score', 0):.2f})\n"
109
  search_summary += f" - {result.get('description', 'N/A')}\n"
110
  search_summary += f" - 출처: {result.get('url', 'N/A')}\n"
111
+ if result.get('published'):
112
+ search_summary += f" - 게시일: {result.get('published')}\n"
113
+
114
+ all_results.extend(results)
115
+
116
+ # 모순 감지
117
+ contradictions = self.detect_contradictions(all_results)
118
+ contradiction_text = ""
119
+ if contradictions:
120
+ contradiction_text = "\n\n**발견된 정보 모순:**\n"
121
+ for cont in contradictions[:3]: # 최대 3개만 표시
122
+ contradiction_text += f"- {cont['type']}: {cont['source1']} vs {cont['source2']}\n"
123
 
124
  return f"""당신은 정보를 조사하고 정리하는 조사자 AI입니다.
125
 
 
128
  감독자 AI의 지침:
129
  {supervisor_guidance}
130
 
131
+ 브레이브 검색 결과 (신뢰도 점수 포함):
132
  {search_summary}
133
+ {contradiction_text}
134
 
135
  위 검색 결과를 바탕으로:
136
  1. 각 키워드별로 중요한 정보를 정리하세요
137
+ 2. 신뢰할 수 있는 출처(신뢰도 0.7 이상)를 우선적으로 참고하세요
138
+ 3. 출처를 명확히 표기하여 실행자 AI가 검증할있도록 하세요
139
+ 4. 정보의 모순이 있다면 양쪽 관점을 모두 제시하세요
140
+ 5. 최신 트렌드나 중요한 통계가 있다면 강조하세요
141
+ 6. 신뢰도가 낮은 정보는 주의 표시와 함께 포함하세요"""
142
 
143
  def create_supervisor_execution_prompt(self, user_query: str, research_summary: str) -> str:
144
  """감독자 AI의 실행 지시 ���롬프트"""
 
195
  4. 명확한 결론과 다음 단계를 제시하세요
196
  5. 전문적이고 완성도 높은 최종 보고서 형식으로 작성하세요"""
197
 
198
+ def create_evaluator_prompt(self, user_query: str, supervisor_responses: List[str], researcher_response: str, executor_responses: List[str], evaluator_responses: List[str] = None) -> str:
199
+ """평가자 AI 프롬프트 생성"""
200
+ evaluator_history = ""
201
+ if evaluator_responses and len(evaluator_responses) > 0:
202
+ evaluator_history = f"""
203
+ 평가자 AI의 이전 평가들:
204
+ - 조사 결과 평가: {evaluator_responses[0] if len(evaluator_responses) > 0 else 'N/A'}
205
+ - 초기 구현 평가: {evaluator_responses[1] if len(evaluator_responses) > 1 else 'N/A'}
206
+ """
207
+
208
+ return f"""당신은 전체 협력 과정과 결과를 평가하는 평가자 AI입니다.
209
+
210
+ 사용자 질문: {user_query}
211
+
212
+ 감독자 AI의 분석 및 지시:
213
+ - 초기 분석: {supervisor_responses[0]}
214
+ - 실행 지시: {supervisor_responses[1] if len(supervisor_responses) > 1 else 'N/A'}
215
+ - 개선 지시: {supervisor_responses[2] if len(supervisor_responses) > 2 else 'N/A'}
216
+
217
+ 조사자 AI의 조사 결과:
218
+ {researcher_response}
219
+
220
+ 실행자 AI의 구현:
221
+ - 초기 구현: {executor_responses[0]}
222
+ - 최종 보고서: {executor_responses[1] if len(executor_responses) > 1 else 'N/A'}
223
+ {evaluator_history}
224
+ 위 전체 과정을 평가하여:
225
+ 1. **품질 평가**: 각 AI의 답변 품질과 역할 수행도를 평가하세요 (10점 만점)
226
+ 2. **협력 효과성**: AI 간 협력이 얼마나 효과적이었는지 평가하세요
227
+ 3. **정보 활용도**: 웹 검색 정보가 얼마나 잘 활용되었는지 평가하세요
228
+ 4. **개선점**: 향후 개선이 필요한 부분을 구체적으로 제시하세요
229
+ 5. **최종 평점**: 전체 프로세스에 대한 종합 평가를 제시하세요
230
+
231
+ 평가는 구체적이고 건설적으로 작성하세요."""
232
+
233
  def extract_keywords(self, supervisor_response: str) -> List[str]:
234
  """감독자 응답에서 키워드 추출"""
235
  keywords = []
 
246
 
247
  return keywords[:7] # 최대 7개로 제한
248
 
249
+ def generate_synonyms(self, keyword: str) -> List[str]:
250
+ """키워드의 동의어/유사어 생성"""
251
+ synonyms = {
252
+ "optimization": ["improvement", "enhancement", "efficiency", "tuning"],
253
+ "performance": ["speed", "efficiency", "throughput", "latency"],
254
+ "strategy": ["approach", "method", "technique", "plan"],
255
+ "implementation": ["deployment", "execution", "development", "integration"],
256
+ "analysis": ["evaluation", "assessment", "study", "research"],
257
+ "management": ["administration", "governance", "control", "supervision"],
258
+ "best practices": ["proven methods", "industry standards", "guidelines", "recommendations"],
259
+ "trends": ["developments", "innovations", "emerging", "future"],
260
+ "machine learning": ["ML", "AI", "deep learning", "neural networks"],
261
+ "프로젝트": ["project", "사업", "업무", "작업"]
262
+ }
263
+
264
+ # 키워드 정규화
265
+ keyword_lower = keyword.lower()
266
+
267
+ # 직접 매칭되는 동의어가 있으면 반환
268
+ if keyword_lower in synonyms:
269
+ return synonyms[keyword_lower][:2] # 최대 2개
270
+
271
+ # 부분 매칭 확인
272
+ for key, values in synonyms.items():
273
+ if key in keyword_lower or keyword_lower in key:
274
+ return values[:2]
275
+
276
+ # 동의어가 없으면 빈 리스트
277
+ return []
278
+
279
+ def calculate_credibility_score(self, result: Dict) -> float:
280
+ """검색 결과의 신뢰도 점수 계산 (0-1)"""
281
+ score = 0.5 # 기본 점수
282
+
283
+ url = result.get('url', '')
284
+ title = result.get('title', '')
285
+ description = result.get('description', '')
286
+
287
+ # URL 기반 점수
288
+ trusted_domains = [
289
+ '.edu', '.gov', '.org', 'wikipedia.org', 'nature.com',
290
+ 'sciencedirect.com', 'ieee.org', 'acm.org', 'springer.com',
291
+ 'harvard.edu', 'mit.edu', 'stanford.edu', 'github.com'
292
+ ]
293
+
294
+ for domain in trusted_domains:
295
+ if domain in url:
296
+ score += 0.2
297
+ break
298
+
299
+ # HTTPS 사용 여부
300
+ if url.startswith('https://'):
301
+ score += 0.1
302
+
303
+ # 제목과 설명의 길이 (너무 짧으면 신뢰도 감소)
304
+ if len(title) > 20:
305
+ score += 0.05
306
+ if len(description) > 50:
307
+ score += 0.05
308
+
309
+ # 광고/스팸 키워드 체크
310
+ spam_keywords = ['buy now', 'sale', 'discount', 'click here', '100% free']
311
+ if any(spam in (title + description).lower() for spam in spam_keywords):
312
+ score -= 0.3
313
+
314
+ # 날짜 정보가 있으면 가산점
315
+ if any(year in description for year in ['2024', '2023', '2022']):
316
+ score += 0.1
317
+
318
+ return max(0, min(1, score)) # 0-1 범위로 제한
319
+
320
+ def fetch_url_content(self, url: str, max_length: int = 2000) -> str:
321
+ """URL에서 콘텐츠 추출"""
322
+ try:
323
+ # User-Agent 설정
324
+ headers = {
325
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
326
+ }
327
+
328
+ req = urllib.request.Request(url, headers=headers)
329
+
330
+ with urllib.request.urlopen(req, timeout=5) as response:
331
+ html = response.read().decode('utf-8', errors='ignore')
332
+
333
+ soup = BeautifulSoup(html, 'html.parser')
334
+
335
+ # 스크립트와 스타일 제거
336
+ for script in soup(["script", "style"]):
337
+ script.decompose()
338
+
339
+ # 본문 텍스트 추출
340
+ text = soup.get_text()
341
+
342
+ # 공백 정리
343
+ lines = (line.strip() for line in text.splitlines())
344
+ chunks = (phrase.strip() for line in lines for phrase in line.split(" "))
345
+ text = ' '.join(chunk for chunk in chunks if chunk)
346
+
347
+ # 길이 제한
348
+ if len(text) > max_length:
349
+ text = text[:max_length] + "..."
350
+
351
+ return text
352
+
353
+ except Exception as e:
354
+ logger.error(f"URL 콘텐츠 가져오기 실패 {url}: {str(e)}")
355
+ return ""
356
+
357
+ def detect_contradictions(self, results: List[Dict]) -> List[Dict]:
358
+ """검색 결과 간 모순 감지"""
359
+ contradictions = []
360
+
361
+ # 간단한 모순 감지 패턴
362
+ opposite_pairs = [
363
+ ("increase", "decrease"),
364
+ ("improve", "worsen"),
365
+ ("effective", "ineffective"),
366
+ ("success", "failure"),
367
+ ("benefit", "harm"),
368
+ ("positive", "negative"),
369
+ ("growth", "decline")
370
+ ]
371
+
372
+ # 결과들을 비교
373
+ for i in range(len(results)):
374
+ for j in range(i + 1, len(results)):
375
+ desc1 = results[i].get('description', '').lower()
376
+ desc2 = results[j].get('description', '').lower()
377
+
378
+ # 반대 개념이 포함되어 있는지 확인
379
+ for word1, word2 in opposite_pairs:
380
+ if (word1 in desc1 and word2 in desc2) or (word2 in desc1 and word1 in desc2):
381
+ # 같은 주제에 대해 반대 의견인지 확인
382
+ common_words = set(desc1.split()) & set(desc2.split())
383
+ if len(common_words) > 5: # 공통 단어가 5개 이상이면 같은 주제로 간주
384
+ contradictions.append({
385
+ 'source1': results[i]['url'],
386
+ 'source2': results[j]['url'],
387
+ 'type': f"{word1} vs {word2}",
388
+ 'desc1': results[i]['description'][:100],
389
+ 'desc2': results[j]['description'][:100]
390
+ })
391
+
392
+ return contradictions
393
+
394
  def brave_search(self, query: str) -> List[Dict]:
395
  """Brave Search API 호출"""
396
  if self.test_mode or self.bapi_token == "YOUR_BRAVE_API_TOKEN":
397
  # 테스트 모드에서는 시뮬레이션된 결과 반환
398
+ test_results = []
399
+ for i in range(5):
400
+ test_results.append({
401
+ "title": f"Best Practices for {query} - Source {i+1}",
402
+ "description": f"Comprehensive guide on implementing {query} with proven methodologies and real-world examples from industry leaders.",
403
+ "url": f"https://example{i+1}.com/{query.replace(' ', '-')}",
404
+ "credibility_score": 0.7 + (i * 0.05)
405
+ })
406
+ return test_results
 
 
 
 
 
 
 
 
407
 
408
  try:
409
  params = {
410
  "q": query,
411
+ "count": 20, # 20개로 증가
412
  "safesearch": "moderate",
413
  "freshness": "pw" # Past week for recent results
414
  }
 
423
  if response.status_code == 200:
424
  data = response.json()
425
  results = []
426
+ for item in data.get("web", {}).get("results", [])[:20]:
427
+ result = {
428
  "title": item.get("title", ""),
429
  "description": item.get("description", ""),
430
+ "url": item.get("url", ""),
431
+ "published": item.get("published", "")
432
+ }
433
+ # 신뢰도 점수 계산
434
+ result["credibility_score"] = self.calculate_credibility_score(result)
435
+ results.append(result)
436
+
437
+ # 신뢰도 점수 기준으로 정렬
438
+ results.sort(key=lambda x: x['credibility_score'], reverse=True)
439
  return results
440
  else:
441
  logger.error(f"Brave API 오류: {response.status_code}")
 
453
  yield chunk + " "
454
  time.sleep(0.05)
455
 
456
+ def call_gemini_streaming(self, messages: List[Dict[str, str]], role: str) -> Generator[str, None, None]:
457
+ """Gemini API 스트리밍 호출"""
458
+ if not self.gemini_client:
459
+ yield "❌ Gemini API 클라이언트가 초기화되지 않았습니다."
460
+ return
461
+
462
+ try:
463
+ # 시스템 프롬프트 설정
464
+ system_prompts = {
465
+ "supervisor": "당신은 거시적 관점에서 분석하고 지도하는 감독자 AI입니다.",
466
+ "researcher": "당신은 정보를 조사하고 체계적으로 정리하는 조사자 AI입니다.",
467
+ "executor": "당신은 세부적인 내용을 구현하는 실행자 AI입니다.",
468
+ "evaluator": "당신은 전체 협력 과정과 결과를 평가하는 평가자 AI입니다."
469
+ }
470
+
471
+ # Gemini 형식의 contents 구성
472
+ contents = []
473
+
474
+ # 시스템 프롬프트를 첫 번째 사용자 메시지로 추가
475
+ contents.append(types.Content(
476
+ role="user",
477
+ parts=[types.Part.from_text(text=system_prompts.get(role, ""))]
478
+ ))
479
+ contents.append(types.Content(
480
+ role="model",
481
+ parts=[types.Part.from_text(text="네, 이해했습니다. 제 역할을 수행하겠습니다.")]
482
+ ))
483
+
484
+ # 사용자 메시지 추가
485
+ for msg in messages:
486
+ if msg["role"] == "user":
487
+ contents.append(types.Content(
488
+ role="user",
489
+ parts=[types.Part.from_text(text=msg["content"])]
490
+ ))
491
+
492
+ # GenerateContentConfig 설정
493
+ generate_content_config = types.GenerateContentConfig(
494
+ temperature=0.7,
495
+ top_p=0.8,
496
+ max_output_tokens=4096,
497
+ response_mime_type="text/plain"
498
+ )
499
+
500
+ # 스트리밍 생성
501
+ for chunk in self.gemini_client.models.generate_content_stream(
502
+ model="gemini-2.5-pro",
503
+ contents=contents,
504
+ config=generate_content_config,
505
+ ):
506
+ if chunk.text:
507
+ yield chunk.text
508
+
509
+ except Exception as e:
510
+ logger.error(f"Gemini API 오류: {str(e)}")
511
+ yield f"❌ Gemini API 오류: {str(e)}"
512
+
513
  def call_llm_streaming(self, messages: List[Dict[str, str]], role: str) -> Generator[str, None, None]:
514
  """스트리밍 LLM API 호출"""
515
 
516
+ # Gemini 모드인 경우
517
+ if self.use_gemini:
518
+ yield from self.call_gemini_streaming(messages, role)
519
+ return
520
+
521
  # 테스트 모드
522
  if self.test_mode:
523
  logger.info(f"테스트 모드 스트리밍 - Role: {role}")
 
543
 
544
  "researcher": """조사 결과를 종합하여 다음과 같이 정리했습니다.
545
 
546
+ **1. Machine Learning Optimization (신뢰도 높음)**
547
+ - 최신 연구에 따르면 모델 최적화의 핵심은 아키텍처 설계와 훈련 전략의 균형입니다 (신뢰도: 0.85)
548
+ - AutoML 도구들이 하이퍼파라미터 튜닝을 자동화하여 효율성을 크게 향상시킵니다 (신뢰도: 0.82)
549
+ - 출처: ML Conference 2024 (https://mlconf2024.org), Google Research (https://research.google)
550
+
551
+ **2. Performance Improvement Strategies (신뢰도 높음)**
552
+ - 데이터 품질 개선이 모델 성능 향상의 80%를 차지한다는 연구 결과 (신뢰도: 0.90)
553
+ - 앙상블 기법과 전이학습이 주요 성능 개선 방법으로 입증됨 (신뢰도: 0.78)
554
+ - 출처: Stanford AI Lab (https://ai.stanford.edu), MIT CSAIL (https://csail.mit.edu)
555
+
556
+ **3. Model Efficiency Techniques (신뢰도 중간)**
557
+ - 모델 경량화(Pruning, Quantization)로 추론 속도 10배 향상 가능 (신뢰도: 0.75)
558
+ - Knowledge Distillation으로 모델 크기 90% 감소, 성능 유지 (신뢰도: 0.72)
559
+ - 출처: ArXiv 논문 (https://arxiv.org/abs/2023.xxxxx)
560
+
561
+ **4. 실제 적용 사례 (신뢰도 높음)**
562
+ - Netflix: 추천 시스템 개선으로 사용자 만족도 35% 향상 (신뢰도: 0.88)
563
+ - Tesla: 실시간 객체 인식 속도 50% 개선 (신뢰도: 0.80)
564
+ - OpenAI: GPT 모델 효율성 개선으로 비용 70% 절감 (신뢰도: 0.85)
565
+
566
+ **핵심 인사이트:**
567
+ - 최신 트렌드는 효율성과 성능의 균형에 초점
568
+ - 2024년 들어 Sparse Models와 MoE(Mixture of Experts) 기법이 부상
569
+ - 실무 적용 시 단계별 검증이 성공의 핵심""",
570
 
571
  "supervisor_execution": """조사 내용을 바탕으로 실행자 AI에게 다음과 같이 구체적으로 지시합니다.
572
 
 
611
  - Knowledge Distillation 구현
612
  * Teacher 모델: 현재 대규모 모델
613
  * Student 모델: 90% 작은 크기 목표 (조사 결과 기반)
614
+ * 구현 프레임워크: PyTorch/TensorFlow""",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
615
 
616
  "supervisor_review": """실행자 AI의 계획을 검토한 결과, 조사 내용이 잘 반영되었습니다. 다음과 같은 개선사항을 제안합니다.
617
 
 
628
  2. **비용 분석 구체화**
629
  - OpenAI 사례의 70% 절감을 위한 구체적인 비용 계산
630
  - ROI 분석 및 투자 대비 효과 측정 방법
 
 
 
 
631
 
632
  **추가 권장사항**
633
  - 최신 연구 동향 모니터링 체계 구축
634
+ - 경쟁사 벤치마킹을 위한 정기적인 조사 프로세스""",
 
 
635
 
636
  "executor_final": """감독자 AI의 피드백을 완전히 반영하여 최종 실행 보고서를 작성합니다.
637
 
638
  # 🎯 기계학습 모델 성능 향상 최종 실행 보고서
639
 
640
  ## 📋 Executive Summary
641
+
642
+ 본 보고서는 웹 검색을 통해 수집된 최신 사례와 감독자 AI의 전략적 지침을 바탕으로, 8주간의 체계적인 모델 최적화 프로젝트를 제시합니다.
643
+
644
+ ### 🎯 목표 달성 지표
645
+
646
+ | 지표 | 현재 | 목표 | 개선율 |
647
+ |------|------|------|--------|
648
+ | 모델 크기 | 2.5GB | 250MB | 90% 감소 |
649
+ | 추론 속도 | 45ms | 4.5ms | 10배 향상 |
650
+ | 운영 비용 | $2,000/월 | $600/월 | 70% 절감 |
651
+ | 정확도 | 92% | 90.5% | 1.5% 손실 |
652
 
653
  ## 📊 1단계: 현재 모델 진단 및 베이스라인 설정 (1주차)
654
 
655
  ### 실행 계획
656
+
657
  **월-화요일: 성능 메트릭 수집**
658
  - MLflow를 통한 현재 모델 전체 분석
659
+ - Netflix 사례 기반 핵심 지표:
660
+ - 정확도: 92%
661
+ - 지연시간: 45ms
662
+ - 처리량: 1,000 req/s
663
+ - GPU 메모리: 8GB
664
 
665
  **수-목요일: AutoML 초기 탐색**
666
+ ```python
667
+ # Optuna 하이퍼파라미터 최적화 설정
668
+ study = optuna.create_study(direction="maximize")
669
+ study.optimize(objective, n_trials=200)
670
+
671
+ # Ray Tune 분산 학습 설정
672
+ analysis = tune.run(
673
+ train_model,
674
+ config=search_space,
675
+ num_samples=50,
676
+ resources_per_trial={"gpu": 1}
677
+ )
678
+ ```
679
 
680
  ### 예상 산출물
681
+ - 상세 성능 베이스라인 문서
682
+ - 개선 기회 우선순위 매트릭스
683
+ - 리스크 레지스터
684
 
685
  ## 📊 2단계: 데이터 품질 개선 (2-3주차)
686
 
687
  ### 실행 계획
688
+
689
+ **데이터 정제 파이프라인 구축**
690
+
691
+ > 조사 결과의 "80% 규칙" 적용: 데이터 품질이 성능의 80%를 결정
692
+
693
  ```python
 
694
  class DataQualityPipeline:
695
  def __init__(self):
696
  self.validators = [
 
701
  ]
702
 
703
  def process(self, data):
 
704
  for validator in self.validators:
705
  data = validator.transform(data)
706
  self.log_metrics(validator.get_stats())
707
  return data
708
  ```
709
 
710
+ **고급 데이터 증강 기법**
711
+ - **MixUp**: 15% 정확도 향상 예상
712
+ - **CutMix**: 경계 검출 성능 20% 개선
713
+ - **AutoAugment**: 자동 최적 증강 정책 탐색
 
714
 
715
+ ### 리스크 대응 전략
 
 
716
 
717
+ | 리스크 | 확률 | 영향도 | 대응 방안 |
718
+ |--------|------|--------|-----------|
719
+ | 데이터 품질 저하 | 중간 | 높음 | 롤백 메커니즘 구현 |
720
+ | 증강 과적합 | 낮음 | 중간 | 검증셋 분리 및 교차 검증 |
721
+ | 처리 시간 증가 | 높음 | 낮음 | 병렬 처리 파이프라인 |
722
 
723
  ## 📊 3단계: 모델 최적화 구현 (4-6주차)
724
 
725
+ ### Knowledge Distillation 상세 계획
726
+
727
+ **Teacher-Student 아키텍처**
728
  - Teacher 모델: 현재 2.5GB 모델
729
+ - Student 모델 스펙:
730
+ - 파라미터: 250M → 25M (90% 감소)
731
+ - 레이어: 24 → 6
732
+ - Hidden dimension: 1024 → 256
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
733
 
734
+ **훈련 전략**
735
+ ```python
736
+ distillation_config = {
737
+ "temperature": 5.0,
738
+ "alpha": 0.7, # KD loss weight
739
+ "beta": 0.3, # Original loss weight
740
+ "epochs": 50,
741
+ "learning_rate": 1e-4,
742
+ "batch_size": 128
743
+ }
744
+ ```
745
+
746
+ ### Pruning & Quantization
747
+
748
+ **구조적 Pruning 계획**
749
+ 1. Magnitude 기반 중요도 평가
750
+ 2. 50% 채널 제거
751
+ 3. Fine-tuning: 10 에폭
752
+ 4. 성능 검증 및 반복
753
+
754
+ **INT8 Quantization**
755
+ - Post-training quantization 적용
756
+ - Calibration dataset: 1,000 샘플
757
+ - 예상 속도 향상: 4배
758
 
759
  ## 📊 4단계: 성과 검증 및 프로덕션 배포 (7-8주차)
760
 
761
+ ### 종합 성능 검증
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
762
 
763
+ **성능 지표 달성도 검증**
764
+
765
+ | 테스트 항목 | 방법 | 성공 기준 | 결과 |
766
+ |-------------|------|-----------|------|
767
+ | 추론 속도 | A/B 테스트 | <5ms | ✅ 4.5ms |
768
+ | 정확도 | 홀드아웃 검증 | >90% | ✅ 90.5% |
769
+ | 메모리 사용량 | 프로파일링 | <300MB | ✅ 250MB |
770
+ | 처리량 | 부하 테스트 | >5000 req/s | ✅ 6000 req/s |
771
+
772
+ ### 단계적 배포 전략
773
+
774
+ ```mermaid
775
+ graph LR
776
+ A[1% 트래픽] --> B[10% 트래픽]
777
+ B --> C[50% 트래픽]
778
+ C --> D[100% 전환]
779
+
780
+ A -->|Day 1-3| B
781
+ B -->|Day 4-7| C
782
+ C -->|Day 8-14| D
783
+ ```
784
+
785
+ ### 모니터링 대시보드
786
+
787
+ **핵심 메트릭**
788
+ - 🔴 P99 지연시간: < 10ms
789
+ - 🟡 오류율: < 0.1%
790
+ - 🟢 CPU/GPU 사용률: < 80%
791
+
792
+ ## 💰 ROI 분석
793
+
794
+ ### 비용-효익 분석
795
+
796
+ | 항목 | 비용/효익 | 세부 내역 |
797
+ |------|-----------|-----------|
798
+ | **초기 투자** | $50,000 | 인건비 + 인프라 |
799
+ | **월간 절감액** | $14,000 | 서버 + GPU 비용 |
800
+ | **투자 회수 기간** | 3.6개월 | - |
801
+ | **1년 순이익** | $118,000 | 절감액 - 투자비 |
802
+
803
+ ### 장기 효과
804
+ - 🚀 확장성 10배 향상
805
+ - 💡 신규 서비스 출시 가능
806
+ - 🌍 탄소 배출 70% 감소
807
 
808
  ## 📈 지속적 개선 계획
809
 
810
+ ### 월간 모니터링
811
+ - 성능 지표 리뷰
812
+ - 사용자 피드백 분석
813
+ - 기술 부채 관리
814
 
815
+ ### 분기별 업데이트
816
+ - 모델 재훈련
817
+ - 새로운 최적화 기법 도입
818
+ - 벤치마크 업데이트
819
 
820
+ ### 차기 프로젝트 로드맵
 
 
 
821
 
822
+ | 분기 | 프로젝트 | 예상 효과 |
823
+ |------|----------|-----------|
824
+ | Q2 2025 | 엣지 디바이스 배포 | 지연시간 90% 감소 |
825
+ | Q3 2025 | 연합 학습 도입 | 프라이버시 강화 |
826
+ | Q4 2025 | AutoML 플랫폼 구축 | 개발 속도 5배 향상 |
827
+
828
+ ## 📝 결론 및 권고사항
829
+
830
+ ### 핵심 성과
831
+ - ✅ 모든 목표 지표 달성
832
+ - ✅ 예산 내 프로젝트 완료
833
+ - ✅ 리스크 성공적 관리
834
+
835
+ ### 향후 권고사항
836
+ 1. **즉시 실행**: 1-2단계 즉시 착수
837
+ 2. **팀 구성**: ML엔지니어 2명, DevOps 1명 필수
838
+ 3. **인프라 준비**: GPU 서버 사전 확보
839
+ 4. **변경 관리**: 이해관계자 사전 교육
840
+
841
+ > 본 프로젝트는 최신 연구 결과와 업계 베스트 프랙티스를 적용하여, 8주 만에 모델 성능을 획기적으로 개선하고 운영 비용을 70% 절감하는 성과를 달성할 것으로 확신합니다.
842
 
843
  ---
844
  *작성일: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}*
845
+ *작성자: 협력적 AI 시스템 (감독자, 조사자, 실행자, 평가자 AI)*""",
846
+
847
+ "evaluator": """## 📊 전체 협력 과정 평가 보고서
848
+
849
+ ### 1️⃣ 품질 평가 (10점 만점)
850
+
851
+ | AI 역할 | 점수 | 평가 내용 |
852
+ |---------|------|-----------|
853
+ | **감독자 AI** | 9.5/10 | 거시적 관점에서 체계적인 분석과 방향 제시 |
854
+ | **조사자 AI** | 9.0/10 | 웹 검색을 통한 최신 정보 수집 우수 |
855
+ | **실행자 AI** | 8.5/10 | 조사 내용을 잘 활용한 구체적 계획 수립 |
856
+
857
+ **상세 평가:**
858
+ - ✅ 감독자 AI: 단계별 구체적인 지시사항 제공이 탁월함
859
+ - ✅ 조사자 AI: 신뢰도 평가와 모순 감지 기능이 효과적
860
+ - ✅ 실행자 AI: 실행 가능한 단계별 접근법 제시 우수
861
+
862
+ ### 2️⃣ 협력 효과성 평가
863
+
864
+ **강점:**
865
+ - 🔄 AI 간 역할 분담이 명확하고 상호보완적
866
+ - 📊 정보 흐름이 체계적이고 일관성 있음
867
+ - ✨ 피드백 반영이 효과적으로 이루어짐
868
+
869
+ **개선점:**
870
+ - ⚡ 실시간 상호작용 메커니즘 추가 고려
871
+ - 📋 중간 점검 단계 도입 필요
872
+
873
+ ### 3️⃣ 정보 활용도 평가
874
+
875
+ | 평가 항목 | 달성도 | 세부 내용 |
876
+ |-----------|--------|-----------|
877
+ | 검색 범위 | 95% | 20개 이상의 웹 소스에서 정보 수집 |
878
+ | 신뢰도 평가 | 90% | 0.7 이상의 신뢰도 소스 우선 활용 |
879
+ | 정보 통합 | 85% | 다양한 관점의 정보를 균형있게 통합 |
880
+
881
+ **우수한 점:**
882
+ - ✅ 신뢰도 기반 정보 선별 효과적
883
+ - ✅ 실제 기업 사례 적절히 활용
884
+ - ✅ 최신 트렌드 반영 우수
885
+
886
+ **보완 필요:**
887
+ - 📚 학술 논문 등 더 깊이 있는 자료 활용
888
+ - 🌍 지역별/산업별 특성 고려 필요
889
+
890
+ ### 4️⃣ 향후 개선 방향
891
+
892
+ #### 1. **실시간 협업 강화**
893
+ - AI 간 중간 체크포인트 추가
894
+ - 동적 역할 조정 메커니즘 도입
895
+
896
+ #### 2. **정보 검증 강화**
897
+ - 교차 검증 프로세스 추가
898
+ - 전문가 검토 단계 고려
899
+
900
+ #### 3. **맞춤화 강화**
901
+ - 사용자 컨텍스트 더 깊이 반영
902
+ - 산업별/규모별 맞춤 전략 제공
903
+
904
+ ### 5️⃣ 최종 평점: ⭐⭐⭐⭐⭐ **9.0/10**
905
+
906
+ > **종합 평가:**
907
+ >
908
+ > 본 협력 시스템은 각 AI의 전문성을 효과적으로 활용하여 사용자 질문에 대한 종합적이고 실행 가능한 답변을 제공했습니다. 특히 웹 검색을 통한 최신 정보 활용과 단계적 피드백 반영이 우수했습니다.
909
+ >
910
+ > 향후 실시간 협업과 맞춤화를 더욱 강화한다면 더욱 뛰어난 성과를 달성할 수 있을 것입니다.
911
+
912
+ ---
913
+
914
+ **평가 완료 시각**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"""
915
  }
916
 
917
  # 프롬프트 내용에 따라 적절한 응답 선택
 
925
  response = test_responses["researcher"]
926
  elif role == "executor" and "최종 보고서" in messages[0]["content"]:
927
  response = test_responses["executor_final"]
928
+ elif role == "evaluator":
929
+ response = test_responses["evaluator"]
930
  else:
931
  response = test_responses["executor"]
932
 
 
938
  system_prompts = {
939
  "supervisor": "당신은 거시적 관점에서 분석하고 지도하는 감독자 AI입니다.",
940
  "researcher": "당신은 정보를 조사하고 체계적으로 정리하는 조사자 AI입니다.",
941
+ "executor": "당신은 세부적인 내용을 구현하는 실행자 AI입니다.",
942
+ "evaluator": "당신은 전체 협력 과정과 결과를 평가하는 평가자 AI입니다."
943
  }
944
 
945
  full_messages = [
 
950
  payload = {
951
  "model": self.model_id,
952
  "messages": full_messages,
953
+ "max_tokens": 4096,
954
  "temperature": 0.7,
955
  "top_p": 0.8,
956
  "stream": True,
 
1002
  # 내부 히스토리 관리 (UI에는 표시하지 않음)
1003
  internal_history = []
1004
 
1005
+ def process_query_streaming(user_query: str, llm_mode: str):
1006
  """스트리밍을 지원하는 쿼리 처리"""
1007
  global internal_history
1008
 
1009
  if not user_query:
1010
+ return "", "", "", "", "", "❌ 질문을 입력해주세요."
1011
+
1012
+ # LLM 모드 설정
1013
+ llm_system.set_llm_mode(llm_mode)
1014
 
1015
  conversation_log = []
1016
+ all_responses = {"supervisor": [], "researcher": [], "executor": [], "evaluator": []}
1017
 
1018
  try:
1019
  # 1단계: 감독자 AI 초기 분석 및 키워드 추출
 
1027
  ):
1028
  supervisor_initial_response += chunk
1029
  supervisor_text = f"[초기 분석] - {datetime.now().strftime('%H:%M:%S')}\n{supervisor_initial_response}"
1030
+ yield supervisor_text, "", "", "", "", "🔄 감독자 AI가 분석 중..."
1031
 
1032
  all_responses["supervisor"].append(supervisor_initial_response)
1033
 
 
1037
 
1038
  # 2단계: 브레이브 검색 수행
1039
  researcher_text = "[웹 검색] 🔍 검색 중...\n"
1040
+ yield supervisor_text, researcher_text, "", "", "", "🔍 웹 검색 수행 중..."
1041
 
1042
  search_results = {}
1043
+ total_search_count = 0
1044
+
1045
+ # 원래 키워드로 검색
1046
  for keyword in keywords:
1047
  results = llm_system.brave_search(keyword)
1048
  if results:
1049
  search_results[keyword] = results
1050
+ total_search_count += len(results)
1051
+ researcher_text += f" '{keyword}' 검색 완료 ({len(results)}개 결과)\n"
1052
+ yield supervisor_text, researcher_text, "", "", "", f"🔍 '{keyword}' 검색 중..."
1053
+
1054
+ # 동의어로 추가 검색
1055
+ synonyms = llm_system.generate_synonyms(keyword)
1056
+ for synonym in synonyms:
1057
+ syn_results = llm_system.brave_search(f"{keyword} {synonym}")
1058
+ if syn_results:
1059
+ search_results[f"{keyword} ({synonym})"] = syn_results
1060
+ total_search_count += len(syn_results)
1061
+ researcher_text += f"✓ 동의어 '{synonym}' 검색 완료 ({len(syn_results)}개 결과)\n"
1062
+ yield supervisor_text, researcher_text, "", "", "", f"🔍 동의어 '{synonym}' 검색 중..."
1063
+
1064
+ researcher_text += f"\n📊 총 {total_search_count}개의 검색 결과 수집 완료\n"
1065
+
1066
+ # URL 콘텐츠 가져오기 (상위 3개)
1067
+ researcher_text += "\n[콘텐츠 분석] 📖 주요 웹페이지 내용 분석 중...\n"
1068
+ yield supervisor_text, researcher_text, "", "", "", "📖 웹페이지 내용 분석 중..."
1069
+
1070
+ content_analyzed = 0
1071
+ for keyword, results in search_results.items():
1072
+ for result in results[:2]: # 각 키워드당 상위 2개만
1073
+ if content_analyzed >= 5: # 총 5개까지만
1074
+ break
1075
+
1076
+ url = result.get('url', '')
1077
+ if url and result.get('credibility_score', 0) >= 0.7:
1078
+ content = llm_system.fetch_url_content(url)
1079
+ if content:
1080
+ result['content_preview'] = content[:500] # 미리보기 저장
1081
+ content_analyzed += 1
1082
+ researcher_text += f"✓ 콘텐츠 분석 완료: {url[:50]}...\n"
1083
+ yield supervisor_text, researcher_text, "", "", "", f"📖 분석 중: {url[:30]}..."
1084
 
1085
  # 3단계: 조사자 AI가 검색 결과 정리
1086
  researcher_prompt = llm_system.create_researcher_prompt(user_query, supervisor_initial_response, search_results)
 
1093
  ):
1094
  researcher_response += chunk
1095
  researcher_text = f"[조사 결과 정리] - {datetime.now().strftime('%H:%M:%S')}\n{researcher_response}"
1096
+ yield supervisor_text, researcher_text, "", "", "", "📝 조사자 AI가 정리 중..."
1097
 
1098
  all_responses["researcher"].append(researcher_response)
1099
 
1100
+ # 4단계: 평가자 AI가 조사 결과 평가
1101
+ evaluator_research_prompt = f"""당신은 전체 협력 과정과 결과를 평가하는 평가자 AI입니다.
1102
+
1103
+ 사용자 질문: {user_query}
1104
+
1105
+ 감독자 AI의 초기 분석:
1106
+ {supervisor_initial_response}
1107
+
1108
+ 조사자 AI의 조사 결과:
1109
+ {researcher_response}
1110
+
1111
+ 위 조사 결과를 평가하여:
1112
+ 1. 조사의 충실도와 신뢰성을 평가하세요
1113
+ 2. 누락된 중요 정보가 있는지 확인하세요
1114
+ 3. 조사 결과의 활용 가능성을 평가하세요
1115
+ 4. 개선이 필요한 부분을 구체적으로 제시하세요"""
1116
+
1117
+ evaluator_research_response = ""
1118
+ evaluator_text = "[조사 결과 평가] 🔄 평가 중...\n"
1119
+
1120
+ for chunk in llm_system.call_llm_streaming(
1121
+ [{"role": "user", "content": evaluator_research_prompt}],
1122
+ "evaluator"
1123
+ ):
1124
+ evaluator_research_response += chunk
1125
+ evaluator_text = f"[조사 결과 평가] - {datetime.now().strftime('%H:%M:%S')}\n{evaluator_research_response}"
1126
+ yield supervisor_text, researcher_text, "", evaluator_text, "", "📊 평가자 AI가 조사 결과 평가 중..."
1127
+
1128
+ all_responses["evaluator"].append(evaluator_research_response)
1129
+
1130
+ # 5단계: 감독자 AI가 평가를 반영한 실행 지시
1131
+ supervisor_execution_prompt = f"""당신은 거시적 관점에서 분석하고 지도하는 감독자 AI입니다.
1132
+
1133
+ 사용자 질문: {user_query}
1134
+
1135
+ 조사자 AI가 정리한 조사 내용:
1136
+ {researcher_response}
1137
+
1138
+ 평가자 AI의 조사 결과 평가:
1139
+ {evaluator_research_response}
1140
+
1141
+ 위 조사 내용과 평가를 기반으로 실행자 AI에게 아주 구체적인 지시를 내려주세요:
1142
+ 1. 평가자의 피드백을 반영하여 지시를 개선하세요
1143
+ 2. 조사된 정보를 어떻게 활용할지 명확히 지시하세요
1144
+ 3. 실행 가능한 단계별 작업을 구체적으로 제시하세요
1145
+ 4. 예상되는 결과물의 형태를 구체적으로 설명하세요"""
1146
+
1147
  supervisor_execution_response = ""
1148
 
1149
  supervisor_text += "\n\n---\n\n[실행 지시] 🔄 생성 중...\n"
 
1154
  supervisor_execution_response += chunk
1155
  temp_text = f"{all_responses['supervisor'][0]}\n\n---\n\n[실행 지시] - {datetime.now().strftime('%H:%M:%S')}\n{supervisor_execution_response}"
1156
  supervisor_text = f"[초기 분석] - {datetime.now().strftime('%H:%M:%S')}\n{temp_text}"
1157
+ yield supervisor_text, researcher_text, "", evaluator_text, "", "🎯 감독자 AI가 지시 중..."
1158
 
1159
  all_responses["supervisor"].append(supervisor_execution_response)
1160
 
1161
+ # 6단계: 실행자 AI가 조사 내용과 지시를 기반으로 초기 구현
1162
  executor_prompt = llm_system.create_executor_prompt(user_query, supervisor_execution_response, researcher_response)
1163
  executor_response = ""
1164
 
 
1169
  ):
1170
  executor_response += chunk
1171
  executor_text = f"[초기 구현] - {datetime.now().strftime('%H:%M:%S')}\n{executor_response}"
1172
+ yield supervisor_text, researcher_text, executor_text, evaluator_text, "", "🔧 실행자 AI가 구현 중..."
1173
 
1174
  all_responses["executor"].append(executor_response)
1175
 
1176
+ # 7단계: 평가자 AI 초기 구현 평가
1177
+ evaluator_execution_prompt = f"""당신은 전체 협력 과정과 결과를 평가하는 평가자 AI입니다.
1178
 
1179
  사용자 질문: {user_query}
1180
 
1181
+ 실행자 AI의 초기 구현:
1182
  {executor_response}
1183
 
1184
+ 감독자 AI의 지시사항:
1185
+ {supervisor_execution_response}
1186
+
1187
+ 위 초기 구현을 평가하여:
1188
+ 1. 지시사항이 얼마나 잘 반영되었는지 평가하세요
1189
+ 2. 구현의 실행 가능성과 구체성을 평가하세요
1190
+ 3. 누락된 중요 요소가 있는지 확인하세요
1191
+ 4. 개선이 필요한 부분을 구체적으로 제시하세요"""
1192
 
1193
+ evaluator_execution_response = ""
1194
+ evaluator_text += "\n\n---\n\n[초기 구현 평가] 🔄 평가 중...\n"
1195
 
1196
  for chunk in llm_system.call_llm_streaming(
1197
+ [{"role": "user", "content": evaluator_execution_prompt}],
1198
+ "evaluator"
1199
+ ):
1200
+ evaluator_execution_response += chunk
1201
+ temp_text = f"{all_responses['evaluator'][0]}\n\n---\n\n[초기 구현 평가] - {datetime.now().strftime('%H:%M:%S')}\n{evaluator_execution_response}"
1202
+ evaluator_text = f"[조사 결과 평가] - {datetime.now().strftime('%H:%M:%S')}\n{temp_text}"
1203
+ yield supervisor_text, researcher_text, executor_text, evaluator_text, "", "📊 평가자 AI가 구현 평가 중..."
1204
+
1205
+ all_responses["evaluator"].append(evaluator_execution_response)
1206
+
1207
+ # 8단계: 감독자 AI가 평가를 반영한 개선 지시
1208
+ supervisor_improvement_prompt = f"""당신은 거시적 관점에서 분석하고 지도하는 감독자 AI입니다.
1209
+
1210
+ 사용자 질문: {user_query}
1211
+
1212
+ 실행자 AI의 초기 구현:
1213
+ {executor_response}
1214
+
1215
+ 평가자 AI의 구현 평가:
1216
+ {evaluator_execution_response}
1217
+
1218
+ 위 평가를 반영하여 최종 보고서 작성을 위한 개선 지시를 내려주세요:
1219
+ 1. 평가자가 지적한 모든 개선사항을 구체적으로 반영하세요
1220
+ 2. 추가로 필요한 구체적인 내용을 지시하세요
1221
+ 3. 최종 보고서의 구조와 포함해야 할 요소를 명확히 제시하세요"""
1222
+
1223
+ supervisor_improvement_response = ""
1224
+ supervisor_text += "\n\n---\n\n[개선 지시] 🔄 생성 중...\n"
1225
+
1226
+ for chunk in llm_system.call_llm_streaming(
1227
+ [{"role": "user", "content": supervisor_improvement_prompt}],
1228
  "supervisor"
1229
  ):
1230
+ supervisor_improvement_response += chunk
1231
+ temp_text = f"{all_responses['supervisor'][0]}\n\n---\n\n[실행 지시] - {datetime.now().strftime('%H:%M:%S')}\n{all_responses['supervisor'][1]}\n\n---\n\n[개선 지시] - {datetime.now().strftime('%H:%M:%S')}\n{supervisor_improvement_response}"
1232
  supervisor_text = f"[초기 분석] - {datetime.now().strftime('%H:%M:%S')}\n{temp_text}"
1233
+ yield supervisor_text, researcher_text, executor_text, evaluator_text, "", "🔄 감독자 AI가 개선 지시 중..."
1234
 
1235
+ all_responses["supervisor"].append(supervisor_improvement_response)
1236
 
1237
+ # 9단계: 평가자 AI 전체 과정 최종 평가
1238
+ evaluator_final_prompt = llm_system.create_evaluator_prompt(
1239
+ user_query,
1240
+ all_responses["supervisor"],
1241
+ all_responses["researcher"][0],
1242
+ all_responses["executor"],
1243
+ all_responses["evaluator"] # 이전 평가들도 전달
1244
  )
1245
+ evaluator_final_response = ""
1246
+
1247
+ evaluator_text += "\n\n---\n\n[전체 과정 최종 평가] 🔄 평가 중...\n"
1248
+ for chunk in llm_system.call_llm_streaming(
1249
+ [{"role": "user", "content": evaluator_final_prompt}],
1250
+ "evaluator"
1251
+ ):
1252
+ evaluator_final_response += chunk
1253
+ temp_text = f"{all_responses['evaluator'][0]}\n\n---\n\n[초기 구현 평가] - {datetime.now().strftime('%H:%M:%S')}\n{all_responses['evaluator'][1]}\n\n---\n\n[전체 과정 최종 평가] - {datetime.now().strftime('%H:%M:%S')}\n{evaluator_final_response}"
1254
+ evaluator_text = f"[조사 결과 평가] - {datetime.now().strftime('%H:%M:%S')}\n{temp_text}"
1255
+ yield supervisor_text, researcher_text, executor_text, evaluator_text, "", "📊 평가자 AI가 최종 평가 중..."
1256
+
1257
+ all_responses["evaluator"].append(evaluator_final_response)
1258
+
1259
+ # 10단계: 실행자 AI 최종 보고서 (모든 피드백 반영)
1260
+ final_executor_prompt = f"""당신은 세부적인 내용을 구현하는 실행자 AI입니다.
1261
+
1262
+ 사용자 질문: {user_query}
1263
+
1264
+ 조사자 AI의 조사 내용:
1265
+ {researcher_response}
1266
+
1267
+ 당신의 초기 구현:
1268
+ {executor_response}
1269
+
1270
+ 감독자 AI의 개선 지시:
1271
+ {supervisor_improvement_response}
1272
+
1273
+ 평가자 AI의 전체 평가:
1274
+ {evaluator_final_response}
1275
+
1276
+ 위 모든 피드백을 완전히 반영하여 최종 보고서를 작성하세요:
1277
+ 1. 모든 개선사항과 지시사항을 빠짐없이 반영하세요
1278
+ 2. 조사 내용을 최대한 구체적으로 활용하세요
1279
+ 3. 실행 가능성을 높이는 세부 계획을 포함하세요
1280
+ 4. 명확한 결론과 다음 단계를 제시하세요
1281
+ 5. 전문적이고 완성도 높은 최종 보고서 형식으로 작성하세요
1282
+
1283
+ **중요: 마크다운 형식을 적극 활용하세요**
1284
+ - 제목은 #, ##, ### 을 사용하여 계층적으로 구성
1285
+ - 중요한 내용은 **굵게** 표시
1286
+ - 리스트는 -, * 또는 1. 2. 3. 형식 사용
1287
+ - 표가 필요한 경우 마크다운 표 형식 사용:
1288
+ | 항목 | 내용 | 비고 |
1289
+ |------|------|------|
1290
+ | 예시1 | 설명1 | 참고1 |
1291
+ - 코드는 ``` 로 감싸서 표시
1292
+ - 인용구는 > 를 사용
1293
+ - 구분선은 --- 사용"""
1294
+
1295
  final_executor_response = ""
1296
 
1297
  executor_text += "\n\n---\n\n[최종 보고서] 🔄 작성 중...\n"
 
1302
  final_executor_response += chunk
1303
  temp_text = f"[초기 구현] - {datetime.now().strftime('%H:%M:%S')}\n{all_responses['executor'][0]}\n\n---\n\n[최종 보고서] - {datetime.now().strftime('%H:%M:%S')}\n{final_executor_response}"
1304
  executor_text = temp_text
1305
+ yield supervisor_text, researcher_text, executor_text, evaluator_text, "", "📄 최종 보고서 작성 중..."
1306
 
1307
  all_responses["executor"].append(final_executor_response)
1308
 
1309
  # 최종 결과 생성 (최종 보고서를 메인으로)
1310
+ final_summary = f"""# 🎯 최종 종합 보고서
1311
 
1312
+ ## 📌 사용자 질문
1313
+ **{user_query}**
1314
+
1315
+ ---
1316
+
1317
+ ## 📄 최종 보고서 (실행자 AI - 모든 피드백 반영)
1318
 
 
1319
  {final_executor_response}
1320
 
1321
  ---
1322
 
1323
+ ## 📊 전체 프로세스 평가 (평가자 AI)
 
1324
 
1325
+ {evaluator_final_response}
 
1326
 
1327
+ ---
 
1328
 
1329
+ ## 🔍 핵심 조사 결과 요약 (조사자 AI)
 
1330
 
1331
+ {researcher_response[:800]}...
1332
+
1333
+ ---
1334
 
1335
+ ## 📋 프로세스 완료
 
1336
 
1337
+ | 항목 | 내용 |
1338
+ |------|------|
1339
+ | **사용 모델** | {'Gemini 2.5 Pro' if llm_system.use_gemini else '기본 LLM'} |
1340
+ | **프로세스** | 감독→조사→평가→감독→실행→평가→감독→평가→실행 |
1341
+ | **총 단계** | 9단계 협력 완료 |
1342
+ | **생성 시간** | {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} |
1343
 
1344
  ---
1345
+
1346
+ > 💡 **참고**: 이 보고서는 4개 AI의 협력을 통해 생성되었으며, 다단계 평가 프로세스를 거쳐 품질이 검증되었습니다."""
1347
 
1348
  # 내부 히스토리 업데이트 (UI에는 표시하지 않음)
1349
  internal_history.append((user_query, final_summary))
1350
 
1351
+ yield supervisor_text, researcher_text, executor_text, evaluator_text, final_summary, "✅ 최종 보고서 완성!"
1352
 
1353
  except Exception as e:
1354
  error_msg = f"❌ 처리 중 오류: {str(e)}"
1355
+ yield "", "", "", "", error_msg, error_msg
1356
 
1357
  def clear_all():
1358
  """모든 내용 초기화"""
1359
  global internal_history
1360
  internal_history = []
1361
+ return "", "", "", "", "", "🔄 초기화되었습니다."
1362
 
1363
  # Gradio 인터페이스
1364
  css = """
 
1368
  .supervisor-box textarea {
1369
  border-left: 4px solid #667eea !important;
1370
  padding-left: 10px !important;
1371
+ background-color: #f8f9ff !important;
1372
  }
1373
  .researcher-box textarea {
1374
  border-left: 4px solid #10b981 !important;
1375
  padding-left: 10px !important;
1376
+ background-color: #f0fdf4 !important;
1377
  }
1378
  .executor-box textarea {
1379
  border-left: 4px solid #764ba2 !important;
1380
  padding-left: 10px !important;
1381
+ background-color: #faf5ff !important;
1382
+ }
1383
+ .evaluator-box textarea {
1384
+ border-left: 4px solid #f59e0b !important;
1385
+ padding-left: 10px !important;
1386
+ background-color: #fffbeb !important;
1387
+ }
1388
+ .final-report-box {
1389
+ border: 2px solid #3b82f6 !important;
1390
+ border-radius: 8px !important;
1391
+ padding: 16px !important;
1392
+ background-color: #eff6ff !important;
1393
+ margin-top: 10px !important;
1394
+ font-size: 14px !important;
1395
+ max-height: 700px !important;
1396
+ overflow-y: auto !important;
1397
+ line-height: 1.6 !important;
1398
+ }
1399
+ .final-report-box h1 {
1400
+ color: #1e40af !important;
1401
+ font-size: 24px !important;
1402
+ margin-bottom: 12px !important;
1403
+ }
1404
+ .final-report-box h2 {
1405
+ color: #2563eb !important;
1406
+ font-size: 20px !important;
1407
+ margin-top: 16px !important;
1408
+ margin-bottom: 10px !important;
1409
+ }
1410
+ .final-report-box h3 {
1411
+ color: #3b82f6 !important;
1412
+ font-size: 18px !important;
1413
+ margin-top: 12px !important;
1414
+ margin-bottom: 8px !important;
1415
+ }
1416
+ .final-report-box table {
1417
+ border-collapse: collapse !important;
1418
+ width: 100% !important;
1419
+ margin: 16px 0 !important;
1420
+ }
1421
+ .final-report-box th, .final-report-box td {
1422
+ border: 1px solid #cbd5e1 !important;
1423
+ padding: 8px 10px !important;
1424
+ text-align: left !important;
1425
+ }
1426
+ .final-report-box th {
1427
+ background-color: #e0e7ff !important;
1428
+ font-weight: bold !important;
1429
+ color: #1e40af !important;
1430
+ }
1431
+ .final-report-box tr:nth-child(even) {
1432
+ background-color: #f8fafc !important;
1433
+ }
1434
+ .final-report-box tr:hover {
1435
+ background-color: #f0f4f8 !important;
1436
+ }
1437
+ .final-report-box code {
1438
+ background-color: #f1f5f9 !important;
1439
+ padding: 2px 6px !important;
1440
+ border-radius: 4px !important;
1441
+ font-family: 'Consolas', 'Monaco', monospace !important;
1442
+ color: #dc2626 !important;
1443
+ }
1444
+ .final-report-box pre {
1445
+ background-color: #1e293b !important;
1446
+ color: #e2e8f0 !important;
1447
+ padding: 12px !important;
1448
+ border-radius: 6px !important;
1449
+ overflow-x: auto !important;
1450
+ margin: 12px 0 !important;
1451
+ font-size: 13px !important;
1452
+ }
1453
+ .final-report-box pre code {
1454
+ background-color: transparent !important;
1455
+ color: #e2e8f0 !important;
1456
+ padding: 0 !important;
1457
+ }
1458
+ .final-report-box blockquote {
1459
+ border-left: 4px solid #3b82f6 !important;
1460
+ padding-left: 12px !important;
1461
+ margin-left: 0 !important;
1462
+ margin: 12px 0 !important;
1463
+ color: #475569 !important;
1464
+ font-style: italic !important;
1465
+ background-color: #f0f9ff !important;
1466
+ padding: 10px 12px !important;
1467
+ border-radius: 0 6px 6px 0 !important;
1468
+ }
1469
+ .final-report-box ul, .final-report-box ol {
1470
+ margin-left: 20px !important;
1471
+ margin-bottom: 12px !important;
1472
+ }
1473
+ .final-report-box li {
1474
+ margin-bottom: 6px !important;
1475
+ line-height: 1.6 !important;
1476
+ }
1477
+ .final-report-box strong {
1478
+ color: #1e40af !important;
1479
+ font-weight: 600 !important;
1480
+ }
1481
+ .final-report-box em {
1482
+ color: #3730a3 !important;
1483
+ }
1484
+ .final-report-box hr {
1485
+ border: none !important;
1486
+ border-top: 2px solid #cbd5e1 !important;
1487
+ margin: 24px 0 !important;
1488
+ }
1489
+ .final-report-box a {
1490
+ color: #2563eb !important;
1491
+ text-decoration: underline !important;
1492
+ }
1493
+ .final-report-box a:hover {
1494
+ color: #1d4ed8 !important;
1495
  }
1496
  """
1497
 
1498
+ with gr.Blocks(title="협력적 LLM 시스템 - 다단계 평가", theme=gr.themes.Soft(), css=css) as app:
1499
+ gr.Markdown(
1500
+ """
1501
+ # 🤝 협력적 LLM 시스템 (다단계 평가 프로세스)
1502
+
1503
+ ### 📋 프로세스 플로우
1504
+ ```
1505
+ 감독(분석) → 조사(검색) → 평가(조사) → 감독(지시) → 실행(초안)
1506
+ → 평가(초안) → 감독(개선) → 평가(최종) → 실행(완성)
1507
+ ```
1508
+
1509
+ **4개 AI의 협력을 통한 최고 품질의 답변 생성**
1510
+ """
1511
+ )
1512
 
1513
  # 입력 섹션
1514
  with gr.Row():
1515
  with gr.Column():
1516
+ gr.Markdown("""
1517
+ ## 🚀 4개 AI의 협력 시스템
1518
+ - **감독자 AI**: 거시적 분석과 전략 수립
1519
+ - **조사자 AI**: 웹 검색과 정보 수집/정리
1520
+ - **실행자 AI**: 구체적 계획 수립과 실행
1521
+ - **평가자 AI**: 전체 과정 평가와 개선점 제시
1522
+
1523
+ ### 🌟 주요 기능
1524
+ - 최대 4096 토큰 지원 (긴 응답 가능)
1525
+ - 20개 검색 결과와 동의어 검색
1526
+ - 신뢰도 기반 정보 평가
1527
+ - 다단계 평가와 피드백 반영
1528
+
1529
+ ### 📋 프로세스
1530
+ 감독 → 조사 → 평가 → 감독 → 실행 → 평가 → 감독 → 평가 → 실행
1531
+ """)
1532
+
1533
+ # LLM 선택 옵션
1534
+ llm_mode = gr.Radio(
1535
+ choices=["default", "commercial"],
1536
+ value="default",
1537
+ label="LLM 모드 선택",
1538
+ info="commercial을 선택하면 Gemini 2.5 Pro를 사용합니다"
1539
+ )
1540
+
1541
  user_input = gr.Textbox(
1542
  label="질문 입력",
1543
  placeholder="예: 기계학습 모델의 성능을 향상시키는 방법은?",
 
1552
  label="상태",
1553
  interactive=False,
1554
  value="대기 중...",
1555
+ max_lines=2
1556
  )
1557
 
1558
+ # 최종 결과 섹션 추가
1559
  with gr.Row():
1560
  with gr.Column():
1561
+ gr.Markdown("### 📊 최종 종합 보고서")
1562
+ final_report = gr.Markdown(
1563
+ value="*최종 보고서가 여기에 표시됩니다.*",
1564
+ elem_classes=["final-report-box"]
1565
+ )
1566
 
1567
+ # AI 출력들 - 2x2 그리드
1568
  with gr.Row():
1569
+ # 상단
1570
  with gr.Column():
1571
  gr.Markdown("### 🧠 감독자 AI (거시적 분석)")
1572
  supervisor_output = gr.Textbox(
1573
  label="",
1574
+ lines=12,
1575
+ max_lines=18,
1576
  interactive=False,
1577
  elem_classes=["supervisor-box"]
1578
  )
1579
 
 
1580
  with gr.Column():
1581
  gr.Markdown("### 🔍 조사자 AI (웹 검색 & 정리)")
1582
  researcher_output = gr.Textbox(
1583
  label="",
1584
+ lines=12,
1585
+ max_lines=18,
1586
  interactive=False,
1587
  elem_classes=["researcher-box"]
1588
  )
1589
+
1590
+ with gr.Row():
1591
+ # 하단 행
1592
  with gr.Column():
1593
  gr.Markdown("### 👁️ 실행자 AI (미시적 구현)")
1594
  executor_output = gr.Textbox(
1595
  label="",
1596
+ lines=12,
1597
+ max_lines=18,
1598
  interactive=False,
1599
  elem_classes=["executor-box"]
1600
  )
1601
+
1602
+ with gr.Column():
1603
+ gr.Markdown("### 📊 평가자 AI (전체 평가)")
1604
+ evaluator_output = gr.Textbox(
1605
+ label="",
1606
+ lines=12,
1607
+ max_lines=18,
1608
+ interactive=False,
1609
+ elem_classes=["evaluator-box"]
1610
+ )
1611
 
1612
  # 예제
1613
  gr.Examples(
1614
  examples=[
1615
  "기계학습 모델의 성능을 향상시키는 최신 방법은?",
1616
+ "2025년 효과적인 프로젝트 관리 도구와 전략은?",
1617
  "지속 가능한 비즈니스 모델의 최신 트렌드는?",
1618
  "최신 데이터 시각화 도구와 기법은?",
1619
+ "원격 팀의 생산성을 높이는 검증된 방법은?",
1620
+ "스타트업을 위한 효과적인 마케팅 전략은?",
1621
+ "AI 윤리와 규제의 최신 동향은?",
1622
+ "클라우드 네이티브 애플리케이션 개발 모범 사례는?"
1623
  ],
1624
  inputs=user_input,
1625
  label="💡 예제 질문"
 
1628
  # 이벤트 핸들러
1629
  submit_btn.click(
1630
  fn=process_query_streaming,
1631
+ inputs=[user_input, llm_mode],
1632
+ outputs=[supervisor_output, researcher_output, executor_output, evaluator_output, final_report, status_text]
1633
  ).then(
1634
  fn=lambda: "",
1635
  outputs=[user_input]
 
1637
 
1638
  user_input.submit(
1639
  fn=process_query_streaming,
1640
+ inputs=[user_input, llm_mode],
1641
+ outputs=[supervisor_output, researcher_output, executor_output, evaluator_output, final_report, status_text]
1642
  ).then(
1643
  fn=lambda: "",
1644
  outputs=[user_input]
 
1646
 
1647
  clear_btn.click(
1648
  fn=clear_all,
1649
+ outputs=[supervisor_output, researcher_output, executor_output, evaluator_output, final_report, status_text]
1650
  )
1651
 
1652