From 4ac8ba98cc32d1e471590355f8866bc39d4715e7 Mon Sep 17 00:00:00 2001 From: Variet Agent Date: Thu, 19 Mar 2026 21:45:31 +0900 Subject: [PATCH] =?UTF-8?q?feat(debate):=20=EC=82=AC=ED=9A=8C=EC=9E=90=20F?= =?UTF-8?q?lash=20=ED=98=B8=EC=B6=9C=20=E2=80=94=20=EB=A7=A5=EB=9D=BD=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80,=20=EB=B0=A9=ED=96=A5=20=EC=A7=80=EC=8B=9C,?= =?UTF-8?q?=20=EC=98=A4=EB=A5=98=20=ED=99=95=EC=9D=B8=20=EC=A7=80=EC=8B=9C?= =?UTF-8?q?=20=ED=8F=AC=ED=95=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- handlers/debate_handler.py | 81 ++++++++++++++++++++++++++++++++------ 1 file changed, 69 insertions(+), 12 deletions(-) diff --git a/handlers/debate_handler.py b/handlers/debate_handler.py index a740cd0..978a0b9 100644 --- a/handlers/debate_handler.py +++ b/handlers/debate_handler.py @@ -160,7 +160,7 @@ class DebateHandler: self.session.current_speaker = speaker # 프롬프트 구성 - prompt = self._build_prompt(speaker, user_injected) + prompt = await self._build_prompt(speaker, user_injected) # 진행 상태 표시 control_ch = self.bot.get_channel(DEBATE_CONTROL_CH) @@ -228,14 +228,76 @@ class DebateHandler: f"⏹️ `!debate-stop` — 종료" ) - def _build_prompt(self, speaker: str, user_injected: str = "") -> str: - """에이전트에게 보낼 프롬프트 구성.""" + async def _build_prompt(self, speaker: str, user_injected: str = "") -> str: + """사회자(Flash)가 에이전트에게 보낼 프롬프트를 생성.""" other = "opus" if speaker == "gemini" else "gemini" + # 직전 상대 발언 가져오기 + prev_opinions = [h for h in self.session.history if h["speaker"] != "user"] + last_opponent = prev_opinions[-1] if prev_opinions else None + + # 사용자 발언 가져오기 + user_opinions = [h for h in self.session.history if h["speaker"] == "user"] + last_user = user_opinions[-1] if user_opinions else None + + # 사회자에게 보내는 메타 프롬프트 + moderator_prompt = f"""당신은 AI 토론 사회자입니다. +두 AI 토론자({', '.join(DEBATE_AGENTS.keys())}) 사이에서 턴을 관리합니다. + +## 현재 상황 +- 토론 주제: {self.session.topic} +- 현재 라운드: {self.session.round}/{self.session.max_rounds} +- 다음 발언자: {speaker} +- 상대: {other} +""" + + if last_opponent: + moderator_prompt += f""" +## 상대방({last_opponent['speaker']})의 직전 발언 (전문): +{last_opponent['content']} +""" + + if last_user: + moderator_prompt += f""" +## 사용자의 의견/판단: +{last_user['content']} +""" + + if user_injected: + moderator_prompt += f""" +## 사용자가 방금 추가한 의견: +{user_injected} +""" + + moderator_prompt += f""" +## 지시 +다음 발언자({speaker})에게 보낼 메시지를 작성하세요. + +규칙: +1. 상대방의 발언이 있으면 **전문을 그대로 포함**하세요 (요약하지 마세요) +2. 이 발언이 **사용자의 어떤 판단이나 의견에 기반**하는지 설명하세요 +3. 상대 발언의 **오류나 논리적 허점을 확인**하고, 개선된 방향이나 잘못된 부분을 지적하라고 지시하세요 +4. 현재 토론의 **핵심 쟁점**이 무엇인지 방향을 제시하세요 +5. 첫 발언이면, 주제를 잘 설명하고 자유롭게 의견을 제시하라고 안내하세요 + +(사회자의 메시지만 출력하세요. 다른 설명은 불필요합니다.) +""" + + try: + from core.gemini_caller import GeminiCaller + caller = GeminiCaller() + moderated = await caller.call_simple(moderator_prompt, timeout=60) + return moderated + except Exception as e: + logger.error(f"사회자 Flash 호출 실패: {e}, 기본 프롬프트 사용") + # fallback: 기본 프롬프트 + return self._build_fallback_prompt(speaker, user_injected) + + def _build_fallback_prompt(self, speaker: str, user_injected: str = "") -> str: + """Flash 호출 실패 시 기본 프롬프트.""" parts = [f"## 토론 주제: {self.session.topic}\n"] parts.append(f"현재 라운드: {self.session.round}/{self.session.max_rounds}\n") - # 직전 발언 포함 prev = [h for h in self.session.history if h["speaker"] != "user"] if prev: last = prev[-1] @@ -243,20 +305,15 @@ class DebateHandler: parts.append(last["content"]) parts.append("\n\n---\n") parts.append( - f"위 발언에 오류가 없는지 확인하고, " - f"더 개선된 방향이나 잘못된 부분을 지적하세요.\n" + "위 발언에 오류가 없는지 확인하고, " + "더 개선된 방향이나 잘못된 부분을 지적하세요.\n" ) - # 사용자 의견 if user_injected: parts.append(f"\n### 사용자 의견:\n{user_injected}\n") - parts.append("사용자의 의견을 반영하여 답변하세요.\n") if not prev and not user_injected: - parts.append( - "당신이 첫 번째 발언자입니다. " - "주제에 대해 자유롭게 의견을 제시하세요.\n" - ) + parts.append("당신이 첫 번째 발언자입니다. 주제에 대해 의견을 제시하세요.\n") return "\n".join(parts)