Files

179 lines
7.1 KiB
Python

# -*- 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)