481 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			481 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Python
		
	
	
	
| #!/usr/bin/env python3
 | ||
| # -*- coding: utf-8 -*-
 | ||
| """
 | ||
| 稷下学宫 - 八仙ADK辩论系统 (Gemini 2.5 Flash版)
 | ||
| 使用Google ADK和Gemini 2.5 Flash模型实现八仙辩论
 | ||
| """
 | ||
| 
 | ||
| import os
 | ||
| import asyncio
 | ||
| import json
 | ||
| from datetime import datetime
 | ||
| from typing import Dict, List, Any, Optional
 | ||
| from google.adk import Agent, Runner
 | ||
| from google.adk.sessions import InMemorySessionService
 | ||
| from google.genai import types
 | ||
| 
 | ||
| # 加载.env文件
 | ||
| try:
 | ||
|     from dotenv import load_dotenv
 | ||
|     load_dotenv()
 | ||
| except ImportError:
 | ||
|     print("⚠️ 未安装python-dotenv,请运行: pip install python-dotenv")
 | ||
|     pass
 | ||
| 
 | ||
| class BaXianADKDebateSystem:
 | ||
|     """八仙ADK辩论系统"""
 | ||
|     
 | ||
|     def __init__(self):
 | ||
|         self.model = "gemini-2.5-flash"
 | ||
|         self.agents = {}
 | ||
|         self.debate_history = []
 | ||
|         self.current_round = 0
 | ||
|         self.max_rounds = 3
 | ||
|         
 | ||
|         # 八仙角色定义
 | ||
|         self.baxian_profiles = {
 | ||
|             "铁拐李": {
 | ||
|                 "personality": "八仙之首,形象为街头乞丐,代表社会底层。性格刚直不阿,善于逆向思维和批判分析。你从底层民众的角度看问题,敢于质疑权贵,为弱势群体发声。",
 | ||
|                 "speaking_style": "直言不讳,接地气,善用反问和草根智慧",
 | ||
|                 "expertise": "批判思维、民生洞察、社会底层视角"
 | ||
|             },
 | ||
|             "吕洞宾": {
 | ||
|                 "personality": "理性务实的学者型仙人,善于分析问题本质和长远影响。你注重逻辑推理,能够平衡各方观点,寻求最优解决方案。",
 | ||
|                 "speaking_style": "条理分明,深入浅出,善用类比和归纳",
 | ||
|                 "expertise": "战略分析、系统思维、决策优化"
 | ||
|             },
 | ||
|             "何仙姑": {
 | ||
|                 "personality": "八仙中唯一的女性,温柔智慧,善于从情感和人文角度思考问题。你关注社会影响和人文关怀,注重和谐与平衡。",
 | ||
|                 "speaking_style": "温和理性,富有同理心,善用情感共鸣",
 | ||
|                 "expertise": "人文关怀、社会影响、情感分析"
 | ||
|             },
 | ||
|             "蓝采和": {
 | ||
|                 "personality": "贫穷的街头歌者,自由奔放的艺术家气质。你代表精神富足但物质贫乏的群体,善于从艺术和美学角度看待问题,关注精神层面的价值。",
 | ||
|                 "speaking_style": "活泼生动,富有想象力,善用诗歌和民谣",
 | ||
|                 "expertise": "创新思维、艺术视角、精神追求、民间智慧"
 | ||
|             },
 | ||
|             "韩湘子": {
 | ||
|                 "personality": "年轻有为的技术专家,对新技术和趋势敏感。你善于从技术角度分析问题,关注实现可行性和技术细节。",
 | ||
|                 "speaking_style": "专业严谨,数据驱动,善用技术术语",
 | ||
|                 "expertise": "技术分析、趋势预测、可行性评估"
 | ||
|             },
 | ||
|             "曹国舅": {
 | ||
|                 "personality": "皇亲国戚,贵族出身,代表上层社会。你具有政治敏感性和大局观,善于从政策和制度角度分析问题,关注权力结构和利益平衡,维护既得利益群体。",
 | ||
|                 "speaking_style": "稳重大气,政治敏锐,善用历史典故和朝堂礼仪",
 | ||
|                 "expertise": "政策分析、制度设计、权力博弈、上层社会视角"
 | ||
|             },
 | ||
|             "张果老": {
 | ||
|                 "personality": "年长智慧的长者,经验丰富,善于从历史和哲学角度看问题。你能提供深刻的人生智慧和历史洞察。",
 | ||
|                 "speaking_style": "深沉睿智,引经据典,善用哲理思辨",
 | ||
|                 "expertise": "历史洞察、哲学思辨、人生智慧"
 | ||
|             },
 | ||
|             "钟离权": {
 | ||
|                 "personality": "汉钟离,出身将门富贵,军事战略家。你善于从战略和执行角度分析问题,注重实战经验和资源配置,关注执行力和结果导向。代表富贵阶层的视角。",
 | ||
|                 "speaking_style": "果断坚定,战略清晰,善用军事比喻和资源分析",
 | ||
|                 "expertise": "战略规划、执行管理、风险控制、资源配置"
 | ||
|             }
 | ||
|         }
 | ||
