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,
|
|||
|
|
}
|