Files
group_xinghuo_jinrong/docs/业务记忆管理/业务记忆管理手册.md
zhanghongyu_0626 3fb0ceb334 Enhance suitability assessment and documentation
- 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.
2026-09-07 11:15:30 +08:00

321 lines
15 KiB
Markdown
Raw Permalink 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.
# 业务记忆管理手册
> 写给:产品、开发、测试、合规
> 目的:说清楚 **什么叫短期记忆、什么必须长期保存**,以及 **Redis / MySQL / Neo4j / Milvus / Core / 本地文件** 各自放什么
> 关联:[00-架构总览.md](../项目框架设计/表设计/00-架构总览.md) · [02-redis-keys.md](../项目框架设计/表设计/02-redis-keys.md) · [03-milvus-collections.md](../项目框架设计/表设计/03-milvus-collections.md) · [04-neo4j-model.md](../项目框架设计/表设计/04-neo4j-model.md) · [数据交互矩阵.md](../需求拆解/数据交互矩阵.md)
---
## 1. 一句话总览
```text
短期记忆 = 为了「这一轮对话跑得顺」的临时数据,丢了能重建,不做法务证据。
权威记忆 = 必须长期保存、能审计、跨 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 短期记忆的读写规则
```text
写:对话每条消息 → 先/并行写 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 适当性(记忆分工):**
```text
计算(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](../项目框架设计/表设计/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](../项目框架设计/表设计/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. 决策流程:新数据放哪儿?
```text
新产生一条数据
│
┌───────────────┼───────────────┐
▼ ▼ ▼
是否官方账事实? 是否多轮对话临时态? 是否文档/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](../项目框架设计/表设计/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](../项目框架设计/表设计/02-redis-keys.md) | Redis Key 明细 |
| [01-mysql-共用底座.sql](../项目框架设计/表设计/01-mysql-共用底座.sql) | 共用表 DDL |
| [02-mysql-agent专用.sql](../项目框架设计/表设计/02-mysql-agent专用.sql) | 专用表 DDL |
| [03-milvus-collections.md](../项目框架设计/表设计/03-milvus-collections.md) | 向量 Collection |
| [04-neo4j-model.md](../项目框架设计/表设计/04-neo4j-model.md) | 图模型 |
| [数据交互矩阵.md](../需求拆解/数据交互矩阵.md) | 跨 Agent 数据对象 |
| [06-用户画像L1-L3设计.md](../项目框架设计/表设计/06-用户画像L1-L3设计.md) | 画像 JSON 约定 |
| [07-risk_suitability_log说明.md](../项目框架设计/表设计/07-risk_suitability_log说明.md) | R-02 落库契约 |
| [FRAMEWORK.md](../memory/FRAMEWORK.md) | 项目框架快照 |
| [FLOW.md](../memory/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」 |