|     
 | ||
|     def create_agents(self) -> bool:
 | ||
|         """创建八仙智能体"""
 | ||
|         try:
 | ||
|             for name, profile in self.baxian_profiles.items():
 | ||
|                 # 构建系统提示词
 | ||
|                 system_prompt = f"""
 | ||
| 你是{name},{profile['personality']}
 | ||
| 
 | ||
| 你的说话风格:{profile['speaking_style']}
 | ||
| 你的专业领域:{profile['expertise']}
 | ||
| 
 | ||
| 在辩论中,请:
 | ||
| 1. 保持你的角色特色和专业视角
 | ||
| 2. 提供有价值的观点和分析
 | ||
| 3. 与其他仙人进行建设性的讨论
 | ||
| 4. 每次发言控制在200字以内
 | ||
| 5. 语言要生动有趣,符合你的性格特点
 | ||
| """
 | ||
|                 
 | ||
|                 # 创建ADK智能体
 | ||
|                 agent = Agent(
 | ||
|                     name=name,
 | ||
|                     model=self.model,
 | ||
|                     instruction=system_prompt
 | ||
|                 )
 | ||
|                 
 | ||
|                 self.agents[name] = agent
 | ||
|                 print(f"✅ 创建智能体: {name}")
 | ||
|             
 | ||
|             return True
 | ||
|             
 | ||
|         except Exception as e:
 | ||
|             print(f"❌ 创建智能体失败: {e}")
 | ||
|             return False
 | ||
|     
 | ||
|     async def conduct_debate(self, topic: str, rounds: int = 3) -> Dict[str, Any]:
 | ||
|         """进行八仙辩论"""
 | ||
|         self.max_rounds = rounds
 | ||
|         debate_id = f"baxian_debate_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
 | ||
|         
 | ||
|         print(f"\n🏛️ 稷下学宫 - 八仙论道")
 | ||
|         print(f"📋 辩论主题: {topic}")
 | ||
|         print(f"🔄 辩论轮次: {rounds}")
 | ||
|         print(f"🤖 使用模型: {self.model}")
 | ||
|         print("=" * 80)
 | ||
|         
 | ||
|         # 辩论开场
 | ||
|         opening_context = f"""
 | ||
| 今日稷下学宫八仙齐聚,共同探讨「{topic}」这一重要议题。
 | ||
| 
 | ||
| 请各位仙人从自己的专业角度和人生阅历出发,分享真知灼见。
 | ||
| 让我们通过思辨碰撞,共同寻求智慧的火花。
 | ||
| """
 | ||
|         
 | ||
|         self.debate_history.append({
 | ||
|             "type": "opening",
 | ||
|             "content": opening_context,
 | ||
|             "timestamp": datetime.now().isoformat()
 | ||
|         })
 | ||
|         
 | ||
|         # 进行多轮辩论
 | ||
|         for round_num in range(1, rounds + 1):
 | ||
|             print(f"\n🎯 第{round_num}轮辩论")
 | ||
|             print("-" * 60)
 | ||
|             
 | ||
|             await self._conduct_round(topic, round_num)
 | ||
|             
 | ||
|             # 轮次间隔
 | ||
|             if round_num < rounds:
 | ||
|                 await asyncio.sleep(1)
 | ||
|         
 | ||
|         # 辩论总结
 | ||
|         await self._generate_summary(topic)
 | ||
|         
 | ||
|         # 保存辩论记录
 | ||
