- Implemented `check_suitability` method in `CoreReadOnlyRepository` for suitability determination based on customer and product risk levels. - Added `build_suitability_log_row` function in `suitability.py` for mapping suitability check results to `risk_suitability_log`. - Updated `AGENTS.md`, `ENVIRONMENT.md`, and `FLOW.md` to reflect changes in suitability assessment processes and documentation. - Revised `FRAMEWORK.md` and `MEMORY.md` to clarify project structure and data flow related to suitability checks. - Expanded `TODO.md` with tasks related to logging and auditing suitability assessments.
15 KiB
业务记忆管理手册
写给:产品、开发、测试、合规
目的:说清楚 什么叫短期记忆、什么必须长期保存,以及 Redis / MySQL / Neo4j / Milvus / Core / 本地文件 各自放什么
关联:00-架构总览.md · 02-redis-keys.md · 03-milvus-collections.md · 04-neo4j-model.md · 数据交互矩阵.md
1. 一句话总览
短期记忆 = 为了「这一轮对话跑得顺」的临时数据,丢了能重建,不做法务证据。
权威记忆 = 必须长期保存、能审计、跨 Agent 共享的业务结论,以 MySQL 为准。
知识记忆 = 产品/制度文档的语义检索(Milvus),不是聊天记录。
关系记忆 = 谁持有啥、谁管谁、产品要什么风险等级(Neo4j),金额事实仍以 Core 为准。
官方事实 = 持仓、流水、正式 C1~C5(Core 只读,Agent 库不复制账表)。
铁律: Redis 里的内容 永远不是最终真相;合规纠纷、监管检查、跨 Agent 交换,一律以 MySQL + Core 为准。
2. 记忆分层模型(业务语言)
可以把整个系统的「记忆」分成五层,从「聊完就忘」到「必须留档」:
| 层级 | 业务名称 | 技术载体 | 生命周期 | 丢了怎么办 |
|---|---|---|---|---|
| M0 | 对话草稿 | Redis | 分钟~小时(TTL) | 从 MySQL 最近消息重建上下文,略慢 |
| M1 | 权威业务记忆 | MySQL | 永久(只增不改的审计表) | 不可接受丢失 |
| M2 | 知识库记忆 | Milvus + 本地 data/kb/ |
随文档版本更新 | 重新切片、embedding 导入 |
| M3 | 关系记忆 | Neo4j | 随 Core 同步刷新 | 从 Core 重跑同步 Job |
| M4 | 官方事实 | Core(只读) | 业务系统权威 | Agent 不建第二套账 |
另外还有 L0~L3 用户画像(见 §4):L0 在 Core,L1/L2/L3 在 MySQL(Redis 只做热缓存)。
3. 什么叫「短期记忆」?
3.1 定义
短期记忆 = 当前会话进行中、为了少查库、少重复推理而放在 Redis 里的数据。
特征:
- 有 TTL(过期自动删)
- 可重建(源数据在 MySQL 或 Core)
- 不参与合规最终认定(例如不能以 Redis 里的草稿代替 audit_log)
- 不跨 Agent 长期共享(跨 Agent 共享走 MySQL 画像表)
3.2 典型短期记忆(P0 全部在 Redis)
| 业务场景 | Redis Key(示例) | 存什么 | TTL | 为何是短期 |
|---|---|---|---|---|
| 多轮对话上下文 | sess:{agent}:{session_id}:ctx |
当前意图、槽位、上一轮 Tool 摘要 | 2h | 关页/超时后不需要;完整消息在 MySQL |
| 最近聊天窗口 | sess:{agent}:{session_id}:msgs |
最近 ≤20 轮 JSON | 2h | 滑动窗口;全量在 agent_message |
| 会话并发锁 | sess:{agent}:{session_id}:lock |
防双写 | 30s | 纯技术锁 |
| 画像热缓存 | profile:l1/l2/l3:{...} |
MySQL 画像 JSON 副本 | 5~10m | 加速读;权威在 MySQL |
| 代理人资产快照缓存 | cache:advisor:snapshot:... |
A-01 查 Core 后的摘要 | 15m | 权威副本在 L2 asset_snapshot |
| 风控预警推送 | risk:pub:alert |
Pub/Sub 通知 | — | 实时通道;单据在 risk_alert |
| 预警去重 | risk:dedup:... |
同日同规则是否已报 | 24h | 防风暴;不是业务台账 |
| 限流/封禁 | guard:rate / guard:block |
计数、临时封禁 | 1m~15m | 安全控制 |
| Token 吊销 | auth:revoked:{jti} |
JWT 黑名单 | 至 exp | 鉴权辅助 |
3.3 短期记忆的读写规则
写:对话每条消息 → 先/并行写 MySQL agent_message → 再更新 Redis 窗口
读:优先 Redis 窗口拼上下文 → 不够再读 MySQL 最近 N 条
删:TTL 到期自动删;画像 MySQL UPDATE 后主动 DEL 对应 profile:* Key
禁止放进 Redis 的(必须 MySQL):
- 审计总账
audit_log - 预警单最终状态
risk_alert.status - 草稿审核结果
advisor_draft.review_status - 分析 SQL 留痕
analytics_query_log - 适当性阻断记录
risk_suitability_log
4. 用户画像:L0~L3 存哪儿?
| 层级 | 业务含义 | 权威存储 | Redis 缓存 | 谁写 |
|---|---|---|---|---|
| L0 | 正式 C1~C5、KYC(性别/学历/收入/资产)、问卷得分、风评过期 | Core 只读(jinrong_core) |
一般不缓存(或极短 TTL) | 非 Agent |
| L1 | 客户偏好:风格、规划、阈值摘要、行为标签 | MySQL customer_profile_l1 |
profile:l1:{customer_id} |
客户 Agent |
| L2 | 服务侧:诉求、待办、资产概况快照、服务标签 | MySQL customer_profile_l2 |
profile:l2:{customer_id}:{advisor_id} |
代理人 Agent |
| L3 | 监测侧:正常/关注/高风险、评分维度 | MySQL customer_profile_l3 |
profile:l3:{customer_id} |
风控 Agent |
记忆管理要点:
- L1/L2/L3 以 MySQL 为权威;Redis 只是「刚查过」的副本。
- 禁止用 L1 客户口头偏好 覆盖 L0 正式风险等级。
- 客户 不可见 L2/L3(API 层 404,不是 Redis 里藏一下就行)。
R-02 适当性(记忆分工):
计算(L0 + 产品 + C×R 矩阵)→ CoreReadOnlyRepository.check_suitability() 【jinrong_core】
记账(审计 + 客户/代理人可读)→ risk_suitability_log 【jinrong_agent】
映射 → app/model/suitability.py · 契约 → 表设计/07-risk_suitability_log说明.md
JSON 字段约定: 06-用户画像L1-L3设计.md
5. MySQL:权威业务记忆放什么?
MySQL = 正式档案柜。凡是 要审计、要跨 Agent 读、要留痕 的,都落 MySQL。
5.1 按业务类型对照表
| 业务类型 | 典型内容 | MySQL 表(P0) | 是否短期 |
|---|---|---|---|
| 会话归档 | 每句 user/assistant/tool | agent_session, agent_message, agent_tool_call |
长期 |
| 合规审计 | 谁问了什么、判定结果 | audit_log, input_guard_log |
长期,只 INSERT |
| 数据归属 | 客户归哪个代理人 | customer_advisor_rel |
长期(Core 同步) |
| 客户画像 L1 | 风格、规划、阈值偏好 | customer_profile_l1 |
长期 |
| 服务画像 L2 | 诉求、待办、快照 | customer_profile_l2 |
长期 |
| 监测画像 L3 | 分层、评分、标签 | customer_profile_l3 |
长期 |
| 风控预警 | 预警单、人工处置 | risk_alert |
长期 |
| 适当性 | 匹配/阻断记录 | risk_suitability_log |
长期 |
| 客户阈值 | C-04 自设亏损线 | customer_threshold_config |
长期 |
| 客户提醒 | 阈值/波动提醒发送记录 | customer_notify_log |
长期 |
| 代理人草稿 | 话术/跟进草稿 | advisor_draft |
长期 |
| 违规命中 | A-07 合规词库 | compliance_hit_log |
长期 |
| 分析留痕 | NL→SQL→解读 | analytics_query_log |
长期 |
5.2 MySQL 不存什么?
| 不存 | 改存 | 原因 |
|---|---|---|
| 产品手册全文块(大段 PDF 文本) | Milvus chunk + 本地 data/kb/ |
体积大、要语义检索 |
| 客户-产品-持仓 关系遍历 | Neo4j | 图遍历更高效 |
| 持仓/流水 权威金额 | Core 只读 API | 禁止 Agent 各算一套 |
| 当前对话「最近 5 轮」窗口 | Redis | 临时、TTL |
6. Milvus:知识库记忆放什么?
Milvus = 按意思找文档,不是存对话、不是存客户画像。
| 放什么 | Collection | 典型场景 |
|---|---|---|
| 基金产品手册、费率、申赎规则、风险说明 | kb_product_rules |
C-02, C-03, A-02 |
| 内部办事流程、办理条件 | kb_business_ops |
A-04 |
| (P1)合规话术规范模板 | kb_compliance_scripts |
A-03 |
每条向量记录应包含: chunk_text、embedding(1024 维 bge-m3)、source_doc_id、source_version、product_id 等(见 03-milvus-collections.md)。
本地文件: 原始 PDF/Word 在 data/kb/(不用 MinIO);Milvus 存切块与向量,MySQL 可选存文档版本索引(P1)。
不放 Milvus:
- 聊天记录、审计日志
- 客户 L1/L2/L3 画像 JSON
- 预警单、适当性结果
7. Neo4j:关系记忆放什么?
Neo4j = 关系网,回答「谁持有啥、产品要什么等级、归哪个代理人管」。
| 放什么 | 节点/关系 | 典型场景 |
|---|---|---|
| 客户、代理人、产品、风险等级、行业 | Customer, Advisor, Product, RiskGrade |
全 Agent 关系查询 |
| 客户归属代理人 | Customer -[:ASSIGNED_TO]-> Advisor |
F-01 归属(与 MySQL rel 表一致) |
| 客户正式风险等级 L0 | Customer -[:HAS_RISK_LEVEL]-> RiskGrade |
R-02 |
| 持仓关系(同步快照) | Customer -[:HOLDS]-> Product |
C-01, A-01, R-01 |
| 产品最低适配等级 | Product -[:REQUIRES_MIN_RISK]-> RiskGrade |
R-02 |
同步原则: 金额、as_of 来自 Core 同步 Job;Agent 写 L1/L2/L3 不进 Neo4j,避免双写。
不放 Neo4j:
- 会话、消息、审计
- 向量、RAG 文档
- 画像 JSON 字段
8. Core 与本地文件
| 存储 | 放什么 | Agent 权限 |
|---|---|---|
| Core | L0 正式档案、持仓、流水、交易、行情/净值 | 只读 |
本地 data/kb/ |
原始制度/产品 PDF、Word | 平台入库用;Agent 通过 Milvus 检索 |
本地 data/milvus.db |
Milvus Lite 文件 | 向量索引文件,非业务表 |
9. 决策流程:新数据放哪儿?
新产生一条数据
│
┌───────────────┼───────────────┐
▼ ▼ ▼
是否官方账事实? 是否多轮对话临时态? 是否文档/RAG?
│ │ │
是 是 是
│ │ │
▼ ▼ ▼
Core 只读 Redis(TTL) Milvus + data/kb/
不在 Agent 建表 + MySQL 消息归档 + source 溯源字段
│ │
否 否
│ │
└───────┬───────┘
▼
是否需要审计 / 跨 Agent 共享?
│
┌────────┴────────┐
是 否
▼ ▼
MySQL 是否关系遍历?
(选对 L1/L2/L3 │
或业务表) ┌─────┴─────┐
是 否
▼ ▼
Neo4j 重新评估
(Core 同步) 是否其实该进 MySQL
9.1 快速对照(常见误区)
| 误区 | 正确做法 |
|---|---|
| 聊天记录只放 Redis | Redis 窗口 + MySQL 全量归档 |
| 画像只放 Redis | MySQL 权威 + Redis 热缓存 |
| 产品规则塞 MySQL TEXT | Milvus 向量检索 + 溯源 ID |
| 持仓金额以 Neo4j 为准 | Core 为准;Neo4j 是同步快照 + 关系 |
| 预警状态放 Redis | MySQL risk_alert;Redis 只做 Pub/Sub 通知 |
| 四 Agent 共享记忆靠互相调 LLM | 统一 MySQL 画像/预警表 + RBAC |
10. 四 Agent × 记忆读写(摘要)
| Agent | 短期(Redis 写) | 权威(MySQL 写) | 只读 |
|---|---|---|---|
| 客户财富 | 会话窗口 | L1、阈值、提醒日志、会话消息 | Core、Milvus 产品库、L3 不可见 |
| 代理人助手 | 会话、快照缓存 | L2、草稿、合规命中 | L1/L3、Core、Milvus |
| 数据分析 | 会话窗口 | 分析 SQL 留痕 | 画像 L1/L2/L3、预警、Core |
| 风控监测 | dedup、Pub/Sub | L3、预警、适当性 | L0/L1/L2、Core、Neo4j |
详细矩阵见 05-多Agent共用底座清单.md §九。
11. 一致性与失效策略
| 场景 | 策略 |
|---|---|
| Redis 挂了 | 从 MySQL 拉最近消息续聊;画像直接读 MySQL;服务降级 |
| MySQL 与 Redis 画像不一致 | 以 MySQL 为准;修复后 DEL Redis Key |
| Milvus 与本地文件不一致 | 以 source_version 为准;A-09 知识库校验 |
| Neo4j 与 Core 不一致 | 以 Core 为准;重跑同步 Job |
| 文档更新 | 重新 parse → embed → 写 Milvus;旧 version 过滤不返回 |
12. 与代码模块的对应(app/)
| 模块 | 记忆职责 |
|---|---|
memory_service.py |
Redis 会话/画像缓存;MySQL 会话与画像落盘 |
rag_service.py |
Milvus 检索 + 溯源 |
agent_service.py |
编排上下文(读 Redis/MySQL);不写错层 |
milvus_tool.py |
Collection CRUD |
repository/core_ro.py |
Core 只读 + R-02 适当性计算 |
model/suitability.py |
check_suitability → risk_suitability_log 行映射 |
13. 验收检查(记忆管理)
- 任意一条对话可在 MySQL 按
trace_id还原,不仅靠 Redis - Redis TTL 过期后,续聊仍可从 MySQL 恢复最近上下文
- L1 更新后,
profile:l1:*被失效 - 产品回答带
source_doc_id,来自 Milvus 而非模型幻觉 - 持仓金额展示与 Core 一致;Neo4j 仅作关系辅助
- 审计表无 UPDATE/DELETE 业务路径
14. 关联文档
| 文档 | 内容 |
|---|---|
| 02-redis-keys.md | Redis Key 明细 |
| 01-mysql-共用底座.sql | 共用表 DDL |
| 02-mysql-agent专用.sql | 专用表 DDL |
| 03-milvus-collections.md | 向量 Collection |
| 04-neo4j-model.md | 图模型 |
| 数据交互矩阵.md | 跨 Agent 数据对象 |
| 06-用户画像L1-L3设计.md | 画像 JSON 约定 |
| 07-risk_suitability_log说明.md | R-02 落库契约 |
| FRAMEWORK.md | 项目框架快照 |
| FLOW.md | 端到端链路 |
附录:记忆类型 × 存储 × 示例一句
| 记忆类型 | 存储 | 示例 |
|---|---|---|
| 短期对话态 | Redis | 「这一轮用户在问 C-02 基金费率」 |
| 长期对话档案 | MySQL | 「2026-09-05 14:03 客户问了 XX 基金申赎规则」 |
| 客户偏好 | MySQL L1 + Redis 缓存 | 「风格偏价值;亏损 10% 要提醒」 |
| 服务记录 | MySQL L2 | 「客户近期关注赎回;待跟进电话」 |
| 监测标签 | MySQL L3 | 「监测分层:关注;最近有大额预警」 |
| 产品知识 | Milvus | 「某基金封闭期 18 个月(chunk + 出处)」 |
| 持有关系 | Neo4j | 「客户 A 持有产品 P1、P2」 |
| 真实持仓金额 | Core | 「截至 T 日市值 100 万」 |
| 合规审计 | MySQL | 「trace-xxx:代理人查客户 B 被拒绝,AUTH_403」 |