# -*- coding: utf-8 -*- """ 多智能体辩论编排引擎 流程:信息分发 → 独立研判 → 交叉质证 → 综合裁决 """ import json import logging import time from typing import Optional from .law_agent import LawAgent from .tech_agent import TechAgent from .finance_agent import FinanceAgent from .judge_agent import JudgeAgent logger = logging.getLogger(__name__) class DebateEngine: """多智能体辩论编排器""" def __init__(self): self.law_agent = LawAgent() self.tech_agent = TechAgent() self.finance_agent = FinanceAgent() self.judge_agent = JudgeAgent() self.debate_log = [] def run_debate(self, company_data: dict, callback=None) -> dict: """ 执行完整的多智能体辩论流程 Args: company_data: 企业数据字典 callback: 进度回调函数 callback(step, message, result) """ self.debate_log = [] company_name = company_data.get("short_name", company_data.get("company_name", "未知")) start_time = time.time() self._log(f"🏁 启动对 [{company_name}] 的多智能体交叉验证辩论") # ============================== # Phase 1: 独立研判 # ============================== self._log("=" * 50) self._log("📋 Phase 1: 各节点独立研判") self._log("=" * 50) # 法务节点 self._log("👩‍⚖️ 法务风控节点开始评估...") if callback: callback("law_start", "法务风控节点开始评估...", None) law_result = self.law_agent.evaluate(company_data) self._log(f"👩‍⚖️ 法务节点完成: 综合法务风险 {law_result.get('overall_law_risk', {}).get('score', '?')} 分") if callback: callback("law_done", "法务风控节点评估完成", law_result) # 技术节点 self._log("👨‍🔬 技术风控节点开始评估...") if callback: callback("tech_start", "技术风控节点开始评估...", None) tech_result = self.tech_agent.evaluate(company_data) self._log(f"👨‍🔬 技术节点完成: 综合技术风险 {tech_result.get('overall_tech_risk', {}).get('score', '?')} 分") if callback: callback("tech_done", "技术风控节点评估完成", tech_result) # 财务节点 self._log("👔 财务风控节点开始评估...") if callback: callback("fin_start", "财务风控节点开始评估...", None) finance_result = self.finance_agent.evaluate(company_data) self._log(f"👔 财务节点完成: 综合财务风险 {finance_result.get('overall_fin_risk', {}).get('score', '?')} 分") if callback: callback("fin_done", "财务风控节点评估完成", finance_result) # ============================== # Phase 2: 交叉质证(记录冲突点) # ============================== self._log("=" * 50) self._log("🔄 Phase 2: 交叉质证") self._log("=" * 50) conflicts = self._identify_conflicts(law_result, tech_result, finance_result) for conflict in conflicts: self._log(f"⚠️ 冲突: {conflict}") if not conflicts: self._log("✅ 各节点意见一致,无冲突") if callback: callback("cross_validation", "交叉质证完成", {"conflicts": conflicts}) # ============================== # Phase 3: 综合裁决 # ============================== self._log("=" * 50) self._log("⚖️ Phase 3: 综合裁决") self._log("=" * 50) if callback: callback("judge_start", "综合裁决节点开始...", None) judge_result = self.judge_agent.evaluate( company_data, law_result, tech_result, finance_result ) self._log(f"⚖️ 综合评分: {judge_result.get('comprehensive_score', '?')} 分") self._log(f"⚖️ 核保建议: 【{judge_result.get('underwriting_decision', '?')}】") if callback: callback("judge_done", "综合裁决完成", judge_result) elapsed = time.time() - start_time self._log(f"🏁 辩论完成,耗时 {elapsed:.1f} 秒") return { "company": company_name, "law_result": law_result, "tech_result": tech_result, "finance_result": finance_result, "conflicts": conflicts, "judge_result": judge_result, "debate_log": self.debate_log, "elapsed_seconds": round(elapsed, 1), } def _identify_conflicts(self, law_result: dict, tech_result: dict, finance_result: dict) -> list: """识别各节点之间的判定冲突""" conflicts = [] # 检查法务和技术的冲突:例如法务认为合规但技术认为路线有风险 law_overall = law_result.get("overall_law_risk", {}).get("score", 50) tech_overall = tech_result.get("overall_tech_risk", {}).get("score", 50) fin_overall = finance_result.get("overall_fin_risk", {}).get("score", 50) # 大幅分歧(差异超过30分) if abs(law_overall - tech_overall) > 30: if law_overall > tech_overall: conflicts.append( f"法务节点({law_overall}分)与技术节点({tech_overall}分)存在较大分歧: " f"法务认为合规风险较高,但技术面评估相对乐观" ) else: conflicts.append( f"技术节点({tech_overall}分)与法务节点({law_overall}分)存在较大分歧: " f"技术风险较高,但法务合规状态相对可控" ) if abs(tech_overall - fin_overall) > 30: conflicts.append( f"技术节点({tech_overall}分)与财务节点({fin_overall}分)存在分歧: " f"需审查技术投入与财务表现的匹配度" ) # 特定维度冲突:技术认为研发投入大=好事,财务可能认为是资本化操纵 tech_rd_view = tech_result.get("tech_iteration_pressure", {}).get("score", 50) fin_rd_view = finance_result.get("rd_capitalization_risk", {}).get("score", 50) if tech_rd_view < 40 and fin_rd_view > 60: conflicts.append( "技术节点认为研发投入合理,但财务节点发现研发资本化率异常," "存在通过资本化手段美化利润的嫌疑" ) return conflicts def _log(self, message: str): """记录辩论日志""" entry = {"timestamp": time.strftime("%H:%M:%S"), "message": message} self.debate_log.append(entry) logger.info(message) def run_debate(stock_code: str) -> dict: """便捷接口:通过股票代码直接运行辩论""" from collectors.financial_collector import get_company_by_code company_data = get_company_by_code(stock_code) if not company_data: return {"error": f"未找到股票代码 {stock_code} 的企业数据"} engine = DebateEngine() return engine.run_debate(company_data)