|         result = {
 | ||
|             "debate_id": debate_id,
 | ||
|             "topic": topic,
 | ||
|             "model": self.model,
 | ||
|             "rounds": rounds,
 | ||
|             "participants": list(self.agents.keys()),
 | ||
|             "debate_history": self.debate_history,
 | ||
|             "timestamp": datetime.now().isoformat()
 | ||
|         }
 | ||
|         
 | ||
|         # 创建输出目录(相对于项目根目录)
 | ||
|         project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 | ||
|         output_dir = os.path.join(project_root, "outputs", "debates")
 | ||
|         os.makedirs(output_dir, exist_ok=True)
 | ||
|         
 | ||
|         # 保存到文件
 | ||
|         filename = f"baxian_debate_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
 | ||
|         filepath = os.path.join(output_dir, filename)
 | ||
|         with open(filepath, 'w', encoding='utf-8') as f:
 | ||
|             json.dump(result, f, ensure_ascii=False, indent=2)
 | ||
|         
 | ||
|         print(f"\n💾 辩论记录已保存: {filepath}")
 | ||
|         
 | ||
|         return result
 | ||
|     
 | ||
|     async def _conduct_round(self, topic: str, round_num: int):
 | ||
|         """进行单轮辩论"""
 | ||
|         # 按照对立统一原则安排发言顺序
 | ||
|         # 基于docs/baxian_debate_order_guide.md的分组原则
 | ||
|         
 | ||
|         if round_num == 1:
 | ||
|             # 第一轮:按对立组依次发言
 | ||
|             speaker_order = [
 | ||
|                 "吕洞宾",   # 乾/男
 | ||
|                 "何仙姑",   # 坤/女  
 | ||
|                 "张果老",   # 老
 | ||
|                 "韩湘子",   # 少
 | ||
|                 "钟离权",   # 富(汉钟离)
 | ||
|                 "蓝采和",   # 贫
 | ||
|                 "曹国舅",   # 贵
 | ||
|                 "铁拐李"    # 贱
 | ||
|             ]
 | ||
|         else:
 | ||
|             # 后续轮次:对立组交替发言,增强辩论张力
 | ||
|             speaker_order = [
 | ||
|                 "铁拐李", "曹国舅",  # 贵贱对立
 | ||
|                 "蓝采和", "钟离权",  # 贫富对立
 | ||
|                 "韩湘子", "张果老",  # 老少对立
 | ||
|                 "何仙姑", "吕洞宾"   # 男女对立
 | ||
|             ]
 | ||
|         
 | ||
|         for speaker_name in speaker_order:
 | ||
|             if speaker_name in self.agents:
 | ||
|                 await self._agent_speak(speaker_name, topic, round_num)
 | ||
|                 await asyncio.sleep(0.5)  # 短暂间隔
 | ||
|     
 | ||
|     async def _agent_speak(self, speaker_name: str, topic: str, round_num: int):
 | ||
|         """智能体发言"""
 | ||
|         agent = self.agents[speaker_name]
 | ||
|         
 | ||
|         # 构建上下文
 | ||
|         context = self._build_context(speaker_name, topic, round_num)
 | ||
|         
 | ||
|         try:
 | ||
|             # 创建会话服务(如果还没有)
 | ||
|             if not hasattr(self, 'session_service'):
 | ||
|                 self.session_service = InMemorySessionService()
 | ||
|                 self.session = await self.session_service.create_session(
 | ||
|                     state={},
 | ||
|                     app_name="八仙论道系统",
 | ||
|                     user_id="debate_user"
 | ||
|                 )
 | ||
|             
 | ||
|             # 创建Runner
 | ||
|             runner = Runner(
 | ||
|                 app_name="八仙论道系统",
 | ||
|                 agent=agent,
 | ||
|                 session_service=self.session_service
 | ||
|             )
 | ||
|             
 | ||
|             # 构建消息内容
 | ||
|             content = types.Content(role='user', parts=[types.Part(text=context)])
 | ||
|             
 | ||
|             # 生成回应
 | ||
|             response_stream = runner.run_async(
 | ||
|                 user_id=self.session.user_id,
 | ||
|                 session_id=self.session.id,
 | ||
|                 new_message=content
 | ||
|             )
 | ||
|             
 | ||
|             # 收集响应
 | ||
|             response_parts = []
 | ||
|             async for event in response_stream:
 | ||
