From 973bf1b8343f8f5872c1ac79666c31ad29f0ab61 Mon Sep 17 00:00:00 2001 From: Andrew Date: Sat, 12 Sep 2026 15:14:29 +0800 Subject: [PATCH] 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. --- docs/memory/MEMORY.md | 6 +- docs/memory/TODO.md | 6 +- .../plans/2026-09-12-advisor-agent-merge.md | 129 ++++++++ .../2026-09-12-advisor-agent-merge-design.md | 88 +++++ docs/项目框架设计/理财顾问Agent-合并说明.md | 313 ++++++++++++++++++ 5 files changed, 536 insertions(+), 6 deletions(-) create mode 100644 docs/superpowers/plans/2026-09-12-advisor-agent-merge.md create mode 100644 docs/superpowers/specs/2026-09-12-advisor-agent-merge-design.md create mode 100644 docs/项目框架设计/理财顾问Agent-合并说明.md diff --git a/docs/memory/MEMORY.md b/docs/memory/MEMORY.md index d67e843..e2668ad 100644 --- a/docs/memory/MEMORY.md +++ b/docs/memory/MEMORY.md @@ -26,7 +26,7 @@ | `app/api/customers.py` `products.py` `advisors.py` `staff.py` `compliance.py` | **已实现(v0.1 + 行情历史)** | 代销平台 REST;`get_platform_auth_context`;**`GET /api/products/{id}/nav/history`**(RBAC · compliance 拒) | | `app/api/analyst.py` `analyst_auth_adapter.py` | **已实现(S3+D-06 + N-03/N-07 + analyze)** | 问数/chat · **`POST /analyze`** · interpret · sample · escalate · dashboard | | `app/api/ready.py` | **已实现(2026-09-11)** | `GET /api/ready`:Redis + 关键路由自检;前端 `DevReadyBanner` | -| `app/service/analyst_agent.py` `template_service.py` `cache_service.py` `analyst_chart.py` | **已实现(S3+D-06)** | NL2SQL · **`_BUILTIN_SQL_FEW_SHOTS` 内置示例**(不接 D-11 表)· `_nl_sql_hints` 仅双极值 UNION · 模板 · **`normalize_union_all_sql`** · analyze 图表 | +| `app/service/analyst_agent.py` `template_service.py` `cache_service.py` `analyst_chart.py` | **已实现(S3+D-06 + D-11)** | NL2SQL · **published few-shot 仅库** · `_nl_sql_hints` 双极值 UNION · 模板 · **`reload_published_assets`** · **`clarify` 结构化** · analyze 图表 | | `app/api/knowledge.py` `admin.py` | 空壳 | 待审计查询台与知识库 API(T-21 拍板一期只做脚本入库,上传/重建端点不做) | | `app/service/platform/` | **已实现(v0.1)** | 封装 core_ro + `PLATFORM_RESPONSE_DESENSITIZE` 脱敏开关 | | `app/service/embedding.py` `milvus_service.py` `rag_service.py` | **已实现(T21-1/2/4)** | Ollama bge-m3 1024 维(失败不静默降级)/ kb_product_rules 建集合+upsert+合规过滤检索 / search_knowledge→chunks+source_refs 溯源 | @@ -176,7 +176,7 @@ audit_log 等审计表(只 INSERT) | **C-08** | 仅 L1 槽位 `investment.allocation_target`(13 槽);**无自动偏离检测/调仓** | `profile_slots.py` | | **问数 vs 分析对话** | 问数页 · **`/interpret`** · **`/analyze` 对话框(文/图)** · N-03/N-07 · 分析对话 URL 重定向问数 | spec `2026-09-11-query-interpret-split` · `2026-09-12-analyst-query-visualization` | | **问数 Demo(2026-09-12)** | **`match_phrases` 原句命中** · `GET /template-prompts` · 问数页标星/最近(**localStorage,非模板**)· UNION 括号 · 分析 **`POST /analyze`** | spec + [TEST-LOG-AN-002](tests/2026-09-12-analyst-template-phrases/TEST-LOG-2026-09-12-AN-002.md) | -| **问数 NL2SQL(2026-09-12)** | **复合问不走模板** · 内置 + **published few-shot** · **published dict** 覆盖同 key 口径 · 模板仍 **published + match_phrases** | MEMORY §D-11 | +| **问数 NL2SQL(2026-09-12)** | **复合问不走模板** · **published few-shot / dict** · 模板 **published + match_phrases** · 问数 **clarify 可点选** | MEMORY §D-11 · `metric_ambiguity.py` | | **客户「趋势/走势」** | **平台行情详情**:`nav/history` + **区间(1M~ALL)/粒度(日周)/图型(走势/涨跌柱/组合)** · Chat 仍无历史 Tool · Phase B 外部 sync 未做 | 见 `web/src/utils/navChartSeries.ts` | | **L0 优先** | 抽槽与 L0 撞车**永远听 L0**;L1 只 enrich 措辞 | `profile_slots` D7 | @@ -244,6 +244,6 @@ RBAC 联调账号:scripts/dev/rbac-seed-reference.md 2. 改动属于 api / service / tool / repository 哪一层? 3. 是否需 customer_id 归属与 JWT RBAC? 4. Core 是模拟库只读还是 agent 库读写? -5. 如何验证?(`python -m pytest` **861 绿** · `cd web && npm run test` **27 绿** · Redis **6380** · `/api/ready` · 问数 **点选常用问法收录句** · 复合问看 NL2SQL+内置 few-shot · 日志 [AN-002](tests/2026-09-12-analyst-template-phrases/TEST-LOG-2026-09-12-AN-002.md)) +5. 如何验证?(`python -m pytest` · `cd web && npm run test` **27 绿** · Redis **6380** · `/api/ready` · 问数 **clarify 点选口径** · 沉淀 **`seed_analyst.ps1` 灌库后重启后端** · 网页发布 **reload 不重启** · 日志 [AN-002](tests/2026-09-12-analyst-template-phrases/TEST-LOG-2026-09-12-AN-002.md)) 大任务:FRAMEWORK/FLOW 与实现状态不符时先更新 memory 再编码(用户确认跳过除外)。 diff --git a/docs/memory/TODO.md b/docs/memory/TODO.md index 298752a..0711179 100644 --- a/docs/memory/TODO.md +++ b/docs/memory/TODO.md @@ -96,9 +96,9 @@ - [x] 四角色 Dashboard · 平台只读 · ChatPanel · 游客试聊 · 行情 · 风控台账+筛选+适当性+AML+模拟交易 · 问数工作台+资产沉淀 - [x] **问数模板原句(2026-09-12)**:`match_phrases` · `/template-prompts` · 常用问法/标星/最近 · TEST-LOG-AN-002 · **861 pytest / 27 Vitest** -- [x] **问数 NL2SQL few-shot(2026-09-12)**:`analyst_agent._BUILTIN_SQL_FEW_SHOTS` · 复合问不模板化 · 无 D-11 库读 -- [x] **D-11 运行时接入(2026-09-12)**:published **dict**→消歧 · **few_shot**→NL2SQL(+内置)· **template**→D-06;`seed-analyst-few-shots.sql` · 沉淀页 **提交并发布** -- [ ] **D-11 后续**:资产列表/回滚 API · 成功问数一键沉淀 · draft 改 published 不重启 +- [x] **问数 NL2SQL few-shot(2026-09-12)**:**仅 published 库**(去掉 `_BUILTIN_SQL_FEW_SHOTS`)· `seed-analyst-few-shots.sql` +- [x] **D-11 运行时(2026-09-12)**:dict/few_shot/template · **`GET /assets`** · **`POST …/publish`** · **`POST /dict/ambiguity-check`** · 沉淀页列表/歧义 Modal · 问数 clarify 按钮 +- [ ] **D-11 后续**:rolled_back · 成功问数一键沉淀 - [x] **答辩稳套餐 ①(2026-09-11)**:A1 sql_guard Q17 · A5 流水 clarify 单测 · C1 种子 +2 模板 · D1 分析对话重定向/菜单收 · E1 `docs/答辩/DEMO-SOP-问数.md` · 答辩清单同步 - [ ] **分析对话菜单下线或强引导**(问数页已承载解读)· **看板钻取** — D-12 往后排 - [ ] **Vitest 补测**(可选):`useChatPanel` · `api/analyst.ts` mock diff --git a/docs/superpowers/plans/2026-09-12-advisor-agent-merge.md b/docs/superpowers/plans/2026-09-12-advisor-agent-merge.md new file mode 100644 index 0000000..fcbc2e8 --- /dev/null +++ b/docs/superpowers/plans/2026-09-12-advisor-agent-merge.md @@ -0,0 +1,129 @@ +# 投资顾问 Agent 并入 merger · Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** 将 `xinghuo/advisor-agent` 以 **只增不盖 + 接缝** 方式接入 `merger`,对外仅 **canonical `/api/advisor-agent/*`**,接线完成后 **全量 pytest 绿**。 + +**Architecture:** 参照客服 S2 / 问数 S3:宿主 `main.py` 挂 router · `get_platform_auth_context` · `advisor_auth_adapter` · 顾问专用表 SQL 迁移 · Milvus/Neo4j 增量共存。 + +**Tech Stack:** FastAPI · merger JWT/deps · MySQL jinrong_agent · Redis(既有)· Milvus · Neo4j Docker · pytest · ruff + +## Global Constraints + +- **禁止**保留对外 `/api/v1/*`(D1) +- 冲突文件 **merger 为准**(D2);`template_service.py` · `app/api/compliance.py` · `auth_service.py` **不得覆盖** +- **先接线后 pytest**(D5);未跑全量 pytest 前不得 claim merge 完成 +- 响应统一 merger `ok` / `ApiError`(非 `success_response`) +- Neo4j:用现有 `scripts/sync/sync_neo4j.py` · `sync_advisor_rel.py`(D6) + +**Spec:** [docs/项目框架设计/理财顾问Agent-合并说明.md](../../项目框架设计/理财顾问Agent-合并说明.md) + +--- + +## File map(实施前锁定) + +| 操作 | 路径 | +| --- | --- | +| 新增 | `app/api/advisor_*.py`(compliance · script_templates · kyc · market · copy · guard · dashboard · allocation) | +| **不迁入** | `app/api/admin.py`(D9 · 通用 audit 列表;风控 UI 已覆盖合规查看) | +| 新增 | `app/api/advisor_auth_adapter.py` | +| 新增 | `app/model/advisor_schemas.py` · `app/model/entities/advisor.py`(或等价) | +| 新增 | `app/service/script_template_service.py` · `script_template_vector_service.py` · 各 `compliance_*` · `kyc_*` · `market_*` | +| 新增 | `app/repository/script_template_repository.py` · 各顾问 repository | +| 新增 | `scripts/agent/migrate-advisor-agent-sprint1-3.sql` | +| 追加 | `app/main.py` · `app/config/settings.py` · `.env.example` · `requirements.txt` | +| 手工合并 | `app/tool/milvus_tool.py` · `embedding_tool.py` · `app/service/memory_service.py` | +| 不迁入 | `app/api/deps.py` · `auth.py`(顾问) · `main.py`(顾问) · `alembic/` · 顾问 `auth_service.py` | + +--- + +## Task 1:隔离工作区 + +- [ ] 使用 `using-git-worktrees`:`git worktree add ../JinRong-advisor-merge -b integrate/advisor-agent merger` +- [ ] 确认工作区干净或已 stash 本地 analyst 改动 +- [ ] `git merge xinghuo/advisor-agent --no-commit` 或按文件 checkout 顾问新增树 + +**Verify:** `git status` 显示预期冲突列表与合并说明 §5.2 一致 + +--- + +## Task 2:解冲突 + 重命名(无行为变更) + +- [ ] 对所有 §5.2 文件 **保留 merger 版本** +- [ ] 将顾问 `compliance.py` 等 **复制为新文件名**(§2.2),改 router prefix 为 `/api/advisor-agent/...` +- [ ] 全局替换服务 import:`template_service` → `script_template_service` +- [ ] 删除误保留的顾问 `deps.py` · `api/auth.py` · `middleware/trace.py` + +**Verify:** `rg "/api/v1" app/` 无结果;`rg "success_response" app/api/advisor` 无结果 + +--- + +## Task 3:接缝 — 鉴权与响应 + +- [ ] 实现 `advisor_auth_adapter.py`(映射 `AuthContext` + `current_trace()`) +- [ ] 所有 advisor router 使用 `Depends(get_platform_auth_context)` + 权限检查 +- [ ] 扩展 development JWT 种子权限(`compliance:check` · `kyc:chat` 等) +- [ ] 异常与返回改为 `ok` / `ApiError` + +**Verify:** 单测 import 不循环依赖 `gateway` + +--- + +## Task 4:宿主挂载 + +- [ ] `main.py` `include_router` 注册各 advisor router +- [ ] `settings.py` / `.env.example` **追加** KYC/合规/LLM 顾问字段(不删 merger 键) +- [ ] `requirements.txt` 追加顾问依赖(与 merger 版本取 max) + +**Verify:** `uvicorn app.main:app` 启动无 `RuntimeError`(development) + +--- + +## Task 5:数据库与种子 + +- [ ] 编写 `scripts/agent/migrate-advisor-agent-sprint1-3.sql`(仅专用表 + agent_message UK) +- [ ] 本机 `jinrong_agent` 执行迁移 +- [ ] 运行 `import_compliance_rules.py` · `import_script_templates.py`(路径迁入后) + +**Verify:** 表存在 · 规则/模板计数与源分支文档数量级一致 + +--- + +## Task 6:Milvus · Neo4j + +- [ ] 手工合并 `milvus_tool.py` / `embedding_tool.py` 支持 `kb_script_templates` +- [ ] 运行模板向量同步脚本(Ollama/Milvus 可用则 full;否则测关键词降级) +- [ ] Docker Neo4j:`python scripts/sync/sync_neo4j.py` · `sync_advisor_rel.py` + +**Verify:** 话术 search 200;归属校验失败路径 403 可构造 + +--- + +## Task 7:测试迁移 + +- [ ] 迁入 `tests/test_sprint*.py` · `test_step*.py` · 改 canonical 路径与响应断言 +- [ ] `conftest.py` 以 merger 为准,必要时 **追加** fixture 不删原有 +- [ ] `pytest tests/test_advisor*` 或 sprint 文件子集先绿 + +**Verify:** 顾问子集全绿 + +--- + +## Task 8:全量回归 + 文档 + +- [ ] `python -m pytest` +- [ ] `ruff check app tests scripts` +- [ ] Scope B 冒烟 §6.3(HTTP 手工或 `run_demo_smoke.ps1` 改路径) +- [ ] 更新 `docs/memory/FRAMEWORK.md` 实现状态 · `TODO.md` · 契约附录草稿 +- [ ] 合并说明 §9 修订记录改为「已接线」+ pytest 数字 + +**Verify:** 输出粘贴到 TEST-LOG 或 MEMORY 基线句 + +--- + +## 不在本 plan 范围 + +- 前端 React 顾问工作台(S4-xx) +- KYC Profile / 资产配置闭环(S3-03+) +- `/api/v1` deprecated 兼容层 +- 生产 IdP / JWKS diff --git a/docs/superpowers/specs/2026-09-12-advisor-agent-merge-design.md b/docs/superpowers/specs/2026-09-12-advisor-agent-merge-design.md new file mode 100644 index 0000000..93b4378 --- /dev/null +++ b/docs/superpowers/specs/2026-09-12-advisor-agent-merge-design.md @@ -0,0 +1,88 @@ +# 投资顾问 Agent 并入 merger · 设计说明 + +> 日期:2026-09-12 +> **Canonical 合并说明(执行细节):** [docs/项目框架设计/理财顾问Agent-合并说明.md](../../项目框架设计/理财顾问Agent-合并说明.md) +> **状态:已写 spec · 未动代码 · 待评审后进入 implementation plan** + +--- + +## 背景 + +源分支 `xinghuo/advisor-agent` @ `68df13c` 在独立仓库形态下使用 `/api/v1`、第二套 `auth_service` / `success_response`,与 `merger`(AL-09 · 平台 `/api/*` · 833 pytest)**不可直接 merge**。 + +产品拍板:**merger 优先** · **顾问侧重命名** · **只增接缝** · **接线后再 pytest** · **Neo4j Docker 已就绪**。 + +--- + +## 方案对比(brainstorming 结论) + +| 方案 | 做法 | 优点 | 缺点 | 结论 | +| --- | --- | --- | --- | --- | +| **A · 接缝迁入(推荐)** | 新 prefix `/api/advisor-agent` · 新文件名 · deps/JWT/response 统一 merger | 与客服/问数/风控 precedent 一致;回归面可控 | 需改 101 条测试路径与 import | **采用** | +| B · 整分支覆盖 merger | 以 advisor `main.py` 为入口 | 顾问侧改动少 | 打穿 chat/risk/analyst/平台 API;**不可接受** | 否决 | +| C · 长期双栈 `/api/v1` | 两套路由并存 | 演示迁移快 | 违反契约拍板;前端/脚本双倍维护 | **否决**(除非日后 deprecated shim) | + +--- + +## 架构(接缝) + +```mermaid +flowchart LR + subgraph host [merger 宿主] + MAIN[main.py] + DEPS[deps.py + auth_service] + TRACE[TraceMiddleware] + end + subgraph platform [平台 API] + ADV[advisors.py] + COMP[compliance suitability-check] + end + subgraph advisor_line [投资顾问 Agent 新增] + AC[advisor_compliance.py] + ST[advisor_script_templates.py] + KYC[advisor_kyc.py] + MK[advisor_market.py] + end + MAIN --> ADV + MAIN --> COMP + MAIN --> AC + MAIN --> ST + MAIN --> KYC + MAIN --> MK + AC --> DEPS + ST --> DEPS + KYC --> DEPS + MK --> DEPS + TRACE --> AC +``` + +--- + +## 关键命名决策 + +1. **HTTP 前缀:** `/api/advisor-agent`(避免与 `/api/advisors` 平台域混淆)。 +2. **文案合规 vs 适当性:** 前者仅在 `.../compliance/content-check`;后者保持 `POST /api/compliance/suitability-check`。 +3. **问数模板:** merger `template_service.py` 不动;顾问话术 → `script_template_service.py`。 +4. **迁移:** Alembic 7 revision → 单文件 `migrate-advisor-agent-sprint1-3.sql`;底座表不重复 CREATE。 + +--- + +## 成功标准 + +- [ ] 无 `/api/v1` 对外文档与测试 +- [ ] `python -m pytest` ≥ merger 原基线 + 顾问新增全绿 +- [ ] Scope B 六条冒烟(见合并说明 §6.3) +- [ ] 平台适当性 + 问数各 1 条回归通过 +- [ ] Neo4j 同步脚本与顾问归属校验一致(本机 Docker) + +--- + +## 评审(2026-09-12 更新) + +| # | 项 | 结论 | +| --- | --- | --- | +| 1 | 前缀 `/api/advisor-agent` | **已确认** | +| 2 | `demo_ui` / `/demo` | **不要** | +| 3 | admin | **不迁入** `GET audit-logs`;合规查看走 merger 风控台账等页面;顾问业务仍写共用 `audit_log` | + +确认后执行:`docs/superpowers/plans/2026-09-12-advisor-agent-merge.md`。 diff --git a/docs/项目框架设计/理财顾问Agent-合并说明.md b/docs/项目框架设计/理财顾问Agent-合并说明.md new file mode 100644 index 0000000..455cc98 --- /dev/null +++ b/docs/项目框架设计/理财顾问Agent-合并说明.md @@ -0,0 +1,313 @@ +# 投资顾问 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 完成 |