# 投资顾问 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 完成 |