455 lines
18 KiB
Python
455 lines
18 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
"""
|
||
稷下学宫AI辩论系统主入口
|
||
提供命令行界面来运行不同的辩论模式
|
||
"""
|
||
|
||
import argparse
|
||
import asyncio
|
||
import sys
|
||
import os
|
||
import warnings
|
||
|
||
# 将项目根目录添加到 Python 路径,以便能正确导入模块
|
||
project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||
sys.path.insert(0, project_root)
|
||
|
||
# 抑制 google-adk 的调试日志和警告
|
||
import logging
|
||
logging.getLogger('google.adk').setLevel(logging.ERROR)
|
||
logging.getLogger('google.genai').setLevel(logging.ERROR)
|
||
# 设置环境变量来抑制ADK调试输出
|
||
os.environ['GOOGLE_CLOUD_DISABLE_GRPC_LOGS'] = 'true'
|
||
os.environ['GRPC_VERBOSITY'] = 'ERROR'
|
||
os.environ['GRPC_TRACE'] = ''
|
||
|
||
# 抑制 warnings
|
||
warnings.filterwarnings('ignore')
|
||
|
||
from config.settings import validate_config
|
||
|
||
|
||
def check_environment():
|
||
"""检查并验证运行环境"""
|
||
print("🔧 检查运行环境...")
|
||
|
||
# 验证基础配置
|
||
if not validate_config():
|
||
print("❌ 环境配置验证失败")
|
||
return False
|
||
|
||
print("✅ 环境检查通过")
|
||
return True
|
||
|
||
|
||
async def run_adk_memory_debate(topic: str, participants: list = None):
|
||
"""运行ADK记忆增强辩论"""
|
||
print("⚠️ ADK记忆增强辩论功能正在适配新版本的 google-adk 库...")
|
||
print("💡 请先使用 'adk_simple' 模式进行测试。")
|
||
return False
|
||
|
||
# 以下代码暂时保留,待适配完成后再启用
|
||
"""
|
||
try:
|
||
from src.jixia.debates.adk_memory_debate import MemoryEnhancedDebate
|
||
|
||
print(f"🚀 启动ADK记忆增强辩论...")
|
||
print(f"📋 辩论主题: {topic}")
|
||
|
||
# 创建并初始化辩论系统
|
||
debate_system = MemoryEnhancedDebate()
|
||
await debate_system.initialize()
|
||
|
||
# 进行辩论
|
||
await debate_system.conduct_memory_debate(
|
||
topic=topic,
|
||
participants=participants
|
||
)
|
||
|
||
# 关闭资源
|
||
await debate_system.close()
|
||
|
||
print("\n🎉 ADK记忆增强辩论完成!")
|
||
return True
|
||
|
||
except ImportError as e:
|
||
print(f"❌ 导入模块失败: {e}")
|
||
print("请确保已安装Google ADK: pip install google-adk")
|
||
return False
|
||
except Exception as e:
|
||
print(f"❌ 运行ADK记忆增强辩论失败: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
return False
|
||
"""
|
||
|
||
|
||
async def run_adk_turn_based_debate(topic: str, participants: list = None, rounds: int = 3):
|
||
"""运行ADK八仙轮流辩论"""
|
||
try:
|
||
from google.adk import Agent, Runner
|
||
from google.adk.sessions import InMemorySessionService
|
||
from google.genai import types
|
||
import asyncio
|
||
|
||
print(f"🚀 启动ADK八仙轮流辩论...")
|
||
print(f"📋 辩论主题: {topic}")
|
||
print(f"🔄 辩论轮数: {rounds}")
|
||
|
||
# 默认参与者为八仙
|
||
if not participants or participants == ["铁拐李", "吕洞宾"]:
|
||
participants = ["铁拐李", "吕洞宾", "何仙姑", "张果老", "蓝采和", "汉钟离", "韩湘子", "曹国舅"]
|
||
|
||
# 定义主持人和八仙角色配置
|
||
roles_config = {
|
||
# 主持人
|
||
"太上老君": {
|
||
"name": "太上老君",
|
||
"model": "gemini-2.5-flash",
|
||
"instruction": "你是太上老君,本次论道的主持人。你负责引导辩论的流程,确保每位仙人都有机会发言,并在每一轮结束后进行简要总结。你的发言风格庄重、睿智,能够调和不同观点之间的矛盾。每次发言控制在100字以内。"
|
||
},
|
||
# 八仙
|
||
"铁拐李": {
|
||
"name": "铁拐李",
|
||
"model": "gemini-2.5-flash",
|
||
"instruction": "你是铁拐李,八仙中的逆向思维专家。你善于从批判和质疑的角度看问题,总是能发现事物的另一面。你的发言风格直接、犀利,但富有智慧。每次发言控制在100字以内。"
|
||
},
|
||
"吕洞宾": {
|
||
"name": "吕洞宾",
|
||
"model": "gemini-2.5-flash",
|
||
"instruction": "你是吕洞宾,八仙中的理性分析者。你善于平衡各方观点,用理性和逻辑来分析问题。你的发言风格温和而深刻,总是能找到问题的核心。每次发言控制在100字以内。"
|
||
},
|
||
"何仙姑": {
|
||
"name": "何仙姑",
|
||
"model": "gemini-2.5-flash",
|
||
"instruction": "你是何仙姑,八仙中的风险控制专家。你总是从风险管理的角度思考问题,善于发现潜在危险。你的发言风格谨慎、细致,总是能提出需要警惕的问题。每次发言控制在100字以内。"
|
||
},
|
||
"张果老": {
|
||
"name": "张果老",
|
||
"model": "gemini-2.5-flash",
|
||
"instruction": "你是张果老,八仙中的历史智慧者。你善于从历史数据中寻找规律和智慧,总是能提供长期视角。你的发言风格沉稳、博学,总是能引经据典。每次发言控制在100字以内。"
|
||
},
|
||
"蓝采和": {
|
||
"name": "蓝采和",
|
||
"model": "gemini-2.5-flash",
|
||
"instruction": "你是蓝采和,八仙中的创新思维者。你善于从新兴视角和非传统方法来看待问题,总能提出独特的见解。你的发言风格活泼、新颖,总是能带来意想不到的观点。每次发言控制在100字以内。"
|
||
},
|
||
"汉钟离": {
|
||
"name": "汉钟离",
|
||
"model": "gemini-2.5-flash",
|
||
"instruction": "你是汉钟离,八仙中的平衡协调者。你善于综合各方观点,寻求和谐统一的解决方案。你的发言风格平和、包容,总是能化解矛盾。每次发言控制在100字以内。"
|
||
},
|
||
"韩湘子": {
|
||
"name": "韩湘子",
|
||
"model": "gemini-2.5-flash",
|
||
"instruction": "你是韩湘子,八仙中的艺术感知者。你善于从美学和感性的角度分析问题,总能发现事物背后的深层含义。你的发言风格优雅、感性,总是能触动人心。每次发言控制在100字以内。"
|
||
},
|
||
"曹国舅": {
|
||
"name": "曹国舅",
|
||
"model": "gemini-2.5-flash",
|
||
"instruction": "你是曹国舅,八仙中的实务执行者。你关注实际操作和具体细节,善于将理论转化为可行的方案。你的发言风格务实、严谨,总是能提出建设性意见。每次发言控制在100字以内。"
|
||
}
|
||
}
|
||
|
||
# 创建会话服务和会话
|
||
session_service = InMemorySessionService()
|
||
session = await session_service.create_session(
|
||
state={},
|
||
app_name="稷下学宫轮流辩论系统",
|
||
user_id="debate_user"
|
||
)
|
||
|
||
# 创建主持人和八仙智能体及Runner
|
||
host_agent = None
|
||
host_runner = None
|
||
baxian_agents = {}
|
||
baxian_runners = {}
|
||
|
||
# 创建主持人
|
||
host_config = roles_config["太上老君"]
|
||
host_agent = Agent(
|
||
name=host_config["name"],
|
||
model=host_config["model"],
|
||
instruction=host_config["instruction"]
|
||
)
|
||
host_runner = Runner(
|
||
app_name="稷下学宫轮流辩论系统",
|
||
agent=host_agent,
|
||
session_service=session_service
|
||
)
|
||
|
||
# 创建八仙
|
||
for name in participants:
|
||
if name in roles_config:
|
||
config = roles_config[name]
|
||
agent = Agent(
|
||
name=config["name"],
|
||
model=config["model"],
|
||
instruction=config["instruction"]
|
||
)
|
||
baxian_agents[name] = agent
|
||
|
||
runner = Runner(
|
||
app_name="稷下学宫轮流辩论系统",
|
||
agent=agent,
|
||
session_service=session_service
|
||
)
|
||
baxian_runners[name] = runner
|
||
else:
|
||
print(f"⚠️ 未知的参与者: {name},将被跳过。")
|
||
|
||
if not baxian_agents:
|
||
print("❌ 没有有效的参与者,请检查参与者列表。")
|
||
return False
|
||
|
||
print(f"🎯 主持人: 太上老君")
|
||
print(f"👥 参与仙人: {', '.join(baxian_agents.keys())}")
|
||
|
||
# 初始化辩论历史
|
||
debate_history = []
|
||
|
||
# 开场白
|
||
print(f"\n📢 太上老君开场:")
|
||
opening_prompt = f"各位仙友,欢迎来到本次论道。今天的主题是:{topic}。请各位依次发表高见。"
|
||
content = types.Content(role='user', parts=[types.Part(text=opening_prompt)])
|
||
response = host_runner.run_async(
|
||
user_id=session.user_id,
|
||
session_id=session.id,
|
||
new_message=content
|
||
)
|
||
reply = ""
|
||
async for event in response:
|
||
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:
|
||
reply += str(part.text)
|
||
elif hasattr(event, 'text') and event.text:
|
||
reply += str(event.text)
|
||
if reply.strip():
|
||
clean_reply = reply.strip()
|
||
print(f" {clean_reply}")
|
||
debate_history.append(f"太上老君: {clean_reply}")
|
||
await asyncio.sleep(1)
|
||
|
||
# 进行辩论
|
||
for round_num in range(rounds):
|
||
print(f"\n🌀 第 {round_num + 1} 轮辩论:")
|
||
|
||
# 主持人引导本轮辩论
|
||
print(f"\n📢 太上老君引导:")
|
||
guide_prompt = f"现在进入第 {round_num + 1} 轮辩论,请各位仙友围绕主题发表看法。"
|
||
content = types.Content(role='user', parts=[types.Part(text=guide_prompt)])
|
||
response = host_runner.run_async(
|
||
user_id=session.user_id,
|
||
session_id=session.id,
|
||
new_message=content
|
||
)
|
||
reply = ""
|
||
async for event in response:
|
||
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:
|
||
reply += str(part.text)
|
||
elif hasattr(event, 'text') and event.text:
|
||
reply += str(event.text)
|
||
if reply.strip():
|
||
clean_reply = reply.strip()
|
||
print(f" {clean_reply}")
|
||
debate_history.append(f"太上老君: {clean_reply}")
|
||
await asyncio.sleep(1)
|
||
|
||
# 八仙轮流发言
|
||
for name in participants:
|
||
if name not in baxian_runners:
|
||
continue
|
||
|
||
print(f"\n🗣️ {name} 发言:")
|
||
|
||
# 构建提示
|
||
history_context = ""
|
||
if debate_history:
|
||
recent_history = debate_history[-5:] # 最近5条发言
|
||
history_context = f"\n最近的论道内容:\n" + "\n".join([f"- {h}" for h in recent_history])
|
||
|
||
prompt = f"论道主题: {topic}{history_context}\n\n请从你的角色特点出发发表观点。请控制在100字以内。"
|
||
|
||
# 发送消息并获取回复
|
||
content = types.Content(role='user', parts=[types.Part(text=prompt)])
|
||
response = baxian_runners[name].run_async(
|
||
user_id=session.user_id,
|
||
session_id=session.id,
|
||
new_message=content
|
||
)
|
||
|
||
# 收集回复
|
||
reply = ""
|
||
async for event in response:
|
||
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:
|
||
reply += str(part.text)
|
||
elif hasattr(event, 'text') and event.text:
|
||
reply += str(event.text)
|
||
|
||
if reply.strip():
|
||
clean_reply = reply.strip()
|
||
print(f" {clean_reply}")
|
||
|
||
# 记录到辩论历史
|
||
debate_entry = f"{name}: {clean_reply}"
|
||
debate_history.append(debate_entry)
|
||
|
||
await asyncio.sleep(1) # 避免API调用过快
|
||
|
||
# 结束语
|
||
print(f"\n📢 太上老君总结:")
|
||
closing_prompt = f"各位仙友的高见令我受益匪浅。本次论道到此结束,希望各位能从不同观点中获得启发。"
|
||
content = types.Content(role='user', parts=[types.Part(text=closing_prompt)])
|
||
response = host_runner.run_async(
|
||
user_id=session.user_id,
|
||
session_id=session.id,
|
||
new_message=content
|
||
)
|
||
reply = ""
|
||
async for event in response:
|
||
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:
|
||
reply += str(part.text)
|
||
elif hasattr(event, 'text') and event.text:
|
||
reply += str(event.text)
|
||
if reply.strip():
|
||
clean_reply = reply.strip()
|
||
print(f" {clean_reply}")
|
||
debate_history.append(f"太上老君: {clean_reply}")
|
||
await asyncio.sleep(1)
|
||
|
||
# 关闭资源
|
||
await host_runner.close()
|
||
for runner in baxian_runners.values():
|
||
await runner.close()
|
||
|
||
print(f"\n🎉 ADK八仙轮流辩论完成!")
|
||
print(f"📝 本次论道共产生 {len(debate_history)} 条发言。")
|
||
return True
|
||
|
||
except ImportError as e:
|
||
print(f"❌ 导入模块失败: {e}")
|
||
print("请确保已安装Google ADK: pip install google-adk")
|
||
return False
|
||
except Exception as e:
|
||
print(f"❌ 运行ADK八仙轮流辩论失败: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
return False
|
||
|
||
|
||
async def run_swarm_debate(topic: str, participants: list = None):
|
||
"""运行Swarm辩论 (示例)"""
|
||
try:
|
||
print(f"🚀 启动Swarm辩论...")
|
||
print(f"📋 辩论主题: {topic}")
|
||
print(f"👥 参与者: {participants}")
|
||
|
||
# TODO: 实现调用 Swarm 辩论逻辑
|
||
# 这里需要根据实际的 swarm_debate.py 接口来实现
|
||
print("⚠️ Swarm辩论功能待实现")
|
||
|
||
print("\n🎉 Swarm辩论完成!")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"❌ 运行Swarm辩论失败: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
return False
|
||
|
||
|
||
async def main_async(args):
|
||
"""异步主函数"""
|
||
# 检查环境
|
||
if not check_environment():
|
||
return 1
|
||
|
||
# 根据模式运行不同的辩论
|
||
if args.mode == "adk_memory":
|
||
participants = args.participants.split(",") if args.participants else None
|
||
success = await run_adk_memory_debate(args.topic, participants)
|
||
return 0 if success else 1
|
||
|
||
elif args.mode == "adk_turn_based":
|
||
participants = args.participants.split(",") if args.participants else None
|
||
success = await run_adk_turn_based_debate(args.topic, participants, args.rounds)
|
||
return 0 if success else 1
|
||
|
||
elif args.mode == "adk_simple":
|
||
# 简单辩论模式暂时使用原来的方式
|
||
try:
|
||
sys.path.insert(0, os.path.join(project_root, 'examples', 'debates'))
|
||
from adk_simple_debate import simple_debate_test
|
||
result = simple_debate_test()
|
||
return 0 if result else 1
|
||
except Exception as e:
|
||
print(f"❌ 运行ADK简单辩论失败: {e}")
|
||
return 1
|
||
|
||
elif args.mode == "swarm":
|
||
participants = args.participants.split(",") if args.participants else None
|
||
success = await run_swarm_debate(args.topic, participants)
|
||
return 0 if success else 1
|
||
|
||
else:
|
||
print(f"❌ 不支持的模式: {args.mode}")
|
||
return 1
|
||
|
||
|
||
def main():
|
||
"""主入口函数"""
|
||
parser = argparse.ArgumentParser(description="稷下学宫AI辩论系统")
|
||
parser.add_argument(
|
||
"mode",
|
||
choices=["adk_memory", "adk_turn_based", "adk_simple", "swarm"],
|
||
help="辩论模式"
|
||
)
|
||
parser.add_argument(
|
||
"--topic",
|
||
"-t",
|
||
default="人工智能对未来社会的影响",
|
||
help="辩论主题"
|
||
)
|
||
parser.add_argument(
|
||
"--participants",
|
||
"-p",
|
||
help="参与者列表(逗号分隔),例如: 铁拐李,吕洞宾,何仙姑"
|
||
)
|
||
parser.add_argument(
|
||
"--rounds",
|
||
"-r",
|
||
type=int,
|
||
default=3,
|
||
help="辩论轮数 (仅适用于 adk_turn_based 模式)"
|
||
)
|
||
|
||
args = parser.parse_args()
|
||
|
||
# 运行异步主函数
|
||
try:
|
||
exit_code = asyncio.run(main_async(args))
|
||
sys.exit(exit_code)
|
||
except KeyboardInterrupt:
|
||
print("\n\n👋 用户中断,退出程序")
|
||
sys.exit(0)
|
||
except Exception as e:
|
||
print(f"\n\n💥 程序运行出错: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
sys.exit(1)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main() |