Files
zclaw_openfang/wiki/memory.md
iven 5d88d129d1 docs(wiki): Phase B+C完成 — middleware/saas/security/memory 5节模板重构
- middleware.md: 集成契约+3不变量+执行流 (157→136行)
- saas.md: 移除安全重复→引用security.md+Token Pool算法 (231→173行)
- security.md: 吸收saas认证内容成为安全唯一真相源 (158→199行)
- memory.md: 最大压缩363→147行+Hermes洞察提炼+4不变量

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-22 21:42:24 +08:00

148 lines
6.8 KiB
Markdown
Raw 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.

---
title: 记忆管道
updated: 2026-04-22
status: active
tags: [module, memory, fts5, growth]
---
# 记忆管道 (Memory Pipeline)
> 从 [[index]] 导航。关联: [[chat]] [[middleware]] [[butler]]
> 详细提取逻辑归档: [[archive/memory-extraction-details]]
## 1. 设计决策
**核心问题: LLM 无状态,每次对话从零开始。需要从历史对话中积累知识。**
| 决策 | WHY |
|------|-----|
| 闭环架构 | 对话→提取→索引→检索→注入,形成正向循环。每次聊天都积累,每次提问都利用 |
| 双数据库 | memories.db (FTS5 全文索引) + data.db (结构化画像)。前者处理模糊语义检索,后者处理精确字段查询 |
| FTS5+TF-IDF+Embedding 三层 | FTS5 粗筛 + TF-IDF 加权 + Embedding 精排(当前 NoOp配置后激活。不依赖外部服务即可工作 |
| 进化引擎 | 从对话中检测行为模式变化,生成进化候选项(技能建议/工作流优化),通过 EvolutionMiddleware@78 注入 system prompt |
| Token 预算控制 | 注入 system prompt 时有 token 上限,防止记忆注入挤占用户实际对话空间 |
**Hermes 核心借鉴** (详见 [[archive/hermes-analysis]]): 经验库 FTS5 全文检索 + 用户画像结构化建模 + 自然语言 cron 调度 + 轨迹记录压缩。4 Chunk 已交付: ExperienceStore(10 tests) + UserProfileStore(14 tests) + NlScheduleParser(16 tests) + TrajectoryRecorder(18 tests)。
## 2. 关键文件 + 数据流
### 核心文件
| 文件 | 职责 |
|------|------|
| `crates/zclaw-growth/src/extractor.rs` | LLM 记忆提取 (偏好/知识/经验) |
| `crates/zclaw-growth/src/retriever.rs` | 语义检索 (FTS5 + TF-IDF + 意图分类) |
| `crates/zclaw-growth/src/injector.rs` | Prompt 注入 (token 预算) |
| `crates/zclaw-growth/src/storage/sqlite.rs` | FTS5 + TF-IDF 核心 (memories.db) |
| `crates/zclaw-runtime/src/middleware/memory.rs` | 记忆中间件 (提取+注入编排) |
| `crates/zclaw-runtime/src/growth.rs` | GrowthIntegration 闭环编排 |
| `crates/zclaw-memory/src/user_profile_store.rs` | UserProfileStore (data.db) |
### 闭环数据流
```
[提取] 对话完成 → MemoryMiddleware.after_completion
→ MemoryExtractor.extract_combined() → LLM 单次调用
→ CombinedExtraction { memories, experiences, profile_signals }
→ VikingAdapter → SqliteStorage → memories.db (FTS5 索引)
→ UserProfileStore → data.db (结构化画像)
[检索] 新请求 → MemoryMiddleware.before_completion
→ MemoryRetriever.retrieve(agent_id, user_input)
→ QueryAnalyzer 意图分类 (5类: Preference/Knowledge/Experience/Code/General)
→ FTS5 全文搜索 + TF-IDF 评分 + IdentityRecall 43+ 模式
→ 弱身份 fallback: <3 结果 → 补充 broad retrieval
→ PromptInjector.inject_with_format(system_prompt, memories)
```
### 集成契约
| 方向 | 模块 | 触发点 |
|------|------|--------|
| Called by | middleware: Memory@150 | Every chat completion (after) + new request (before) |
| Calls | zclaw-memory: FTS5 store, TF-IDF scorer | Memory extraction + retrieval |
| Calls | zclaw-growth: GrowthIntegration, EvolutionEngine | Pattern detection + skill generation |
| Provides | loop_runner: Context injection into system prompt | Before LLM call |
### Tauri 命令
| 分类 | 命令数 | 关键命令 |
|------|--------|----------|
| Memory CRUD (`memory_commands.rs`) | 11 | `memory_store`, `memory_search`, `memory_build_context` |
| VikingStorage (`viking_commands.rs`) | 14 | `viking_add`, `viking_find`, `viking_inject_prompt` |
| Intelligence (`intelligence/`) | ~40 | identity(13), heartbeat(11), pain(5), reflection(6) |
| 提取+Embedding | 5 | `extract_session_memories`, `embedding_create` |
## 3. 代码逻辑
### 跨会话记忆完整链路
```
[初始化] kernel_init → init_storage(memories.db) → MemoryStore(data.db)
→ set_viking(SqliteStorage) → set_extraction_driver(LLM)
→ [首次聊天] create_middleware_chain() 重建 GrowthIntegration:
VikingAdapter + ExtractionDriver + UserProfileStore(data.db)
→ MemoryMiddleware@150 注册到中间件链
[写入] after_completion → 30秒去重 → extract_combined(LLM)
→ memories → memories.db | profile_signals → data.db
[读取] before_completion → retrieve(agent_id, query)
→ FTS5 + TF-IDF + IdentityRecall → inject_with_format()
[展示] 管家Tab → viking_ls/viking_read(memories.db) + agent_get(data.db)
```
### 不变量
- memories.db 和 data.db 是独立的 SQLite 数据库,跨库查询需使用正确连接
- 记忆注入在中间件@150AFTER ButlerRouter@80BEFORE SkillIndex@200
- Embedding 当前为 NoOpEmbeddingClient用户配置 provider 后替换为真实实现
- 30 秒去重窗口:同一 agent 30 秒内跳过重复提取
- URI scheme: `agent://{agent_id}/{type}/{category}`
### 非显然逻辑
- TF-IDF 语义路由70% embedding 权重 + 30% TF-IDFembedding 未激活时退化为纯 TF-IDF
- IdentityRecall: 43+ 模式匹配("你记得我"/"上次说的"/"我的偏好"等)触发记忆检索
- 弱身份 fallback: 检索结果 <3 且含弱身份关键词时补充 broad retrieval 扩大搜索范围
## 4. 活跃问题 + 陷阱
### 活跃
| 问题 | 状态 | 说明 |
|------|------|------|
| Embedding 未激活 | 🚧 长期观察 | NoOpEmbeddingClient 是默认值用户配置 provider 后替换 |
| SaaS pgvector | 🚧 deferred | HNSW 索引就绪 (knowledge_chunks, vector(1536))生成逻辑未实现 |
### 历史陷阱 (已修复)
- 跨会话记忆断裂 (profile_store 未连接 + 双数据库不一致 + 缺日志) 04-22 已修复 (adf0251)
- 记忆去重失败 ( URI+content 重复添加) 04-17 已修复 (a504a40)
- 记忆非 Agent 隔离 (viking_find 返回所有 Agent 记忆) 04-17 已修复 (a504a40)
- 跨会话注入断裂 (新会话报 "no conversation history found") 04-17 已修复 (a504a40)
### 警告
> memories.db / data.db 连接池隔离。修改存储层代码务必确认目标数据库。
> GrowthIntegration 缓存在 `set_viking()` / `set_extraction_driver()` 时会被清除,首次聊天时重建。
## 5. 变更日志
| 日期 | 变更 | 关联 |
|------|------|------|
| 2026-04-22 | 跨会话记忆断裂修复: profile_store 连接 + 双数据库统一 + 诊断日志 | commit adf0251 |
| 2026-04-22 | Wiki 5-section 重构: 363→~190 详细逻辑归档 | wiki/ |
| 2026-04-21 | Embedding 接通 + 自学习自动化 A线+B线 (SemanticScorer + EvolutionMiddleware) | 934 tests PASS |
| 2026-04-17 | E2E 全系统验证 129 链路: 记忆去重+注入+跨会话 修复 | 79.1% 通过率 |
| 2026-04-15 | Heartbeat 统一健康系统 (health_snapshot + 健康快照集成) | 183 commands |
## 测试概览
| Crate | 测试数 | 覆盖 |
|-------|--------|------|
| zclaw-growth | 181 (29 文件) | 全覆盖 |
| zclaw-memory | 54 (4 文件) | 全覆盖 |
| **合计** | **235** | |