|                 # 过滤ADK系统调试信息
 | ||
|                 event_str = str(event)
 | ||
|                 if ('Event from an unknown agent' in event_str or 
 | ||
|                     'event id:' in event_str or 
 | ||
|                     'API_KEY' in event_str):
 | ||
|                     continue
 | ||
|                     
 | ||
|                 if hasattr(event, 'content') and event.content:
 | ||
|                     if hasattr(event.content, 'parts') and event.content.parts:
 | ||
|                         for part in event.content.parts:
 | ||
|                             if hasattr(part, 'text') and part.text and part.text.strip():
 | ||
|                                 text_content = str(part.text).strip()
 | ||
|                                 # 进一步过滤调试信息
 | ||
|                                 if (not text_content.startswith('Event from') and 
 | ||
|                                     'API_KEY' not in text_content and
 | ||
|                                     'event id:' not in text_content and
 | ||
|                                     'unknown agent' not in text_content):
 | ||
|                                     response_parts.append(text_content)
 | ||
|                 elif hasattr(event, 'text') and event.text:
 | ||
|                     text_content = str(event.text).strip()
 | ||
|                     if (not text_content.startswith('Event from') and 
 | ||
|                         'API_KEY' not in text_content and
 | ||
|                         'event id:' not in text_content and
 | ||
|                         'unknown agent' not in text_content):
 | ||
|                         response_parts.append(text_content)
 | ||
|             
 | ||
|             response = ''.join(response_parts).strip()
 | ||
|             
 | ||
|             # 记录发言
 | ||
|             speech_record = {
 | ||
|                 "type": "speech",
 | ||
|                 "round": round_num,
 | ||
|                 "speaker": speaker_name,
 | ||
|                 "content": response,
 | ||
|                 "timestamp": datetime.now().isoformat()
 | ||
|             }
 | ||
|             
 | ||
|             self.debate_history.append(speech_record)
 | ||
|             
 | ||
|             # 显示发言
 | ||
|             print(f"\n🗣️ {speaker_name}:")
 | ||
|             print(f"{response}")
 | ||
|             
 | ||
|         except Exception as e:
 | ||
|             print(f"❌ {speaker_name} 发言失败: {e}")
 | ||
|             # 记录错误
 | ||
|             error_record = {
 | ||
|                 "type": "error",
 | ||
|                 "round": round_num,
 | ||
|                 "speaker": speaker_name,
 | ||
|                 "error": str(e),
 | ||
|                 "timestamp": datetime.now().isoformat()
 | ||
|             }
 | ||
|             self.debate_history.append(error_record)
 | ||
|     
 | ||
|     def _build_context(self, speaker_name: str, topic: str, round_num: int) -> str:
 | ||
|         """构建发言上下文"""
 | ||
|         # 获取最近的发言历史
 | ||
|         recent_speeches = []
 | ||
|         for record in self.debate_history[-6:]:  # 最近6条记录
 | ||
|             if record["type"] == "speech" and record["speaker"] != speaker_name:
 | ||
|                 recent_speeches.append(f"{record['speaker']}: {record['content']}")
 | ||
|         
 | ||
|         context = f"""
 | ||
| 辩论主题:{topic}
 | ||
| 当前轮次:第{round_num}轮
 | ||
| 
 | ||
| """
 | ||
|         
 | ||
|         if recent_speeches:
 | ||
|             context += "最近的讨论:\n" + "\n".join(recent_speeches[-3:]) + "\n\n"
 | ||
|         
 | ||
|         if round_num == 1:
 | ||
|             context += "请从你的专业角度对这个主题发表观点,阐述你的立场和理由。"
 | ||
|         else:
 | ||
|             context += "请结合前面的讨论,进一步阐述你的观点,或对其他仙人的观点进行回应和补充。"
 | ||
|         
 | ||
|         return context
 | ||
|     
 | ||
|     async def _generate_summary(self, topic: str):
 | ||
|         """生成辩论总结"""
 | ||
|         print(f"\n📝 辩论总结")
 | ||
|         print("=" * 60)
 | ||
|         
 | ||
|         # 统计各仙人发言次数
 | ||
|         speech_count = {}
 | ||
|         for record in self.debate_history:
 | ||
|             if record["type"] == "speech":
 | ||
|                 speaker = record["speaker"]
 | ||
