- Implemented `_merged_items` and `_merged_memory_text` functions to consolidate consult and chitchat memories, improving context awareness in intent classification and response generation. - Updated intent prompts to include recent dialogue history, aiding in the resolution of ambiguous user queries. - Enhanced `search_knowledge` tool to utilize context window for better query understanding, addressing issues with omitted references in user inputs. - Fixed existing test cases to reflect changes in intent constants and ensure accurate context handling during tests. This update significantly improves the handling of multi-turn dialogues, ensuring a more coherent and contextually aware interaction for users.
42 KiB
项目记忆(人 + Agent 共用)
各阶段的简化快照(门闸索引)。只留基础信息,不写源文件正文。
新 Agent 无上下文:先读本节 → 第 0 节交接清单 → 按需打开源文件。
0. 新 Agent 交接(5 分钟)
项目是什么: 金融四 Agent(客户财富 / 代理人 / 数据分析 / 风控)共用数据层与合规底座;不互调 LLM,跨 Agent 走 L1/L2/L3 画像与预警表。
当前进度: 需求与表设计已定 · pytest 实测 1236 passed / 102 failed / 9 skipped / 21 errors(全量 1368 collected,2026-09-13 第五轮实测;⚠️ 旧记的「926 / 896 passed」已作废 —— 见 F-α(文档门槛陈旧)与 F-ζ(--ignore-glob=test_sprint*.py 为空操作,"排除 sprint"从未生效);修正 glob '*/test_sprint*.py' 后为 1199 passed / 45 failed / 9 skipped / 21 errors)· ⚠️ 套件非幂等(F-η):连跑两次 FAIL 集合不同 ⇒ 引用该数字须附跑批序号 · 27 Vitest · Redis @ 6380 · merger 未 commit · 前端设计栈补强未 commit(2026-09-13:Inter 自托管 + Radix 状态阶) · 客户线交易 + 选购清单 + 持仓快照/行情快捷交易未 commit(2026-09-13) · 顾问线已 fast-forward 合入 merger · 端到端第三轮(真浏览器 + 真 HTTP)174 用例 161 PASS / 12 FAIL / 1 SKIP → 6 缺陷待修(FE-001 · D1 已关闭 ✅ · D2 KYC created_at · D3 Milvus 集合 released · F1 转换页预置跨主体必失败 ✅ 第四轮复跑已转绿 · F2 ✅ 已转绿 · alert_id/alert_ids 字段名不匹配F3 无路由级角色守卫 ✅ 已转绿 · F4 确认日默认越界)
端到端第四轮(客户线交易 · 真浏览器 + 真 HTTP + 真库对账)(CT-001 v1.2 · 初稿 203 用例 162 PASS / 6 FAIL → 同日复跑取证:Part A 161 行 135 PASS / 0 FAIL / 1 SKIP / 25 INFO(退出码 0)· Part B 48 行 41 PASS / 0 FAIL / 0 SKIP / 7 INFO(退出码 0))
- ✅ P0 已修:
jwt_service.infer_roles()忽略外部roles,只认DEFAULT_ROLES_BY_ACTOR;未知 actor 登录 → 401。单测test_wave0_auth.py - ✅ P1 已修:自助通道
simulate_self_service_blocked()(allowed_with_disclosure/requires_disclosure/needs_branch_confirm视同阻断)·trade_gateway+convert_service转入端 · 单测test_trade_gateway/test_convert_accept - ✅ L1 已修:同
client_request_id、不同 body → 409IDEMPOTENCY_CONFLICT(accept_convert比对四元组 ·CT7-05硬断言) - ✅ CT6 脚本已修:
derive_redeem_qty()由 T+2 批次推导申报量(优先 FIFO 跨档),不再写死35000·CT10-07无赎回时 SKIP(避免空 PASS) - ✅ 复跑已取证(2026-09-13 19:26):P0/P1/L1 三条同期望值转绿(退出码 1 → 0),CT6 赎回覆盖缺口关闭(组中止 SKIP → 7 PASS,含 FIFO 跨档
30000+150与金额复算44922.38);5 表还原核对95 / 59 / 73 / 19 / 0 - ⚠️ 复跑新发现(需拍板):① P0 只堵了方向① ——
infer_roles已不信任入参,但/api/auth/login仍无app_env门禁、main.py:103仍无条件挂载;② P1 可能收窄业务能力 ——allowed_with_disclosure被并入阻断 ⇒ R4 产品自助通道完全不可下单(原设计是「弹揭示书后可买」),需业务确认是否补揭示书续接流程;③CT3-05顺序敏感 —— 15 分钟墙钟窗口 +jinrong_agent永不还原 ⇒ 距上一轮 <15 min 复跑会假 FAIL(本轮踩过,已声明复跑口径) - ⚠️ 仍开放:B1 持仓 vs 批次和基线不一致(种子/历史态,非本轮引入)· T1
run_demo_smoke.ps1仅登录改 canonical(后续/api/v1/*仍 404)· 仓库外11-cross-role.mjsC1.6陈旧断言 · Redis 降级路径(两轮均未跑,唯一未覆盖的功能路径) - ⚠️ 证据链缺口(如实声明):
_raw/shots/的 11 张截图被 v1.1 复跑就地覆盖,v1.0 的修复前截图不可恢复;v1.0 结论仅有报告文本与 JSON 可查 - ✅ 初轮已证口径:前端渲染与后端 raw 核对到分 · 数据副作用可回滚 · 对话/挂单红线全绿
端到端第五轮(覆盖缺口补测 · 三条线全补 · 一线一包 · 2026-09-13) —— 起因:「还有哪块没有端到端跑过?」
- 产出四个包:AN-003 问数线 · AD-001 理财师线 · RK-001 风控线 · XC-001 横切
- ✅ Part A 真实 HTTP:问数线 137 PASS / 6 FAIL(= 缺陷 A/A2/B,此前 12 条路由零 HTTP E2E)· 理财师 31 PASS / 4 FAIL(AD8 为取证组)· 风控 23 PASS / 0 FAIL · 横切 33 PASS / 0 FAIL / 1 SKIP
- ✅ Part B 真浏览器:8 支脚本 123 PASS / 0 FAIL / 6 INFO(
03/04/06/07/08/09/10/11全部收复进scripts/e2e/,改指向仓库内 harness) - ⚠️ Part C 回归:
npm run build✅ 0 ·npm run test✅ 27 · 四文件交易单测 ❌ 49/28(F-β) ·pytest❌ 1236/102/9/21(F-α + F-ζ) - ✅ Phase 6 还原已校验:
core5 表按快照还原,逐表 COUNT + CHECKSUM 与快照完全一致(95/59/73/19/0)·script_template页面可见恢复到 20 - 🟢 已拍板 2 项(用户 2026-09-13 定):F-14 维持现状(「目前够用就行」—— 接受 LLM 自撰风险提示措辞,不扩
compliance_guard.py:109名单;代价是措辞与是否出现由 LLM 随机决定,06-chat.mjs中该条已降级为 2 条 INFO)· RK 发现-1 关闭(「这个不用管」—— 未知客户语义保持 officer 200 / advisor 403 / customer 403 无一 404,现状不泄漏客户存在性,仅作实测事实保留在风控包与横切包) - 🟢 已拍板 · F-β = 选 A(用户 2026-09-13 定):维持现状语义不动,下一轮只改测试(
test_convert_confirm.py客户档位 C3→C4 或产品 R4→R3),零业务代码改动。规则固化:C3×R4/C4×R5= 匹配但需揭示 ⇒ 自助渠道阻断并引导线下,这是设计意图不是缺陷;禁止给阻断响应体补forced_full_transfer让测试变绿。上一轮 P1 修复使test_convert_confirm.py28 条失败,根因是测试前提过期,非接口缺陷。依据:① L0 矩阵刻意设三态(core_suitability_rule25 行实测)——C3×R4/C4×R5=allowed_with_disclosure,服务层matched=True/blocked=False/mismatch_type="none"/block_code="SUIT_NEED_DISCLOSURE",不是"不匹配",而是"匹配但须特别风险警示+签揭示书"(适当性办法 §19);② "需揭示→自助端阻断"是已定设计,三处同指:答辩稿答辩知识点清单.md:59「C3×R4 揭示 block」·CustomerTradePage.tsx:116「标有『风险不匹配/需揭示』的请换产品或到网点办理」·tradeEligibility.ts两类均canSelfServe:false+tone:'warn'+标签「需揭示/网点办理」(揭示需双录/柜面,线上无法完成"签署"动作)⇒ P1 修复是后端追平前端;③ 28 条失败根因 = 测试前提过期:test_convert_confirm.py:1013的forced_full_transfer是受理成功路径字段,CUST-CC(C3) 被阻断后受理未发生 ⇒KeyError;阻断体里本就不该有该键。选项 B(已否决)=把 PRD 二期(放行+提示)提前做,需新建前端揭示书 Modal + 留痕 + 后端受理分支;只改后端不建前端更糟。🟠 新增记账(真缺口,只记录不修):文案引导的「网点办理/请联系持证投顾」无实现通路 —— 理财师线零交易 API,全仓唯一入口POST /api/simulate/trade不区分渠道身份 ⇒C3×R4当前任何渠道都买不成,文案承诺 > 实现能力。处置二选一待定:① 答辩口径统一为"线下受理一期未实现";② 改前端文案(CustomerTradePage.tsx:116) - 🟢 F-ε(已修 · 2026-09-13 修复轮):
pytest写真库根因 = 测试文件模块级from app.advisor_db import AgentSessionLocal在收集期绑定真库 sessionmaker,绕过 fixture 对app.advisor_db.AgentSessionLocal的 monkeypatch(test_sprint1_compliance_rule_import.py早已用正确模式import app.advisor_db as advisor_db)。修法:① 10 个test_sprint*.py改from app import advisor_db+ 调用点advisor_db.AgentSessionLocal/advisor_db.agent_engine;②import_script_templates.py同改;③ 唯一写真库的 subprocess 用例(seed 脚本独立跑)改@pytest.mark.skip(另两处 subprocesssync_template_vectors --dry-run只计数、evaluate_compliance不带 trace_id/advisor_id 不写日志,经查只读)。验证:跑后script_template仍 65 / seed 20 /test:*36,零污染。同轮另发现并修:6 个test_sprint2_*.py的token_for(username,password)打/api/v1/auth/login+{username,password},与现行POST /api/auth/login(actor_id+token_type+roles)不符 ⇒ 迁移到tests/advisor_test_utils.login_token。副作用(如实):转 sqlite 后暴露 F-α 假 DDL 缺列(agent_session无metadata等),sprint 组 45 条失败为陈旧 DDL/期望,非本轮引入 - 🔴 F-ζ:
--ignore-glob=test_sprint*.py是空操作(pytest 匹配完整路径,缺*/)⇒ 文档门槛"排除 sprint 后的 896"从未按设计生效。修正写法--ignore-glob='*/test_sprint*.py'(1368→1274) - 🔴 F-η:测试套件非幂等 —— 同库同命令连跑两次 FAIL 集合不同(129 vs 127 行)⇒ 单次
pytest的 passed 数不可作"不退步"基线,引用须附跑批序号 - ⚠️ F-γ 更正:Phase 0 记的
core_share_lot=74与同次快照(73 行)不自洽 ⇒ 还原判据改为「与快照逐表 CHECKSUM 一致」,不再用某个读数值 - ✅ ADV-3 实证(原为读码推断):
agent_graph.py的 5 个工具有 3 个接错(chat/search/check不存在、get_session缺 keyword-onlyauth),孤儿代码 ⇒ P3;tests/test_step11_agent_graph.py全注入Mock()⇒ 遮蔽(Mock 对任意属性返回可调用对象) - ⚠️ 本轮未做完(如实声明):
/register注册链路仍零覆盖 ·/app/home·/app未访问 · 面包屑/登出/会话侧栏切换未做浏览器验证 ·AnalystAssetsPage表单仍未提交 - ⚠️ 已登记残留:
risk_alert.pending_review41 → 35(追加型审计表,按语义不还原)·script_template的test:*行置is_active=0留库
多轮对话三缺陷修复(visitor/customer/advisor · 2026-09-14 · 未 commit) —— 起因「看看其他 agent 有没有类似缺陷」。
- 三缺陷(RAG 只用当前消息 · 意图分类只用当前消息 · 闲聊+咨询记忆割裂从不合并)是节点函数设计选择,非 LangGraph 架构问题;全仓唯一历史感知路径是交易续轮(
_trade_context_window/_resolve_advisor_tool)。 - 修法(6 文件 +90/−20,问数线
analyst_agent排除——单发 NL→SQL,无 RAG/意图/记忆):① visitor/customer 各加_merged_items/_merged_memory_text/_rag_query,从已加载 state 合并 consult+chitchat(按 ts 排序),不再回 Redis 重取;② RAG query 拼接近期原文(解「那申购呢」省略指代);③ INTENT prompt 注入{memory};④tool_service.run_tool给search_knowledge转发context_window(原死管道:tool_node 注入但 run_tool 丢弃);⑤kb_tools.search_knowledge加context_window参数拼接进 query。 - 顺带收口 5 处既存测试 bug(均非本轮三缺陷引入,已 git stash 取证为 pristine HEAD 即失败):
fake_suit缺user_message形参 ·test_query_injected断言缺_context_window·VALID_INTENTS14 非 13(含trade_action)·looks_like_trade_execute把「申购了啥」误判 trade_action ·test_chatmock 返 4 元组现返 5(+pending_trade)。 - F-β 选A 收口(2026-09-14):
test_convert_confirm.py的 28 条其实已在f856ab4(客户 C3→C4)修掉;仅剩test_convert_accept.py::test_accept_uk_idem_race_falls_back_to_idempotent(L1 同键异体→409 后,竞态用例「抢占者」份额 100≠50 四元组不匹配)→ 抢占者份额改 50。五文件 99 passed / 0 failed。
工作分支: 主线 merger(已纳入顾问线 + 基金转换线 · HEAD c09b987);保留 integrate/advisor-agent 作历史指针;历史 risk-control-agent 交付冻结。
仓库地图:
| 路径 | 状态 | 说明 |
|---|---|---|
app/main.py |
已集成(AL-09) | 宿主 TraceMiddleware + 模块 audit/trace + 路由(auth/platform/chat/risk/simulate)+ lifespan |
app/api/auth.py |
已实现(AL-09) | Mock 登录;签发走 auth_service.issue_dev_token(与模块 API 同一 issuer) |
app/api/auth_adapter.py |
已接线(S2) | module_auth_from_host():宿主 AuthContext → 模块 AuthContext |
app/gateway/ |
宿主 Wave 0(并存) | jwt_service(infer_roles 忽略 body.roles · 2026-09-13 CT-001 P0)/ auth_deps / rbac / ownership;模块 API 走 deps.py,禁止模块 import gateway |
app/api/risk.py simulate.py deps.py |
已实现 | 风控 4 API + 模拟网关 · compliance/service_risk 矩阵(F2/F3) · 台账 stats 待审计数(F7) |
app/api/chat.py audit_middleware.py |
已实现 | POST /api/chat · POST /api/chat/stream(customer 分流 → prepare_customer_stream) · visitor · sessions 三端点 |
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/advisor_*.py kyc.py market.py copy.py 等 |
已合入 merger |
对外 /api/advisor-agent/*(合规 · 话术 · 异动 · KYC · 复制门闸 · guard · dashboard/allocation ping);鉴权 advisor_auth_adapter + get_platform_auth_context;不迁 /api/v1 · demo_ui · admin/audit-logs。端到端实测(v1.1):鉴权/合规/门闸/模板/防护/跨线回归全绿;市场异动 D1 已修转绿(10/10 + 浏览器 4/4);KYC 采集(D2)仍 500,语义检索(D3)仍静默降级——ADV-001 · FE-001 |
app/advisor_db.py entities_advisor.py advisor_schemas.py |
接缝已挂 | 顾问 ORM/会话工厂 · 与 merger entities.AgentSession 共用 metadata_ 列名 |
scripts/agent/migrate-advisor-agent-sprint1-3.sql |
已新增(待本机执行) | 顾问专用表(compliance_rule · kyc_session · market_alert · script_template 等) |
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 + 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 溯源 |
app/tool/kb_tools.py |
已实现(T21-5) | search_knowledge 对话 Tool(skip_access_check 公开知识;仅 customer/advisor 意图开放,risk 不开放);kb_product_rules 尚未灌入向量库(2026-09-14 实测两份 milvus store 均无此 collection,MEMORY 此前「24 块已入库」为误记;源文档 = data/kb 6 产品手册,待跑 scripts/kb/build_kb.py 灌入) |
app/service/auth_service.py |
已实现(T-01) | Auth SDK:JWT 验签(HS256 dev/RS256 生产)、必填 claims、jti 吊销(Redis fail-open);签发 CLI scripts/dev/issue_dev_token.py |
app/service/risk/* + service/suitability.py |
已实现 | RISK-001 |
app/service/agent_service.py memory_service.py |
已实现(T-07/T-06/T-04/C2 + 方案 C) | LangGraph StateGraph(tool→llm→guard)+ DeepSeek(无 key 降级);T-04 tool 节点(关键词意图 customer/advisor/risk 分组 + tool_service.run_tool);C2 tool_node 守卫放宽(requires_customer=False 允许无绑定客户,支撑 A-6 全量待审);Redis 会话窗口 + MySQL 回源。方案 C:stream_chat 生成器(Tool 同步跑完→逐块推 LLM 文本)+ needs_disclaimer(首帧 meta 与落库尾部共用口径) |
app/service/tool_service.py app/tool/core_tools.py service/risk/chat_tools.py |
已实现(T-04/C1) | 对话 Tool 编排(统一注册表 get_registered_tool:core+risk / 归属校验 / agent_tool_call 落库)+ Core RO 三只读 Tool(L0/持仓/流水)+ C1 风控四只读 Tool(alert_query/customer_context/suitability_check/aml_lookup,RISK_TOOL_REGISTRY) |
app/repository/session_repository.py |
已实现(T-06/T-04 + 前端接入 B/C) | agent_session / agent_message / agent_tool_call 读写;方案 B 增 list_sessions(分页+total)/ list_messages_page(seq 升序分页,勿与 LLM 窗口的 list_messages 混用)/ close_session(条件更新防并发);方案 C 增 insert_turn(user+assistant 同事务落库 + 事务内取 seq,修评审 P0/P1) |
app/gateway/gateway_repository.py trade_gateway.py |
已实现(2026-09-13 持仓同步 + 自助适当性) | 模拟交易网关 · R4 揭示类自助阻断(simulate_self_service_blocked)· 申赎 _maintain_lots 同步 core_holding |
app/repository/core_ro.py |
已实现(2026-09-13 持仓补偿读) | Core 只读 SELECT;list_holdings(qty>0) · list_holdings_from_lots_gap(批次有余量但快照未体现 · 历史只写 lot 的演示修复)· check_suitability / list_products_for_customer / list_trades / get_customer_l0 |
app/service/platform/customer_service.py |
已实现(v0.1 + 持仓合并) | list_holdings 合并 gap 行并按净值估市值 · L0/流水/可购产品 |
app/repository/risk_repository.py |
已实现 | risk_alert / … · list_alerts 须 RiskListAccess(F1) · status=handled 聚合筛选 · count_pending_stats |
app/repository/repo_access.py |
已实现(2026-09-11) | RiskListAccess / ThresholdWriteAccess 仓储调用凭证 |
app/repository/threshold_repository.py |
已实现 | 阈值配置 · upsert_portfolio 须 ThresholdWriteAccess |
app/utils/ |
基本就绪 | trace(trace_id+request_id 双 contextvar)/ desensitize / db(引擎工厂)/ response(统一错误体+4xx/500 handler)/ exceptions(含 ApiError)已实现;logger 占位 |
app/config/database.py |
已实现 | MySQL 双引擎 + Redis 单例(REDIS_URL · RESP2 protocol=2 兼容 Docker Redis 7 / 旧 Windows Redis 3) |
app/config/settings.py |
已实现 | 双库 + risk_* 阈值 + JWT + customer/visitor/profile 字段 + kb_root_dir |
app/service/customer_service.py visitor_service.py |
已实现(S2 + Wave3 + 交易 + 问候快路由) | 客服 14 节点 + trade_prepare/process_trade_turn · C-04/C-05/C-11 · 选购清单 fact_text 不经 LLM 改写(防压成「能买几只」)· trade_dialogue_should_continue 续轮 · 问候 chit_chat · 游客 9 节点;sanitize_postprocess(1B);RAG fin_ 三库* |
app/service/trade_flow_service.py trade_action_service.py |
已实现(2026-09-13 · 未 commit) | Redis 交易抽槽 · 菜单序号解析 · restore_flow_from_context(Redis 丢态从助手菜单恢复)· 申购/赎回/转换草稿 · C3×R4 揭示类 subscribe_suitability_block · 与 simulate 字段对齐 |
app/tool/trade_tools.py app/tool/core_ro_tool.py |
已实现(扩展) | 顾问 prepare_simulate_trade · 适当性:多 R 列清单 · 无参「我能买什么」→ _list_purchasable_product_catalog(【R1】… 全局序号 + PROD 编号 · 回复序号进申购) |
web/src/pages/customer/CustomerTradePage.tsx CustomerTradesPage.tsx TradeConfirmModal.tsx tradeEligibility.ts tradeEvents.ts |
已实现(2026-09-13 · 未 commit) | 交易中心三 Tab · 适当性标签 · simulate 须 CUST- 客户 JWT*(非客户顶栏警示)· 确认成功 jr:trade-completed → 首页/持仓/交易明细 刷新 · Modal 成功态自关(父页不再抢先关窗)· Chat pending_trade(spec customer-trade-design) |
web/src/components/trade/TradeProductActions.tsx · ProductNavDetailPage · MarketQuotesPage |
已实现(2026-09-13 · 未 commit) | 客户角色:净值详情「快捷交易」三按钮(申购/赎回/转换)· 行情列表列 申购·走势/赎回·转换(赎回建议在详情看持仓份数) |
scripts/dev/restart-dev.ps1 restart-dev.bat |
已增强(2026-09-13) | 重启 uvicorn + Vite · 不启动 Redis(须先 start-redis.ps1 或 docker compose up -d redis)· 结束时 探测 api/ready checks.redis 并黄字提醒 · .bat 可双击 |
scripts/dev/start-redis.ps1 |
已实现 | Docker jinrong-redis · 6380→6379 · .env REDIS_URL=redis://127.0.0.1:6380/0 |
app/service/threshold_service.py |
已实现(C-04) | L1 threshold_pref_summary → customer_threshold_config;持仓查询加权盈亏 vs 阈值 → customer_notify_log |
app/utils/sanitize_postprocess.py |
已实现(1B 共用) | 数据查询 intent(含 nav_query)违禁 → 回退 fact_text;RAG/闲聊 → COMPLIANCE_REJECT;均不自动 transfer |
scripts/core/*.sql + reset.ps1 |
已实现 | Core 模拟库 DDL + 种子 · 07-seed-nav-history.sql(14 产品 ×364 日) · 再生 seed_nav_history.py --export-sql |
scripts/agent/ scripts/demo/ scripts/dev/ |
已实现 | prepare_all.ps1 · push_threshold_alerts.py · seed_analyst.ps1 · sandbox_risk_test.py · run_query_battery.py(不入库) |
scripts/sync/*.py |
已实现 | 归属同步 + Neo4j 全图 |
tests/ |
已实现 | 926+ 用例(含顾问 sprint)· merger 回归 896 绿(-k 'not test_sprint' 口径:--ignore-glob=test_sprint*.py)· 问数 AN-002 |
docs/项目框架设计/理财顾问Agent-合并说明.md |
实施中 | D1–D9 拍板 · 接缝清单 · 与 docs/superpowers/plans/2026-09-12-advisor-agent-merge.md 对齐 |
docs/答辩/ |
答辩手册 + Demo SOP + 幻灯片 + 答辩稿 + 功能测试 | README.md · 知识点清单 · DEMO-SOP-* · presentation/index.html · 答辩稿.md · DEMO-功能测试流程.md |
docs/course/ |
交互课程集 | 导览中心 + 总览 8 模块 + 问数 5 模块(D-06)+ 风控深潜 7 模块 · 与答辩清单同步 |
docs/PRD/PRD-风控监测Agent.md |
已冻结(v1.1) | 风控 PRD v1.0 + v1.1 追加 FR-8/9/10(§4A)+ 规则表附录 |
docs/项目框架设计/实现方案-风控追加需求v1.1-C4C6.md |
已定稿 | C4~C6 编码依据(经独立 AI 评审修订闭环);分支/进度速览另见项目根 交接文档.md |
docs/项目框架设计/合并注意事项-风控模块并入main.md |
AL-09 已执行(2026-09-08) | 合并接线完成;接缝见《风控Agent模块边界与合并接缝标注.md》 |
docs/项目管理/04-从需求到公共API开发方法.md |
已定(2026-09-08) | 需求→矩阵→存储→Service→API→Agent 主线;Phase A 清单 |
docs/项目框架设计/接口契约-代销平台API-v0.1.md |
已定(2026-09-08) | 代销平台 REST canonical 路径、命名规范、Agent 迁移表 |
docs/项目框架设计/C-05-行情数据源选型对比.md |
已定(2026-09-09) | C-05 净值数据源分阶段选型;禁止爬虫/前端直连第三方 |
docs/项目框架设计/接口契约-代销平台API-v0.2-行情扩展草案.md |
草案(2026-09-09) | nav-snapshot · sync_market_nav · 前端产品行情 Phase B |
docs/项目框架设计/表设计/ |
已定 | Agent 共用 11 表 + agent 专用 SQL |
docs/项目框架设计/Core模拟底座/ |
已定 | 无真实 Core 时的 L0 方案 |
web/ |
P0 + 行情详情图表 + 客户快捷交易(2026-09-11/13) | /app/market/:productId:走势图表 + TradeProductActions · 列表客户列三链 · DevReadyBanner · restart-dev.ps1 校验 nav/history |
web/src/styles/tokens.css src/theme.ts |
字体/状态阶(2026-09-13) | Inter Variable 自托管(@fontsource-variable/inter · 字体栈已提到最前 · 字族名带 Variable 后缀,写 "Inter" 匹配不上)· Radix Colors 只引 slate/jade,补 6 个状态阶 token(11 个品牌色一律未替换)· 选用依据与「色温陷阱」见 TODO 2026-09-13 |
本地 bootstrap(首次): 完整步骤与前置说明见 FLOW.md §0(权威),速览:
1. cp .env.example .env → 填 MYSQL_PASSWORD、NEO4J_PASSWORD、DEEPSEEK_API_KEY
2. pip install -r requirements.txt
3. .\scripts\core\reset.ps1 # 建 jinrong_core(含 07 净值历史 ~365 日/产品)
4. mysql … < 01-mysql-共用底座.sql # jinrong_agent 共用 11 表
mysql … < 02-mysql-agent专用.sql # 风控四表 + risk_aml_list
mysql … < scripts/agent/migrate-advisor-agent-sprint1-3.sql # 投资顾问专用表(合并后必跑)
5. mysql … < scripts/agent/seed-aml-list.sql # AML 名单(Windows 乱码:`python scripts/dev/fix_utf8_seed.py`)
python scripts/seed/import_compliance_rules.py # 顾问合规规则(源:`docs/开发文档/20-Sprint1首批合规规则数据集.md`)
.\scripts\demo\seed_advisor_agent.ps1 # 一键:迁移 + 规则 + 话术 + 演示审核(推荐)
.\scripts\demo\seed_advisor_agent.ps1 # 一键:迁移 + 规则 + 话术 + 演示审核(推荐)
(风控演示:`.\scripts\demo\prepare_all.ps1` 或 `prepare_risk_demo.sql` · PRD §10.2)
6. python scripts/sync/sync_advisor_rel.py && python scripts/sync/sync_neo4j.py
7. `docker compose up -d redis`(或 `.\scripts\dev\start-redis.ps1`)→ **REDIS_URL=redis://127.0.0.1:6380/0**(Docker Redis 7;避开本机 Windows Redis 占 6379)
8. uvicorn … · python -m pytest(**merger 回归 ~896 绿**;全量含 sprint **926 passed / 65 failed**);问数答辩:`docs/答辩/DEMO-SOP-问数.md` · 模板种子 **`scripts/agent/seed-analyst-query-templates.sql`**
AL-09 合并后架构(一句话): 宿主 gateway/ + 模块 deps.py 双栈并存;对外登录/token 统一;chat/risk 均走模块鉴权;接缝 S2 用 auth_adapter。
下一步(见 TODO): 修 F1/F2(演示可见 · 改动面极小)→ D2 → F4 → F3 → D3 · git commit merger · battery · 客服验收 · D-12 往后排
⚠️ 前端 E2E 覆盖现状: 2026-09-12 第三轮已完成顾问前端四页 + 风控前端六页的逐功能点按(真浏览器 · 47 用例,见 FE-001),两个 SSE 对话页与客户线仍属 2026-09-10 的「仅能渲染」口径 —— 接口错误态、对话多轮/会话管理、数据与后端 raw 对账、排序分页正确性等仍未验证(CHAT-1~4 就是这样漏掉的)。未跑清单见 TODO.md §「前端 E2E · 未跑测试」,旧报告见 docs/整体测试/前端整体测试交接.md。
⚠️ 本轮已知复现性缺口: 浏览器脚本(09/10/11-*.mjs)在仓库外 C:/Users/Windows/e2e-jinrong/,他人 clone 拿不到 → 已挂 TODO.md「E2E 最小集进仓库」P0。
Redis(2026-09-09): 推荐 Docker jinrong-redis(redis:7-alpine)· 宿主机 6380 → 容器 6379 · .env REDIS_URL=redis://127.0.0.1:6380/0 · 客户端 RESP2(database.py / redis_gateway.py)。
Redis 不加速页面看板(2026-09-10 澄清): Redis 管 Chat 会话窗口 / 问数 D-06 结果 / 限流 / L3 热读;平台 GET(持仓/净值/预警列表)与 Dashboard hooks 每次进页仍打 MySQL,前端无跨路由缓存 · 净值 fetchNavMap 按产品 N 次 HTTP → 体感「每页都转圈」见 TODO.md §2026-09-11 · FRONTEND-HANDOFF.md §10。
前端启动(web/): npm install → npm run dev(5173,/api 代理 8000)· 验收四 demo 账号见 docs/frontend/FRONTEND-HANDOFF.md §8 · 改 UI 后跑 npm run build && npm run test && npm run lint。
平台 API 硬规则(2026-09-08 拍板): 路由 A · 按业务域(/api/customers 等);与 Agent 功能重复时 以本平台 API 为准;命名见契约 §2;合并时统一改 canonical 路径。
禁止(改代码前必记): Core 正式 C1~C5 不可被画像覆盖 · 审计表只 INSERT · 代理人草稿不外发 · 仅 R-02 可阻断交易 · 四 Agent 不互调 LLM。
里程碑 tag 中文对照(tag 本体保留英文原名——git 技术标识符需跨平台/脚本稳定引用,符合「技术字面量保留英文」约定;中文名经对照表统一):
| tag | 中文名 | 状态 |
|---|---|---|
risk-m1 |
阶段A · 适当性校验可用 | 已补打(2026-09-07,指向阶段 A 完成提交 3c07de6,历史归档) |
risk-m2 |
阶段B · 事件线全链路 | 已打(2026-09-07,附注含验收走查记录) |
risk-m3 |
阶段C前半 · 对话线闭环 | 已打(2026-09-07,指向 C1~C3 完成提交) |
risk-m4 |
追加需求 · C4~C6(FR-8/9/10) | 已打(2026-09-07,annoted tag 指向 323d98b,仅本地未 push;C4 fe4801b/C5 90d0660/C6 66ec7eb 三提交 + 文档落账 323d98b,全量 482 绿,挂账 #1~#9 核对无违规) |
risk-align1(拟) |
阶段一 · 对齐 main 基准 | 待定(AL-01~08 已完成,是否为此打 tag 由用户拍板;当前仅 AL 逐项 commit) |
1. 项目简介
- 名称: JinRong 金融四 Agent 智能管家
- 当前阶段: 代销平台 v0.1 + AL-09 + 客服 Wave3 + 客户交易/选购清单(2026-09-13)+ 问数 D-06/D-11 + 投资顾问 Agent 接缝(2026-09-12)
- 当前优先级: CT-001 复跑已完成 ✅ · merger commit(客户线 + CT 收口 + 字体栈 —— 现在可以提交了对某个确定 SHA 负责)· 复跑新发现三条待拍板(P0 补方向②③ / P1 业务口径 /
CT3-05顺序敏感)· F4/D2/D3 · battery · sprint pytest
2. 阶段快照
| 阶段 | 当前一句话 | 源文件 |
|---|---|---|
| 服务对象大环境 | 公募四类角色;无真实 Core,L0 由 jinrong_core 模拟库供给 |
ENVIRONMENT.md |
| 需求目的 | 四 Agent + 统一数据层 + 合规可审计;Wave 0~3 P0 见 REQUIREMENTS | REQUIREMENTS.md |
| 项目框架 | FastAPI 分层 + LangGraph + MySQL 双库/Redis/Milvus Lite/Neo4j + React | FRAMEWORK.md |
| 实现流程 | Gateway JWT → chat → LangGraph → Tool → 审计;bootstrap 见 FLOW §0 | FLOW.md |
3. 约束
硬阀门:技术选型
docs/项目框架设计/技术选型和版本/01-技术栈与版本.md 中已标「已定」视为用户确认;新增依赖须再确认。
禁止触碰:
Core 正式 C1~C5、持仓/交易真账(Agent 只读;当前为模拟库)
audit_log 等审计表(只 INSERT)
代理人草稿自动外发客户
风控自动冻户 / 改正式风险等级
各 Agent 自建第二套 JWT/RBAC
高风险(改前需确认): 数据库表结构、JWT/RBAC、部署密钥、删生产数据。
开发开关:
| 项 | YES / NO |
|---|---|
| 允许新增依赖 | YES(对齐技术选型文档) |
| 允许重构 | YES(最小范围) |
| 允许改表 / schema | 需确认 |
| 允许改接口协议 | 需确认 |
特殊规则:
四 Agent 不互调 LLM;跨 Agent 走 L1/L2/L3 画像与预警表
客户 Agent:无投资建议/收益承诺/自动下单
代理人:不对 C 端直发
数据分析:仅 SELECT,不处置预警
画像不得覆盖 L0 正式测评
客服合规拍板(2026-09-10 · 已落地):
| ID | 决策 | 代码落点 |
|---|---|---|
| 1B | 数据查询 intent(持仓/流水/风评/适当性/净值)经 sanitize_reply 命中违禁词 → 回退 fact_text,不转人工;RAG/闲聊命中 → COMPLIANCE_REJECT,也不自动 transfer;customer + visitor 共用 |
app/utils/sanitize_postprocess.py · finalize_sanitized_reply |
| R1 | L1 product_preferences / excluded_products 合并时写 items_meta;注入 prompt Top-K + 时间衰减 + TTL(K=3 · TTL=90d · 半衰 30d) |
profile_service · settings.profile_preference_* |
| C-04 | 持仓内联提醒 + 演示 push:POST /api/customers/{id}/threshold-check?push= · push_threshold_alerts.py · 持仓页按钮(无定时 cron) |
threshold_service · customers.py |
| C-05 | 「最新净值/单位净值」→ Core get_latest_nav(快照,非实时盘口);「实时净值」仍 reject |
core_ro_tool.query_product_nav · intent nav_query |
| C-11 | 「我能买什么/有什么可以买」→ suitability_check · 按 R1–R5 列产品名 + 全局序号 + PROD-* 编号(非各档「能买 N 只」计数);回复序号接交易菜单(仅 可直接申购 进金额;揭示/双录 引导代理人;forbidden 拦截)· 「推荐稳赚/买什么好」仍 reject |
core_ro_tool._list_purchasable_product_catalog · customer_prompts._ELIGIBLE_PRODUCTS_KW · trade_flow_service.parse_product_menu_from_context |
| 客户交易(2026-09-13) | 助手内 不 聊天打字确认下单 · Modal + POST simulate;多轮抽槽 Redis + 上下文恢复;见 spec | docs/superpowers/specs/2026-09-13-customer-trade-design.md · trade_action_service · chat SSE pending_trade |
| 客户交易 · 持仓与 UI(2026-09-13) | 展示口径:GET .../holdings = core_holding(qty>0)∪ 批次 gap 补偿(list_holdings_from_lots_gap)· 新单网关 apply_holding_* 写快照 · 前端 subscribeEligibility(requires_disclosure 按 0/1)· jr:trade-completed 刷新看板+交易明细 · 演示须 CUST-* 登录否则 simulate 403、流水不会出现 |
customer_service.list_holdings · gateway_repository · CustomerTradesPage · tradeEvents.ts |
| C-07 | 风评查询走 Core;「重新测评/重做风评」 → 引导 App/网点(Agent 内不做问卷) | customer_prompts._RISK_KW |
| 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 |
| 问数 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 |
4. 入口与运行
后端入口:app/main.py · 配置 app/config/settings.py · Core 只读 app/repository/core_ro.py
Agent 库 SQL:docs/项目框架设计/表设计/01-mysql-共用底座.sql · 02-mysql-agent专用.sql(含 risk_aml_list)
Core 模拟:scripts/core/reset.ps1 · 文档 docs/项目框架设计/Core模拟底座/
种子:scripts/agent/seed-aml-list.sql(AML 名单)· scripts/demo/prepare_risk_demo.sql(reset 后重跑)
依赖:requirements.txt(LangGraph + langchain-core/openai + FastAPI + SQLAlchemy)
启动:uvicorn app.main:app --reload → GET /health · **GET /api/ready**(环境自检)
Redis:`docker compose up -d redis` · `REDIS_URL=redis://127.0.0.1:6380/0` · `scripts/dev/start-redis.ps1`
测试:python -m pytest(**926 passed / 65 failed / 1 skipped** 全量 · **896 passed** 不含 `test_sprint*`;集成需 MySQL + 顾问迁移 SQL + AML + 风控演示数据)
风控沙盘:`python scripts/dev/sandbox_risk_test.py`(TEST-RISK-001 · **`:325-326` 断言已腐化**:仍期 `convert` → 400,`03fce88` 后合法受理为 202)
真实 HTTP E2E:`python scripts/dev/advisor_e2e_smoke.py` · `python scripts/dev/risk_e2e_smoke.py`(**需 uvicorn 已起** · 退出码 0 全过 / 1 有 FAIL / 2 前置失败 · `--only R6` 单组 · `--report <path>`)
浏览器 E2E(**仓库外**):`cd C:/Users/Windows/e2e-jinrong && node 09-advisor-pages.mjs && node 10-risk-pages.mjs && node 11-cross-role.mjs`(**须先起 Vite 5173**)
前端:cd web && npm run dev · npm run build/test/lint(**27** Vitest)· 四角色 Demo 见 **`docs/frontend/FRONTEND-HANDOFF.md` §8** · 本地后端 **`scripts/dev/restart-dev.ps1 -Backend Local`**
问数模板:mysql … < scripts/agent/seed-analyst-query-templates.sql
风控一键灌库:.\scripts\demo\prepare_all.ps1
运维/演示脚本:scripts/demo/subscribe_alerts.py(订阅推送演示)· rebuild_alerts.py TRD-xxx(引擎异常补偿重放)
JWT 联调:python scripts/dev/issue_dev_token.py --sub STAFF-30001 --roles risk_officer(+ Authorization: Bearer + X-Agent-Type)
配置:.env(见 .env.example)
RBAC 联调账号:scripts/dev/rbac-seed-reference.md
5. 文档资产约定
| 文件 | 何时读 |
|---|---|
docs/memory/MEMORY.md |
每次任务先读(本文件) |
docs/memory/REQUIREMENTS.md |
对照场景 ID(F/C/A/D/R)与 Wave |
docs/memory/FRAMEWORK.md |
分层、选型、模块、实现状态表 |
docs/memory/FLOW.md |
端到端链路 + 本地 bootstrap |
docs/memory/ENVIRONMENT.md |
As-Is 业务环境与 Core 模拟说明 |
docs/memory/TODO.md |
当前待办与已完成 |
docs/PRD/PRD-风控监测Agent.md |
风控 PRD v1.0(已冻结;FR-1~FR-7 + §8 验收表) |
docs/PRD/附-风控规则表.md |
RISK-001 |
docs/项目框架设计/开发计划-风控模块.md |
风控分阶段计划(阶段 A/B/C + 挂账登记 + B7~B9b 复审记录)风控开发必读 |
docs/项目框架设计/演示SOP-风控模块.md |
演示/走查操作手册(重灌 + A-1~A-9 步骤 + 核查单结论);跑集成测试前先按 §2 重灌 |
docs/项目框架设计/架构设计-风控模块.md |
风控模块架构(§3.1 编排 / §5 service 职责) |
docs/需求拆解/ |
业务原文(场景、矩阵、合规) |
docs/项目框架设计/ |
表结构、JWT 手册、Core 模拟、技术版本 |
docs/项目管理/04-从需求到公共API开发方法.md |
搭公共底座/API 前;新人 onboarding |
docs/项目框架设计/接口契约-代销平台API-v0.1.md |
写/Review 代销平台 REST;Agent 合并对照 canonical 路径 |
docs/项目框架设计/C-05-行情数据源选型对比.md |
C-05 行情/净值数据源拍板与禁止项 |
docs/项目框架设计/接口契约-代销平台API-v0.2-行情扩展草案.md |
Phase B nav-snapshot 与 sync 脚本契约(未实现) |
docs/frontend/FRONTEND-HANDOFF.md |
改 web/ 必读:启动/分层/设计令牌/组件边界/浏览器验收清单 |
缺 docs/memory/* 文件:按 project-memory-kit 同名补回,禁止空模板盖进度。
6. 协作口令
【大环境】→ ENVIRONMENT · 【需求讨论】→ REQUIREMENTS · 【框架讨论】→ FRAMEWORK · 【实现流程】→ FLOW · 【Plan】→ TODO
7. 阅读完成门闸(Agent)
- 四个 Agent 服务谁、禁止什么?
- 改动属于 api / service / tool / repository 哪一层?
- 是否需 customer_id 归属与 JWT RBAC?
- Core 是模拟库只读还是 agent 库读写?
- 如何验证?(
python -m pytest· 顾问冒烟tests/test_sprint0_foundation.py·from app.main import app→ OpenAPI 62 路径 ·cd web && npm run test27 绿 · Redis 6380 ·/api/ready· 问数 AN-002 · 真实 HTTP E2Epython scripts/dev/{advisor,risk}_e2e_smoke.py(需 uvicorn 起着 · 退出码 0/1/2)· 浏览器 E2E 见 FE-001 · 合并说明docs/项目框架设计/理财顾问Agent-合并说明.md)
大任务:FRAMEWORK/FLOW 与实现状态不符时先更新 memory 再编码(用户确认跳过除外)。