98 lines
3.0 KiB
Python
98 lines
3.0 KiB
Python
"""将意图计算结果组装为可持久化的 Agent 草稿。"""
|
||
from __future__ import annotations
|
||
|
||
from decimal import Decimal
|
||
|
||
from agent.advisor_agent.intent.rebalance import build_rebalance_plan
|
||
from agent.advisor_agent.intent.recommend import recommend_candidates
|
||
from common.common_const import (
|
||
AGENT_INTENT_REBALANCE,
|
||
AGENT_INTENT_RECOMMEND,
|
||
DRAFT_STATUS_DRAFT,
|
||
)
|
||
from service.advisor_agent.draft import build_generated_content
|
||
|
||
|
||
def _recommend_markdown(items: list[dict]) -> str:
|
||
lines = ["# 基金推荐草稿", ""]
|
||
for item in items:
|
||
lines.append(
|
||
f"- {item.get('product_name', item.get('product_code'))}"
|
||
f"({item.get('product_code')},风险等级 {item.get('risk_level')})"
|
||
)
|
||
return "\n".join(lines)
|
||
|
||
|
||
def build_recommendation_draft(
|
||
*,
|
||
customer_id: int,
|
||
advisor_id: int,
|
||
customer_risk: str,
|
||
candidates: list[dict],
|
||
relation_status: str,
|
||
memories: list[dict] | None = None,
|
||
) -> dict:
|
||
items = recommend_candidates(
|
||
customer_risk,
|
||
candidates,
|
||
memories=memories or [],
|
||
)
|
||
return {
|
||
"customer_id": customer_id,
|
||
"advisor_id": advisor_id,
|
||
"intent": AGENT_INTENT_RECOMMEND,
|
||
"title": "基金推荐草稿",
|
||
"status": DRAFT_STATUS_DRAFT,
|
||
"structured_data": {
|
||
"customer_risk": customer_risk,
|
||
"items": items,
|
||
"relation_status": relation_status,
|
||
},
|
||
"content": build_generated_content(_recommend_markdown(items)),
|
||
"disclaimer_ok": True,
|
||
}
|
||
|
||
|
||
def build_rebalance_draft(
|
||
*,
|
||
customer_id: int,
|
||
advisor_id: int,
|
||
customer_risk: str,
|
||
relation_status: str,
|
||
holdings: list[dict],
|
||
target_allocation: dict[str, int | float | Decimal],
|
||
threshold: Decimal,
|
||
candidates: list[dict],
|
||
) -> dict | None:
|
||
plan = build_rebalance_plan(
|
||
relation_status=relation_status,
|
||
customer_risk=customer_risk,
|
||
holdings=holdings,
|
||
target_allocation=target_allocation,
|
||
threshold=threshold,
|
||
candidates=candidates,
|
||
)
|
||
if plan is None:
|
||
return None
|
||
structured_data = dict(plan)
|
||
structured_data["customer_risk"] = customer_risk
|
||
content = ["# 组合调仓建议草稿", "", "## 赎回清单"]
|
||
content.extend(
|
||
f"- {item['product_code']}:{item['amount']} 元" for item in plan["sell"]
|
||
)
|
||
content.append("\n## 申购清单")
|
||
content.extend(
|
||
f"- {item['product_code']}:{item['amount']} 元" for item in plan["buy"]
|
||
)
|
||
return {
|
||
"customer_id": customer_id,
|
||
"advisor_id": advisor_id,
|
||
"intent": AGENT_INTENT_REBALANCE,
|
||
"title": "组合调仓建议草稿",
|
||
"status": DRAFT_STATUS_DRAFT,
|
||
"structured_data": structured_data,
|
||
"deviation": max((abs(value) for value in plan["deviation"].values()), default=Decimal("0")),
|
||
"content": build_generated_content("\n".join(content)),
|
||
"disclaimer_ok": True,
|
||
}
|