Files
XH-202626/risk_engine/report_generator.py
T

147 lines
5.4 KiB
Python

# -*- coding: utf-8 -*-
"""
核保决策报告生成器
生成结构化的风险评估报告
"""
import json
import logging
from datetime import datetime
from typing import Optional
logger = logging.getLogger(__name__)
def generate_report(
company_data: dict,
debate_result: dict,
pricing_results: list,
) -> dict:
"""
生成完整的核保决策报告
"""
company_name = company_data.get("short_name", "未知企业")
judge = debate_result.get("judge_result", {})
scores = judge.get("six_dimension_scores", {})
comprehensive = judge.get("comprehensive_score", 50)
decision = judge.get("underwriting_decision", "标准承保")
report = {
"title": f"科创企业智能风控核保报告 —— {company_name}",
"report_id": f"RPT-{datetime.now().strftime('%Y%m%d%H%M%S')}",
"generate_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"company_profile": {
"name": company_name,
"stock_code": company_data.get("stock_code", ""),
"industry": company_data.get("industry", ""),
"sector": company_data.get("sector", ""),
"description": company_data.get("description", ""),
},
"risk_assessment": {
"comprehensive_score": comprehensive,
"risk_level": judge.get("risk_level", "中"),
"six_dimension_scores": scores,
"key_risks": judge.get("key_risks", []),
},
"debate_summary": {
"law_findings": debate_result.get("law_result", {}).get("key_findings", []),
"tech_findings": debate_result.get("tech_result", {}).get("key_findings", []),
"fin_findings": debate_result.get("finance_result", {}).get("key_findings", []),
"conflicts": debate_result.get("conflicts", []),
"resolution": judge.get("conflict_resolution", ""),
},
"underwriting_decision": {
"decision": decision,
"conditions": judge.get("underwriting_conditions", []),
"summary": judge.get("summary", ""),
},
"pricing": pricing_results,
}
return report
def format_report_markdown(report: dict) -> str:
"""将报告格式化为 Markdown"""
lines = []
lines.append(f"# {report['title']}")
lines.append(f"\n> 报告编号: {report['report_id']} | 生成时间: {report['generate_time']}")
# 企业概况
profile = report["company_profile"]
lines.append("\n## 一、企业概况")
lines.append(f"- **企业名称**: {profile['name']}")
lines.append(f"- **股票代码**: {profile['stock_code']}")
lines.append(f"- **所属行业**: {profile['industry']}")
lines.append(f"- **企业描述**: {profile['description']}")
# 风险评估
risk = report["risk_assessment"]
lines.append("\n## 二、风险评估")
lines.append(f"- **综合风险评分**: {risk['comprehensive_score']} 分")
lines.append(f"- **风险等级**: {risk['risk_level']}")
lines.append("\n### 六维风险评分")
dim_names = {
"tech_disruption": "技术路线颠覆",
"talent_loss": "核心人员流失",
"algo_compliance": "算法/数据合规",
"geopolitical": "地缘政治/出口管制",
"rd_capitalization": "研发资本化操纵",
"concentration": "客户/供应商集中",
}
lines.append("| 风险维度 | 评分 | 等级 |")
lines.append("|---------|------|------|")
for dim, score in risk.get("six_dimension_scores", {}).items():
name = dim_names.get(dim, dim)
level = "高" if score >= 70 else ("中" if score >= 40 else "低")
lines.append(f"| {name} | {score} | {level} |")
# 辩论摘要
debate = report["debate_summary"]
lines.append("\n## 三、多智能体交叉验证摘要")
lines.append("\n### 👩‍⚖️ 法务风控节点")
for f in debate.get("law_findings", []):
lines.append(f"- {f}")
lines.append("\n### 👨‍🔬 技术风控节点")
for f in debate.get("tech_findings", []):
lines.append(f"- {f}")
lines.append("\n### 👔 财务风控节点")
for f in debate.get("fin_findings", []):
lines.append(f"- {f}")
if debate.get("conflicts"):
lines.append("\n### ⚠️ 冲突点")
for c in debate["conflicts"]:
lines.append(f"- {c}")
# 核保决策
uw = report["underwriting_decision"]
lines.append(f"\n## 四、核保决策")
lines.append(f"\n**决策**: 【{uw['decision']}】")
lines.append(f"\n{uw.get('summary', '')}")
if uw.get("conditions"):
lines.append("\n### 核保附加条件")
for c in uw["conditions"]:
lines.append(f"- {c}")
# 保费方案
lines.append("\n## 五、保险产品费率方案")
if report.get("pricing"):
lines.append("| 险种 | 基础保费 | 最终保费 | 保额 | 免赔率 |")
lines.append("|------|---------|---------|------|--------|")
for p in report["pricing"]:
if p.get("is_insurable"):
lines.append(
f"| {p['product_name']} | ¥{p['base_premium']:,.0f} | "
f{p['final_premium']:,.0f} | ¥{p['adjusted_coverage']:,.0f} | "
f"{p['deductible_rate']:.0%} |"
)
else:
lines.append(f"| {p['product_name']} | - | **拒保** | - | - |")
return "\n".join(lines)