Files
group_xinghuo_jinrong/docs/项目框架设计/理财顾问Agent-合并说明.md
T
zhanghongyu_0626 973bf1b834 feat(advisor-agent): Integrate advisor agent into merger with new API structure
- Merged `xinghuo/advisor-agent` into the `merger` branch, establishing a new API prefix `/api/advisor-agent` to avoid conflicts with existing endpoints.
- Implemented a comprehensive implementation plan detailing the integration steps, including conflict resolution, database migrations, and service adaptations.
- Introduced new files for advisor compliance, script templates, KYC, and market alerts, ensuring a cohesive addition to the existing architecture.
- Updated documentation to reflect the new structure and integration process, enhancing clarity for future development and maintenance.

This integration significantly expands the capabilities of the merger, providing a robust framework for advisor-related functionalities while maintaining compliance and operational integrity.
2026-09-12 15:14:29 +08:00

314 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 投资顾问 Agent · 从 `advisor-agent` 合并说明
> 日期:2026-09-12
> 源分支:`xinghuo/advisor-agent` @ `68df13c`(Sprint0~3 后端 MVP · 101 pytest)
> 目标分支:`merger`(AL-09 宿主 + 客服 / 风控 / 问数已接线)
> 状态:**接缝设计稿(未 merge、未改码)** — 实施前以本文 + `docs/superpowers/plans/2026-09-12-advisor-agent-merge.md` 为准。
---
## 0. 已拍板决策(2026-09-12)
| # | 决策 | 结论 |
| --- | --- | --- |
| D1 | API 前缀与契约 | **以 merger / 代销平台 API v0.1 为准**;**不保留** `/api/v1/*` 对外形态 |
| D2 | 冲突文件 | **只增不盖**;与 merger 同路径冲突时 **保留 merger**(同客服 / 问数合并说明) |
| D3 | 顾问侧命名 | 迁入代码 **按 merger 习惯重命名**(见 §2);禁止覆盖问数 `template_service`、平台 `compliance` |
| D4 | 集成方式 | **新增投资顾问 Agent + 接缝**;不接顾问独立 `main.py` / 第二套 JWT |
| D5 | 验证顺序 | **先接线 → 再跑全量 pytest**;Neo4j 以本机 Docker 已就绪为前提 |
| D6 | 图库 | 复用 merger 已有 **`scripts/sync/sync_neo4j.py` / `sync_advisor_rel.py`**,不迁入顾问分支重复同步实现 |
| D7 | HTTP 前缀 | **已定稿:** `/api/advisor-agent/*`(2026-09-12 确认) |
| D8 | 演示 UI | **不迁入** 源分支 `demo_ui/` · **不挂载** `/demo` StaticFiles(2026-09-12 确认) |
| D9 | 管理/审计 API | **第一批不迁入** 源分支 `admin/audit-logs`(2026-09-12:风控侧页面已覆盖合规查看诉求;见 §2.1) |
---
## 1. 一句话定位
投资顾问 Agent = **顾问工作台后端线**(合规文案检测 · 复制门闸 · 话术模板 · 市场异动 · KYC 采集),与:
- **平台 API**(`/api/advisors/*` 归属 · `/api/compliance/suitability-check` 适当性)
- **通用对话线**(`POST /api/chat` + `X-Agent-Type`)
- **问数线**(`/api/analyst/*`)
**并行存在**。合并时 **不替换** `main.py` 骨架、不覆盖 `auth_service.py`、不把 KYC 硬塞进 `chat.py`(与问数 §3.1 双轨理由相同:响应形态与审计字段不同)。
---
## 2. 重命名与路径对照(advisor → merger)
### 2.1 HTTP:废弃 `/api/v1`,统一业务域前缀
**推荐对外前缀:** `/api/advisor-agent`(**单数 advisor + agent**,与平台复数 `/api/advisors` 区分,避免路由与文档歧义)。
| 中文职责 | 源分支挂载(勿保留) | 合并后 canonical 路径(kebab-case) |
| --- | --- | --- |
| 顾问文案合规检测与规则库 | `/api/v1/compliance/*` | `/api/advisor-agent/compliance/content-check` · `.../compliance/rules` · `.../compliance/rules/{rule_id}` |
| 复制追踪门闸 | `/api/v1/copy/track` | `POST /api/advisor-agent/copy/track` |
| 话术模板 CRUD / 检索 / 引用 | `/api/v1/templates/*` | `/api/advisor-agent/script-templates/*` |
| 市场异动扫描 / 解读 / 反馈 | `/api/v1/market-alerts/*` · `/api/v1/market/*` | `/api/advisor-agent/market-alerts/*` · `/api/advisor-agent/market/*` |
| KYC 会话与采集对话 | `/api/v1/kyc/*` | `/api/advisor-agent/kyc/sessions` · `.../chat` · `.../complete` |
| 输入防护探测 | `/api/v1/guard/*` | `/api/advisor-agent/guard/check` |
| 顾问看板(个人/全局) | `/api/v1/dashboard/*` | `/api/advisor-agent/dashboard/*` |
| 资产配置(当前 stub) | `/api/v1/allocation/*` | `/api/advisor-agent/allocation/*` |
| ~~审计日志只读列表~~ | `/api/v1/admin/audit-logs` | **不迁入**(D9) |
**D9 说明(与风控页面的关系):**
- merger **风控菜单**已给合规/风控可看、可操作的 **业务留痕面**:例如 **预警台账**(`RiskAlertsPage` · compliance 角色看 AML 单并处置)、**适当性检查** / **AML 扫描**(操作结果写 `audit_log` / 业务表,页面上体现为「留痕」说明)。
- 源分支 `GET /admin/audit-logs` 是 **整张 `audit_log` 的通用翻页列表**,merger **前端目前没有对应页**;与上述风控台账 **用途重叠**(合规日常看单),**不是** MVP 合并必带。
- 投资顾问线 **仍须写** 共用 `audit_log`(合规检测 · KYC · 复制门闸等),与风控/问数 **同表**;日后若要做「全事件审计检索」,应在 **风控/运维统一入口** 扩展 API + 页面,**不要**再挂一条顾问专用 `admin/audit-logs`。
**平台层禁止占用 / 混淆:**
| 中文职责 | merger 已有路径 | 顾问迁入时 |
| --- | --- | --- |
| G-01 适当性判定 | `POST /api/compliance/suitability-check`(`app/api/compliance.py`) | **不得**把文案检测挂到 `/api/compliance/check` |
| 理财师客户归属 | `GET /api/advisors/{advisor_id}/customers` | **不得**用 `/api/advisors` 挂 KYC/合规 |
> 契约附录:合并落地后补 **`接口契约-代销平台API-v0.1.md` § 路由树** 一段「投资顾问 Agent 扩展」(与 v0.2 行情草案同级,标注 **已实现 / MVP**)。
### 2.2 路由文件(merger 习惯:按域拆分 + `main.py` 挂载)
| 中文职责 | 建议路径 | 说明 |
| --- | --- | --- |
| 顾问线路由聚合(可选) | `app/api/advisor_agent/__init__.py` | `APIRouter(prefix="/api/advisor-agent")` + `include_router` |
| 文案合规 API | `app/api/advisor_compliance.py` | 自源 `compliance.py` 改写 prefix/response |
| 话术模板 API | `app/api/advisor_script_templates.py` | 自源 `templates.py` |
| KYC API | `app/api/advisor_kyc.py` | 自源 `kyc.py` |
| 市场异动 API | `app/api/advisor_market.py` | 自源 `market.py` |
| 复制门闸 API | `app/api/advisor_copy.py` | 自源 `copy.py` |
| 输入防护 API | `app/api/advisor_guard.py` | 自源 `guard.py` |
| 看板 / 配置 stub | `app/api/advisor_dashboard.py` · `advisor_allocation.py` | 源分支同名改写 |
**不迁入(含 D9):**
| `app/api/admin.py`(`audit-logs` 列表) | 风控侧已有合规查看链路;通用审计查询留待平台统一 |
**不迁入(宿主/冲突):**
| 路径 | 原因 |
| --- | --- |
| `app/api/__init__.py`(v1 聚合) | 由 merger `main.py` 挂载 |
| `app/api/deps.py` | merger 完整 JWT + 归属矩阵 |
| `app/api/auth.py` | 统一 `app/api/auth.py` + `auth_service` 签发 |
| `app/api/chat.py` | 宿主对话线;顾问 KYC **独立 REST**,不走 Chat 四件套 |
| `app/main.py` | AL-09 宿主入口 |
### 2.3 Service / Repository 重命名(消除与问数撞名)
| 源分支 | 合并后 | 原因 |
| --- | --- | --- |
| `app/service/template_service.py` | `app/service/script_template_service.py` | merger 已有问数 **`template_service.py`(NL2SQL 模板)** |
| `app/service/template_vector_service.py` | `app/service/script_template_vector_service.py` | 话术 Milvus 专用 |
| `app/repository/template_repository.py` | `app/repository/script_template_repository.py` | 与上配套 |
| `app/service/auth_service.py` | **不迁入** | merger Auth SDK 唯一验签 |
| `app/service/llm_client.py` | `app/service/advisor_llm_client.py` | 与问数 `llm.py`、宿主 embedding 区分(可选,merge 时二选一) |
| `app/middleware/trace.py` | **不迁入** | 宿主 `TraceMiddleware` + `utils.trace` |
| `app/utils/response.py` · `success_response` | **不迁入** | 统一 `app/utils/response.py` 的 `ok` / `fail` / `error_body` |
| `app/utils/exceptions.py` · `AuthenticationError` | **不迁入** | 统一 `ApiError` / `PermissionDenied` + `register_error_handlers` |
### 2.4 模型层
| 策略 | 说明 |
| --- | --- |
| 请求/响应 Pydantic | **`app/model/advisor_schemas.py`**(对齐 `analyst_schemas.py`;**不**扩写 merger 巨型 `schemas.py` 覆盖) |
| ORM 实体 | **`app/model/entities/advisor.py`** 或追加 `entities.py` **仅新增类**(禁止覆盖已有 risk/analytics 映射) |
| 内部 Auth 视图 | 由 **`advisor_auth_adapter.py`** 从 `deps.AuthContext` 映射(见 §3.2) |
### 2.5 测试文件
| 源分支 | 合并后建议 |
| --- | --- |
| `tests/test_sprint*.py` · `tests/test_step*.py` | 保留文件名或统一 `tests/test_advisor_sprint*.py` |
| 断言中的 `/api/v1` | 全部改为 §2.1 canonical 路径 |
| 断言 `success_response` 形 | 改为 merger 统一响应 envelope(与 `test_wave6_analyst` 一致) |
---
## 3. S4 接缝设计(对齐问数 S3 · 客服 S2)
### 3.1 宿主挂载(唯一 `main.py` 改动面)
```python
# 示例:按域 router 逐个 include,或单一 advisor_agent 聚合 router
from app.api.advisor_compliance import router as advisor_compliance_router
# ...
app.include_router(advisor_compliance_router)
# 各 router 内部 prefix 已含 /api/advisor-agent/...
```
**不**挂载 `/demo` StaticFiles · **不复制** `demo_ui/`(D8);MVP 以 pytest + 既有 `web/` 为准。
### 3.2 鉴权接缝
1. 路由层:`Depends(get_platform_auth_context)`(与问数 / 平台 API 一致)。
2. 新增 **`app/api/advisor_auth_adapter.py`**(或扩展 `auth_adapter.py`):
- `deps.AuthContext` → 顾问服务内使用的视图(`actor_id` / `roles` / `permissions` / `trace_id`)。
- 源分支 `require_permission("compliance:check")` → merger **`has_permission` / 矩阵**;权限字符串 **原样保留** 或映射到现有 staff 角色(`advisor` / `compliance` / `admin`)。
3. **dev 测试账号**:在 merger `auth.py` / 种子 JWT 中补齐源分支文档中的 `advisor_test` · `compliance_test` · `admin_test` **权限集**(仅 development)。
4. **禁止**顾问代码 import 宿主 `gateway/*`;**禁止**宿主 import 顾问私有 repo 绕过 deps。
### 3.3 归属与客户访问
- KYC / 合规检测带 `customer_id` 的写读:**必须**走 merger 已有 **`assert_platform_customer_access` / `core_customer_advisor`** 口径(与问数 advisor 域一致)。
- 源分支 `ownership_service.py` 若与 `deps` 重复,合并后 **删私有版**,逻辑收敛到 `deps` + `core_ro`。
### 3.4 响应与异常
- 所有新 router 返回 **`ok(request, data)`** 或 **`fail(...)`** / 抛出 **`ApiError`**。
- 源分支 `ApiResponse` 包装层:仅在 adapter 测试期保留 thin wrapper,**不**对外暴露第二套 JSON 形。
### 3.5 共用底座表(agent_session / agent_message / audit_log)
merger **`01-mysql-共用底座.sql` 已建** 11 张底座表;源分支 Alembic `20260911_0001` **不得**在已灌库环境重复 CREATE。
| 动作 | 说明 |
| --- | --- |
| 跳过 | Sprint0 foundation 中与底座重复的 `CREATE TABLE` |
| 增量 | 仅执行顾问 **专用表** + **`agent_message` 唯一约束**(源 `20260912_0007`)等 **ALTER** |
| 写入 | KYC 会话写 `agent_session.agent_type='advisor'` · 消息写 `agent_message` · 审计写 `audit_log.agent_type='advisor'` |
### 3.6 Milvus / Embedding(与客服 fin_* · 问数并存)
| 集合 / 用途 | 策略 |
| --- | --- |
| `kb_script_templates` | 顾问话术向量;**仅扩展** `milvus_tool.py` / `embedding_tool.py`,**不**改 fin_* collection 名 |
| 降级 | 与源分支一致:Milvus/Ollama 不可用时 **关键词检索降级** |
| 灌库 | `scripts/sync/sync_template_vectors.py`(迁入并重命名路径到 `scripts/sync/sync_script_template_vectors.py` 可选) |
### 3.7 Neo4j(Docker 已就绪)
- **不**把 Neo4j 查询接进 KYC HTTP 主链路(一期)。
- 合并后验证:`python scripts/sync/sync_neo4j.py` · `sync_advisor_rel.py`(或 `prepare_all.ps1` 已有步骤)与顾问归属校验 **数据一致**。
- 源分支文档中的「28 客户 · 3 顾问 · 2 产品」验收,改为 **merger Core 种子 + 同步脚本** 复测一遍并记入 TEST-LOG。
### 3.8 memory_service
- merger `memory_service.py` 已含客服/游客逻辑;源分支扩展 **仅追加** 顾问/KYC 所需方法(或 `AdvisorSessionMessageRepository` 独立模块)。
- **禁止**用顾问版本覆盖整个 `memory_service.py`。
---
## 4. 数据库:Alembic → SQL 迁移(merger 习惯)
**不**把 `alembic/` 作为 merger 唯一迁移入口(与问数 / 客服一致),改为:
```text
scripts/agent/migrate-advisor-agent-sprint1-3.sql
→ compliance_rule · compliance_check_log
→ copy_track_log
→ script_template · template_use_log(及源 0004 全部对象)
→ market_alert(及关联索引)
→ kyc_session(及关联字段)
→ agent_message 上 uk_agent_message_session_seq(若本机尚无)
```
| 步骤 | 说明 |
| --- | --- |
| 前置 | `jinrong_agent` 已执行 01 共用底座 + 02 agent 专用(风控/问数/客服已有表) |
| 种子 | `scripts/seed/import_compliance_rules.py` · `import_script_templates.py`(迁入 `scripts/agent/` 或 `scripts/seed/`) |
| 重置 | **不**改 `scripts/core/reset.ps1` 破坏 core;可选 `scripts/agent/reset-advisor-agent.sql` 仅清顾问专用表 |
---
## 5. 合并什么 / 不合并什么
### 5.1 整包迁入(新增或重命名后迁入)
| 类别 | 源路径(示意) | 作用 |
| --- | --- | --- |
| 合规引擎 | `compliance_*_service.py` · `compliance_*_repository.py` | 硬规则 + 语义兜底 + 日志 |
| 复制门闸 | `copy_track_*` | WARN/BLOCK 与审计 |
| 话术 | `script_template_*`(重命名后) | CRUD · 混合检索 · 引用留痕 |
| 市场 | `market_*_service.py` · `market_alert_*` | 扫描 · 解读 · 反馈闭环 |
| KYC | `kyc_*` | 会话状态机 · 字段解析 · 消息序号 |
| 编排(未完成) | `agent_graph.py` · `agent_tools.py` | **可选迁入**;LangGraph 未落地前 **不挂 chat** |
| 评测脚本 | `scripts/eval/evaluate_compliance.py` · `evaluate_agent.py` | 开发回归资产 |
| 演示 | `scripts/demo/run_demo_smoke.ps1` | 改为调 canonical 路径后保留 |
| 测试 | `tests/test_sprint*.py` 等 | 改路径/响应/import 后解禁 |
| 文档 | `docs/开发文档/35~39` · `docs/演示文档/*` | 迁入 `docs/项目框架设计/` 或 `docs/需求拆解/` 子目录,**不**覆盖 `docs/memory/*` |
### 5.2 禁止覆盖(冲突时保留 merger)
| 文件 | 原因 |
| --- | --- |
| `app/main.py` | AL-09 宿主 |
| `app/api/deps.py` · `app/service/auth_service.py` | 唯一 JWT |
| `app/api/compliance.py` | 平台适当性 |
| `app/service/template_service.py` | 问数 D-06 |
| `app/repository/core_ro.py` | 含 `check_suitability` 等 |
| `app/config/settings.py` | **仅追加** `advisor_*` / `kyc_*` / `compliance_content_*` 字段 |
| `app/tool/milvus_tool.py` · `embedding_tool.py` | **手工合并** 增量,禁止整文件覆盖 |
| `docs/memory/*` · `web/` · 风控/问数/客服模块 | 全部保留 merger |
| `docs/项目框架设计/表设计/01-mysql-共用底座.sql` | 仅 **新 SQL 脚本** 追加顾问表,不改 canonical 01 历史 |
---
## 6. 测试与验收
### 6.1 顺序(与 D5 一致)
```text
1. worktree / 集成分支完成 §2 重命名 + §3 接缝(不推 main)
2. 执行 migrate-advisor-agent-sprint1-3.sql + 规则/模板种子
3. (可选)sync_script_template_vectors · Neo4j 同步
4. python -m pytest # 目标:merger 基线 + 顾问新增全绿
5. ruff check app tests scripts
6. Scope B 冒烟(§6.3)
7. 更新 FRAMEWORK 实现状态表 · TODO · MEMORY(§7)
```
### 6.2 基线期望
| 指标 | 合并前 merger | 合并后目标 |
| --- | --- | --- |
| pytest | **833 passed**(见 MEMORY §0) | **833 + M passed**(M ≈ 源分支 101,去重后略少) |
| 顾问子集 | — | `pytest tests/test_advisor_sprint*.py`(或原 sprint 名) |
### 6.3 Scope B 冒烟(canonical 路径)
1. `POST /api/advisor-agent/compliance/content-check` + advisor JWT → 200 + 风险等级
2. `POST /api/advisor-agent/copy/track` · WARN 需 confirm · BLOCK 拒绝
3. `GET /api/advisor-agent/script-templates/search?q=…` → 200(Milvus 不可用时关键词降级)
4. `POST /api/advisor-agent/kyc/sessions` → chat 一轮 → `complete`
5. `POST /api/compliance/suitability-check` **仍 200**(平台路由未回归)
6. `POST /api/analyst/chat` **仍 200**(问数 template_service 未回归)
---
## 7. Merge 操作顺序(SOP · 尚未执行)
```text
1. git worktree add ../JinRong-advisor-merge -b integrate/advisor-agent merger
2. git merge xinghuo/advisor-agent --no-commit # 或 git read-tree + 按 §5.1 只 checkout 新增路径
3. 冲突:按 §5.2 一律保留 merger,顾问逻辑拷贝到新文件名(§2)
4. 接缝:advisor_auth_adapter · main.py include_router · settings 追加 · requirements 追加
5. 删除误迁入:advisor deps/auth/main/alembic(迁移已转 SQL)
6. 改测试路径与响应形 · pytest 全绿
7. 文档:契约附录 · FRAMEWORK · 本说明状态改为「已接线」
```
---
## 8. 风险与开放项(合并不解决)
| 项 | 说明 |
| --- | --- |
| KYC Profile / 资产配置 | 源分支自述未闭环;合并 **不包含** S3-03~S3-08 |
| 前端工作台 | 不纳入本次 merge;`web/` 后续单独立项 |
| `/api/v1` 兼容 | **不做**;若演示客户端依赖,单独加 shim router(deprecated) |
| 101 vs 833 测试重叠 | `conftest` · DB fixture 以 merger 为准,顾问测试禁止 drop 宿主表 |
| 双 `llm_client` | merge 时统一配置项命名,避免 `.env` 键冲突 |
---
## 9. 修订记录
| 日期 | 说明 |
| --- | --- |
| 2026-09-12 | 首版:merge 优先 · `/api/advisor-agent` · 重命名表 · S4 接缝 · 不测前不 claim 完成 |