#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 稷下学宫完整版 - 基于OpenAI Swarm的八仙辩论系统 实现完整的八仙论道 + 三清决策 """ import os import asyncio import json import subprocess from datetime import datetime from swarm import Swarm, Agent from typing import Dict, List, Any, Optional import random class JixiaSwarmAcademy: """稷下学宫 - 完整的八仙辩论系统""" def __init__(self): # 从Doppler获取API密钥 self.api_key = self.get_secure_api_key() # 设置环境变量 if self.api_key: os.environ["OPENAI_API_KEY"] = self.api_key os.environ["OPENAI_BASE_URL"] = "https://openrouter.ai/api/v1" # 初始化Swarm客户端,传入配置 from openai import OpenAI openai_client = OpenAI( api_key=self.api_key, base_url="https://openrouter.ai/api/v1", default_headers={ "HTTP-Referer": "https://github.com/ben/cauldron", "X-Title": "Jixia Academy Debate System" # 避免中文字符 } ) self.client = Swarm(client=openai_client) else: print("❌ 无法获取有效的API密钥") self.client = None # 八仙配置 - 完整版 self.immortals_config = { '吕洞宾': { 'role': '剑仙投资顾问', 'gua_position': '乾☰', 'specialty': '技术分析', 'stance': 'positive', 'style': '一剑封喉,直指要害', 'personality': '犀利直接,善于识破市场迷雾', 'weapon': '纯阳剑', 'next': '何仙姑' }, '何仙姑': { 'role': '慈悲风控专家', 'gua_position': '坤☷', 'specialty': '风险控制', 'stance': 'negative', 'style': '荷花在手,全局在胸', 'personality': '温和坚定,关注风险控制', 'weapon': '荷花', 'next': '张果老' }, '张果老': { 'role': '历史数据分析师', 'gua_position': '艮☶', 'specialty': '历史回测', 'stance': 'positive', 'style': '倒骑毛驴,逆向思维', 'personality': '博古通今,从历史中寻找规律', 'weapon': '鱼鼓', 'next': '韩湘子' }, '韩湘子': { 'role': '市场情绪分析师', 'gua_position': '兑☱', 'specialty': '情绪分析', 'stance': 'negative', 'style': '笛声悠扬,感知人心', 'personality': '敏感细腻,善于捕捉市场情绪', 'weapon': '洞箫', 'next': '汉钟离' }, '汉钟离': { 'role': '宏观经济分析师', 'gua_position': '离☲', 'specialty': '宏观分析', 'stance': 'positive', 'style': '扇子一挥,大局明了', 'personality': '气度恢宏,关注宏观大势', 'weapon': '芭蕉扇', 'next': '蓝采和' }, '蓝采和': { 'role': '量化交易专家', 'gua_position': '巽☴', 'specialty': '量化模型', 'stance': 'negative', 'style': '花篮一抛,数据飞舞', 'personality': '逻辑严密,依赖数学模型', 'weapon': '花篮', 'next': '曹国舅' }, '曹国舅': { 'role': '价值投资专家', 'gua_position': '坎☵', 'specialty': '基本面分析', 'stance': 'positive', 'style': '玉板一敲,价值显现', 'personality': '稳重踏实,注重内在价值', 'weapon': '玉板', 'next': '铁拐李' }, '铁拐李': { 'role': '逆向投资大师', 'gua_position': '震☳', 'specialty': '逆向投资', 'stance': 'negative', 'style': '铁拐一点,危机毕现', 'personality': '不拘一格,挑战主流观点', 'weapon': '铁拐杖', 'next': 'summary' } } # 三清决策层配置 self.sanqing_config = { '元始天尊': { 'role': '最终决策者', 'specialty': '综合决策', 'style': '无极生太极,一言定乾坤' }, '灵宝天尊': { 'role': '风险评估师', 'specialty': '风险量化', 'style': '太极生两仪,阴阳定风险' }, '道德天尊': { 'role': '合规审查员', 'specialty': '合规检查', 'style': '两仪生四象,四象定规矩' } } # 创建智能体 self.immortal_agents = self.create_immortal_agents() self.sanqing_agents = self.create_sanqing_agents() # 辩论历史 self.debate_history = [] self.current_round = 0 self.max_rounds = 2 # 每个仙人最多发言2轮 def get_secure_api_key(self): """获取API密钥 - 支持多种方式""" # 从环境变量获取API密钥 available_keys = [ os.getenv("OPENROUTER_API_KEY_1"), os.getenv("OPENROUTER_API_KEY_2"), os.getenv("OPENROUTER_API_KEY_3"), os.getenv("OPENROUTER_API_KEY_4") ] # 过滤掉None值 available_keys = [key for key in available_keys if key] # 直接使用第一个密钥进行测试 test_key = available_keys[0] print(f"🔑 直接使用测试密钥: {test_key[:20]}...") return test_key def create_immortal_agents(self) -> Dict[str, Agent]: """创建八仙智能体""" agents = {} for name, config in self.immortals_config.items(): # 创建转换函数 - 使用英文名称避免特殊字符问题 next_immortal = config['next'] if next_immortal == 'summary': transfer_func = self.transfer_to_sanqing else: # 创建一个简单的转换函数,避免lambda的问题 def create_transfer_func(next_name): def transfer(): return self.transfer_to_immortal(next_name) transfer.__name__ = f"transfer_to_{self.get_english_name(next_name)}" return transfer transfer_func = create_transfer_func(next_immortal) # 构建详细的指令 instructions = self.build_immortal_instructions(name, config) agents[name] = Agent( name=name, instructions=instructions, functions=[transfer_func] ) return agents def create_sanqing_agents(self) -> Dict[str, Agent]: """创建三清决策层智能体""" agents = {} # 元始天尊 - 最终决策者 agents['元始天尊'] = Agent( name="元始天尊", instructions=""" 你是元始天尊,道教三清之首,稷下学宫的最终决策者。 你的使命: 1. 综合八仙的所有观点,做出最终投资决策 2. 平衡正反两方的观点,寻找最优解 3. 给出具体的投资建议和操作指导 4. 评估决策的风险等级和预期收益 你的风格: - 高屋建瓴,统揽全局 - 言简意赅,一锤定音 - 既不偏向乐观,也不偏向悲观 - 以数据和逻辑为准绳 请以"元始天尊曰"开头,给出最终决策。 决策格式: - 投资建议:买入/持有/卖出 - 风险等级:低/中/高 - 预期收益:具体百分比 - 操作建议:具体的操作指导 - 决策依据:主要的决策理由 """, functions=[] ) return agents def build_immortal_instructions(self, name: str, config: Dict) -> str: """构建仙人的详细指令""" stance_desc = "看涨派,倾向于发现投资机会" if config['stance'] == 'positive' else "看跌派,倾向于发现投资风险" instructions = f""" 你是{name},八仙之一,{config['role']}。 你的身份特征: - 位居{config['gua_position']}之位,代表{self.get_gua_meaning(config['gua_position'])} - 持有{config['weapon']},{config['style']} - 擅长{config['specialty']},{config['personality']} - 立场倾向:{stance_desc} 在稷下学宫辩论中,你要: 1. **专业分析**:从{config['specialty']}角度深入分析 2. **立场鲜明**:作为{stance_desc},要有明确的观点 3. **数据支撑**:用具体的数据、图表、历史案例支撑观点 4. **互动辩论**:可以质疑前面仙人的观点,但要有理有据 5. **仙风道骨**:保持古雅的表达风格,但不影响专业性 6. **承上启下**:总结前面的观点,为后面的仙人铺垫 发言格式: - 以"{name}曰:"开头 - 先简要回应前面仙人的观点(如果有) - 然后从你的专业角度进行分析 - 最后明确表达你的投资倾向 - 结尾时说"请{config['next']}仙长继续论道"(如果不是最后一个) 记住:你是{stance_desc},要体现这个立场,但也要保持专业和客观。 """ return instructions def get_gua_meaning(self, gua: str) -> str: """获取卦象含义""" meanings = { '乾☰': '天行健,自强不息', '坤☷': '地势坤,厚德载物', '艮☶': '艮为山,止于至善', '兑☱': '兑为泽,和悦致祥', '离☲': '离为火,光明磊落', '巽☴': '巽为风,随风而化', '坎☵': '坎为水,智慧如水', '震☳': '震为雷,威震四方' } return meanings.get(gua, '神秘莫测') def transfer_to_hexiangu(self): """转到何仙姑""" return self.immortal_agents.get('何仙姑') def transfer_to_zhangguolao(self): """转到张果老""" return self.immortal_agents.get('张果老') def transfer_to_hanxiangzi(self): """转到韩湘子""" return self.immortal_agents.get('韩湘子') def transfer_to_hanzhongli(self): """转到汉钟离""" return self.immortal_agents.get('汉钟离') def transfer_to_lancaihe(self): """转到蓝采和""" return self.immortal_agents.get('蓝采和') def transfer_to_caoguojiu(self): """转到曹国舅""" return self.immortal_agents.get('曹国舅') def transfer_to_tieguaili(self): """转到铁拐李""" return self.immortal_agents.get('铁拐李') def transfer_to_sanqing(self): """转到三清决策层""" return self.sanqing_agents['元始天尊'] async def conduct_full_debate(self, topic: str, context: Dict[str, Any] = None) -> Dict[str, Any]: """进行完整的稷下学宫辩论""" if not self.api_key or not self.client: print("❌ 无法获取API密钥或初始化客户端,无法进行论道") return None print("🏛️ 稷下学宫八仙论道正式开始!") print("=" * 80) print(f"🎯 论道主题: {topic}") print(f"⏰ 开始时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") print() # 构建初始提示 initial_prompt = self.build_debate_prompt(topic, context) try: # 从吕洞宾开始论道 print("⚔️ 吕洞宾仙长请先发言...") print("-" * 60) response = self.client.run( agent=self.immortal_agents['吕洞宾'], messages=[{"role": "user", "content": initial_prompt}], max_turns=20 # 允许多轮对话 ) print("\n" + "=" * 80) print("🎊 稷下学宫八仙论道圆满结束!") print("📊 三清决策已生成") # 处理辩论结果 debate_result = self.process_debate_result(response, topic, context) # 显示辩论总结 self.display_debate_summary(debate_result) return debate_result except Exception as e: print(f"❌ 论道过程中出错: {e}") import traceback traceback.print_exc() return None def build_debate_prompt(self, topic: str, context: Dict[str, Any] = None) -> str: """构建辩论提示""" context_str = "" if context: context_str = f"\n📊 市场背景:\n{json.dumps(context, indent=2, ensure_ascii=False)}\n" # 随机选择一些市场数据作为背景 market_context = self.generate_market_context(topic) prompt = f""" 🏛️ 稷下学宫八仙论道正式开始! 📜 论道主题: {topic} {context_str} 📈 当前市场环境: {market_context} 🎭 论道规则: 1. 八仙按序发言:吕洞宾 → 何仙姑 → 张果老 → 韩湘子 → 汉钟离 → 蓝采和 → 曹国舅 → 铁拐李 2. 正反方交替:正方(看涨) vs 反方(看跌) 3. 每位仙人从专业角度分析,必须提供数据支撑 4. 可以质疑前面仙人的观点,但要有理有据 5. 保持仙风道骨的表达风格 6. 最后由三清做出最终决策 🗡️ 请吕洞宾仙长首先发言,展现剑仙的犀利分析! 记住:你是看涨派,要从技术分析角度找到投资机会! """ return prompt def generate_market_context(self, topic: str) -> str: """生成模拟的市场背景数据""" # 这里可以集成真实的市场数据,现在先用模拟数据 contexts = { "英伟达": "NVDA当前价格$120,P/E比率65,市值$3T,AI芯片需求旺盛", "比特币": "BTC当前价格$43,000,24h涨幅+2.3%,机构持续买入", "美联储": "联邦基金利率5.25%,通胀率3.2%,就业数据强劲", "中国股市": "上证指数3100点,外资流入放缓,政策支持预期" } # 根据主题选择相关背景 for key, context in contexts.items(): if key in topic: return context return "市场情绪谨慎,波动率上升,投资者观望情绪浓厚" def process_debate_result(self, response, topic: str, context: Dict[str, Any]) -> Dict[str, Any]: """处理辩论结果""" # 提取所有消息 all_messages = response.messages if hasattr(response, 'messages') else [] # 分析发言者和内容 debate_messages = [] speakers = [] for msg in all_messages: if msg.get('role') == 'assistant' and msg.get('content'): content = msg['content'] speaker = self.extract_speaker_from_content(content) debate_messages.append({ 'speaker': speaker, 'content': content, 'timestamp': datetime.now().isoformat(), 'stance': self.get_speaker_stance(speaker) }) if speaker not in speakers: speakers.append(speaker) # 提取最终决策(通常是最后一条消息) final_decision = "" if debate_messages: final_decision = debate_messages[-1]['content'] # 构建结果 result = { "debate_id": f"jixia_debate_{datetime.now().strftime('%Y%m%d_%H%M%S')}", "topic": topic, "context": context, "participants": speakers, "messages": debate_messages, "final_decision": final_decision, "summary": self.generate_debate_summary(debate_messages), "timestamp": datetime.now().isoformat(), "framework": "OpenAI Swarm", "academy": "稷下学宫" } self.debate_history.append(result) return result def extract_speaker_from_content(self, content: str) -> str: """从内容中提取发言者""" for name in list(self.immortals_config.keys()) + list(self.sanqing_config.keys()): if f"{name}曰" in content or name in content[:20]: return name return "未知仙人" def get_speaker_stance(self, speaker: str) -> str: """获取发言者立场""" if speaker in self.immortals_config: return self.immortals_config[speaker]['stance'] elif speaker in self.sanqing_config: return 'neutral' return 'unknown' def generate_debate_summary(self, messages: List[Dict]) -> str: """生成辩论摘要""" positive_count = len([m for m in messages if m.get('stance') == 'positive']) negative_count = len([m for m in messages if m.get('stance') == 'negative']) summary = f""" 📊 辩论统计: - 参与仙人: {len(set(m['speaker'] for m in messages))}位 - 看涨观点: {positive_count}条 - 看跌观点: {negative_count}条 - 总发言数: {len(messages)}条 🎯 观点倾向: {'偏向看涨' if positive_count > negative_count else '偏向看跌' if negative_count > positive_count else '观点平衡'} """ return summary def display_debate_summary(self, result: Dict[str, Any]): """显示辩论总结""" print("\n🌟 稷下学宫辩论总结") print("=" * 80) print(f"📜 主题: {result['topic']}") print(f"🎭 参与仙人: {', '.join(result['participants'])}") print(f"⏰ 辩论时间: {result['timestamp']}") print(f"🔧 技术框架: {result['framework']}") print(result['summary']) print("\n🏆 最终决策:") print("-" * 40) print(result['final_decision']) print("\n✨ 稷下学宫辩论特色:") print("🗡️ 八仙各展所长,观点多元化") print("⚖️ 正反方交替发言,辩论更激烈") print("🧠 三清最终决策,权威性更强") print("🔄 基于Swarm框架,性能更优越") # 主函数和测试 async def main(): """主函数 - 演示完整的稷下学宫辩论""" print("🏛️ 稷下学宫 - OpenAI Swarm完整版") print("🔐 使用Doppler安全管理API密钥") print("🚀 八仙论道 + 三清决策的完整体验") print() # 创建学宫 academy = JixiaSwarmAcademy() if not academy.api_key: print("❌ 无法获取API密钥,请检查Doppler配置或环境变量") return # 辩论主题列表 topics = [ "英伟达股价走势:AI泡沫还是技术革命?", "美联储2024年货币政策:加息还是降息?", "比特币vs黄金:谁是更好的避险资产?", "中国房地产市场:触底反弹还是继续下行?", "特斯拉股价:马斯克效应还是基本面支撑?" ] # 随机选择主题 topic = random.choice(topics) # 构建市场背景 context = { "market_sentiment": "谨慎乐观", "volatility": "中等", "major_events": ["美联储会议", "财报季", "地缘政治紧张"], "technical_indicators": { "RSI": 65, "MACD": "金叉", "MA20": "上穿" } } # 开始辩论 result = await academy.conduct_full_debate(topic, context) if result: print(f"\n🎉 辩论成功完成!辩论ID: {result['debate_id']}") else: print("❌ 辩论失败") if __name__ == "__main__": asyncio.run(main())