feat:修复客服agent功能
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
"""为投顾 Agent 组装经过裁剪的客户综合上下文。"""
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from decimal import Decimal
|
||||
|
||||
from repositories.fin_customer_profile import FinCustomerProfileRepo
|
||||
from repositories.fin_holdings import FinHoldingsRepo
|
||||
from repositories.fin_transaction import FinTransactionRepo
|
||||
|
||||
MAX_HOLDINGS = 50
|
||||
MAX_TRANSACTIONS = 20
|
||||
MAX_MEMORIES = 10
|
||||
logger = logging.getLogger("advisor.customer_context")
|
||||
|
||||
|
||||
def _number(value):
|
||||
if isinstance(value, Decimal):
|
||||
return float(value)
|
||||
return value
|
||||
|
||||
|
||||
def _profile_payload(profile) -> dict:
|
||||
if profile is None:
|
||||
return {}
|
||||
return {
|
||||
"risk_level": getattr(profile, "risk_level", None),
|
||||
"risk_score": getattr(profile, "risk_score", None),
|
||||
"investment_experience": getattr(profile, "investment_experience", None),
|
||||
"annual_income_range": getattr(profile, "annual_income_range", None),
|
||||
"total_assets": _number(getattr(profile, "total_assets", None)),
|
||||
"asset_allocation": getattr(profile, "asset_allocation", None),
|
||||
"product_preference": getattr(profile, "product_preference", None),
|
||||
"customer_level": getattr(profile, "customer_level", None),
|
||||
}
|
||||
|
||||
|
||||
def _holding_payload(holding, product) -> dict:
|
||||
return {
|
||||
"product_id": holding.product_id,
|
||||
"product_code": getattr(product, "product_code", None),
|
||||
"product_name": getattr(product, "product_name", None),
|
||||
"shares": _number(holding.shares),
|
||||
"cost_amount": _number(holding.cost_amount),
|
||||
"current_value": _number(holding.current_value),
|
||||
"profit_loss": _number(holding.profit_loss),
|
||||
"profit_ratio": _number(holding.profit_ratio),
|
||||
"status": holding.status,
|
||||
}
|
||||
|
||||
|
||||
def _transaction_payload(transaction) -> dict:
|
||||
return {
|
||||
"product_id": transaction.product_id,
|
||||
"transaction_type": transaction.transaction_type,
|
||||
"amount": _number(transaction.amount),
|
||||
"shares": _number(transaction.shares),
|
||||
"nav": _number(transaction.nav),
|
||||
"status": transaction.status,
|
||||
"create_time": transaction.create_time.isoformat()
|
||||
if hasattr(transaction.create_time, "isoformat")
|
||||
else str(transaction.create_time),
|
||||
}
|
||||
|
||||
|
||||
def _memory_payload(memory) -> dict:
|
||||
return {
|
||||
"tag": memory.get("tag"),
|
||||
"content": str(memory.get("content") or "")[:500],
|
||||
"info_type": memory.get("info_type"),
|
||||
"memory_type": memory.get("memory_type"),
|
||||
}
|
||||
|
||||
|
||||
async def load_customer_context(
|
||||
db,
|
||||
*,
|
||||
customer_id: int,
|
||||
memories: list[dict] | None = None,
|
||||
profile_repo_cls=FinCustomerProfileRepo,
|
||||
holdings_repo_cls=FinHoldingsRepo,
|
||||
transaction_repo_cls=FinTransactionRepo,
|
||||
) -> dict:
|
||||
"""读取并裁剪客户画像、持仓、交易和长期记忆。"""
|
||||
try:
|
||||
profile = await profile_repo_cls(db).get_by_customer_id(customer_id)
|
||||
except Exception: # noqa: BLE001 个性化上下文故障不阻断主流程
|
||||
logger.warning("customer profile context unavailable", exc_info=True)
|
||||
profile = None
|
||||
try:
|
||||
holding_rows = await holdings_repo_cls(db).list_with_products(
|
||||
customer_id, include_closed=False
|
||||
)
|
||||
except Exception: # noqa: BLE001 个性化上下文故障不阻断主流程
|
||||
logger.warning("customer holdings context unavailable", exc_info=True)
|
||||
holding_rows = []
|
||||
try:
|
||||
transactions = await transaction_repo_cls(db).list_recent(
|
||||
customer_id, limit=MAX_TRANSACTIONS
|
||||
)
|
||||
except Exception: # noqa: BLE001 个性化上下文故障不阻断主流程
|
||||
logger.warning("customer transaction context unavailable", exc_info=True)
|
||||
transactions = []
|
||||
return {
|
||||
"customer_id": customer_id,
|
||||
"profile": _profile_payload(profile),
|
||||
"holdings": [
|
||||
_holding_payload(holding, product)
|
||||
for holding, product in holding_rows[:MAX_HOLDINGS]
|
||||
],
|
||||
"transactions": [
|
||||
_transaction_payload(item) for item in transactions[:MAX_TRANSACTIONS]
|
||||
],
|
||||
"memories": [_memory_payload(item) for item in (memories or [])[:MAX_MEMORIES]],
|
||||
}
|
||||
Reference in New Issue
Block a user