aiqtech commited on
Commit
19f25c1
ยท
verified ยท
1 Parent(s): 6ca9347

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +0 -1245
app.py CHANGED
@@ -1236,1251 +1236,6 @@ with gr.Blocks(title="ํ˜‘๋ ฅ์  LLM ์‹œ์Šคํ…œ", theme=gr.themes.Soft(), css=css)
1236
  )
1237
 
1238
 
1239
- if __name__ == "__main__":
1240
- app.queue() # ์ŠคํŠธ๋ฆฌ๋ฐ์„ ์œ„ํ•œ ํ ํ™œ์„ฑํ™”
1241
- app.launch(
1242
- server_name="0.0.0.0",
1243
- server_port=7860,
1244
- share=True,
1245
- show_error=True
1246
- )import gradio as gr
1247
- import os
1248
- import json
1249
- import requests
1250
- from datetime import datetime
1251
- import time
1252
- from typing import List, Dict, Any, Generator, Tuple
1253
- import logging
1254
- import re
1255
-
1256
- # ๋กœ๊น… ์„ค์ •
1257
- logging.basicConfig(level=logging.INFO)
1258
- logger = logging.getLogger(__name__)
1259
-
1260
- # ์ถ”๊ฐ€ ์ž„ํฌํŠธ
1261
- from bs4 import BeautifulSoup
1262
- from urllib.parse import urlparse
1263
- import urllib.request
1264
-
1265
- # Gemini API ์ž„ํฌํŠธ
1266
- try:
1267
- from google import genai
1268
- from google.genai import types
1269
- GEMINI_AVAILABLE = True
1270
- except ImportError:
1271
- GEMINI_AVAILABLE = False
1272
- logger.warning("Google Gemini API๊ฐ€ ์„ค์น˜๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. pip install google-genai๋กœ ์„ค์น˜ํ•˜์„ธ์š”.")
1273
-
1274
- # ํ™˜๊ฒฝ ๋ณ€์ˆ˜์—์„œ ํ† ํฐ ๊ฐ€์ ธ์˜ค๊ธฐ
1275
- FRIENDLI_TOKEN = os.getenv("FRIENDLI_TOKEN", "YOUR_FRIENDLI_TOKEN")
1276
- BAPI_TOKEN = os.getenv("BAPI_TOKEN", "YOUR_BRAVE_API_TOKEN")
1277
- GEMINI_API_KEY = os.getenv("GEMINI_API_KEY", "YOUR_GEMINI_API_KEY")
1278
- API_URL = "https://api.friendli.ai/dedicated/v1/chat/completions"
1279
- BRAVE_SEARCH_URL = "https://api.search.brave.com/res/v1/web/search"
1280
- MODEL_ID = "dep89a2fld32mcm"
1281
- TEST_MODE = os.getenv("TEST_MODE", "false").lower() == "true"
1282
-
1283
- # ์ „์—ญ ๋ณ€์ˆ˜
1284
- conversation_history = []
1285
-
1286
- class LLMCollaborativeSystem:
1287
- def __init__(self):
1288
- self.token = FRIENDLI_TOKEN
1289
- self.bapi_token = BAPI_TOKEN
1290
- self.gemini_api_key = GEMINI_API_KEY
1291
- self.api_url = API_URL
1292
- self.brave_url = BRAVE_SEARCH_URL
1293
- self.model_id = MODEL_ID
1294
- self.test_mode = TEST_MODE or (self.token == "YOUR_FRIENDLI_TOKEN")
1295
- self.use_gemini = False
1296
- self.gemini_client = None
1297
-
1298
- if self.test_mode:
1299
- logger.warning("ํ…Œ์ŠคํŠธ ๋ชจ๋“œ๋กœ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.")
1300
- if self.bapi_token == "YOUR_BRAVE_API_TOKEN":
1301
- logger.warning("Brave API ํ† ํฐ์ด ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.")
1302
- if self.gemini_api_key == "YOUR_GEMINI_API_KEY":
1303
- logger.warning("Gemini API ํ† ํฐ์ด ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.")
1304
-
1305
- def set_llm_mode(self, mode: str):
1306
- """LLM ๋ชจ๋“œ ์„ค์ • (default ๋˜๋Š” commercial)"""
1307
- if mode == "commercial" and GEMINI_AVAILABLE and self.gemini_api_key != "YOUR_GEMINI_API_KEY":
1308
- self.use_gemini = True
1309
- if not self.gemini_client:
1310
- self.gemini_client = genai.Client(api_key=self.gemini_api_key)
1311
- logger.info("Gemini 2.5 Pro ๋ชจ๋“œ๋กœ ์ „ํ™˜๋˜์—ˆ์Šต๋‹ˆ๋‹ค.")
1312
- else:
1313
- self.use_gemini = False
1314
- logger.info("๊ธฐ๋ณธ LLM ๋ชจ๋“œ๋กœ ์ „ํ™˜๋˜์—ˆ์Šต๋‹ˆ๋‹ค.")
1315
-
1316
- def create_headers(self):
1317
- """API ํ—ค๋” ์ƒ์„ฑ"""
1318
- return {
1319
- "Authorization": f"Bearer {self.token}",
1320
- "Content-Type": "application/json"
1321
- }
1322
-
1323
- def create_brave_headers(self):
1324
- """Brave API ํ—ค๋” ์ƒ์„ฑ"""
1325
- return {
1326
- "Accept": "application/json",
1327
- "Accept-Encoding": "gzip",
1328
- "X-Subscription-Token": self.bapi_token
1329
- }
1330
-
1331
- def create_supervisor_initial_prompt(self, user_query: str) -> str:
1332
- """๊ฐ๋…์ž AI ์ดˆ๊ธฐ ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ"""
1333
- return f"""๋‹น์‹ ์€ ๊ฑฐ์‹œ์  ๊ด€์ ์—์„œ ๋ถ„์„ํ•˜๊ณ  ์ง€๋„ํ•˜๋Š” ๊ฐ๋…์ž AI์ž…๋‹ˆ๋‹ค.
1334
-
1335
- ์‚ฌ์šฉ์ž ์งˆ๋ฌธ: {user_query}
1336
-
1337
- ์ด ์งˆ๋ฌธ์— ๋Œ€ํ•ด:
1338
- 1. ์ „์ฒด์ ์ธ ์ ‘๊ทผ ๋ฐฉํ–ฅ๊ณผ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์ œ์‹œํ•˜์„ธ์š”
1339
- 2. ํ•ต์‹ฌ ์š”์†Œ์™€ ๊ณ ๋ ค์‚ฌํ•ญ์„ ๊ตฌ์กฐํ™”ํ•˜์—ฌ ์„ค๋ช…ํ•˜์„ธ์š”
1340
- 3. ์ด ์ฃผ์ œ์— ๋Œ€ํ•ด ์กฐ์‚ฌ๊ฐ€ ํ•„์š”ํ•œ 5-7๊ฐœ์˜ ๊ตฌ์ฒด์ ์ธ ํ‚ค์›Œ๋“œ๋‚˜ ๊ฒ€์ƒ‰์–ด๋ฅผ ์ œ์‹œํ•˜์„ธ์š”
1341
-
1342
- ํ‚ค์›Œ๋“œ๋Š” ๋‹ค์Œ ํ˜•์‹์œผ๋กœ ์ œ์‹œํ•˜์„ธ์š”:
1343
- [๊ฒ€์ƒ‰ ํ‚ค์›Œ๋“œ]: ํ‚ค์›Œ๋“œ1, ํ‚ค์›Œ๋“œ2, ํ‚ค์›Œ๋“œ3, ํ‚ค์›Œ๋“œ4, ํ‚ค์›Œ๋“œ5"""
1344
-
1345
- def create_researcher_prompt(self, user_query: str, supervisor_guidance: str, search_results: Dict[str, List[Dict]]) -> str:
1346
- """์กฐ์‚ฌ์ž AI ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ"""
1347
- search_summary = ""
1348
- all_results = []
1349
-
1350
- for keyword, results in search_results.items():
1351
- search_summary += f"\n\n**{keyword}์— ๋Œ€ํ•œ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ:**\n"
1352
- for i, result in enumerate(results[:10], 1): # ์ƒ์œ„ 10๊ฐœ๋งŒ ํ‘œ์‹œ
1353
- search_summary += f"{i}. {result.get('title', 'N/A')} (์‹ ๋ขฐ๋„: {result.get('credibility_score', 0):.2f})\n"
1354
- search_summary += f" - {result.get('description', 'N/A')}\n"
1355
- search_summary += f" - ์ถœ์ฒ˜: {result.get('url', 'N/A')}\n"
1356
- if result.get('published'):
1357
- search_summary += f" - ๊ฒŒ์‹œ์ผ: {result.get('published')}\n"
1358
-
1359
- all_results.extend(results)
1360
-
1361
- # ๋ชจ์ˆœ ๊ฐ์ง€
1362
- contradictions = self.detect_contradictions(all_results)
1363
- contradiction_text = ""
1364
- if contradictions:
1365
- contradiction_text = "\n\n**๋ฐœ๊ฒฌ๋œ ์ •๋ณด ๋ชจ์ˆœ:**\n"
1366
- for cont in contradictions[:3]: # ์ตœ๋Œ€ 3๊ฐœ๋งŒ ํ‘œ์‹œ
1367
- contradiction_text += f"- {cont['type']}: {cont['source1']} vs {cont['source2']}\n"
1368
-
1369
- return f"""๋‹น์‹ ์€ ์ •๋ณด๋ฅผ ์กฐ์‚ฌํ•˜๊ณ  ์ •๋ฆฌํ•˜๋Š” ์กฐ์‚ฌ์ž AI์ž…๋‹ˆ๋‹ค.
1370
-
1371
- ์‚ฌ์šฉ์ž ์งˆ๋ฌธ: {user_query}
1372
-
1373
- ๊ฐ๋…์ž AI์˜ ์ง€์นจ:
1374
- {supervisor_guidance}
1375
-
1376
- ๋ธŒ๋ ˆ์ด๋ธŒ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ (์‹ ๋ขฐ๋„ ์ ์ˆ˜ ํฌํ•จ):
1377
- {search_summary}
1378
- {contradiction_text}
1379
-
1380
- ์œ„ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ:
1381
- 1. ๊ฐ ํ‚ค์›Œ๋“œ๋ณ„๋กœ ์ค‘์š”ํ•œ ์ •๋ณด๋ฅผ ์ •๋ฆฌํ•˜์„ธ์š”
1382
- 2. ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ์ถœ์ฒ˜(์‹ ๋ขฐ๋„ 0.7 ์ด์ƒ)๋ฅผ ์šฐ์„ ์ ์œผ๋กœ ์ฐธ๊ณ ํ•˜์„ธ์š”
1383
- 3. ์ถœ์ฒ˜๋ฅผ ๋ช…ํ™•ํžˆ ํ‘œ๊ธฐํ•˜์—ฌ ์‹คํ–‰์ž AI๊ฐ€ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜์„ธ์š”
1384
- 4. ์ •๋ณด์˜ ๋ชจ์ˆœ์ด ์žˆ๋‹ค๋ฉด ์–‘์ชฝ ๊ด€์ ์„ ๋ชจ๋‘ ์ œ์‹œํ•˜์„ธ์š”
1385
- 5. ์ตœ์‹  ํŠธ๋ Œ๋“œ๋‚˜ ์ค‘์š”ํ•œ ํ†ต๊ณ„๊ฐ€ ์žˆ๋‹ค๋ฉด ๊ฐ•์กฐํ•˜์„ธ์š”
1386
- 6. ์‹ ๋ขฐ๋„๊ฐ€ ๋‚ฎ์€ ์ •๋ณด๋Š” ์ฃผ์˜ ํ‘œ์‹œ์™€ ํ•จ๊ป˜ ํฌํ•จํ•˜์„ธ์š”"""
1387
-
1388
- def create_supervisor_execution_prompt(self, user_query: str, research_summary: str) -> str:
1389
- """๊ฐ๋…์ž AI์˜ ์‹คํ–‰ ์ง€์‹œ ํ”„๋กฌํ”„ํŠธ"""
1390
- return f"""๋‹น์‹ ์€ ๊ฑฐ์‹œ์  ๊ด€์ ์—์„œ ๋ถ„์„ํ•˜๊ณ  ์ง€๋„ํ•˜๋Š” ๊ฐ๋…์ž AI์ž…๋‹ˆ๋‹ค.
1391
-
1392
- ์‚ฌ์šฉ์ž ์งˆ๋ฌธ: {user_query}
1393
-
1394
- ์กฐ์‚ฌ์ž AI๊ฐ€ ์ •๋ฆฌํ•œ ์กฐ์‚ฌ ๋‚ด์šฉ:
1395
- {research_summary}
1396
-
1397
- ์œ„ ์กฐ์‚ฌ ๋‚ด์šฉ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์‹คํ–‰์ž AI์—๊ฒŒ ์•„์ฃผ ๊ตฌ์ฒด์ ์ธ ์ง€์‹œ๋ฅผ ๋‚ด๋ ค์ฃผ์„ธ์š”:
1398
- 1. ์กฐ์‚ฌ๋œ ์ •๋ณด๋ฅผ ์–ด๋–ป๊ฒŒ ํ™œ์šฉํ• ์ง€ ๋ช…ํ™•ํžˆ ์ง€์‹œํ•˜์„ธ์š”
1399
- 2. ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ๋‹จ๊ณ„๋ณ„ ์ž‘์—…์„ ๊ตฌ์ฒด์ ์œผ๋กœ ์ œ์‹œํ•˜์„ธ์š”
1400
- 3. ๊ฐ ๋‹จ๊ณ„์—์„œ ์ฐธ๊ณ ํ•ด์•ผ ํ•  ์กฐ์‚ฌ ๋‚ด์šฉ์„ ๋ช…์‹œํ•˜์„ธ์š”
1401
- 4. ์˜ˆ์ƒ๋˜๋Š” ๊ฒฐ๊ณผ๋ฌผ์˜ ํ˜•ํƒœ๋ฅผ ๊ตฌ์ฒด์ ์œผ๋กœ ์„ค๋ช…ํ•˜์„ธ์š”"""
1402
-
1403
- def create_executor_prompt(self, user_query: str, supervisor_guidance: str, research_summary: str) -> str:
1404
- """์‹คํ–‰์ž AI ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ"""
1405
- return f"""๋‹น์‹ ์€ ์„ธ๋ถ€์ ์ธ ๋‚ด์šฉ์„ ๊ตฌํ˜„ํ•˜๋Š” ์‹คํ–‰์ž AI์ž…๋‹ˆ๋‹ค.
1406
-
1407
- ์‚ฌ์šฉ์ž ์งˆ๋ฌธ: {user_query}
1408
-
1409
- ์กฐ์‚ฌ์ž AI๊ฐ€ ์ •๋ฆฌํ•œ ์กฐ์‚ฌ ๋‚ด์šฉ:
1410
- {research_summary}
1411
-
1412
- ๊ฐ๋…์ž AI์˜ ๊ตฌ์ฒด์ ์ธ ์ง€์‹œ:
1413
- {supervisor_guidance}
1414
-
1415
- ์œ„ ์กฐ์‚ฌ ๋‚ด์šฉ๊ณผ ์ง€์‹œ์‚ฌํ•ญ์„ ๋ฐ”ํƒ•์œผ๋กœ:
1416
- 1. ์กฐ์‚ฌ๋œ ์ •๋ณด๋ฅผ ์ ๊ทน ํ™œ์šฉํ•˜์—ฌ ๊ตฌ์ฒด์ ์ธ ์‹คํ–‰ ๊ณ„ํš์„ ์ž‘์„ฑํ•˜์„ธ์š”
1417
- 2. ๊ฐ ๋‹จ๊ณ„๋ณ„๋กœ ์ฐธ๊ณ ํ•œ ์กฐ์‚ฌ ๋‚ด์šฉ์„ ๋ช…์‹œํ•˜์„ธ์š”
1418
- 3. ์‹ค์ œ๋กœ ์ ์šฉ ๊ฐ€๋Šฅํ•œ ๊ตฌ์ฒด์ ์ธ ๋ฐฉ๋ฒ•๋ก ์„ ์ œ์‹œํ•˜์„ธ์š”
1419
- 4. ์˜ˆ์ƒ๋˜๋Š” ์„ฑ๊ณผ์™€ ์ธก์ • ๋ฐฉ๋ฒ•์„ ํฌํ•จํ•˜์„ธ์š”"""
1420
-
1421
- def create_executor_final_prompt(self, user_query: str, initial_response: str, supervisor_feedback: str, research_summary: str) -> str:
1422
- """์‹คํ–‰์ž AI ์ตœ์ข… ๋ณด๊ณ ์„œ ํ”„๋กฌํ”„ํŠธ"""
1423
- return f"""๋‹น์‹ ์€ ์„ธ๋ถ€์ ์ธ ๋‚ด์šฉ์„ ๊ตฌํ˜„ํ•˜๋Š” ์‹คํ–‰์ž AI์ž…๋‹ˆ๋‹ค.
1424
-
1425
- ์‚ฌ์šฉ์ž ์งˆ๋ฌธ: {user_query}
1426
-
1427
- ์กฐ์‚ฌ์ž AI์˜ ์กฐ์‚ฌ ๋‚ด์šฉ:
1428
- {research_summary}
1429
-
1430
- ๋‹น์‹ ์˜ ์ดˆ๊ธฐ ๋‹ต๋ณ€:
1431
- {initial_response}
1432
-
1433
- ๊ฐ๋…์ž AI์˜ ํ”ผ๋“œ๋ฐฑ ๋ฐ ๊ฐœ์„ ์‚ฌํ•ญ:
1434
- {supervisor_feedback}
1435
-
1436
- ์œ„ ํ”ผ๋“œ๋ฐฑ์„ ์™„์ „ํžˆ ๋ฐ˜์˜ํ•˜์—ฌ ์ตœ์ข… ๋ณด๊ณ ์„œ๋ฅผ ์ž‘์„ฑํ•˜์„ธ์š”:
1437
- 1. ๊ฐ๋…์ž์˜ ๋ชจ๋“  ๊ฐœ์„ ์‚ฌํ•ญ์„ ๋ฐ˜์˜ํ•˜์„ธ์š”
1438
- 2. ์กฐ์‚ฌ ๋‚ด์šฉ์„ ๋”์šฑ ๊ตฌ์ฒด์ ์œผ๋กœ ํ™œ์šฉํ•˜์„ธ์š”
1439
- 3. ์‹คํ–‰ ๊ฐ€๋Šฅ์„ฑ์„ ๋†’์ด๋Š” ์„ธ๋ถ€ ๊ณ„ํš์„ ํฌํ•จํ•˜์„ธ์š”
1440
- 4. ๋ช…ํ™•ํ•œ ๊ฒฐ๋ก ๊ณผ ๋‹ค์Œ ๋‹จ๊ณ„๋ฅผ ์ œ์‹œํ•˜์„ธ์š”
1441
- 5. ์ „๋ฌธ์ ์ด๊ณ  ์™„์„ฑ๋„ ๋†’์€ ์ตœ์ข… ๋ณด๊ณ ์„œ ํ˜•์‹์œผ๋กœ ์ž‘์„ฑํ•˜์„ธ์š”"""
1442
-
1443
- def create_evaluator_prompt(self, user_query: str, supervisor_responses: List[str], researcher_response: str, executor_responses: List[str]) -> str:
1444
- """ํ‰๊ฐ€์ž AI ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ"""
1445
- return f"""๋‹น์‹ ์€ ์ „์ฒด ํ˜‘๋ ฅ ๊ณผ์ •๊ณผ ๊ฒฐ๊ณผ๋ฅผ ํ‰๊ฐ€ํ•˜๋Š” ํ‰๊ฐ€์ž AI์ž…๋‹ˆ๋‹ค.
1446
-
1447
- ์‚ฌ์šฉ์ž ์งˆ๋ฌธ: {user_query}
1448
-
1449
- ๊ฐ๋…์ž AI์˜ ๋ถ„์„ ๋ฐ ์ง€์‹œ:
1450
- - ์ดˆ๊ธฐ ๋ถ„์„: {supervisor_responses[0]}
1451
- - ์‹คํ–‰ ์ง€์‹œ: {supervisor_responses[1]}
1452
- - ๊ฒ€ํ†  ํ”ผ๋“œ๋ฐฑ: {supervisor_responses[2]}
1453
-
1454
- ์กฐ์‚ฌ์ž AI์˜ ์กฐ์‚ฌ ๊ฒฐ๊ณผ:
1455
- {researcher_response}
1456
-
1457
- ์‹คํ–‰์ž AI์˜ ๊ตฌํ˜„:
1458
- - ์ดˆ๊ธฐ ๊ตฌํ˜„: {executor_responses[0]}
1459
- - ์ตœ์ข… ๋ณด๊ณ ์„œ: {executor_responses[1]}
1460
-
1461
- ์œ„ ์ „์ฒด ๊ณผ์ •์„ ํ‰๊ฐ€ํ•˜์—ฌ:
1462
- 1. **ํ’ˆ์งˆ ํ‰๊ฐ€**: ๊ฐ AI์˜ ๋‹ต๋ณ€ ํ’ˆ์งˆ๊ณผ ์—ญํ•  ์ˆ˜ํ–‰๋„๋ฅผ ํ‰๊ฐ€ํ•˜์„ธ์š” (10์  ๋งŒ์ )
1463
- 2. **ํ˜‘๋ ฅ ํšจ๊ณผ์„ฑ**: AI ๊ฐ„ ํ˜‘๋ ฅ์ด ์–ผ๋งˆ๋‚˜ ํšจ๊ณผ์ ์ด์—ˆ๋Š”์ง€ ํ‰๊ฐ€ํ•˜์„ธ์š”
1464
- 3. **์ •๋ณด ํ™œ์šฉ๋„**: ์›น ๊ฒ€์ƒ‰ ์ •๋ณด๊ฐ€ ์–ผ๋งˆ๋‚˜ ์ž˜ ํ™œ์šฉ๋˜์—ˆ๋Š”์ง€ ํ‰๊ฐ€ํ•˜์„ธ์š”
1465
- 4. **๊ฐœ์„ ์ **: ํ–ฅํ›„ ๊ฐœ์„ ์ด ํ•„์š”ํ•œ ๋ถ€๋ถ„์„ ๊ตฌ์ฒด์ ์œผ๋กœ ์ œ์‹œํ•˜์„ธ์š”
1466
- 5. **์ตœ์ข… ํ‰์ **: ์ „์ฒด ํ”„๋กœ์„ธ์Šค์— ๋Œ€ํ•œ ์ข…ํ•ฉ ํ‰๊ฐ€๋ฅผ ์ œ์‹œํ•˜์„ธ์š”
1467
-
1468
- ํ‰๊ฐ€๋Š” ๊ตฌ์ฒด์ ์ด๊ณ  ๊ฑด์„ค์ ์œผ๋กœ ์ž‘์„ฑํ•˜์„ธ์š”."""
1469
-
1470
- def extract_keywords(self, supervisor_response: str) -> List[str]:
1471
- """๊ฐ๋…์ž ์‘๋‹ต์—์„œ ํ‚ค์›Œ๋“œ ์ถ”์ถœ"""
1472
- keywords = []
1473
-
1474
- # [๊ฒ€์ƒ‰ ํ‚ค์›Œ๋“œ]: ํ˜•์‹์œผ๋กœ ํ‚ค์›Œ๋“œ ์ฐพ๊ธฐ
1475
- keyword_match = re.search(r'\[๊ฒ€์ƒ‰ ํ‚ค์›Œ๋“œ\]:\s*(.+)', supervisor_response, re.IGNORECASE)
1476
- if keyword_match:
1477
- keyword_str = keyword_match.group(1)
1478
- keywords = [k.strip() for k in keyword_str.split(',') if k.strip()]
1479
-
1480
- # ํ‚ค์›Œ๋“œ๊ฐ€ ์—†์œผ๋ฉด ๊ธฐ๋ณธ ํ‚ค์›Œ๋“œ ์ƒ์„ฑ
1481
- if not keywords:
1482
- keywords = ["best practices", "implementation guide", "case studies", "latest trends", "success factors"]
1483
-
1484
- return keywords[:7] # ์ตœ๋Œ€ 7๊ฐœ๋กœ ์ œํ•œ
1485
-
1486
- def generate_synonyms(self, keyword: str) -> List[str]:
1487
- """ํ‚ค์›Œ๋“œ์˜ ๋™์˜์–ด/์œ ์‚ฌ์–ด ์ƒ์„ฑ"""
1488
- synonyms = {
1489
- "optimization": ["improvement", "enhancement", "efficiency", "tuning"],
1490
- "performance": ["speed", "efficiency", "throughput", "latency"],
1491
- "strategy": ["approach", "method", "technique", "plan"],
1492
- "implementation": ["deployment", "execution", "development", "integration"],
1493
- "analysis": ["evaluation", "assessment", "study", "research"],
1494
- "management": ["administration", "governance", "control", "supervision"],
1495
- "best practices": ["proven methods", "industry standards", "guidelines", "recommendations"],
1496
- "trends": ["developments", "innovations", "emerging", "future"],
1497
- "machine learning": ["ML", "AI", "deep learning", "neural networks"],
1498
- "ํ”„๋กœ์ ํŠธ": ["project", "์‚ฌ์—…", "์—…๋ฌด", "์ž‘์—…"]
1499
- }
1500
-
1501
- # ํ‚ค์›Œ๋“œ ์ •๊ทœํ™”
1502
- keyword_lower = keyword.lower()
1503
-
1504
- # ์ง์ ‘ ๋งค์นญ๋˜๋Š” ๋™์˜์–ด๊ฐ€ ์žˆ์œผ๋ฉด ๋ฐ˜ํ™˜
1505
- if keyword_lower in synonyms:
1506
- return synonyms[keyword_lower][:2] # ์ตœ๋Œ€ 2๊ฐœ
1507
-
1508
- # ๋ถ€๋ถ„ ๋งค์นญ ํ™•์ธ
1509
- for key, values in synonyms.items():
1510
- if key in keyword_lower or keyword_lower in key:
1511
- return values[:2]
1512
-
1513
- # ๋™์˜์–ด๊ฐ€ ์—†์œผ๋ฉด ๋นˆ ๋ฆฌ์ŠคํŠธ
1514
- return []
1515
-
1516
- def calculate_credibility_score(self, result: Dict) -> float:
1517
- """๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ์˜ ์‹ ๋ขฐ๋„ ์ ์ˆ˜ ๊ณ„์‚ฐ (0-1)"""
1518
- score = 0.5 # ๊ธฐ๋ณธ ์ ์ˆ˜
1519
-
1520
- url = result.get('url', '')
1521
- title = result.get('title', '')
1522
- description = result.get('description', '')
1523
-
1524
- # URL ๊ธฐ๋ฐ˜ ์ ์ˆ˜
1525
- trusted_domains = [
1526
- '.edu', '.gov', '.org', 'wikipedia.org', 'nature.com',
1527
- 'sciencedirect.com', 'ieee.org', 'acm.org', 'springer.com',
1528
- 'harvard.edu', 'mit.edu', 'stanford.edu', 'github.com'
1529
- ]
1530
-
1531
- for domain in trusted_domains:
1532
- if domain in url:
1533
- score += 0.2
1534
- break
1535
-
1536
- # HTTPS ์‚ฌ์šฉ ์—ฌ๋ถ€
1537
- if url.startswith('https://'):
1538
- score += 0.1
1539
-
1540
- # ์ œ๋ชฉ๊ณผ ์„ค๋ช…์˜ ๊ธธ์ด (๋„ˆ๋ฌด ์งง์œผ๋ฉด ์‹ ๋ขฐ๋„ ๊ฐ์†Œ)
1541
- if len(title) > 20:
1542
- score += 0.05
1543
- if len(description) > 50:
1544
- score += 0.05
1545
-
1546
- # ๊ด‘๊ณ /์ŠคํŒธ ํ‚ค์›Œ๋“œ ์ฒดํฌ
1547
- spam_keywords = ['buy now', 'sale', 'discount', 'click here', '100% free']
1548
- if any(spam in (title + description).lower() for spam in spam_keywords):
1549
- score -= 0.3
1550
-
1551
- # ๋‚ ์งœ ์ •๋ณด๊ฐ€ ์žˆ์œผ๋ฉด ๊ฐ€์‚ฐ์ 
1552
- if any(year in description for year in ['2024', '2023', '2022']):
1553
- score += 0.1
1554
-
1555
- return max(0, min(1, score)) # 0-1 ๋ฒ”์œ„๋กœ ์ œํ•œ
1556
-
1557
- def fetch_url_content(self, url: str, max_length: int = 2000) -> str:
1558
- """URL์—์„œ ์ฝ˜ํ…์ธ  ์ถ”์ถœ"""
1559
- try:
1560
- # User-Agent ์„ค์ •
1561
- headers = {
1562
- 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
1563
- }
1564
-
1565
- req = urllib.request.Request(url, headers=headers)
1566
-
1567
- with urllib.request.urlopen(req, timeout=5) as response:
1568
- html = response.read().decode('utf-8', errors='ignore')
1569
-
1570
- soup = BeautifulSoup(html, 'html.parser')
1571
-
1572
- # ์Šคํฌ๋ฆฝํŠธ์™€ ์Šคํƒ€์ผ ์ œ๊ฑฐ
1573
- for script in soup(["script", "style"]):
1574
- script.decompose()
1575
-
1576
- # ๋ณธ๋ฌธ ํ…์ŠคํŠธ ์ถ”์ถœ
1577
- text = soup.get_text()
1578
-
1579
- # ๊ณต๋ฐฑ ์ •๋ฆฌ
1580
- lines = (line.strip() for line in text.splitlines())
1581
- chunks = (phrase.strip() for line in lines for phrase in line.split(" "))
1582
- text = ' '.join(chunk for chunk in chunks if chunk)
1583
-
1584
- # ๊ธธ์ด ์ œํ•œ
1585
- if len(text) > max_length:
1586
- text = text[:max_length] + "..."
1587
-
1588
- return text
1589
-
1590
- except Exception as e:
1591
- logger.error(f"URL ์ฝ˜ํ…์ธ  ๊ฐ€์ ธ์˜ค๊ธฐ ์‹คํŒจ {url}: {str(e)}")
1592
- return ""
1593
-
1594
- def detect_contradictions(self, results: List[Dict]) -> List[Dict]:
1595
- """๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ๊ฐ„ ๋ชจ์ˆœ ๊ฐ์ง€"""
1596
- contradictions = []
1597
-
1598
- # ๊ฐ„๋‹จํ•œ ๋ชจ์ˆœ ๊ฐ์ง€ ํŒจํ„ด
1599
- opposite_pairs = [
1600
- ("increase", "decrease"),
1601
- ("improve", "worsen"),
1602
- ("effective", "ineffective"),
1603
- ("success", "failure"),
1604
- ("benefit", "harm"),
1605
- ("positive", "negative"),
1606
- ("growth", "decline")
1607
- ]
1608
-
1609
- # ๊ฒฐ๊ณผ๋“ค์„ ๋น„๊ต
1610
- for i in range(len(results)):
1611
- for j in range(i + 1, len(results)):
1612
- desc1 = results[i].get('description', '').lower()
1613
- desc2 = results[j].get('description', '').lower()
1614
-
1615
- # ๋ฐ˜๋Œ€ ๊ฐœ๋…์ด ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธ
1616
- for word1, word2 in opposite_pairs:
1617
- if (word1 in desc1 and word2 in desc2) or (word2 in desc1 and word1 in desc2):
1618
- # ๊ฐ™์€ ์ฃผ์ œ์— ๋Œ€ํ•ด ๋ฐ˜๋Œ€ ์˜๊ฒฌ์ธ์ง€ ํ™•์ธ
1619
- common_words = set(desc1.split()) & set(desc2.split())
1620
- if len(common_words) > 5: # ๊ณตํ†ต ๋‹จ์–ด๊ฐ€ 5๊ฐœ ์ด์ƒ์ด๋ฉด ๊ฐ™์€ ์ฃผ์ œ๋กœ ๊ฐ„์ฃผ
1621
- contradictions.append({
1622
- 'source1': results[i]['url'],
1623
- 'source2': results[j]['url'],
1624
- 'type': f"{word1} vs {word2}",
1625
- 'desc1': results[i]['description'][:100],
1626
- 'desc2': results[j]['description'][:100]
1627
- })
1628
-
1629
- return contradictions
1630
-
1631
- def brave_search(self, query: str) -> List[Dict]:
1632
- """Brave Search API ํ˜ธ์ถœ"""
1633
- if self.test_mode or self.bapi_token == "YOUR_BRAVE_API_TOKEN":
1634
- # ํ…Œ์ŠคํŠธ ๋ชจ๋“œ์—์„œ๋Š” ์‹œ๋ฎฌ๋ ˆ์ด์…˜๋œ ๊ฒฐ๊ณผ ๋ฐ˜ํ™˜
1635
- test_results = []
1636
- for i in range(5):
1637
- test_results.append({
1638
- "title": f"Best Practices for {query} - Source {i+1}",
1639
- "description": f"Comprehensive guide on implementing {query} with proven methodologies and real-world examples from industry leaders.",
1640
- "url": f"https://example{i+1}.com/{query.replace(' ', '-')}",
1641
- "credibility_score": 0.7 + (i * 0.05)
1642
- })
1643
- return test_results
1644
-
1645
- try:
1646
- params = {
1647
- "q": query,
1648
- "count": 20, # 20๊ฐœ๋กœ ์ฆ๊ฐ€
1649
- "safesearch": "moderate",
1650
- "freshness": "pw" # Past week for recent results
1651
- }
1652
-
1653
- response = requests.get(
1654
- self.brave_url,
1655
- headers=self.create_brave_headers(),
1656
- params=params,
1657
- timeout=10
1658
- )
1659
-
1660
- if response.status_code == 200:
1661
- data = response.json()
1662
- results = []
1663
- for item in data.get("web", {}).get("results", [])[:20]:
1664
- result = {
1665
- "title": item.get("title", ""),
1666
- "description": item.get("description", ""),
1667
- "url": item.get("url", ""),
1668
- "published": item.get("published", "")
1669
- }
1670
- # ์‹ ๋ขฐ๋„ ์ ์ˆ˜ ๊ณ„์‚ฐ
1671
- result["credibility_score"] = self.calculate_credibility_score(result)
1672
- results.append(result)
1673
-
1674
- # ์‹ ๋ขฐ๋„ ์ ์ˆ˜ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌ
1675
- results.sort(key=lambda x: x['credibility_score'], reverse=True)
1676
- return results
1677
- else:
1678
- logger.error(f"Brave API ์˜ค๋ฅ˜: {response.status_code}")
1679
- return []
1680
-
1681
- except Exception as e:
1682
- logger.error(f"Brave ๊ฒ€์ƒ‰ ์ค‘ ์˜ค๋ฅ˜: {str(e)}")
1683
- return []
1684
-
1685
- def simulate_streaming(self, text: str, role: str) -> Generator[str, None, None]:
1686
- """ํ…Œ์ŠคํŠธ ๋ชจ๋“œ์—์„œ ์ŠคํŠธ๋ฆฌ๋ฐ ์‹œ๋ฎฌ๋ ˆ์ด์…˜"""
1687
- words = text.split()
1688
- for i in range(0, len(words), 3):
1689
- chunk = " ".join(words[i:i+3])
1690
- yield chunk + " "
1691
- time.sleep(0.05)
1692
-
1693
- def call_gemini_streaming(self, messages: List[Dict[str, str]], role: str) -> Generator[str, None, None]:
1694
- """Gemini API ์ŠคํŠธ๋ฆฌ๋ฐ ํ˜ธ์ถœ"""
1695
- if not self.gemini_client:
1696
- yield "โŒ Gemini API ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค."
1697
- return
1698
-
1699
- try:
1700
- # ์‹œ์Šคํ…œ ํ”„๋กฌํ”„ํŠธ ์„ค์ •
1701
- system_prompts = {
1702
- "supervisor": "๋‹น์‹ ์€ ๊ฑฐ์‹œ์  ๊ด€์ ์—์„œ ๋ถ„์„ํ•˜๊ณ  ์ง€๋„ํ•˜๋Š” ๊ฐ๋…์ž AI์ž…๋‹ˆ๋‹ค.",
1703
- "researcher": "๋‹น์‹ ์€ ์ •๋ณด๋ฅผ ์กฐ์‚ฌํ•˜๊ณ  ์ฒด๊ณ„์ ์œผ๋กœ ์ •๋ฆฌํ•˜๋Š” ์กฐ์‚ฌ์ž AI์ž…๋‹ˆ๋‹ค.",
1704
- "executor": "๋‹น์‹ ์€ ์„ธ๋ถ€์ ์ธ ๋‚ด์šฉ์„ ๊ตฌํ˜„ํ•˜๋Š” ์‹คํ–‰์ž AI์ž…๋‹ˆ๋‹ค.",
1705
- "evaluator": "๋‹น์‹ ์€ ์ „์ฒด ํ˜‘๋ ฅ ๊ณผ์ •๊ณผ ๊ฒฐ๊ณผ๋ฅผ ํ‰๊ฐ€ํ•˜๋Š” ํ‰๊ฐ€์ž AI์ž…๋‹ˆ๋‹ค."
1706
- }
1707
-
1708
- # Gemini ํ˜•์‹์˜ contents ๊ตฌ์„ฑ
1709
- contents = []
1710
-
1711
- # ์‹œ์Šคํ…œ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ฒซ ๋ฒˆ์งธ ์‚ฌ์šฉ์ž ๋ฉ”์‹œ์ง€๋กœ ์ถ”๊ฐ€
1712
- contents.append(types.Content(
1713
- role="user",
1714
- parts=[types.Part.from_text(text=system_prompts.get(role, ""))]
1715
- ))
1716
- contents.append(types.Content(
1717
- role="model",
1718
- parts=[types.Part.from_text(text="๋„ค, ์ดํ•ดํ–ˆ์Šต๋‹ˆ๋‹ค. ์ œ ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.")]
1719
- ))
1720
-
1721
- # ์‚ฌ์šฉ์ž ๋ฉ”์‹œ์ง€ ์ถ”๊ฐ€
1722
- for msg in messages:
1723
- if msg["role"] == "user":
1724
- contents.append(types.Content(
1725
- role="user",
1726
- parts=[types.Part.from_text(text=msg["content"])]
1727
- ))
1728
-
1729
- # GenerateContentConfig ์„ค์ •
1730
- generate_content_config = types.GenerateContentConfig(
1731
- temperature=0.7,
1732
- top_p=0.8,
1733
- max_output_tokens=2048,
1734
- response_mime_type="text/plain"
1735
- )
1736
-
1737
- # ์ŠคํŠธ๋ฆฌ๋ฐ ์ƒ์„ฑ
1738
- for chunk in self.gemini_client.models.generate_content_stream(
1739
- model="gemini-2.5-pro",
1740
- contents=contents,
1741
- config=generate_content_config,
1742
- ):
1743
- if chunk.text:
1744
- yield chunk.text
1745
-
1746
- except Exception as e:
1747
- logger.error(f"Gemini API ์˜ค๋ฅ˜: {str(e)}")
1748
- yield f"โŒ Gemini API ์˜ค๋ฅ˜: {str(e)}"
1749
-
1750
- def call_llm_streaming(self, messages: List[Dict[str, str]], role: str) -> Generator[str, None, None]:
1751
- """์ŠคํŠธ๋ฆฌ๋ฐ LLM API ํ˜ธ์ถœ"""
1752
-
1753
- # Gemini ๋ชจ๋“œ์ธ ๊ฒฝ์šฐ
1754
- if self.use_gemini:
1755
- yield from self.call_gemini_streaming(messages, role)
1756
- return
1757
-
1758
- # ํ…Œ์ŠคํŠธ ๋ชจ๋“œ
1759
- if self.test_mode:
1760
- logger.info(f"ํ…Œ์ŠคํŠธ ๋ชจ๋“œ ์ŠคํŠธ๋ฆฌ๋ฐ - Role: {role}")
1761
- test_responses = {
1762
- "supervisor_initial": """์ด ์งˆ๋ฌธ์— ๋Œ€ํ•œ ๊ฑฐ์‹œ์  ๋ถ„์„์„ ์ œ์‹œํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.
1763
-
1764
- 1. **ํ•ต์‹ฌ ๊ฐœ๋… ํŒŒ์•…**
1765
- - ์งˆ๋ฌธ์˜ ๋ณธ์งˆ์  ์š”์†Œ๋ฅผ ์‹ฌ์ธต ๋ถ„์„ํ•ฉ๋‹ˆ๋‹ค
1766
- - ๊ด€๋ จ๋œ ์ฃผ์š” ์ด๋ก ๊ณผ ์›์น™์„ ๊ฒ€ํ† ํ•ฉ๋‹ˆ๋‹ค
1767
- - ๋‹ค์–‘ํ•œ ๊ด€์ ์—์„œ์˜ ์ ‘๊ทผ ๋ฐฉ๋ฒ•์„ ๊ณ ๋ คํ•ฉ๋‹ˆ๋‹ค
1768
-
1769
- 2. **์ „๋žต์  ์ ‘๊ทผ ๋ฐฉํ–ฅ**
1770
- - ์ฒด๊ณ„์ ์ด๊ณ  ๋‹จ๊ณ„๋ณ„ ํ•ด๊ฒฐ ๋ฐฉ์•ˆ์„ ์ˆ˜๋ฆฝํ•ฉ๋‹ˆ๋‹ค
1771
- - ์žฅ๋‹จ๊ธฐ ๋ชฉํ‘œ๋ฅผ ๋ช…ํ™•ํžˆ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค
1772
- - ๋ฆฌ์Šคํฌ ์š”์ธ๊ณผ ๋Œ€์‘ ๋ฐฉ์•ˆ์„ ๋งˆ๋ จํ•ฉ๋‹ˆ๋‹ค
1773
-
1774
- 3. **๊ธฐ๋Œ€ ํšจ๊ณผ์™€ ๊ณผ์ œ**
1775
- - ์˜ˆ์ƒ๋˜๋Š” ๊ธ์ •์  ์„ฑ๊ณผ๋ฅผ ๋ถ„์„ํ•ฉ๋‹ˆ๋‹ค
1776
- - ์ž ์žฌ์  ๋„์ „ ๊ณผ์ œ๋ฅผ ์‹๋ณ„ํ•ฉ๋‹ˆ๋‹ค
1777
- - ์ง€์†๊ฐ€๋Šฅํ•œ ๋ฐœ์ „ ๋ฐฉํ–ฅ์„ ์ œ์‹œํ•ฉ๋‹ˆ๋‹ค
1778
-
1779
- [๊ฒ€์ƒ‰ ํ‚ค์›Œ๋“œ]: machine learning optimization, performance improvement strategies, model efficiency techniques, hyperparameter tuning best practices, latest ML trends 2024""",
1780
-
1781
- "researcher": """์กฐ์‚ฌ ๊ฒฐ๊ณผ๋ฅผ ์ข…ํ•ฉํ•˜์—ฌ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค.
1782
-
1783
- **1. Machine Learning Optimization (์‹ ๋ขฐ๋„ ๋†’์Œ)**
1784
- - ์ตœ์‹  ์—ฐ๊ตฌ์— ๋”ฐ๋ฅด๋ฉด ๋ชจ๋ธ ์ตœ์ ํ™”์˜ ํ•ต์‹ฌ์€ ์•„ํ‚คํ…์ฒ˜ ์„ค๊ณ„์™€ ํ›ˆ๋ จ ์ „๋žต์˜ ๊ท ํ˜•์ž…๋‹ˆ๋‹ค (์‹ ๋ขฐ๋„: 0.85)
1785
- - AutoML ๋„๊ตฌ๋“ค์ด ํ•˜์ดํผํŒŒ๋ผ๋ฏธํ„ฐ ํŠœ๋‹์„ ์ž๋™ํ™”ํ•˜์—ฌ ํšจ์œจ์„ฑ์„ ํฌ๊ฒŒ ํ–ฅ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค (์‹ ๋ขฐ๋„: 0.82)
1786
- - ์ถœ์ฒ˜: ML Conference 2024 (https://mlconf2024.org), Google Research (https://research.google)
1787
-
1788
- **2. Performance Improvement Strategies (์‹ ๋ขฐ๋„ ๋†’์Œ)**
1789
- - ๋ฐ์ดํ„ฐ ํ’ˆ์งˆ ๊ฐœ์„ ์ด ๋ชจ๋ธ ์„ฑ๋Šฅ ํ–ฅ์ƒ์˜ 80%๋ฅผ ์ฐจ์ง€ํ•œ๋‹ค๋Š” ์—ฐ๊ตฌ ๊ฒฐ๊ณผ (์‹ ๋ขฐ๋„: 0.90)
1790
- - ์•™์ƒ๋ธ” ๊ธฐ๋ฒ•๊ณผ ์ „์ดํ•™์Šต์ด ์ฃผ์š” ์„ฑ๋Šฅ ๊ฐœ์„  ๋ฐฉ๋ฒ•์œผ๋กœ ์ž…์ฆ๋จ (์‹ ๋ขฐ๋„: 0.78)
1791
- - ์ถœ์ฒ˜: Stanford AI Lab (https://ai.stanford.edu), MIT CSAIL (https://csail.mit.edu)
1792
-
1793
- **3. Model Efficiency Techniques (์‹ ๋ขฐ๋„ ์ค‘๊ฐ„)**
1794
- - ๋ชจ๋ธ ๊ฒฝ๋Ÿ‰ํ™”(Pruning, Quantization)๋กœ ์ถ”๋ก  ์†๋„ 10๋ฐฐ ํ–ฅ์ƒ ๊ฐ€๋Šฅ (์‹ ๋ขฐ๋„: 0.75)
1795
- - Knowledge Distillation์œผ๋กœ ๋ชจ๋ธ ํฌ๊ธฐ 90% ๊ฐ์†Œ, ์„ฑ๋Šฅ ์œ ์ง€ (์‹ ๋ขฐ๋„: 0.72)
1796
- - ์ถœ์ฒ˜: ArXiv ๋…ผ๋ฌธ (https://arxiv.org/abs/2023.xxxxx)
1797
-
1798
- **4. ์‹ค์ œ ์ ์šฉ ์‚ฌ๋ก€ (์‹ ๋ขฐ๋„ ๋†’์Œ)**
1799
- - Netflix: ์ถ”์ฒœ ์‹œ์Šคํ…œ ๊ฐœ์„ ์œผ๋กœ ์‚ฌ์šฉ์ž ๋งŒ์กฑ๋„ 35% ํ–ฅ์ƒ (์‹ ๋ขฐ๋„: 0.88)
1800
- - Tesla: ์‹ค์‹œ๊ฐ„ ๊ฐ์ฒด ์ธ์‹ ์†๋„ 50% ๊ฐœ์„  (์‹ ๋ขฐ๋„: 0.80)
1801
- - OpenAI: GPT ๋ชจ๋ธ ํšจ์œจ์„ฑ ๊ฐœ์„ ์œผ๋กœ ๋น„์šฉ 70% ์ ˆ๊ฐ (์‹ ๋ขฐ๋„: 0.85)
1802
-
1803
- **ํ•ต์‹ฌ ์ธ์‚ฌ์ดํŠธ:**
1804
- - ์ตœ์‹  ํŠธ๋ Œ๋“œ๋Š” ํšจ์œจ์„ฑ๊ณผ ์„ฑ๋Šฅ์˜ ๊ท ํ˜•์— ์ดˆ์ 
1805
- - 2024๋…„ ๋“ค์–ด Sparse Models์™€ MoE(Mixture of Experts) ๊ธฐ๋ฒ•์ด ๋ถ€์ƒ
1806
- - ์‹ค๋ฌด ์ ์šฉ ์‹œ ๋‹จ๊ณ„๋ณ„ ๊ฒ€์ฆ์ด ์„ฑ๊ณต์˜ ํ•ต์‹ฌ""",
1807
-
1808
- "supervisor_execution": """์กฐ์‚ฌ ๋‚ด์šฉ์„ ๋ฐ”ํƒ•์œผ๋กœ ์‹คํ–‰์ž AI์—๊ฒŒ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ตฌ์ฒด์ ์œผ๋กœ ์ง€์‹œํ•ฉ๋‹ˆ๋‹ค.
1809
-
1810
- **1๋‹จ๊ณ„: ํ˜„์žฌ ๋ชจ๋ธ ์ง„๋‹จ (1์ฃผ์ฐจ)**
1811
- - ์กฐ์‚ฌ๋œ ๋ฒค์น˜๋งˆํฌ ๊ธฐ์ค€์œผ๋กœ ํ˜„์žฌ ๋ชจ๋ธ ์„ฑ๋Šฅ ํ‰๊ฐ€
1812
- - Netflix ์‚ฌ๋ก€๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ ์ฃผ์š” ๋ณ‘๋ชฉ ์ง€์  ์‹๋ณ„
1813
- - AutoML ๋„๊ตฌ๋ฅผ ํ™œ์šฉํ•œ ์ดˆ๊ธฐ ์ตœ์ ํ™” ๊ฐ€๋Šฅ์„ฑ ํƒ์ƒ‰
1814
-
1815
- **2๋‹จ๊ณ„: ๋ฐ์ดํ„ฐ ํ’ˆ์งˆ ๊ฐœ์„  (2-3์ฃผ์ฐจ)**
1816
- - ์กฐ์‚ฌ ๊ฒฐ๊ณผ์˜ "80% ๊ทœ์น™"์— ๋”ฐ๋ผ ๋ฐ์ดํ„ฐ ์ •์ œ ์šฐ์„  ์‹คํ–‰
1817
- - ๋ฐ์ดํ„ฐ ์ฆ๊ฐ• ๊ธฐ๋ฒ• ์ ์šฉ (์กฐ์‚ฌ๋œ ์ตœ์‹  ๊ธฐ๋ฒ• ํ™œ์šฉ)
1818
- - A/B ํ…Œ์ŠคํŠธ๋กœ ๊ฐœ์„  ํšจ๊ณผ ์ธก์ •
1819
-
1820
- **3๋‹จ๊ณ„: ๋ชจ๋ธ ์ตœ์ ํ™” ๊ตฌํ˜„ (4-6์ฃผ์ฐจ)**
1821
- - Knowledge Distillation ์ ์šฉํ•˜์—ฌ ๋ชจ๋ธ ๊ฒฝ๋Ÿ‰ํ™”
1822
- - ์กฐ์‚ฌ๋œ Pruning ๊ธฐ๋ฒ•์œผ๋กœ ์ถ”๋ก  ์†๋„ ๊ฐœ์„ 
1823
- - Tesla ์‚ฌ๋ก€์˜ ์‹ค์‹œ๊ฐ„ ์ฒ˜๋ฆฌ ์ตœ์ ํ™” ๊ธฐ๋ฒ• ๋ฒค์น˜๋งˆํ‚น
1824
-
1825
- **4๋‹จ๊ณ„: ์„ฑ๊ณผ ๊ฒ€์ฆ ๋ฐ ๋ฐฐํฌ (7-8์ฃผ์ฐจ)**
1826
- - OpenAI ์‚ฌ๋ก€์˜ ๋น„์šฉ ์ ˆ๊ฐ ์ง€ํ‘œ ์ ์šฉ
1827
- - ์กฐ์‚ฌ๋œ ์„ฑ๋Šฅ ์ง€ํ‘œ๋กœ ๊ฐœ์„ ์œจ ์ธก์ •
1828
- - ๋‹จ๊ณ„์  ๋ฐฐํฌ ์ „๋žต ์ˆ˜๋ฆฝ""",
1829
-
1830
- "executor": """๊ฐ๋…์ž์˜ ์ง€์‹œ์™€ ์กฐ์‚ฌ ๋‚ด์šฉ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์ฒด์ ์ธ ์‹คํ–‰ ๊ณ„ํš์„ ์ˆ˜๋ฆฝํ•ฉ๋‹ˆ๋‹ค.
1831
-
1832
- **1๋‹จ๊ณ„: ํ˜„์žฌ ๋ชจ๋ธ ์ง„๋‹จ (1์ฃผ์ฐจ)**
1833
- - ์›”์š”์ผ-ํ™”์š”์ผ: MLflow๋ฅผ ์‚ฌ์šฉํ•œ ํ˜„์žฌ ๋ชจ๋ธ ๋ฉ”ํŠธ๋ฆญ ์ˆ˜์ง‘
1834
- * ์กฐ์‚ฌ ๊ฒฐ๊ณผ ์ฐธ๊ณ : Netflix๊ฐ€ ์‚ฌ์šฉํ•œ ํ•ต์‹ฌ ์ง€ํ‘œ (์ •ํ™•๋„, ์ง€์—ฐ์‹œ๊ฐ„, ์ฒ˜๋ฆฌ๋Ÿ‰)
1835
- - ์ˆ˜์š”์ผ-๋ชฉ์š”์ผ: AutoML ๋„๊ตฌ (Optuna, Ray Tune) ์„ค์ • ๋ฐ ์ดˆ๊ธฐ ์‹คํ–‰
1836
- * ์กฐ์‚ฌ๋œ best practice์— ๋”ฐ๋ผ search space ์ •์˜
1837
- - ๊ธˆ์š”์ผ: ์ง„๋‹จ ๋ณด๊ณ ์„œ ์ž‘์„ฑ ๋ฐ ๊ฐœ์„  ์šฐ์„ ์ˆœ์œ„ ๊ฒฐ์ •
1838
-
1839
- **2๋‹จ๊ณ„: ๋ฐ์ดํ„ฐ ํ’ˆ์งˆ ๊ฐœ์„  (2-3์ฃผ์ฐจ)**
1840
- - ๋ฐ์ดํ„ฐ ์ •์ œ ํŒŒ์ดํ”„๋ผ์ธ ๊ตฌ์ถ•
1841
- * ์กฐ์‚ฌ ๊ฒฐ๊ณผ์˜ "80% ๊ทœ์น™" ์ ์šฉ: ๋ˆ„๋ฝ๊ฐ’, ์ด์ƒ์น˜, ๋ ˆ์ด๋ธ” ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ
1842
- * ์ฝ”๋“œ ์˜ˆ์‹œ: `data_quality_pipeline.py` ๊ตฌํ˜„
1843
- - ๋ฐ์ดํ„ฐ ์ฆ๊ฐ• ๊ตฌํ˜„
1844
- * ์ตœ์‹  ๊ธฐ๋ฒ• ์ ์šฉ: MixUp, CutMix, AutoAugment
1845
- * ๊ฒ€์ฆ ๋ฐ์ดํ„ฐ์…‹์œผ๋กœ ํšจ๊ณผ ์ธก์ • (๋ชฉํ‘œ: 15% ์„ฑ๋Šฅ ํ–ฅ์ƒ)
1846
-
1847
- **3๋‹จ๊ณ„: ๋ชจ๋ธ ์ตœ์ ํ™” ๊ตฌํ˜„ (4-6์ฃผ์ฐจ)**
1848
- - Knowledge Distillation ๊ตฌํ˜„
1849
- * Teacher ๋ชจ๋ธ: ํ˜„์žฌ ๋Œ€๊ทœ๋ชจ ๋ชจ๋ธ
1850
- * Student ๋ชจ๋ธ: 90% ์ž‘์€ ํฌ๊ธฐ ๋ชฉํ‘œ (์กฐ์‚ฌ ๊ฒฐ๊ณผ ๊ธฐ๋ฐ˜)
1851
- * ๊ตฌํ˜„ ํ”„๋ ˆ์ž„์›Œํฌ: PyTorch/TensorFlow""",
1852
-
1853
- "supervisor_review": """์‹คํ–‰์ž AI์˜ ๊ณ„ํš์„ ๊ฒ€ํ† ํ•œ ๊ฒฐ๊ณผ, ์กฐ์‚ฌ ๋‚ด์šฉ์ด ์ž˜ ๋ฐ˜์˜๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฐœ์„ ์‚ฌํ•ญ์„ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค.
1854
-
1855
- **๊ฐ•์ **
1856
- - ์กฐ์‚ฌ๋œ ์‚ฌ๋ก€๋“ค(Netflix, Tesla, OpenAI)์ด ๊ฐ ๋‹จ๊ณ„์— ์ ์ ˆํžˆ ํ™œ์šฉ๋จ
1857
- - ๊ตฌ์ฒด์ ์ธ ๋„๊ตฌ์™€ ๊ธฐ๋ฒ•์ด ๋ช…์‹œ๋˜์–ด ์‹คํ–‰ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์Œ
1858
- - ์ธก์ • ๊ฐ€๋Šฅํ•œ ๋ชฉํ‘œ๊ฐ€ ์กฐ์‚ฌ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์„ค์ •๋จ
1859
-
1860
- **๊ฐœ์„  ํ•„์š”์‚ฌํ•ญ**
1861
- 1. **๋ฆฌ์Šคํฌ ๊ด€๋ฆฌ ๊ฐ•ํ™”**
1862
- - ๊ฐ ๋‹จ๊ณ„๋ณ„ ์‹คํŒจ ์‹œ๋‚˜๋ฆฌ์˜ค์™€ ๋Œ€์‘ ๋ฐฉ์•ˆ ์ถ”๊ฐ€ ํ•„์š”
1863
- - ๊ธฐ์ˆ ์  ๋ฌธ์ œ ๋ฐœ์ƒ ์‹œ ๋ฐฑ์—… ๊ณ„ํš ์ˆ˜๋ฆฝ
1864
-
1865
- 2. **๋น„์šฉ ๋ถ„์„ ๊ตฌ์ฒดํ™”**
1866
- - OpenAI ์‚ฌ๋ก€์˜ 70% ์ ˆ๊ฐ์„ ์œ„ํ•œ ๊ตฌ์ฒด์ ์ธ ๋น„์šฉ ๊ณ„์‚ฐ
1867
- - ROI ๋ถ„์„ ๋ฐ ํˆฌ์ž ๋Œ€๋น„ ํšจ๊ณผ ์ธก์ • ๋ฐฉ๋ฒ•
1868
-
1869
- **์ถ”๊ฐ€ ๊ถŒ์žฅ์‚ฌํ•ญ**
1870
- - ์ตœ์‹  ์—ฐ๊ตฌ ๋™ํ–ฅ ๋ชจ๋‹ˆํ„ฐ๋ง ์ฒด๊ณ„ ๊ตฌ์ถ•
1871
- - ๊ฒฝ์Ÿ์‚ฌ ๋ฒค์น˜๋งˆํ‚น์„ ์œ„ํ•œ ์ •๊ธฐ์ ์ธ ์กฐ์‚ฌ ํ”„๋กœ์„ธ์Šค""",
1872
-
1873
- "executor_final": """๊ฐ๋…์ž AI์˜ ํ”ผ๋“œ๋ฐฑ์„ ์™„์ „ํžˆ ๋ฐ˜์˜ํ•˜์—ฌ ์ตœ์ข… ์‹คํ–‰ ๋ณด๊ณ ์„œ๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.
1874
-
1875
- # ๐ŸŽฏ ๊ธฐ๊ณ„ํ•™์Šต ๋ชจ๋ธ ์„ฑ๋Šฅ ํ–ฅ์ƒ ์ตœ์ข… ์‹คํ–‰ ๋ณด๊ณ ์„œ
1876
-
1877
- ## ๐Ÿ“‹ Executive Summary
1878
- ๋ณธ ๋ณด๊ณ ์„œ๋Š” ์›น ๊ฒ€์ƒ‰์„ ํ†ตํ•ด ์ˆ˜์ง‘๋œ ์ตœ์‹  ์‚ฌ๋ก€์™€ ๊ฐ๋…์ž AI์˜ ์ „๋žต์  ์ง€์นจ์„ ๋ฐ”ํƒ•์œผ๋กœ, 8์ฃผ๊ฐ„์˜ ์ฒด๊ณ„์ ์ธ ๋ชจ๋ธ ์ตœ์ ํ™” ํ”„๋กœ์ ํŠธ๋ฅผ ์ œ์‹œํ•ฉ๋‹ˆ๋‹ค. ๋ชฉํ‘œ๋Š” ๋ชจ๋ธ ํฌ๊ธฐ 90% ๊ฐ์†Œ, ์ถ”๋ก  ์†๋„ 10๋ฐฐ ํ–ฅ์ƒ, ์šด์˜ ๋น„์šฉ 70% ์ ˆ๊ฐ์ž…๋‹ˆ๋‹ค.
1879
-
1880
- ## ๐Ÿ“Š 1๋‹จ๊ณ„: ํ˜„์žฌ ๋ชจ๋ธ ์ง„๋‹จ ๋ฐ ๋ฒ ์ด์Šค๋ผ์ธ ์„ค์ • (1์ฃผ์ฐจ)
1881
-
1882
- ### ์‹คํ–‰ ๊ณ„ํš
1883
- **์›”-ํ™”์š”์ผ: ์„ฑ๋Šฅ ๋ฉ”ํŠธ๋ฆญ ์ˆ˜์ง‘**
1884
- - MLflow๋ฅผ ํ†ตํ•œ ํ˜„์žฌ ๋ชจ๋ธ ์ „์ฒด ๋ถ„์„
1885
- - Netflix ์‚ฌ๋ก€ ๊ธฐ๋ฐ˜ ํ•ต์‹ฌ ์ง€ํ‘œ: ์ •ํ™•๋„(92%), ์ง€์—ฐ์‹œ๊ฐ„(45ms), ์ฒ˜๋ฆฌ๋Ÿ‰(1,000 req/s)
1886
-
1887
- **์ˆ˜-๋ชฉ์š”์ผ: AutoML ์ดˆ๊ธฐ ํƒ์ƒ‰**
1888
- - Optuna๋กœ ํ•˜์ดํผํŒŒ๋ผ๋ฏธํ„ฐ ์ตœ์ ํ™” (200ํšŒ ์‹œ๋„)
1889
- - Ray Tune์œผ๋กœ ๋ถ„์‚ฐ ํ•™์Šต ํ™˜๊ฒฝ ๊ตฌ์ถ•
1890
-
1891
- ### ์˜ˆ์ƒ ์‚ฐ์ถœ๋ฌผ
1892
- - ์ƒ์„ธ ์„ฑ๋Šฅ ๋ฒ ์ด์Šค๋ผ์ธ ๋ฌธ์„œ
1893
- - ๊ฐœ์„  ๊ธฐํšŒ ์šฐ์„ ์ˆœ์œ„ ๋งคํŠธ๋ฆญ์Šค
1894
-
1895
- ## ๐Ÿ“Š 2๋‹จ๊ณ„: ๋ฐ์ดํ„ฐ ํ’ˆ์งˆ ๊ฐœ์„  (2-3์ฃผ์ฐจ)
1896
-
1897
- ### ์‹คํ–‰ ๊ณ„ํš
1898
- - ๋ฐ์ดํ„ฐ ์ •์ œ ํŒŒ์ดํ”„๋ผ์ธ ๊ตฌ์ถ•
1899
- - ๊ณ ๊ธ‰ ๋ฐ์ดํ„ฐ ์ฆ๊ฐ• ๊ธฐ๋ฒ• ์ ์šฉ
1900
- - A/B ํ…Œ์ŠคํŠธ๋กœ ํšจ๊ณผ ๊ฒ€์ฆ
1901
-
1902
- ## ๐Ÿ“Š 3๋‹จ๊ณ„: ๋ชจ๋ธ ์ตœ์ ํ™” ๊ตฌํ˜„ (4-6์ฃผ์ฐจ)
1903
-
1904
- ### ์‹คํ–‰ ๊ณ„ํš
1905
- - Knowledge Distillation์œผ๋กœ ๋ชจ๋ธ ๊ฒฝ๋Ÿ‰ํ™”
1906
- - Pruning & Quantization ์ ์šฉ
1907
- - TensorRT ์ตœ์ ํ™” (Tesla ์‚ฌ๋ก€ ์ ์šฉ)
1908
-
1909
- ## ๐Ÿ“Š 4๋‹จ๊ณ„: ์„ฑ๊ณผ ๊ฒ€์ฆ ๋ฐ ํ”„๋กœ๋•์…˜ ๋ฐฐํฌ (7-8์ฃผ์ฐจ)
1910
-
1911
- ### ์‹คํ–‰ ๊ณ„ํš
1912
- - ์ข…ํ•ฉ ์„ฑ๋Šฅ ๊ฒ€์ฆ ๋ฐ ์ง€ํ‘œ ๋‹ฌ์„ฑ๋„ ํ™•์ธ
1913
- - Canary ๋ฐฐํฌ ์ „๋žต ์‹คํ–‰
1914
- - ์‹ค์‹œ๊ฐ„ ๋ชจ๋‹ˆํ„ฐ๋ง ์ฒด๊ณ„ ๊ตฌ์ถ•
1915
-
1916
- ## ๐Ÿ“ ๊ฒฐ๋ก 
1917
- ๋ณธ ํ”„๋กœ์ ํŠธ๋Š” ์ตœ์‹  ์—ฐ๊ตฌ ๊ฒฐ๊ณผ์™€ ์—…๊ณ„ ๋ฒ ์ŠคํŠธ ํ”„๋ž™ํ‹ฐ์Šค๋ฅผ ์ ์šฉํ•˜์—ฌ, 8์ฃผ ๋งŒ์— ๋ชจ๋ธ ์„ฑ๋Šฅ์„ ํš๊ธฐ์ ์œผ๋กœ ๊ฐœ์„ ํ•˜๊ณ  ์šด์˜ ๋น„์šฉ์„ 70% ์ ˆ๊ฐํ•˜๋Š” ์„ฑ๊ณผ๋ฅผ ๋‹ฌ์„ฑํ•  ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒ๋ฉ๋‹ˆ๋‹ค.""",
1918
-
1919
- "evaluator": """## ๐Ÿ“Š ์ „์ฒด ํ˜‘๋ ฅ ๊ณผ์ • ํ‰๊ฐ€ ๋ณด๊ณ ์„œ
1920
-
1921
- ### 1๏ธโƒฃ ํ’ˆ์งˆ ํ‰๊ฐ€ (10์  ๋งŒ์ )
1922
-
1923
- **๊ฐ๋…์ž AI: 9.5/10**
1924
- - ๊ฑฐ์‹œ์  ๊ด€์ ์—์„œ ์ฒด๊ณ„์ ์ธ ๋ถ„์„๊ณผ ๋ฐฉํ–ฅ ์ œ์‹œ
1925
- - ๋‹จ๊ณ„๋ณ„ ๊ตฌ์ฒด์ ์ธ ์ง€์‹œ์‚ฌํ•ญ ์ œ๊ณต
1926
- - ํ”ผ๋“œ๋ฐฑ์ด ๊ฑด์„ค์ ์ด๊ณ  ์‹คํ–‰ ๊ฐ€๋Šฅํ•จ
1927
-
1928
- **์กฐ์‚ฌ๏ฟฝ๏ฟฝ๏ฟฝ AI: 9.0/10**
1929
- - ์›น ๊ฒ€์ƒ‰์„ ํ†ตํ•œ ์ตœ์‹  ์ •๋ณด ์ˆ˜์ง‘ ์šฐ์ˆ˜
1930
- - ์‹ ๋ขฐ๋„ ํ‰๊ฐ€์™€ ๋ชจ์ˆœ ๊ฐ์ง€ ๊ธฐ๋Šฅ ํšจ๊ณผ์ 
1931
- - ์ถœ์ฒ˜ ํ‘œ๊ธฐ์™€ ์ •๋ณด ์ •๋ฆฌ๊ฐ€ ์ฒด๊ณ„์ 
1932
-
1933
- **์‹คํ–‰์ž AI: 8.5/10**
1934
- - ์กฐ์‚ฌ ๋‚ด์šฉ์„ ์ž˜ ํ™œ์šฉํ•œ ๊ตฌ์ฒด์  ๊ณ„ํš ์ˆ˜๋ฆฝ
1935
- - ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ๋‹จ๊ณ„๋ณ„ ์ ‘๊ทผ๋ฒ• ์ œ์‹œ
1936
- - ์ผ๋ถ€ ์„ธ๋ถ€์‚ฌํ•ญ์—์„œ ๋” ๊ตฌ์ฒดํ™” ํ•„์š”
1937
-
1938
- ### 2๏ธโƒฃ ํ˜‘๋ ฅ ํšจ๊ณผ์„ฑ ํ‰๊ฐ€
1939
-
1940
- **๊ฐ•์ :**
1941
- - AI ๊ฐ„ ์—ญํ•  ๋ถ„๋‹ด์ด ๋ช…ํ™•ํ•˜๊ณ  ์ƒํ˜ธ๋ณด์™„์ 
1942
- - ์ •๋ณด ํ๋ฆ„์ด ์ฒด๊ณ„์ ์ด๊ณ  ์ผ๊ด€์„ฑ ์žˆ์Œ
1943
- - ํ”ผ๋“œ๋ฐฑ ๋ฐ˜์˜์ด ํšจ๊ณผ์ ์œผ๋กœ ์ด๋ฃจ์–ด์ง
1944
-
1945
- **๊ฐœ์„ ์ :**
1946
- - ์‹ค์‹œ๊ฐ„ ์ƒํ˜ธ์ž‘์šฉ ๋ฉ”์ปค๋‹ˆ์ฆ˜ ์ถ”๊ฐ€ ๊ณ ๋ ค
1947
- - ์ค‘๊ฐ„ ์ ๊ฒ€ ๋‹จ๊ณ„ ๋„์ž… ํ•„์š”
1948
-
1949
- ### 3๏ธโƒฃ ์ •๋ณด ํ™œ์šฉ๋„ ํ‰๊ฐ€
1950
-
1951
- **์šฐ์ˆ˜ํ•œ ์ :**
1952
- - 20๊ฐœ ์ด์ƒ์˜ ์›น ์†Œ์Šค์—์„œ ์ •๋ณด ์ˆ˜์ง‘
1953
- - ์‹ ๋ขฐ๋„ ๊ธฐ๋ฐ˜ ์ •๋ณด ์„ ๋ณ„ ํšจ๊ณผ์ 
1954
- - ์‹ค์ œ ๊ธฐ์—… ์‚ฌ๋ก€ ์ ์ ˆํžˆ ํ™œ์šฉ
1955
-
1956
- **๋ณด์™„ ํ•„์š”:**
1957
- - ํ•™์ˆ  ๋…ผ๋ฌธ ๋“ฑ ๋” ๊นŠ์ด ์žˆ๋Š” ์ž๋ฃŒ ํ™œ์šฉ
1958
- - ์ง€์—ญ๋ณ„/์‚ฐ์—…๋ณ„ ํŠน์„ฑ ๊ณ ๋ ค ํ•„์š”
1959
-
1960
- ### 4๏ธโƒฃ ํ–ฅํ›„ ๊ฐœ์„  ๋ฐฉํ–ฅ
1961
-
1962
- 1. **์‹ค์‹œ๊ฐ„ ํ˜‘์—… ๊ฐ•ํ™”**
1963
- - AI ๊ฐ„ ์ค‘๊ฐ„ ์ฒดํฌํฌ์ธํŠธ ์ถ”๊ฐ€
1964
- - ๋™์  ์—ญํ•  ์กฐ์ • ๋ฉ”์ปค๋‹ˆ์ฆ˜ ๋„์ž…
1965
-
1966
- 2. **์ •๋ณด ๊ฒ€์ฆ ๊ฐ•ํ™”**
1967
- - ๊ต์ฐจ ๊ฒ€์ฆ ํ”„๋กœ์„ธ์Šค ์ถ”๊ฐ€
1968
- - ์ „๋ฌธ๊ฐ€ ๊ฒ€ํ†  ๋‹จ๊ณ„ ๊ณ ๋ ค
1969
-
1970
- 3. **๋งž์ถคํ™” ๊ฐ•ํ™”**
1971
- - ์‚ฌ์šฉ์ž ์ปจํ…์ŠคํŠธ ๋” ๊นŠ์ด ๋ฐ˜์˜
1972
- - ์‚ฐ์—…๋ณ„/๊ทœ๋ชจ๋ณ„ ๋งž์ถค ์ „๋žต ์ œ๊ณต
1973
-
1974
- ### 5๏ธโƒฃ ์ตœ์ข… ํ‰์ : โญโญโญโญโญ 9.0/10
1975
-
1976
- **์ข…ํ•ฉ ํ‰๊ฐ€:**
1977
- ๋ณธ ํ˜‘๋ ฅ ์‹œ์Šคํ…œ์€ ๊ฐ AI์˜ ์ „๋ฌธ์„ฑ์„ ํšจ๊ณผ์ ์œผ๋กœ ํ™œ์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž ์งˆ๋ฌธ์— ๋Œ€ํ•œ ์ข…ํ•ฉ์ ์ด๊ณ  ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ๋‹ต๋ณ€์„ ์ œ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค. ํŠนํžˆ ์›น ๊ฒ€์ƒ‰์„ ํ†ตํ•œ ์ตœ์‹  ์ •๋ณด ํ™œ์šฉ๊ณผ ๋‹จ๊ณ„์  ํ”ผ๋“œ๋ฐฑ ๋ฐ˜์˜์ด ์šฐ์ˆ˜ํ–ˆ์Šต๋‹ˆ๋‹ค. ํ–ฅํ›„ ์‹ค์‹œ๊ฐ„ ํ˜‘์—…๊ณผ ๋งž์ถคํ™”๋ฅผ ๋”์šฑ ๊ฐ•ํ™”ํ•œ๋‹ค๋ฉด ๋”์šฑ ๋›ฐ์–ด๋‚œ ์„ฑ๊ณผ๋ฅผ ๋‹ฌ์„ฑํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค."""
1978
- }
1979
-
1980
- # ํ”„๋กฌํ”„ํŠธ ๋‚ด์šฉ์— ๋”ฐ๋ผ ์ ์ ˆํ•œ ์‘๋‹ต ์„ ํƒ
1981
- if role == "supervisor" and "์กฐ์‚ฌ์ž AI๊ฐ€ ์ •๋ฆฌํ•œ" in messages[0]["content"]:
1982
- response = test_responses["supervisor_execution"]
1983
- elif role == "supervisor" and messages[0]["content"].find("์‹คํ–‰์ž AI์˜ ๋‹ต๋ณ€") > -1:
1984
- response = test_responses["supervisor_review"]
1985
- elif role == "supervisor":
1986
- response = test_responses["supervisor_initial"]
1987
- elif role == "researcher":
1988
- response = test_responses["researcher"]
1989
- elif role == "executor" and "์ตœ์ข… ๋ณด๊ณ ์„œ" in messages[0]["content"]:
1990
- response = test_responses["executor_final"]
1991
- elif role == "evaluator":
1992
- response = test_responses["evaluator"]
1993
- else:
1994
- response = test_responses["executor"]
1995
-
1996
- yield from self.simulate_streaming(response, role)
1997
- return
1998
-
1999
- # ์‹ค์ œ API ํ˜ธ์ถœ
2000
- try:
2001
- system_prompts = {
2002
- "supervisor": "๋‹น์‹ ์€ ๊ฑฐ์‹œ์  ๊ด€์ ์—์„œ ๋ถ„์„ํ•˜๊ณ  ์ง€๋„ํ•˜๋Š” ๊ฐ๋…์ž AI์ž…๋‹ˆ๋‹ค.",
2003
- "researcher": "๋‹น์‹ ์€ ์ •๋ณด๋ฅผ ์กฐ์‚ฌํ•˜๊ณ  ์ฒด๊ณ„์ ์œผ๋กœ ์ •๋ฆฌํ•˜๋Š” ์กฐ์‚ฌ์ž AI์ž…๋‹ˆ๋‹ค.",
2004
- "executor": "๋‹น์‹ ์€ ์„ธ๋ถ€์ ์ธ ๋‚ด์šฉ์„ ๊ตฌํ˜„ํ•˜๋Š” ์‹คํ–‰์ž AI์ž…๋‹ˆ๋‹ค.",
2005
- "evaluator": "๋‹น์‹ ์€ ์ „์ฒด ํ˜‘๋ ฅ ๊ณผ์ •๊ณผ ๊ฒฐ๊ณผ๋ฅผ ํ‰๊ฐ€ํ•˜๋Š” ํ‰๊ฐ€์ž AI์ž…๋‹ˆ๋‹ค."
2006
- }
2007
-
2008
- full_messages = [
2009
- {"role": "system", "content": system_prompts.get(role, "")},
2010
- *messages
2011
- ]
2012
-
2013
- payload = {
2014
- "model": self.model_id,
2015
- "messages": full_messages,
2016
- "max_tokens": 2048,
2017
- "temperature": 0.7,
2018
- "top_p": 0.8,
2019
- "stream": True,
2020
- "stream_options": {"include_usage": True}
2021
- }
2022
-
2023
- logger.info(f"API ์ŠคํŠธ๋ฆฌ๋ฐ ํ˜ธ์ถœ ์‹œ์ž‘ - Role: {role}")
2024
-
2025
- response = requests.post(
2026
- self.api_url,
2027
- headers=self.create_headers(),
2028
- json=payload,
2029
- stream=True,
2030
- timeout=10
2031
- )
2032
-
2033
- if response.status_code != 200:
2034
- logger.error(f"API ์˜ค๋ฅ˜: {response.status_code}")
2035
- yield f"โŒ API ์˜ค๋ฅ˜ ({response.status_code}): {response.text[:200]}"
2036
- return
2037
-
2038
- for line in response.iter_lines():
2039
- if line:
2040
- line = line.decode('utf-8')
2041
- if line.startswith("data: "):
2042
- data = line[6:]
2043
- if data == "[DONE]":
2044
- break
2045
- try:
2046
- chunk = json.loads(data)
2047
- if "choices" in chunk and chunk["choices"]:
2048
- content = chunk["choices"][0].get("delta", {}).get("content", "")
2049
- if content:
2050
- yield content
2051
- except json.JSONDecodeError:
2052
- continue
2053
-
2054
- except requests.exceptions.Timeout:
2055
- yield "โฑ๏ธ API ํ˜ธ์ถœ ์‹œ๊ฐ„์ด ์ดˆ๊ณผ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ์‹œ๋„ํ•ด์ฃผ์„ธ์š”."
2056
- except requests.exceptions.ConnectionError:
2057
- yield "๐Ÿ”Œ API ์„œ๋ฒ„์— ์—ฐ๊ฒฐํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ธํ„ฐ๋„ท ์—ฐ๊ฒฐ์„ ํ™•์ธํ•ด์ฃผ์„ธ์š”."
2058
- except Exception as e:
2059
- logger.error(f"์ŠคํŠธ๋ฆฌ๋ฐ ์ค‘ ์˜ค๋ฅ˜: {str(e)}")
2060
- yield f"โŒ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}"
2061
-
2062
- # ์‹œ์Šคํ…œ ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ
2063
- llm_system = LLMCollaborativeSystem()
2064
-
2065
- # ๋‚ด๋ถ€ ํžˆ์Šคํ† ๋ฆฌ ๊ด€๋ฆฌ (UI์—๋Š” ํ‘œ์‹œํ•˜์ง€ ์•Š์Œ)
2066
- internal_history = []
2067
-
2068
- def process_query_streaming(user_query: str, llm_mode: str):
2069
- """์ŠคํŠธ๋ฆฌ๋ฐ์„ ์ง€์›ํ•˜๋Š” ์ฟผ๋ฆฌ ์ฒ˜๋ฆฌ"""
2070
- global internal_history
2071
-
2072
- if not user_query:
2073
- return "", "", "", "", "โŒ ์งˆ๋ฌธ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”."
2074
-
2075
- # LLM ๋ชจ๋“œ ์„ค์ •
2076
- llm_system.set_llm_mode(llm_mode)
2077
-
2078
- conversation_log = []
2079
- all_responses = {"supervisor": [], "researcher": [], "executor": [], "evaluator": []}
2080
-
2081
- try:
2082
- # 1๋‹จ๊ณ„: ๊ฐ๋…์ž AI ์ดˆ๊ธฐ ๋ถ„์„ ๋ฐ ํ‚ค์›Œ๋“œ ์ถ”์ถœ
2083
- supervisor_prompt = llm_system.create_supervisor_initial_prompt(user_query)
2084
- supervisor_initial_response = ""
2085
-
2086
- supervisor_text = "[์ดˆ๊ธฐ ๋ถ„์„] ๐Ÿ”„ ์ƒ์„ฑ ์ค‘...\n"
2087
- for chunk in llm_system.call_llm_streaming(
2088
- [{"role": "user", "content": supervisor_prompt}],
2089
- "supervisor"
2090
- ):
2091
- supervisor_initial_response += chunk
2092
- supervisor_text = f"[์ดˆ๊ธฐ ๋ถ„์„] - {datetime.now().strftime('%H:%M:%S')}\n{supervisor_initial_response}"
2093
- yield supervisor_text, "", "", "", "๐Ÿ”„ ๊ฐ๋…์ž AI๊ฐ€ ๋ถ„์„ ์ค‘..."
2094
-
2095
- all_responses["supervisor"].append(supervisor_initial_response)
2096
-
2097
- # ํ‚ค์›Œ๋“œ ์ถ”์ถœ
2098
- keywords = llm_system.extract_keywords(supervisor_initial_response)
2099
- logger.info(f"์ถ”์ถœ๋œ ํ‚ค์›Œ๋“œ: {keywords}")
2100
-
2101
- # 2๋‹จ๊ณ„: ๋ธŒ๋ ˆ์ด๋ธŒ ๊ฒ€์ƒ‰ ์ˆ˜ํ–‰
2102
- researcher_text = "[์›น ๊ฒ€์ƒ‰] ๐Ÿ” ๊ฒ€์ƒ‰ ์ค‘...\n"
2103
- yield supervisor_text, researcher_text, "", "", "๐Ÿ” ์›น ๊ฒ€์ƒ‰ ์ˆ˜ํ–‰ ์ค‘..."
2104
-
2105
- search_results = {}
2106
- total_search_count = 0
2107
-
2108
- # ์›๋ž˜ ํ‚ค์›Œ๋“œ๋กœ ๊ฒ€์ƒ‰
2109
- for keyword in keywords:
2110
- results = llm_system.brave_search(keyword)
2111
- if results:
2112
- search_results[keyword] = results
2113
- total_search_count += len(results)
2114
- researcher_text += f"โœ“ '{keyword}' ๊ฒ€์ƒ‰ ์™„๋ฃŒ ({len(results)}๊ฐœ ๊ฒฐ๊ณผ)\n"
2115
- yield supervisor_text, researcher_text, "", "", f"๐Ÿ” '{keyword}' ๊ฒ€์ƒ‰ ์ค‘..."
2116
-
2117
- # ๋™์˜์–ด๋กœ ์ถ”๊ฐ€ ๊ฒ€์ƒ‰
2118
- synonyms = llm_system.generate_synonyms(keyword)
2119
- for synonym in synonyms:
2120
- syn_results = llm_system.brave_search(f"{keyword} {synonym}")
2121
- if syn_results:
2122
- search_results[f"{keyword} ({synonym})"] = syn_results
2123
- total_search_count += len(syn_results)
2124
- researcher_text += f"โœ“ ๋™์˜์–ด '{synonym}' ๊ฒ€์ƒ‰ ์™„๋ฃŒ ({len(syn_results)}๊ฐœ ๊ฒฐ๊ณผ)\n"
2125
- yield supervisor_text, researcher_text, "", "", f"๐Ÿ” ๋™์˜์–ด '{synonym}' ๊ฒ€์ƒ‰ ์ค‘..."
2126
-
2127
- researcher_text += f"\n๐Ÿ“Š ์ด {total_search_count}๊ฐœ์˜ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ์ˆ˜์ง‘ ์™„๋ฃŒ\n"
2128
-
2129
- # URL ์ฝ˜ํ…์ธ  ๊ฐ€์ ธ์˜ค๊ธฐ (์ƒ์œ„ 3๊ฐœ)
2130
- researcher_text += "\n[์ฝ˜ํ…์ธ  ๋ถ„์„] ๐Ÿ“– ์ฃผ์š” ์›นํŽ˜์ด์ง€ ๋‚ด์šฉ ๋ถ„์„ ์ค‘...\n"
2131
- yield supervisor_text, researcher_text, "", "", "๐Ÿ“– ์›นํŽ˜์ด์ง€ ๋‚ด์šฉ ๋ถ„์„ ์ค‘..."
2132
-
2133
- content_analyzed = 0
2134
- for keyword, results in search_results.items():
2135
- for result in results[:2]: # ๊ฐ ํ‚ค์›Œ๋“œ๋‹น ์ƒ์œ„ 2๊ฐœ๋งŒ
2136
- if content_analyzed >= 5: # ์ด 5๊ฐœ๊นŒ์ง€๋งŒ
2137
- break
2138
-
2139
- url = result.get('url', '')
2140
- if url and result.get('credibility_score', 0) >= 0.7:
2141
- content = llm_system.fetch_url_content(url)
2142
- if content:
2143
- result['content_preview'] = content[:500] # ๋ฏธ๋ฆฌ๋ณด๊ธฐ ์ €์žฅ
2144
- content_analyzed += 1
2145
- researcher_text += f"โœ“ ์ฝ˜ํ…์ธ  ๋ถ„์„ ์™„๋ฃŒ: {url[:50]}...\n"
2146
- yield supervisor_text, researcher_text, "", "", f"๐Ÿ“– ๋ถ„์„ ์ค‘: {url[:30]}..."
2147
-
2148
- # 3๋‹จ๊ณ„: ์กฐ์‚ฌ์ž AI๊ฐ€ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ์ •๋ฆฌ
2149
- researcher_prompt = llm_system.create_researcher_prompt(user_query, supervisor_initial_response, search_results)
2150
- researcher_response = ""
2151
-
2152
- researcher_text = "[์กฐ์‚ฌ ๊ฒฐ๊ณผ ์ •๋ฆฌ] ๐Ÿ”„ ์ƒ์„ฑ ์ค‘...\n"
2153
- for chunk in llm_system.call_llm_streaming(
2154
- [{"role": "user", "content": researcher_prompt}],
2155
- "researcher"
2156
- ):
2157
- researcher_response += chunk
2158
- researcher_text = f"[์กฐ์‚ฌ ๊ฒฐ๊ณผ ์ •๋ฆฌ] - {datetime.now().strftime('%H:%M:%S')}\n{researcher_response}"
2159
- yield supervisor_text, researcher_text, "", "", "๐Ÿ“ ์กฐ์‚ฌ์ž AI๊ฐ€ ์ •๋ฆฌ ์ค‘..."
2160
-
2161
- all_responses["researcher"].append(researcher_response)
2162
-
2163
- # 4๋‹จ๊ณ„: ๊ฐ๋…์ž AI๊ฐ€ ์กฐ์‚ฌ ๋‚ด์šฉ ๊ธฐ๋ฐ˜์œผ๋กœ ์‹คํ–‰ ์ง€์‹œ
2164
- supervisor_execution_prompt = llm_system.create_supervisor_execution_prompt(user_query, researcher_response)
2165
- supervisor_execution_response = ""
2166
-
2167
- supervisor_text += "\n\n---\n\n[์‹คํ–‰ ์ง€์‹œ] ๐Ÿ”„ ์ƒ์„ฑ ์ค‘...\n"
2168
- for chunk in llm_system.call_llm_streaming(
2169
- [{"role": "user", "content": supervisor_execution_prompt}],
2170
- "supervisor"
2171
- ):
2172
- supervisor_execution_response += chunk
2173
- temp_text = f"{all_responses['supervisor'][0]}\n\n---\n\n[์‹คํ–‰ ์ง€์‹œ] - {datetime.now().strftime('%H:%M:%S')}\n{supervisor_execution_response}"
2174
- supervisor_text = f"[์ดˆ๊ธฐ ๋ถ„์„] - {datetime.now().strftime('%H:%M:%S')}\n{temp_text}"
2175
- yield supervisor_text, researcher_text, "", "", "๐ŸŽฏ ๊ฐ๋…์ž AI๊ฐ€ ์ง€์‹œ ์ค‘..."
2176
-
2177
- all_responses["supervisor"].append(supervisor_execution_response)
2178
-
2179
- # 5๋‹จ๊ณ„: ์‹คํ–‰์ž AI๊ฐ€ ์กฐ์‚ฌ ๋‚ด์šฉ๊ณผ ์ง€์‹œ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ดˆ๊ธฐ ๊ตฌํ˜„
2180
- executor_prompt = llm_system.create_executor_prompt(user_query, supervisor_execution_response, researcher_response)
2181
- executor_response = ""
2182
-
2183
- executor_text = "[์ดˆ๊ธฐ ๊ตฌํ˜„] ๐Ÿ”„ ์ƒ์„ฑ ์ค‘...\n"
2184
- for chunk in llm_system.call_llm_streaming(
2185
- [{"role": "user", "content": executor_prompt}],
2186
- "executor"
2187
- ):
2188
- executor_response += chunk
2189
- executor_text = f"[์ดˆ๊ธฐ ๊ตฌํ˜„] - {datetime.now().strftime('%H:%M:%S')}\n{executor_response}"
2190
- yield supervisor_text, researcher_text, executor_text, "", "๐Ÿ”ง ์‹คํ–‰์ž AI๊ฐ€ ๊ตฌํ˜„ ์ค‘..."
2191
-
2192
- all_responses["executor"].append(executor_response)
2193
-
2194
- # 6๋‹จ๊ณ„: ๊ฐ๋…์ž AI ๊ฒ€ํ†  ๋ฐ ํ”ผ๋“œ๋ฐฑ
2195
- review_prompt = f"""๋‹น์‹ ์€ ๊ฑฐ์‹œ์  ๊ด€์ ์—์„œ ๋ถ„์„ํ•˜๊ณ  ์ง€๋„ํ•˜๋Š” ๊ฐ๋…์ž AI์ž…๋‹ˆ๋‹ค.
2196
-
2197
- ์‚ฌ์šฉ์ž ์งˆ๋ฌธ: {user_query}
2198
-
2199
- ์‹คํ–‰์ž AI์˜ ๋‹ต๋ณ€:
2200
- {executor_response}
2201
-
2202
- ์ด ๋‹ต๋ณ€์„ ๊ฒ€ํ† ํ•˜๊ณ  ๊ฐœ์„ ์ ๊ณผ ์ถ”๊ฐ€ ๊ณ ๋ ค์‚ฌํ•ญ์„ ์ œ์‹œํ•ด์ฃผ์„ธ์š”. ๊ตฌ์ฒด์ ์ด๊ณ  ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ๊ฐœ์„  ๋ฐฉ์•ˆ์„ ์ œ์‹œํ•˜์„ธ์š”."""
2203
-
2204
- review_response = ""
2205
- 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"
2206
-
2207
- for chunk in llm_system.call_llm_streaming(
2208
- [{"role": "user", "content": review_prompt}],
2209
- "supervisor"
2210
- ):
2211
- review_response += chunk
2212
- 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}"
2213
- supervisor_text = f"[์ดˆ๊ธฐ ๋ถ„์„] - {datetime.now().strftime('%H:%M:%S')}\n{temp_text}"
2214
- yield supervisor_text, researcher_text, executor_text, "", "๐Ÿ”„ ๊ฐ๋…์ž AI๊ฐ€ ๊ฒ€ํ†  ์ค‘..."
2215
-
2216
- all_responses["supervisor"].append(review_response)
2217
-
2218
- # 7๋‹จ๊ณ„: ์‹คํ–‰์ž AI ์ตœ์ข… ๋ณด๊ณ ์„œ (ํ”ผ๋“œ๋ฐฑ ๋ฐ˜์˜)
2219
- final_executor_prompt = llm_system.create_executor_final_prompt(
2220
- user_query,
2221
- executor_response,
2222
- review_response,
2223
- researcher_response
2224
- )
2225
- final_executor_response = ""
2226
-
2227
- executor_text += "\n\n---\n\n[์ตœ์ข… ๋ณด๊ณ ์„œ] ๐Ÿ”„ ์ž‘์„ฑ ์ค‘...\n"
2228
- for chunk in llm_system.call_llm_streaming(
2229
- [{"role": "user", "content": final_executor_prompt}],
2230
- "executor"
2231
- ):
2232
- final_executor_response += chunk
2233
- 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}"
2234
- executor_text = temp_text
2235
- yield supervisor_text, researcher_text, executor_text, "", "๐Ÿ“„ ์ตœ์ข… ๋ณด๊ณ ์„œ ์ž‘์„ฑ ์ค‘..."
2236
-
2237
- all_responses["executor"].append(final_executor_response)
2238
-
2239
- # 8๋‹จ๊ณ„: ํ‰๊ฐ€์ž AI๊ฐ€ ์ „์ฒด ๊ณผ์ • ํ‰๊ฐ€
2240
- evaluator_prompt = llm_system.create_evaluator_prompt(
2241
- user_query,
2242
- all_responses["supervisor"],
2243
- all_responses["researcher"][0],
2244
- all_responses["executor"]
2245
- )
2246
- evaluator_response = ""
2247
-
2248
- evaluator_text = "[์ „์ฒด ํ‰๊ฐ€] ๐Ÿ”„ ํ‰๊ฐ€ ์ค‘...\n"
2249
- for chunk in llm_system.call_llm_streaming(
2250
- [{"role": "user", "content": evaluator_prompt}],
2251
- "evaluator"
2252
- ):
2253
- evaluator_response += chunk
2254
- evaluator_text = f"[์ „์ฒด ํ‰๊ฐ€] - {datetime.now().strftime('%H:%M:%S')}\n{evaluator_response}"
2255
- yield supervisor_text, researcher_text, executor_text, evaluator_text, "๐Ÿ“Š ํ‰๊ฐ€์ž AI๊ฐ€ ํ‰๊ฐ€ ์ค‘..."
2256
-
2257
- all_responses["evaluator"].append(evaluator_response)
2258
-
2259
- # ์ตœ์ข… ๊ฒฐ๊ณผ ์ƒ์„ฑ (์ตœ์ข… ๋ณด๊ณ ์„œ๋ฅผ ๋ฉ”์ธ์œผ๋กœ)
2260
- final_summary = f"""## ๐ŸŽฏ ์ตœ์ข… ์ข…ํ•ฉ ๋ณด๊ณ ์„œ
2261
-
2262
- ### ๐Ÿ“Œ ์‚ฌ์šฉ์ž ์งˆ๋ฌธ
2263
- {user_query}
2264
-
2265
- ### ๐Ÿ“„ ์ตœ์ข… ๋ณด๊ณ ์„œ (์‹คํ–‰์ž AI - ํ”ผ๋“œ๋ฐฑ ๋ฐ˜์˜)
2266
- {final_executor_response}
2267
-
2268
- ---
2269
-
2270
- ### ๐Ÿ“Š ์ „์ฒด ํ”„๋กœ์„ธ์Šค ํ‰๊ฐ€ (ํ‰๊ฐ€์ž AI)
2271
- {evaluator_response}
2272
-
2273
- ---
2274
-
2275
- <details>
2276
- <summary>๐Ÿ“‹ ์ „์ฒด ํ˜‘๋ ฅ ๊ณผ์ • ๋ณด๊ธฐ</summary>
2277
-
2278
- #### ๐Ÿ” ๊ฑฐ์‹œ์  ๋ถ„์„ (๊ฐ๋…์ž AI)
2279
- {all_responses['supervisor'][0]}
2280
-
2281
- #### ๐Ÿ“š ์กฐ์‚ฌ ๊ฒฐ๊ณผ (์กฐ์‚ฌ์ž AI)
2282
- {researcher_response}
2283
-
2284
- #### ๐ŸŽฏ ์‹คํ–‰ ์ง€์‹œ (๊ฐ๋…์ž AI)
2285
- {all_responses['supervisor'][1]}
2286
-
2287
- #### ๐Ÿ’ก ์ดˆ๊ธฐ ๊ตฌํ˜„ (์‹คํ–‰์ž AI)
2288
- {executor_response}
2289
-
2290
- #### โœจ ๊ฒ€ํ†  ๋ฐ ๊ฐœ์„ ์‚ฌํ•ญ (๊ฐ๋…์ž AI)
2291
- {review_response}
2292
-
2293
- </details>
2294
-
2295
- ---
2296
- *์ด ๋ณด๊ณ ์„œ๋Š” {'Gemini 2.5 Pro' if llm_system.use_gemini else '๊ธฐ๋ณธ LLM'}๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›น ๊ฒ€์ƒ‰๊ณผ AI ํ˜‘๋ ฅ์„ ํ†ตํ•ด ์ž‘์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.*"""
2297
-
2298
- # ๋‚ด๋ถ€ ํžˆ์Šคํ† ๋ฆฌ ์—…๋ฐ์ดํŠธ (UI์—๋Š” ํ‘œ์‹œํ•˜์ง€ ์•Š์Œ)
2299
- internal_history.append((user_query, final_summary))
2300
-
2301
- # ์ตœ์ข… ์š”์•ฝ๋งŒ ํ‘œ์‹œ
2302
- display_summary = f"""## ๐ŸŽฏ ์ตœ์ข… ๊ฒฐ๊ณผ
2303
-
2304
- ### ๐Ÿ“„ ์‹คํ–‰ ๋ณด๊ณ ์„œ
2305
- {final_executor_response}
2306
-
2307
- ### ๐Ÿ“Š ํ‰๊ฐ€ ์š”์•ฝ
2308
- {evaluator_response.split('### 5๏ธโƒฃ')[1] if '### 5๏ธโƒฃ' in evaluator_response else evaluator_response[-500:]}
2309
-
2310
- ---
2311
- *{'Gemini 2.5 Pro' if llm_system.use_gemini else '๊ธฐ๋ณธ LLM'} ์‚ฌ์šฉ | 4๊ฐœ AI ํ˜‘๋ ฅ ์™„๋ฃŒ*"""
2312
-
2313
- yield supervisor_text, researcher_text, executor_text, evaluator_text, "โœ… ์ตœ์ข… ๋ณด๊ณ ์„œ ์™„์„ฑ!"
2314
-
2315
- except Exception as e:
2316
- error_msg = f"โŒ ์ฒ˜๋ฆฌ ์ค‘ ์˜ค๋ฅ˜: {str(e)}"
2317
- yield "", "", "", "", error_msg
2318
-
2319
- def clear_all():
2320
- """๋ชจ๋“  ๋‚ด์šฉ ์ดˆ๊ธฐํ™”"""
2321
- global internal_history
2322
- internal_history = []
2323
- return "", "", "", "", "๐Ÿ”„ ์ดˆ๊ธฐํ™”๋˜์—ˆ์Šต๋‹ˆ๋‹ค."
2324
-
2325
- # Gradio ์ธํ„ฐํŽ˜์ด์Šค
2326
- css = """
2327
- .gradio-container {
2328
- font-family: 'Arial', sans-serif;
2329
- }
2330
- .supervisor-box textarea {
2331
- border-left: 4px solid #667eea !important;
2332
- padding-left: 10px !important;
2333
- background-color: #f8f9ff !important;
2334
- }
2335
- .researcher-box textarea {
2336
- border-left: 4px solid #10b981 !important;
2337
- padding-left: 10px !important;
2338
- background-color: #f0fdf4 !important;
2339
- }
2340
- .executor-box textarea {
2341
- border-left: 4px solid #764ba2 !important;
2342
- padding-left: 10px !important;
2343
- background-color: #faf5ff !important;
2344
- }
2345
- .evaluator-box textarea {
2346
- border-left: 4px solid #f59e0b !important;
2347
- padding-left: 10px !important;
2348
- background-color: #fffbeb !important;
2349
- }
2350
- """
2351
-
2352
- with gr.Blocks(title="ํ˜‘๋ ฅ์  LLM ์‹œ์Šคํ…œ", theme=gr.themes.Soft(), css=css) as app:
2353
- gr.Markdown(
2354
- f"""
2355
- # ๐Ÿค ํ˜‘๋ ฅ์  LLM ์‹œ์Šคํ…œ (4-AI ํ˜‘์—… + ํ‰๊ฐ€์ž)
2356
- """
2357
- )
2358
-
2359
- # ์ž…๋ ฅ ์„น์…˜
2360
- with gr.Row():
2361
- with gr.Column():
2362
- gr.Markdown("""
2363
- ## ๐Ÿš€ 4๊ฐœ AI์˜ ํ˜‘๋ ฅ ์‹œ์Šคํ…œ
2364
- - **๊ฐ๋…์ž AI**: ๊ฑฐ์‹œ์  ๋ถ„์„๊ณผ ์ „๋žต ์ˆ˜๋ฆฝ
2365
- - **์กฐ์‚ฌ์ž AI**: ์›น ๊ฒ€์ƒ‰๊ณผ ์ •๋ณด ์ˆ˜์ง‘/์ •๋ฆฌ
2366
- - **์‹คํ–‰์ž AI**: ๊ตฌ์ฒด์  ๊ณ„ํš ์ˆ˜๋ฆฝ๊ณผ ์‹คํ–‰
2367
- - **ํ‰๊ฐ€์ž AI**: ์ „์ฒด ๊ณผ์ • ํ‰๊ฐ€์™€ ๊ฐœ์„ ์  ์ œ์‹œ
2368
-
2369
- ### ๐ŸŒŸ ์ฃผ์š” ๊ธฐ๋Šฅ
2370
- - 20๊ฐœ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ์™€ ๋™์˜์–ด ๊ฒ€์ƒ‰
2371
- - ์‹ ๋ขฐ๋„ ๊ธฐ๋ฐ˜ ์ •๋ณด ํ‰๊ฐ€
2372
- - ์‹ค์‹œ๊ฐ„ ํ˜‘์—…๊ณผ ํ”ผ๋“œ๋ฐฑ ๋ฐ˜์˜
2373
- - ์ข…ํ•ฉ์ ์ธ ํ’ˆ์งˆ ํ‰๊ฐ€
2374
- """)
2375
-
2376
- # LLM ์„ ํƒ ์˜ต์…˜
2377
- llm_mode = gr.Radio(
2378
- choices=["default", "commercial"],
2379
- value="default",
2380
- label="LLM ๋ชจ๋“œ ์„ ํƒ",
2381
- info="commercial์„ ์„ ํƒํ•˜๋ฉด Gemini 2.5 Pro๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค"
2382
- )
2383
-
2384
- user_input = gr.Textbox(
2385
- label="์งˆ๋ฌธ ์ž…๋ ฅ",
2386
- placeholder="์˜ˆ: ๊ธฐ๊ณ„ํ•™์Šต ๋ชจ๋ธ์˜ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ค๋Š” ๋ฐฉ๋ฒ•์€?",
2387
- lines=3
2388
- )
2389
-
2390
- with gr.Row():
2391
- submit_btn = gr.Button("๐Ÿš€ ๋ถ„์„ ์‹œ์ž‘", variant="primary", scale=2)
2392
- clear_btn = gr.Button("๐Ÿ—‘๏ธ ์ดˆ๊ธฐํ™”", scale=1)
2393
-
2394
- status_text = gr.Textbox(
2395
- label="์ƒํƒœ",
2396
- interactive=False,
2397
- value="๋Œ€๊ธฐ ์ค‘...",
2398
- max_lines=1
2399
- )
2400
-
2401
- # AI ์ถœ๋ ฅ๋“ค - 2x2 ๊ทธ๋ฆฌ๋“œ
2402
- with gr.Row():
2403
- # ์ƒ๋‹จ ํ–‰
2404
- with gr.Column():
2405
- gr.Markdown("### ๐Ÿง  ๊ฐ๋…์ž AI (๊ฑฐ์‹œ์  ๋ถ„์„)")
2406
- supervisor_output = gr.Textbox(
2407
- label="",
2408
- lines=15,
2409
- max_lines=20,
2410
- interactive=False,
2411
- elem_classes=["supervisor-box"]
2412
- )
2413
-
2414
- with gr.Column():
2415
- gr.Markdown("### ๐Ÿ” ์กฐ์‚ฌ์ž AI (์›น ๊ฒ€์ƒ‰ & ์ •๋ฆฌ)")
2416
- researcher_output = gr.Textbox(
2417
- label="",
2418
- lines=15,
2419
- max_lines=20,
2420
- interactive=False,
2421
- elem_classes=["researcher-box"]
2422
- )
2423
-
2424
- with gr.Row():
2425
- # ํ•˜๋‹จ ํ–‰
2426
- with gr.Column():
2427
- gr.Markdown("### ๐Ÿ‘๏ธ ์‹คํ–‰์ž AI (๋ฏธ์‹œ์  ๊ตฌํ˜„)")
2428
- executor_output = gr.Textbox(
2429
- label="",
2430
- lines=15,
2431
- max_lines=20,
2432
- interactive=False,
2433
- elem_classes=["executor-box"]
2434
- )
2435
-
2436
- with gr.Column():
2437
- gr.Markdown("### ๐Ÿ“Š ํ‰๊ฐ€์ž AI (์ „์ฒด ํ‰๊ฐ€)")
2438
- evaluator_output = gr.Textbox(
2439
- label="",
2440
- lines=15,
2441
- max_lines=20,
2442
- interactive=False,
2443
- elem_classes=["evaluator-box"]
2444
- )
2445
-
2446
- # ์˜ˆ์ œ
2447
- gr.Examples(
2448
- examples=[
2449
- "๊ธฐ๊ณ„ํ•™์Šต ๋ชจ๋ธ์˜ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ค๋Š” ์ตœ์‹  ๋ฐฉ๋ฒ•์€?",
2450
- "2024๋…„ ํšจ๊ณผ์ ์ธ ํ”„๋กœ์ ํŠธ ๊ด€๋ฆฌ ๋„๊ตฌ์™€ ์ „๋žต์€?",
2451
- "์ง€์† ๊ฐ€๋Šฅํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ๋ชจ๋ธ์˜ ์ตœ์‹  ํŠธ๋ Œ๋“œ๋Š”?",
2452
- "์ตœ์‹  ๋ฐ์ดํ„ฐ ์‹œ๊ฐํ™” ๋„๊ตฌ์™€ ๊ธฐ๋ฒ•์€?",
2453
- "์›๊ฒฉ ํŒ€์˜ ์ƒ์‚ฐ์„ฑ์„ ๋†’์ด๋Š” ๊ฒ€์ฆ๋œ ๋ฐฉ๋ฒ•์€?"
2454
- ],
2455
- inputs=user_input,
2456
- label="๐Ÿ’ก ์˜ˆ์ œ ์งˆ๋ฌธ"
2457
- )
2458
-
2459
- # ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ
2460
- submit_btn.click(
2461
- fn=process_query_streaming,
2462
- inputs=[user_input, llm_mode],
2463
- outputs=[supervisor_output, researcher_output, executor_output, evaluator_output, status_text]
2464
- ).then(
2465
- fn=lambda: "",
2466
- outputs=[user_input]
2467
- )
2468
-
2469
- user_input.submit(
2470
- fn=process_query_streaming,
2471
- inputs=[user_input, llm_mode],
2472
- outputs=[supervisor_output, researcher_output, executor_output, evaluator_output, status_text]
2473
- ).then(
2474
- fn=lambda: "",
2475
- outputs=[user_input]
2476
- )
2477
-
2478
- clear_btn.click(
2479
- fn=clear_all,
2480
- outputs=[supervisor_output, researcher_output, executor_output, evaluator_output, status_text]
2481
- )
2482
-
2483
-
2484
  if __name__ == "__main__":
2485
  app.queue() # ์ŠคํŠธ๋ฆฌ๋ฐ์„ ์œ„ํ•œ ํ ํ™œ์„ฑํ™”
2486
  app.launch(
 
1236
  )
1237
 
1238
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1239
  if __name__ == "__main__":
1240
  app.queue() # ์ŠคํŠธ๋ฆฌ๋ฐ์„ ์œ„ํ•œ ํ ํ™œ์„ฑํ™”
1241
  app.launch(