Files
zclaw_openfang/wiki/memory.md
iven 14f2f497b6
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
docs(wiki): 记录跨会话记忆链路 + 管家Tab记忆展示架构
- memory.md: 添加"跨会话记忆完整链路"章节,覆盖初始化/写入/读取/展示/数据库架构/关键文件地图
- butler.md: 添加"管家Tab记忆展示"章节,记录MemorySection数据源和组件结构
2026-04-22 19:13:08 +08:00

414 lines
19 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, growth]
---
# 记忆管道 (Memory Pipeline)
> 从 [[index]] 导航。关联模块: [[chat]] [[middleware]]
## 设计思想
**核心问题: LLM 无状态,每次对话都从零开始。需要从历史对话中积累知识。**
设计决策:
1. **闭环架构** — 对话 → 提取 → 索引 → 检索 → 注入,形成正向循环
2. **FTS5 + TF-IDF** — 轻量级语义搜索,不依赖外部 embedding 服务
3. **Token 预算控制** — 注入 system prompt 时有 token 上限,防止溢出
4. **EmbeddingClient trait 已预留** — 接口已写,激活即可升级到向量搜索
## 功能清单
| 功能 | 描述 | 入口文件 | 状态 |
|------|------|----------|------|
| 记忆提取 | LLM 从对话中提取偏好/知识/经验 | extractor.rs | ✅ |
| FTS5 全文检索 | SQLite FTS5 + TF-IDF 权重搜索 | storage/sqlite.rs | ✅ |
| 语义检索 | 意图分类 + CJK 关键词 + 混合评分 | retriever.rs, retrieval/query.rs | ✅ |
| Prompt 注入 | token 预算控制 + 结构化上下文注入 | injector.rs | ✅ |
| 经验管理 | pain→solution→outcome CRUD | experience_store.rs | ✅ |
| 用户画像 | 结构化偏好/兴趣/能力管理 | profile_updater.rs | ✅ |
| 进化引擎 | 行为模式检测 → 技能/工作流建议 | evolution_engine.rs | ✅ |
| 质量门控 | 长度/标题/置信度/去重校验 | quality_gate.rs | ✅ |
| 自动技能生成 | 从模式生成 SkillManifest | skill_generator.rs | ✅ |
| 上下文压缩 | 超长对话压缩摘要 | summarizer.rs | ✅ |
| 嵌入向量 | EmbeddingClient trait + NoOp 默认 | retrieval/semantic.rs | 🚧 接口就绪 |
| SaaS pgvector | knowledge_chunks 向量索引 | saas/generate_embedding.rs | 🚧 索引就绪,生成未实现 |
## 代码逻辑
### 闭环数据流
```
[提取] 对话发生
→ MemoryExtractor (crates/zclaw-growth/src/extractor.rs)
→ LLM 提取: 偏好 (Preference) / 知识 (Knowledge) / 经验 (Experience)
→ MemoryEntry { agent_id, memory_type, content, keywords, importance }
[索引] 存储
→ SqliteStorage.store() (crates/zclaw-growth/src/storage/sqlite.rs)
→ SQLite + FTS5 全文索引
→ TF-IDF 权重计算
→ (可选) EmbeddingClient.embed() → 向量存储 [未激活]
[检索] 查询时
→ MemoryRetriever.retrieve(query, agent_id) (crates/zclaw-growth/src/retriever.rs)
→ QueryAnalyzer: 意图分类 (Preference/Knowledge/Experience/Code/General)
→ 中文+英文关键词提取 + CJK 支持 + 同义词扩展
→ SemanticScorer: TF-IDF 匹配 (70% embedding / 30% TF-IDF, embedding 未激活)
→ 返回 top-k 相关记忆
[注入] 给 LLM
→ PromptInjector.inject(system_prompt, memories) (crates/zclaw-growth/src/injector.rs)
→ token 预算控制
→ 格式化为结构化上下文块
→ 插入到 system prompt 中
```
### 跨会话记忆完整链路2026-04-22 验证通过)
> **重要:修改任何环节前请先阅读此链路,避免引入断裂。**
```
[初始化] kernel_init (desktop/src-tauri/src/kernel_commands/lifecycle.rs)
① viking_commands::init_storage() → 初始化 SqliteStorage → memories.db
② Kernel::boot(config) → 创建 MemoryStore (data.db) + in-memory VikingAdapter
③ viking_commands::get_storage() → SqliteStorage 包装为 VikingAdapter → kernel.set_viking()
↑ 此时 GrowthIntegration 缓存被清除
④ TauriExtractionDriver::new(driver, model) → kernel.set_extraction_driver()
↑ GrowthIntegration 缓存再次清除
⑤ [首次聊天时] create_middleware_chain() 重建 GrowthIntegration:
- GrowthIntegration::new(self.viking.clone()) ← 持久化 SqliteStorage
- .with_llm_driver(extraction_driver) ← LLM 提取能力
- .with_profile_store(UserProfileStore::new(memory.pool())) ← data.db 画像持久化
- .configure_embedding(embedding_client) ← 语义检索(可选)
→ 缓存到 kernel.growth (Mutex<Arc<GrowthIntegration>>)
→ MemoryMiddleware::new(growth) 注册到中间件链 (priority=150)
[写入] after_completion — 记忆提取 (crates/zclaw-runtime/src/middleware/memory.rs)
MemoryMiddleware.after_completion(ctx)
→ 30秒去重: should_extract(agent_id) — 同一 agent 30秒内跳过
→ growth.extract_combined(agent_id, messages, session_id)
→ MemoryExtractor.extract_combined() (crates/zclaw-growth/src/extractor.rs)
→ LLM 单次调用 (COMBINED_EXTRACTION_PROMPT + 对话文本)
→ 返回 CombinedExtraction { memories, experiences, profile_signals }
→ extractor.store_memories(agent_id, memories)
→ VikingAdapter → SqliteStorage.store() → memories.db (FTS5 索引)
→ experience_extractor.persist_experiences(agent_id, combined)
→ agent://{agent_id}/experience/... URI
→ profile_updater.collect_updates(combined)
→ UserProfileStore.update_field/add_recent_topic/add_pain_point/add_preferred_tool
→ 写入 data.db.user_profiles 表 (user_id = agent_id)
[读取] before_completion — 记忆检索+注入 (每个新请求)
MemoryMiddleware.before_completion(ctx)
→ growth.enhance_prompt(agent_id, system_prompt, user_input)
→ retriever.retrieve(agent_id, user_input)
→ 按 agent_id 构建搜索范围: agent://{agent_id}/{type}
→ QueryAnalyzer 意图分析 + IdentityRecall 43+ 模式匹配
→ FTS5 全文搜索 + TF-IDF 评分 + 语义重排序
→ 弱身份 fallback: <3 结果 + weak_identity → 补充 broad retrieval
→ injector.inject_with_format(system_prompt, memories)
→ 按 token 预算注入结构化上下文
[展示] 管家Tab — 前端读取 (desktop/src/components/ButlerPanel/)
MemorySection.tsx:
→ listVikingResources("agent://{agent_id}/") → viking_ls → memories.db
→ readVikingResource(uri, "L1") → viking_read → L1 摘要
→ 按类型分组: 偏好/知识/经验/会话
→ agent_get(agentId) → kernel.memory() → UserProfileStore.get() → data.db
→ 用户画像卡片: 行业/角色/沟通风格/近期话题/常用工具
[数据库架构]
memories.db (SqliteStorage, viking_commands 管理)
→ memories 表: URI + memory_type + content + FTS5 索引
→ memories_fts 虚拟表: FTS5 trigram tokenizer (CJK 支持)
data.db (MemoryStore, kernel 管理)
→ user_profiles 表: user_id + industry + role + recent_topics(JSON) + ...
→ agents 表: agent 配置
→ sessions 表: 会话数据
[关键文件地图]
crates/zclaw-kernel/src/kernel/mod.rs create_middleware_chain() + memory()
crates/zclaw-runtime/src/middleware/memory.rs MemoryMiddleware before/after
crates/zclaw-runtime/src/growth.rs GrowthIntegration 闭环编排
crates/zclaw-growth/src/extractor.rs extract_combined() LLM 提取
crates/zclaw-growth/src/retriever.rs retrieve() FTS5+TF-IDF 检索
crates/zclaw-growth/src/injector.rs inject_with_format() prompt 注入
crates/zclaw-growth/src/storage/sqlite.rs SqliteStorage (memories.db)
crates/zclaw-memory/src/user_profile_store.rs UserProfileStore (data.db)
desktop/src-tauri/src/viking_commands.rs viking_ls/viking_read Tauri 命令
desktop/src-tauri/src/kernel_commands/agent.rs agent_get (读取 UserProfile)
desktop/src-tauri/src/kernel_commands/lifecycle.rs kernel_init (初始化链路)
desktop/src/components/ButlerPanel/MemorySection.tsx 前端展示
```
### 经验存储 (ExperienceStore)
Hermes 管线 Chunk1 新增:
```
ExperienceStore (crates/zclaw-growth/src/experience_store.rs)
→ CRUD 封装: pain → solution → outcome 结构化经验
→ 底层使用 VikingAdapter
→ URI scheme: agent://{agent_id}/experience/...
```
### Hermes 管线 (4 Chunk)
| Chunk | 模块 | 文件 | 测试 |
|-------|------|------|------|
| 1 | ExperienceStore + Extractor | experience_store.rs | 10 |
| 2 | UserProfileStore + Profiler | user_profile.rs | 14 |
| 3 | NlScheduleParser | nl_schedule.rs | 16 |
| 4 | TrajectoryRecorder + Compressor | middleware/trajectory_recorder.rs | 18 |
Hermes 相关测试分布:
- `nl_schedule.rs`: 16 tests (中文时间→cron 解析)
- `types.rs`: 9 tests (记忆类型)
- `injector.rs`: 9 tests (prompt 注入)
### 查询意图分类
`QueryAnalyzer` 支持 5 种意图:
| 意图 | 说明 | 检索策略 |
|------|------|----------|
| Preference | 用户偏好 | 精确匹配 preference 类型记忆 |
| Knowledge | 知识查询 | 语义搜索 knowledge 类型 |
| Experience | 经验检索 | 时间+相关性排序 |
| Code | 代码相关 | 关键词优先 |
| General | 通用 | 混合策略 |
### Embedding 基础设施 (已写未激活)
```
EmbeddingClient trait (crates/zclaw-growth/src/retrieval/semantic.rs)
→ async embed(&str) -> Vec<f32>
→ is_available() -> bool
→ 当前实现: NoOpEmbeddingClient (始终返回空)
SaaS 侧:
→ pgvector HNSW 索引就绪 (knowledge_chunks 表, vector(1536))
→ generate_embedding Worker: 内容分块 + 中文关键词提取 (Phase 2 embedding deferred)
```
### 进化引擎 (EvolutionEngine)
zclaw-growth 包含完整的自我改进闭环:
```
EvolutionEngine (crates/zclaw-growth/src/evolution_engine.rs)
→ 从对话历史中检测行为模式变化
→ 生成进化候选项 (新技能建议/工作流优化)
→ EvolutionMiddleware@78 注入 system prompt
配套组件:
→ FeedbackCollector — 收集用户反馈信号
→ PatternAggregator — 行为模式聚合
→ QualityGate — 进化质量门控
→ SkillGenerator — 自动技能生成
→ WorkflowComposer — 工作流自动编排
→ ProfileUpdater — 用户画像更新
→ ExperienceExtractor — 经验提取器
→ Summarizer — 记忆摘要
```
zclaw-growth 模块结构 (19 文件):
```
crates/zclaw-growth/src/
├── evolution_engine.rs 进化引擎核心
├── experience_extractor.rs 经验提取
├── experience_store.rs 经验 CRUD
├── extractor.rs 记忆提取
├── feedback_collector.rs 反馈收集
├── injector.rs Prompt 注入
├── json_utils.rs JSON 工具
├── pattern_aggregator.rs 模式聚合
├── profile_updater.rs 画像更新
├── quality_gate.rs 质量门控
├── retriever.rs 语义检索
├── skill_generator.rs 技能生成
├── summarizer.rs 摘要生成
├── tracker.rs 追踪器
├── types.rs 类型定义
├── viking_adapter.rs Viking 适配器
├── workflow_composer.rs 工作流编排
├── retrieval/ 检索子模块
│ ├── query.rs 意图分类 + CJK
│ └── semantic.rs EmbeddingClient
└── storage/ 存储子模块
└── sqlite.rs FTS5 + TF-IDF
```
### 前端 Tauri 命令
> 完整 API 接口详情见下方 `## API 接口` 章节。
**Memory CRUD** (`desktop/src-tauri/src/memory_commands.rs`, 11 命令):
| 命令 | 参数 | 说明 |
|------|------|------|
| `memory_store` | MemoryEntryInput | 存储记忆条目 |
| `memory_get` | id | 按 ID 获取 |
| `memory_search` | MemorySearchOptions | FTS5 + TF-IDF 搜索 |
| `memory_delete` | id | 删除单条 |
| `memory_delete_all` | agent_id | 删除 Agent 全部记忆 |
| `memory_stats` | — | 记忆统计 |
| `memory_export` | — | 导出全部 |
| `memory_import` | Vec\<PersistentMemory\> | 批量导入 |
| `memory_build_context` | agent_id, query, max_tokens? | 构建检索增强上下文 |
| `memory_db_path` | — | SQLite 路径 |
| `memory_init` | — | 初始化 (no-op, Viking 自动初始化) |
**VikingStorage** (`desktop/src-tauri/src/viking_commands.rs`, 14 命令):
| 命令 | 说明 |
|------|------|
| `viking_add` / `viking_add_with_metadata` | 添加记忆 (URI scheme: agent://{id}/{type}/{category}) |
| `viking_find` | 语义/关键词搜索 |
| `viking_grep` | 正则搜索 |
| `viking_ls` / `viking_tree` / `viking_read` | 浏览/读取 |
| `viking_remove` | 删除 |
| `viking_inject_prompt` | 记忆注入 prompt |
| `viking_configure_embedding` | 配置 embedding provider |
| `viking_configure_summary_driver` | 配置摘要 LLM |
| `viking_store_with_summaries` | 自动摘要存储 |
| `viking_status` | 存储健康检查 |
| `viking_load_industry_keywords` | 加载行业关键词 |
**Intelligence** (`desktop/src-tauri/src/intelligence/`, ~40 命令):
| 模块 | 命令数 | 功能 |
|------|--------|------|
| identity.rs | 13 | Agent 身份/SOUL.md 管理 |
| heartbeat.rs | 11 | Heartbeat 引擎配置+记录 |
| pain_aggregator.rs | 5 | 痛点追踪+方案生成 |
| reflection.rs | 6 | 自我反思引擎 |
| compactor.rs | 4 | 上下文压缩 |
| health_snapshot.rs | 1 | 综合健康快照 |
**记忆提取** (`desktop/src-tauri/src/memory/`, 3 命令):
`extract_session_memories`, `extract_and_store_memories`, `estimate_content_tokens`
**Embedding** (`desktop/src-tauri/src/llm/`, 2 命令):
`embedding_create`, `embedding_providers`
**总计 ~74 个** memory/growth/intelligence 相关 Tauri 命令。
## API 接口
### Memory CRUD (`desktop/src-tauri/src/memory_commands.rs`, 11 命令)
| 命令 | 参数 | 说明 |
|------|------|------|
| `memory_store` | MemoryEntryInput | 存储记忆条目 |
| `memory_get` | id | 按 ID 获取 |
| `memory_search` | MemorySearchOptions | FTS5 + TF-IDF 搜索 |
| `memory_delete` | id | 删除单条 |
| `memory_delete_all` | agent_id | 删除 Agent 全部记忆 |
| `memory_stats` | — | 记忆统计 |
| `memory_export` | — | 导出全部 |
| `memory_import` | Vec\<PersistentMemory\> | 批量导入 |
| `memory_build_context` | agent_id, query, max_tokens? | 构建检索增强上下文 |
| `memory_db_path` | — | SQLite 路径 |
| `memory_init` | — | 初始化 (no-op) |
### VikingStorage (`desktop/src-tauri/src/viking_commands.rs`, 14 命令)
| 命令 | 说明 |
|------|------|
| `viking_add` / `viking_add_with_metadata` | 添加记忆 (URI: agent://{id}/{type}/{category}) |
| `viking_find` | 语义/关键词搜索 |
| `viking_grep` | 正则搜索 |
| `viking_ls` / `viking_tree` / `viking_read` | 浏览/读取 |
| `viking_remove` | 删除 |
| `viking_inject_prompt` | 记忆注入 prompt |
| `viking_configure_embedding` | 配置 embedding provider |
| `viking_configure_summary_driver` | 配置摘要 LLM |
| `viking_store_with_summaries` | 自动摘要存储 |
| `viking_status` / `viking_load_industry_keywords` | 健康检查/行业关键词 |
### Intelligence (`desktop/src-tauri/src/intelligence/`, ~40 命令)
| 模块 | 命令数 | 功能 |
|------|--------|------|
| identity.rs | 13 | Agent 身份/SOUL.md 管理 |
| heartbeat.rs | 11 | Heartbeat 引擎配置+记录 |
| pain_aggregator.rs | 5 | 痛点追踪+方案生成 |
| reflection.rs | 6 | 自我反思引擎 |
| compactor.rs | 4 | 上下文压缩 |
| health_snapshot.rs | 1 | 综合健康快照 |
### 记忆提取 + Embedding (5 命令)
`extract_session_memories`, `extract_and_store_memories`, `estimate_content_tokens` (memory/)
+ `embedding_create`, `embedding_providers` (llm/)
**总计 ~74 个** memory/growth/intelligence 相关 Tauri 命令。
## 测试链路
| 功能 | Crate | 测试文件 | 测试数 | 覆盖状态 |
|------|-------|---------|--------|---------|
| 记忆存储/检索 | zclaw-growth | storage/sqlite.rs | 6 | ✅ |
| 经验 CRUD | zclaw-growth | experience_store.rs | 12 | ✅ |
| 提取器 | zclaw-growth | extractor.rs | 8 | ✅ |
| 注入器 | zclaw-growth | injector.rs | 9 | ✅ |
| 质量门控 | zclaw-growth | quality_gate.rs | 9 | ✅ |
| 进化引擎 | zclaw-growth | evolution_engine.rs | 5 | ✅ |
| 技能生成 | zclaw-growth | skill_generator.rs | 6 | ✅ |
| 工作流编排 | zclaw-growth | workflow_composer.rs | 5 | ✅ |
| 意图分类+CJK | zclaw-growth | retrieval/query.rs | 11 | ✅ |
| 语义评分 | zclaw-growth | retrieval/semantic.rs | 9 | ✅ |
| Embedding | zclaw-growth | retrieval/cache.rs | 7 | ✅ |
| 模式聚合 | zclaw-growth | pattern_aggregator.rs | 6 | ✅ |
| 反馈收集 | zclaw-growth | feedback_collector.rs | 10 | ✅ |
| 摘要 | zclaw-growth | summarizer.rs | 5 | ✅ |
| 类型定义 | zclaw-growth | types.rs | 13 | ✅ |
| 进化闭环 | zclaw-growth | tests/evolution_loop_test.rs | 6 | ✅ |
| 经验链 | zclaw-growth | tests/experience_chain_test.rs | 6 | ✅ |
| 集成 | zclaw-growth | tests/integration_test.rs | 9 | ✅ |
| **zclaw-growth 小计** | | 29 文件 | **181** | |
| 记忆存储 | zclaw-memory | store.rs | 20 | ✅ |
| 用户画像 | zclaw-memory | user_profile_store.rs | 20 | ✅ |
| 轨迹记录 | zclaw-memory | trajectory_store.rs | 9 | ✅ |
| 事实提取 | zclaw-memory | fact.rs | 5 | ✅ |
| **zclaw-memory 小计** | | 4 文件 | **54** | |
| **合计** | | 33 文件 | **235** | |
## 关联模块
- [[chat]] — 对话是记忆的输入源
- [[butler]] — 管家模式可能利用记忆提供个性化响应
- [[middleware]] — Memory 中间件自动提取 + SkillIndex 注入
## 关键文件
| 文件 | 职责 |
|------|------|
| `crates/zclaw-growth/src/extractor.rs` | LLM 记忆提取 |
| `crates/zclaw-growth/src/retriever.rs` | 语义检索 |
| `crates/zclaw-growth/src/injector.rs` | Prompt 注入 (token 预算) |
| `crates/zclaw-growth/src/experience_store.rs` | 经验 CRUD |
| `crates/zclaw-growth/src/storage/sqlite.rs` | FTS5 + TF-IDF 核心 |
| `crates/zclaw-growth/src/retrieval/semantic.rs` | EmbeddingClient trait |
| `crates/zclaw-growth/src/retrieval/query.rs` | 意图分类 + CJK 关键词 |
| `crates/zclaw-growth/src/nl_schedule.rs` | 中文时间→cron 解析 (16 tests) |
| `crates/zclaw-runtime/src/middleware/memory.rs` | 记忆中间件 |
| `crates/zclaw-runtime/src/middleware/trajectory_recorder.rs` | 轨迹记录中间件 |
| `desktop/src/store/memoryGraphStore.ts` | 前端记忆 UI |
| `desktop/src-tauri/src/memory/` | Tauri 记忆命令桥接 |
| `desktop/src-tauri/src/memory_commands.rs` | 13 个 memory CRUD 命令 |
## 已知问题
-**记忆去重失败** — BUG-H2 已修复 (commit a504a40)。`viking_add` 同 URI+content 重复添加
-**记忆非 Agent 隔离** — BUG-M3 已修复 (commit a504a40)。`viking_find` 返回所有 Agent 记忆
-**跨会话注入断裂** — BUG-M5 已修复 (commit a504a40)。新会话报 "no conversation history found"
-**profile_store 未连接** — 已修复 (commit adf0251)。create_middleware_chain() 中未设置 UserProfileStore导致 profile_signals 被静默丢弃
-**双数据库 UserProfile 不一致** — 已修复 (commit adf0251)。UserProfileStore 写入 data.db 而 agent_get 读取 memories.db
- ⚠️ **NoOpEmbeddingClient 是默认值** — 正常设计,用户配置 provider 后替换
- ⚠️ **SaaS pgvector embedding 生成未实现** — 索引就绪,生成逻辑 deferred