投顾 Agent 需求文档(PRD)
文档版本:v1.0(2026-09-16)
文档状态:已实现反推稿 —— 本章所记需求均已在本仓库落地并本地验证,非前瞻设计
适用范围:投顾 Agent(投顾工作台 + 客户端「我的投顾方案」+ 客户主动申报)
依据材料(均为仓库内既有文档与代码,非本文件臆造):
· 设计:docs/01(通用 Agent 平台)、docs/03(端到端流程)、docs/05(接口文档)、
docs/22(四大 Agent 拆解)、docs/30(投顾迁移 TODO)、docs/31(投顾灰度与回滚)、
docs/43(场内产品手册)、docs/44(演示流程)
· 代码:app/service/product_recommendation_service.py、advisor_service_request_service.py、
advisor_reason_service.py、app/api/controllers/recommendations.py、advisor_service_requests.py、
app/static/portal/employee-advisor/dashboard/*、app/static/portal/customer/advisor-plans/*
1. 背景与目标
1.1 问题陈述
投顾业务的真实痛点在于「选品可解释 + 交付可追溯」:
- 投顾给客户荐品,必须能说清为什么是这几只(适当性匹配、期限/流动性匹配、证据可核查);
- 方案从生成到到达客户手里,必须留痕、且未经审核不得对客户可见;
- 客户侧长期是单向接收,缺少「主动提出需求」的入口。
此前系统里推荐能力存在,但存在三处断点:
| 断点 |
表现 |
| 交付无落点 |
投顾「发送给客户」只改数据状态,客户端没有任何页面/接口能读到已发布方案 |
| 文案不可读 |
每只产品的「推荐依据」是同一句套话,客户看不出差异 |
| 客户无入口 |
客户只能被动等方案,无法主动申报 |
1.2 目标(G)
| 编号 |
目标 |
衡量方式 |
| G1 |
推荐可解释:每只入选产品都能给出基于真实参数的依据 |
方案里每只产品都有独立依据,且含风险等级/匹配关系 |
| G2 |
交付可追溯:审核与发布分离,未发布对客户不可见 |
状态机 + published_at 双条件;客户接口只返回已发布 |
| G3 |
呈现可感知:客户能看到走势图、指标与组合构成 |
客户端可展示净值折线图、环形配置图、区间收益与最大回撤 |
| G4 |
客户能发起:客户可主动申报,投顾后台受理后出方案 |
申报→受理→生成草稿→审核→发送 全链路打通 |
| G5 |
合规不越线:不得承诺收益,证据缺失即整只排除 |
硬约束 fail-closed + 文案合规守卫 |
1.3 非目标(本期明确不做)
| 非目标 |
说明 |
| 真实下单 |
推荐方案不产生交易指令,客户仍需在交易页自行下单 |
| 收益预测 |
不预测未来收益,只呈现历史区间收益与最大回撤 |
| 自动投资 |
无自动调仓、无定投、无代客操作 |
| 场外基金 |
投顾范围限定场内基金,场外走独立模块(见 docs/22) |
2. 角色与场景
2.1 角色定义
| 角色 |
角色码 |
入口 |
核心诉求 |
| 投顾 |
advisor |
/portal/employee-advisor/dashboard/ |
代客出方案、审核发布、处理客户申报 |
| 客户 |
customer |
/portal/customer/advisor-plans/ |
接收方案、主动申报、查看申报进度 |
| 管理员 |
admin / super_admin |
管理面 |
审核、发布、故障处置(不受灰度限制) |
2.2 核心场景
| 编号 |
场景 |
触发方 |
| SC-01 |
投顾选择名下客户 → 生成推荐方案 → 审核通过 → 发送给客户 |
投顾 |
| SC-02 |
投顾查看历史方案记录(含草稿)→ 抽查内容详情 |
投顾 |
| SC-03 |
客户登录 → 在「我的投顾方案」查看已收到的方案 |
客户 |
| SC-04 |
客户提交投顾方案申报 → 投顾受理 → 自动出草稿 |
客户→投顾 |
| SC-05 |
投顾受理后审核、发布,客户看到方案变为「已发送方案」 |
投顾→客户 |
3. 业务流程
3.1 主链路 A:投顾主动出方案
3.2 主链路 B:客户主动申报
4. 功能需求
优先级:P0 本期必须 / P1 重要 / P2 增强。
4.1 客户与画像
| 编号 |
功能 |
口径 |
优先级 |
验收标准 |
| FR-01 |
投顾查看名下客户 |
范围 = 本人 + sys_customer_assignment 归属客户 |
P0 |
非归属客户不可见,越权返回 403 |
| FR-02 |
风险测评(客户自助) |
ONB001 取题 / ONB002 提交;结果落服务端权威画像 |
P0 |
测评结果由服务端权威返回,前端不得自行计算风险等级 |
| FR-03 |
熔断前置校验 |
测评超过 12 个月或缺失 → FM-03 拦截 |
P0 |
前端展示熔断横幅,接口返回 blocked_by_fuse |
4.2 组合诊断与配置
| 编号 |
功能 |
口径 |
优先级 |
验收标准 |
| FR-04 |
组合分析 |
集中度、行业穿透与流动性 |
P1 |
返回可展示的诊断结论 |
| FR-05 |
资产配置 |
按风评与目标给出配比与偏离 |
P1 |
目标缺失时返回 investment_goal_required |
| FR-06 |
画像评分 |
本地演示引擎计算(后端无对应接口,明确标注"规则模拟") |
P2 |
结果区必须带演示标识 |
| FR-07 |
调仓建议 |
同上,本地引擎 |
P2 |
结果区必须带演示标识 |
FR-06/FR-07 由本地演示引擎计算,前端会明确标注;不得被误认为真实后端结论。
4.3 推荐方案生成(核心)
| 编号 |
功能 |
口径 |
优先级 |
验收标准 |
| FR-08 |
生成推荐方案 |
POST /api/v1/advisor/recommendations,需 16-128 位 ASCII 幂等键 |
P0 |
同键重试返回同一方案,不重复建单 |
| FR-09 |
候选池硬约束 |
产品须同时具备:场内可交易 + 销售机构已验证适当性证据 + 基金合同快照;缺任一即整只排除 |
P0 |
排除原因可查(前端「排除原因」提示词) |
| FR-10 |
排序与入选 |
按适当性等级、目标期限、目标流动性筛选后综合打分取 TopN(默认 3) |
P0 |
返回 selection_summary:候选/入选/排除数 |
| FR-11 |
推荐依据生成 |
规则文案兜底;配置大模型时改写为面向客户的说明 |
P0 |
文案必须含真实参数;命中收益承诺词即丢弃并回退 |
| FR-12 |
审核 |
reviews 接口,decision ∈ {approved, rejected} |
P0 |
未审核不得发布 |
| FR-13 |
发布 |
publications 接口,置 review_status 与 published_at |
P0 |
发布后客户可见;重复发布幂等 |
4.4 历史记录与交付
| 编号 |
功能 |
口径 |
优先级 |
验收标准 |
| FR-14 |
历史方案记录 |
本人生成的全部状态方案 |
P0 |
状态标签与后端状态一致,不使用枚举兜底文案 |
| FR-15 |
客户接收方案 |
GET /api/v1/users/me/advisor-contents:只看本人、已审核且 published_at 非空 |
P0 |
未发布的方案对客户不可见 |
| FR-16 |
方案可视化 |
净值折线图(带坐标轴/网格)、组合业绩(等权合成 + 最大回撤)、资产配置环形图 |
P1 |
数据缺失显示「暂无数据」,不显示 0 |
4.5 客户主动申报
| 编号 |
功能 |
口径 |
优先级 |
验收标准 |
| FR-17 |
客户提交申报 |
金额(万元)/ 投资期限 / 风险偏好 / 备注 |
P0 |
服务端校验取值与风评有效性 |
| FR-18 |
我的申报 |
只看自己的申报单与状态 |
P0 |
状态含 待受理/已受理/已发送/已驳回 |
| FR-19 |
投顾申报队列 |
本人 + 归属客户的申报,待受理排前 |
P0 |
非归属客户的申报不可处理 |
| FR-20 |
受理并生成方案 |
受理即调用现有推荐逻辑自动出待审核草稿 |
P0 |
生成失败给出人话原因,并保持待受理 |
| FR-21 |
驳回 |
需填理由(可选),客户可见 |
P1 |
驳回后申报单不可再被受理 |
5. 业务规则
5.1 候选池硬约束(fail-closed)
产品必须同时满足三项,缺一即排除:
- 场内可交易;
- 适当性证据:销售机构的已验证适当性证据,带可核查来源链接与
document_sha256;
- 合同快照:基金合同快照,同样带来源与摘要。
按目标继续过滤:
| 维度 |
规则 |
| 风险等级 |
客户风评等级对应的禁投风险级直接排除 |
| 投资期限 |
短于目标期限下限的产品排除 |
| 流动性 |
不符合目标流动性要求(如 30 日内可用)的产品排除 |
5.2 合规红线(必须遵守,代码强制)
| # |
红线 |
| 1 |
不得出现收益承诺与绝对化表述(保本/保证收益/稳赚/无风险/收益承诺…) |
| 2 |
未审核发布的方案对客户不可见 |
| 3 |
推荐不产生交易指令,仅作分析参考 |
| 4 |
客户不得自行修改风险测评结果(服务端权威) |
| 5 |
全流程留痕(审核、发布、受理、驳回均记录操作人与时间) |
5.3 状态机
推荐方案
「已发布」不是独立状态字段,而是 review_status ∈ {approved, published} 且 published_at 非空 —— 避免两处状态各写各的而对不上。
客户申报单
已发送(delivered) 同样不落库,由关联方案的 published_at 推导。
5.4 熔断 FM-03
| 条件 |
结果 |
| 无风险测评 |
拦截,提示先完成测评 |
| 测评超过 12 个月 |
拦截(服务端判 valid_until,缺失时按 12 个月兜底) |
| 熔断生效时 |
客户仅可办理赎回,流程转人工 |
6. 非功能需求
| 类别 |
要求 |
| 幂等 |
写接口必须带 16-128 位 ASCII Idempotency-Key;同键重试返回首次结果 |
| 降级 |
图谱(Neo4j)、大模型、行情任一不可用,业务继续可用并明确标注降级 |
| 留痕 |
审核/发布/受理/驳回写入审计;演示口径留存 ≥ 20 年 |
| 限流 |
按「用户 + 方法 + 路由」计数,超限 429;Redis 不可用时降级放行 |
| 灰度 |
ADVISOR_ROLLOUT_ENABLED 开启后仅白名单客户与管理员可访问投顾业务 |
| 前端一致性 |
同一页面内同一模块的 ?v= 版本号必须一致(否则双实例) |
7. 异常处理
| 场景 |
返回 |
前端呈现 |
可恢复动作 |
| 客户无风险测评 |
profile_required |
结果区提示 |
先做风险测评 |
| 无已确认投资目标 |
investment_goal_required |
结果区提示 |
先录入并确认目标 |
| 推荐数量越界 |
422 RECOMMENDATION_PARAM_INVALID |
结果区提示 |
改为 1-3 |
| 权限不足 |
403 |
「当前账户暂不可访问 / 权限不足」+ toast |
换有权限的账号 |
| 未开户(资金类) |
404 |
「客户未开户」 |
先建模拟账户 |
| 行情/净值缺失 |
503 / 空数据 |
「暂无净值数据」 |
跑 tools/sync_nav_history.py |
| 大模型不可用 |
无异常 |
依据回退为规则文案 |
关闭开关或换 key |
| 熔断 |
blocked_by_fuse |
熔断横幅 |
转人工 |
8. 权限矩阵
| 能力 |
客户 |
投顾 |
管理员 |
| 提交/查看自己的申报 |
✅ advisor-request:write:self / read:self |
— |
— |
| 查看自己的已发布方案 |
✅ product-recommendation:read:self |
— |
— |
| 生成/查看/删除推荐方案 |
— |
✅ |
✅ |
| 审核 / 发布方案 |
— |
✅(自助) |
✅ |
| 查看客户申报队列 |
— |
✅ advisor-request:read |
✅ |
| 受理 / 驳回申报 |
— |
✅ advisor-request:review |
✅ |
| 灰度限制 |
— |
受白名单限制 |
不受限 |
权限码定义源:tools/seed_test_rbac.py;投顾角色的授权工具:tools/grant_advisor_role.py。
9. 数据需求
| 表 |
用途 |
关键字段 |
client_facing_content |
方案与方案书 |
content_type / customer_id / review_status / published_at / draft_content |
advisor_service_request |
客户申报单 |
request_no(唯一) / customer_id / amount_wan / horizon / risk_preference / status / result_content_id |
sys_customer_assignment |
投顾-客户归属 |
决定投顾可见范围 |
fin_product / fin_market_price / fin_nav_history |
产品、行情、净值 |
图表与指标的数据源 |
api_request_receipt |
幂等 |
user_id / scope_hash / idempotency_key / request_hash |
interaction_audit |
审计留痕 |
操作人、动作、明细 |
10. 验收清单
| # |
验收项 |
方法 |
| 1 |
投顾生成方案 → 结果区出现卡片与图表 |
工作台执行「生成推荐方案」 |
| 2 |
审核通过后发布 → 客户可见 |
客户页出现该方案 |
| 3 |
未发布方案对客户不可见 |
客户页不出现草稿 |
| 4 |
同幂等键重试不重复建单 |
连续两次提交同键 |
| 5 |
客户申报 → 投顾队列出现 → 受理后自动出草稿 |
两端对照 |
| 6 |
文案命中收益承诺词被丢弃 |
单测 test_advisor_reason_service.py |
| 7 |
大模型不可用时回退规则文案 |
关闭开关后重生成 |
| 8 |
越权客户不可见/不可处理 |
换非归属客户验证 403 |
11. 待确认问题
| # |
问题 |
影响 |
| Q1 |
适当性证据与合同快照的真实数据来源何时接入?当前候选为 0(证据缺失 fail-closed) |
阻塞:决定演示用真实方案还是本地引擎 |
| Q2 |
推荐依据是否允许出现历史业绩之外的表述(如基金经理风格)? |
影响文案提示词 |
| Q3 |
客户申报是否需要额度/频率限制(防刷)? |
影响 FR-17 |
| Q4 |
申报单与投资目标的关系:受理后是否自动创建投资目标? |
影响 FR-20 之后流程 |
| Q5 |
灰度白名单的最终放量范围? |
影响验收范围 |