|                 speech_count[speaker] = speech_count.get(speaker, 0) + 1
 | ||
|         
 | ||
|         print(f"\n📊 发言统计:")
 | ||
|         for speaker, count in speech_count.items():
 | ||
|             print(f"  {speaker}: {count}次发言")
 | ||
|         
 | ||
|         # 可以添加更多总结逻辑
 | ||
|         summary_record = {
 | ||
|             "type": "summary",
 | ||
|             "topic": topic,
 | ||
|             "speech_count": speech_count,
 | ||
|             "total_speeches": sum(speech_count.values()),
 | ||
|             "timestamp": datetime.now().isoformat()
 | ||
|         }
 | ||
|         
 | ||
|         self.debate_history.append(summary_record)
 | ||
| 
 | ||
| def check_api_key() -> bool:
 | ||
|     """检查API密钥"""
 | ||
|     # 优先使用 GOOGLE_API_KEY,如果没有则使用 GEMINI_API_KEY
 | ||
|     google_api_key = os.getenv('GOOGLE_API_KEY')
 | ||
|     gemini_api_key = os.getenv('GEMINI_API_KEY')
 | ||
|     
 | ||
|     if google_api_key and gemini_api_key:
 | ||
|         print("⚠️ 检测到同时设置了 GOOGLE_API_KEY 和 GEMINI_API_KEY")
 | ||
|         print("📝 建议:统一使用 GOOGLE_API_KEY,将移除 GEMINI_API_KEY")
 | ||
|         # 使用 GOOGLE_API_KEY
 | ||
|         api_key = google_api_key
 | ||
|         print(f"✅ 使用 GOOGLE_API_KEY (长度: {len(api_key)} 字符)")
 | ||
|         return True
 | ||
|     elif google_api_key:
 | ||
|         print(f"✅ 使用 GOOGLE_API_KEY (长度: {len(google_api_key)} 字符)")
 | ||
|         return True
 | ||
|     elif gemini_api_key:
 | ||
|         print(f"✅ 使用 GEMINI_API_KEY (长度: {len(gemini_api_key)} 字符)")
 | ||
|         # 设置 GOOGLE_API_KEY 为 GEMINI_API_KEY 的值
 | ||
|         os.environ['GOOGLE_API_KEY'] = gemini_api_key
 | ||
|         return True
 | ||
|     else:
 | ||
|         print("❌ 未找到 GOOGLE_API_KEY 或 GEMINI_API_KEY 环境变量")
 | ||
|         print("请设置环境变量: export GOOGLE_API_KEY=your_api_key")
 | ||
|         print("或使用: doppler run -- python examples/debates/baxian_adk_gemini_debate.py")
 | ||
|         return False
 | ||
| 
 | ||
| def demo_mode():
 | ||
|     """演示模式 - 模拟辩论过程"""
 | ||
|     print("🎭 演示模式:八仙论道模拟")
 | ||
|     print("=" * 60)
 | ||
|     
 | ||
|     topic = "人工智能对未来社会的影响"
 | ||
|     print(f"📋 辩论主题: {topic}")
 | ||
|     print("🔄 辩论轮次: 2")
 | ||
|     print("🤖 模拟模式: 演示版本")
 | ||
|     print("=" * 80)
 | ||
|     
 | ||
|     # 模拟八仙发言
 | ||
|     demo_speeches = {
 | ||
|         "铁拐李": "人工智能虽然强大,但我们不能盲目崇拜。技术的发展必须以人为本,警惕其可能带来的风险和挑战。",
 | ||
|         "吕洞宾": "从长远来看,AI将重塑社会结构。我们需要理性分析其影响,制定合适的发展策略,平衡效率与公平。",
 | ||
|         "何仙姑": "技术进步应该服务于人类福祉。我们要关注AI对就业、教育的影响,确保技术发展不会加剧社会不平等。",
 | ||
|         "蓝采和": "AI为艺术创作开辟了新天地!想象一下,人机协作能创造出多么奇妙的作品,这是前所未有的创新机遇。",
 | ||
|         "韩湘子": "从技术角度看,AI的算力和算法正在指数级增长。我们需要关注数据安全、隐私保护等技术挑战。",
 | ||
|         "曹国舅": "政策制定者必须未雨绸缪,建立完善的AI治理框架,平衡创新发展与风险管控的关系。",
 | ||
|         "张果老": "纵观历史,每次技术革命都伴随着社会变迁。AI亦如此,关键在于如何引导其造福人类。",
 | ||
|         "钟离权": "战略上要重视AI的军事应用,确保国家安全。同时要有执行力,将AI政策落到实处。"
 | ||
|     }
 | ||
|     
 | ||
|     print("\n🎯 第1轮辩论")
 | ||
|     print("-" * 60)
 | ||
|     
 | ||
|     for name, speech in demo_speeches.items():
 | ||
|         print(f"\n🗣️ {name}:")
 | ||
|         print(f"{speech}")
 | ||
|         import time
 | ||
|         time.sleep(1)
 | ||
|     
 | ||
|     print("\n📝 辩论总结")
 | ||
|     print("=" * 60)
 | ||
|     print("📊 发言统计:")
 | ||
|     for name in demo_speeches.keys():
 | ||
|         print(f"  {name}: 1次发言")
 | ||
|     
 | ||
|     print("\n🎉 演示完成!")
 | ||
|     print("💡 要体验完整的AI辩论功能,请配置真实的 GOOGLE_API_KEY")
 | ||
| 
 | ||
| async def main():
 | ||
|     """主函数"""
 | ||
|     print("🏛️ 稷下学宫 - 八仙ADK辩论系统 (Gemini 2.5 Flash版)")
 | ||
|     print("🤖 使用Google ADK + Gemini 2.5 Flash模型")
 | ||
|     print("🎭 八仙齐聚,共论天下大事")
 | ||
|     print("\n📝 注意:运行过程中可能出现ADK系统调试信息,这是正常现象")
 | ||
|     print("   包括'Event from an unknown agent'等信息,不影响辩论功能")
 | ||
|     print()
 | ||
|     
 | ||
|     # 检查API密钥
 | ||
|     if not check_api_key():
 | ||
|         print("⚠️ 未找到有效的 GOOGLE_API_KEY,启动演示模式")
 | ||
|         print("💡 请设置环境变量以体验完整功能: export GOOGLE_API_KEY=your_api_key")
 | ||
|         print("📝 获取API密钥: https://aistudio.google.com/app/apikey")
 | ||
|         print()
 | ||
|         
 | ||
|         # 演示模式 - 模拟辩论过程
 | ||
|         demo_mode()
 | ||
|         return
 | ||
|     
 | ||
|     # 创建辩论系统
 | ||
|     debate_system = BaXianADKDebateSystem()
 | ||
|     
 | ||
|     # 创建智能体
 | ||
|     if not debate_system.create_agents():
 | ||
|         print("❌ 智能体创建失败,无法进行辩论")
 | ||
|         return
 | ||
|     
 | ||
|     # 辩论主题
 | ||
|     topics = [
 | ||
|         "人工智能对未来社会的影响",
 | ||
|         "数字货币与传统金融的博弈",
 | ||
|         "元宇宙技术的发展前景",
 | ||
|         "可持续发展与经济增长的平衡",
 | ||
|         "教育数字化转型的机遇与挑战"
 | ||
|     ]
 | ||
|     
 | ||
|     # 选择主题(可以随机选择或让用户选择)
 | ||
|     topic = topics[0]  # 默认使用第一个主题
 | ||
|     
 | ||
|     try:
 | ||
|         # 开始辩论
 | ||
|         result = await debate_system.conduct_debate(topic, rounds=2)
 | ||
|         
 | ||
|         if result:
 | ||
|             print(f"\n🎉 辩论成功完成!")
 | ||
|             print(f"📁 辩论ID: {result['debate_id']}")
 | ||
|             print(f"🎯 参与者: {', '.join(result['participants'])}")
 | ||
|             print(f"📊 总发言数: {len([r for r in result['debate_history'] if r['type'] == 'speech'])}")
 | ||
|         else:
 | ||
|             print("❌ 辩论失败")
 | ||
|             
 | ||
|     except KeyboardInterrupt:
 | ||
|         print("\n👋 用户中断,辩论结束")
 | ||
|     except Exception as e:
 | ||
|         print(f"❌ 辩论过程中发生错误: {e}")
 | ||
|         import traceback
 | ||
|         traceback.print_exc()
 | ||
| 
 | ||
| if __name__ == "__main__":
 | ||
|     asyncio.run(main()) |