339 lines
14 KiB
Markdown
339 lines
14 KiB
Markdown
# 织忆系统修复工作记录
|
||
|
||
> 维护者:小唯 A06
|
||
> 创建:2026-05-30
|
||
> 最新更新:2026-06-02
|
||
|
||
## G7 E3 自优化闭环完成 (2026-06-02)
|
||
| 组件 | 状态 | 验证 |
|
||
|------|------|------|
|
||
| GetSkillCandidates (candidates) | ✅ | 返回 20 条候选(min_recall=5 过滤),Rust IPC lancedb_query |
|
||
| crystallize 端点 | ✅ | 返回 eta=0.5, status=probation, linked_entities, prompt_template |
|
||
| execute 端点 | ✅ | 基于 linked memories 返回 enriched_prompt(需先 crystallize 建立链接) |
|
||
| trial/feedback | ✅ | success trial 后 ETA=1.0→0.99,贝叶斯正常更新 |
|
||
| lancedb_query IPC | ✅ | Go 通过 Rust IPC 查 LanceDB,解决 candidates 永远为 0 的问题 |
|
||
| 空时间字符串处理 | ✅ | map[string]interface{} 反序列化,空字符串保持零值 |
|
||
| crystallize 路由路径 | ✅ | 去掉 "POST " 前缀,标准库 mux 正确识别 |
|
||
| commit | `b005916` | fix G7 E3: crystallize路由路径+GetSkillCandidates通过Rust IPC查LanceDB |
|
||
|
||
## E4.3 Bug Fix (2026-06-01)
|
||
| 问题 | 根因 | 修复 |
|
||
|------|------|------|
|
||
| ShouldForget 的 degree 参数始终为 0 | admin.go:73 用 `mem["namespace"]` 但 LanceDB 返回 map 里无此 key;且 namespace 值(如 hermes-main)不是实体 | 改为从 `mem["content"]` 提取实体(大写单词、中文实体、技术标记),取图谱最大度 |
|
||
| 涉及文件 | go/internal/api/routes/admin.go | 替换 namespace 读取为 extractTopEntityDegree() |
|
||
|
||
## 阶段状态
|
||
|
||
| 阶段 | 状态 | 备注 |
|
||
|------|------|------|
|
||
| G1: Recall 管线 | ✅ 完成 | MMR 修复 + E1 图谱扩展 + 搜索缓存 |
|
||
| └ E1: 图谱导航激活 | ✅ 完成 | ExpandFromResults 已接入 Recall Step 5,condition=len<5 时触发 |
|
||
| └ E2: 多 agent 命名空间激活 | ✅ 完成 | hermes→hermes-main, openclaw→openclaw-main,Rust sidecar namespace 过滤已验证 |
|
||
| └ E3: 增量 embedding | ✅ 完成 | Go Commit 时同步调用 BGE HTTP → vector 立即写入 LanceDB,recall 无需等待 batch |
|
||
| G2: 本地 BGE | ✅ 完成 | 8000 端口 bge-m3,延迟 110ms |
|
||
| G3: self-metrics | ✅ 完成 | deprecated_per_day=2, auto_resolve_rate=0(无冲突是正常状态)|
|
||
| G4: WebSocket | ✅ 完成 | prefetch.push + consolidation.done 推送正常 |
|
||
| G5: Eval 框架 | ✅ 完成 | eval/run + eval/generate(12条) + vprop 端点 |
|
||
| G6: 聚类+蒸馏深化 | ✅ 完成 | G6.1 DBSCAN + G6.2 LLM质量回溯 + G6.3 L2 Patterns + gap |
|
||
| G7: 遗忘 + 技能系统 | ✅ 完成 | E4.3: extractTopEntityDegree + ShouldForget graphDegree;G7 E3: 贝叶斯+crystallize+execute+feedback 完整闭环 |
|
||
| G8: 备份恢复 | ✅ 完成 | Backup ✅ 已有;新增 Restore + ListBackups,支持 systemctl 停启服务恢复 |
|
||
| G9: 缓存 + 持久化 | ✅ 完成 | SearchCache 改造为 L1(内存)+ L2(Redis)双级,TTL 3555s 验证通过 |
|
||
|
||
## G8+G9 实现细节 (2026-06-02)
|
||
|
||
### G8 Restore API
|
||
- `GET /api/v1/admin/backups` — 列出 `/home/muc/backups/memoryweave/` 下所有备份
|
||
- `POST /api/v1/admin/restore` — 从指定备份恢复:stop 服务 → 清理 lances → 解压 tar → 还原 sqlite → 重启服务
|
||
|
||
### G9 多级缓存
|
||
- L1: 进程内 SearchCache(LRU+TTL,1000 条,1h TTL)
|
||
- L2: Redis `zhiyi:cache:*`(TTL≈3600s,进程重启后不丢)
|
||
- Get: L1 miss → 查 L2 → 回填 L1
|
||
- Set: 写 L1 + 写 L2
|
||
- Invalidate: L1 + L2 同步失效
|
||
|
||
### 蒸馏队列端点修复 (2026-06-02)
|
||
- `GET /api/v1/distill/status` — 引擎状态(queue_len, batch_size, last_distill, daily_used)
|
||
- `GET /api/v1/distill/queue` — 队列内容(episode_id, content, category)
|
||
- `GET /api/v1/distill/quota` — 配额(remaining, used, limit, percent, status)
|
||
- Engine 新增 QueueLen/QueueItems/GetStatus/GetQuota 导出方法
|
||
|
||
## 提交记录
|
||
|
||
- `[本次提交]` — distill端点: /status /queue /quota;G8: Restore+ListBackups;G9: SearchCache 双级缓存
|
||
- `[前次提交]` — G8: Restore+ListBackups 端点;G9: SearchCache 双级缓存(内存+Redis L2)
|
||
|
||
- `b005916` — G7 E3: crystallize路由路径+GetSkillCandidates通过Rust IPC查LanceDB
|
||
- `243a206` — G7.3: skill execute + quality_score fix
|
||
- `43286dd` — G7.1+G7.2: skill persistence + crystallize API
|
||
- `cd0f898` — G6: eps=1.0 (23 clusters), col_vector() for FixedSizeListArray reading
|
||
- `cc615c5` — docs: consolidate fix work log (2026-05-31)
|
||
- `3b031ed` — G6完整提交: skill trial路由 + LLM API key传Rust sidecar + Authorization header + reasoning_content fallback
|
||
- `e8b3a9f` — E1 RuneCount bug fix
|
||
- `f4a2c71` — MMRSelect text-based diversity
|
||
- `4f1e8d2` — WSPrefetchAdapter wired to recall pipeline
|
||
- `a7b2c3d` — G5: eval framework + vprop endpoints
|
||
|
||
## 已修复的 bug
|
||
|
||
### E1 图谱扩展 len() 字节数 bug
|
||
- 文件:`go/internal/governance/graph_sqlite.go`
|
||
- `len(chinese)` → `utf8.RuneCountInString(chinese)`
|
||
- 提交: `e8b3a9f`
|
||
|
||
### G6.2 LLM 质量回溯修复(2026-05-31)
|
||
- **问题1**:API key 有 `sk-` 前缀 → 修正为 `0ExNiL...`(无前缀)
|
||
- **问题2**:MiniMax M2.7 是推理模型,响应在 `reasoning_content` 而非 `content` → 加 fallback
|
||
- **问题3**:Go client 不传 LLM API key → 从 `LLM_API_KEY` 环境变量读取
|
||
- **问题4**:Rust IPC handler 用空 CLI args → 改用 `req.llm_endpoint`
|
||
- **模型切换**:MiniMax M2.7 → Qwen3.5-122B(速度 2s,更稳定)
|
||
- 提交: `3b031ed`
|
||
|
||
### G6.1 Rust IPC 字段映射错误
|
||
- `clusters_found` → `clusters`(Rust IPC 返回字段名与 Go 期望不匹配)
|
||
- consolidation 用 `cluster_only` 绕过 LLM 超时(定时器路径)
|
||
|
||
### MMR 多样性去重失效
|
||
- 文件:`go/internal/storage/recall.go`
|
||
- Rust IPC 不返回 vector → 改用 `jaccardBigramSimilarity`
|
||
- 修正 MMR 公式
|
||
- 提交: `f4a2c71`
|
||
|
||
### WebSocket prefetch 未接入 recall 管线
|
||
- 文件:`go/internal/api/routes/ws_events.go` + `core.go`
|
||
- 新增 `WSPrefetchAdapter` 实现 `storage.PrefetchPusher` 接口
|
||
- 在 `NewAPI` 中通过 `SetPrefetchPusher` 注入
|
||
- 提交: `4f1e8d2`
|
||
|
||
### E1 图谱导航激活(2026-05-31)
|
||
- **现状**:E1 代码已全部实现并通过 `server.go:112` 接入 `RecallPipeline.SetGraphExpander(graphStore)`
|
||
- **触发条件**:`recall.go` Step 5 — 结果 < 5 条时调用 `ExpandFromResults` 扩展 1 跳图谱邻居
|
||
- **扩展流程**:实体提取 → BFS Navigate → 邻居去重 → 合并返回
|
||
- **清理内容**:移除 `ExpandFromResults` 中残留的 5 条 `fmt.Printf("[E1] ...")` debug 语句
|
||
- **下一步**:图谱节点命名规范(recall 结果实体 ↔ graph 节点名对齐)
|
||
|
||
### E2 多 agent 命名空间激活(2026-05-31)
|
||
- **现状**:代码早已实现,本次验证确认有效
|
||
- **Hermes**:`agent_id="hermes-a06"` → `namespace="hermes-main"`(Go `deriveNamespace`)
|
||
- **OpenClaw**:`agent_id="openclaw"`,`namespace="openclaw-main"`(zhiyi client 显式传递)
|
||
- **验证**:同一 query 在 hermes-main 和 default-main 返回不同 ID 的记忆,namespace 过滤生效
|
||
- **Rust sidecar**:`search()` 和 `scan_all()` 均有 `only_if("namespace = '{}'", ns)` 过滤
|
||
|
||
## 验证数据
|
||
|
||
- 搜索缓存: 首次 934ms → 二次 18ms ✅
|
||
- BGE 延迟: 110-145ms < 200ms ✅
|
||
- BGE 自相似度: 1.0 ≥ 0.99 ✅
|
||
- WebSocket prefetch: 第 2 次 recall 后触发 ✅
|
||
- WebSocket consolidation.done: 直接触发 ✅
|
||
- LLM 速度测试(Qwen3.5-122B): 2076ms ✅
|
||
- Consolidation full 路径: 3.7s(cluster_only,未触发 LLM 是设计预期)
|
||
- Recall 七维度: encode→ann→rerank→mmr 全链路 814ms ✅
|
||
- Self-optimization 自动调参: diversity/gap_threshold/distill_interval ✅
|
||
- Eval recall@5=1.0, MRR=1.0, nDCG=1.0 ✅
|
||
|
||
## 服务拓扑
|
||
|
||
### 进程与服务
|
||
|
||
| 服务 | 二进制路径 | 端口/Socket | systemd 服务 | 用途 |
|
||
|------|-----------|-------------|--------------|------|
|
||
| **zhiyid** | `~/.local/bin/zhiyid` | `7821`(HTTP) | `zhiyid.service` | Go HTTP API 主服务 |
|
||
| **zhiyi-sidecar** | `~/projects/memoryweave/rust/target/release/zhiyi-consolidate` | `/tmp/zhiyi-ipc.sock` | `zhiyi-sidecar.service` | Rust IPC Consolidation 处理器 |
|
||
| **BGE Embed Server** | `~/projects/memoryweave/rust/bge_embed_server.py` | `8000` | `bge-embed.service` | 本地向量嵌入服务 |
|
||
| **VLLM Gateway** | — | `3000` | — | LLM 推理网关(OneAPI) |
|
||
|
||
### 数据存储
|
||
|
||
| 存储 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| **LanceDB** | `/var/lib/memoryweave/` | 向量存储 + 记忆数据 |
|
||
| **SQLite** | `/var/lib/memoryweave/memoryweave.db` | 结构化关系数据 |
|
||
| **Graph DB** | `/var/lib/memoryweave/graph.db` | 知识图谱 |
|
||
| **IPC Socket** | `/tmp/zhiyi-ipc.sock` | Go → Rust 通信 |
|
||
|
||
### LLM 配置
|
||
|
||
| 参数 | 值 |
|
||
|------|-----|
|
||
| ENDPOINT | `http://127.0.0.1:3000/v1/chat/completions` |
|
||
| MODEL | `qwen/qwen3.5-122b-a10b` |
|
||
| API KEY | `0ExNiL...MWBP`(无 sk- 前缀) |
|
||
|
||
### BGE 配置
|
||
|
||
| 参数 | 值 |
|
||
|------|-----|
|
||
| ENDPOINT | `http://127.0.0.1:8000/v1/embeddings` |
|
||
| MODEL | `BAAI/bge-m3` |
|
||
| 向量维度 | 1024 |
|
||
|
||
## 部署命令
|
||
|
||
```bash
|
||
# Go 服务(用户级 systemd)
|
||
cd ~/projects/memoryweave/go
|
||
go build -o /tmp/zhiyid-test ./cmd/zhiyid/
|
||
systemctl --user stop zhiyid
|
||
cp /tmp/zhiyid-test ~/.local/bin/zhiyid
|
||
systemctl --user daemon-reload
|
||
systemctl --user restart zhiyid
|
||
|
||
# Rust sidecar(用户级 systemd)
|
||
cd ~/projects/memoryweave/rust
|
||
cargo build --release
|
||
systemctl --user stop zhiyi-sidecar
|
||
cp target/release/zhiyi-consolidate <原路径>
|
||
systemctl --user daemon-reload
|
||
systemctl --user restart zhiyi-sidecar
|
||
```
|
||
|
||
## API 端点
|
||
|
||
```
|
||
认证:X-API-Key: zhiyi-dev-key-2026
|
||
|
||
POST /api/v1/commit # 提交记忆
|
||
POST /api/v1/recall # 检索记忆
|
||
POST /api/v1/recall/debug # 检索七维度诊断
|
||
POST /api/v1/graph/navigate # 图谱导航
|
||
GET /api/v1/stats # 统计信息
|
||
GET /api/v1/metrics/self # 自优化指标
|
||
POST /api/v1/admin/consolidate # 触发深度整合
|
||
POST /api/v1/admin/dedup # 去重
|
||
POST /api/v1/eval/run # 评估
|
||
POST /api/v1/tuning/run # 自动调参
|
||
GET /api/v1/health # 健康检查
|
||
WS /api/v1/ws # WebSocket 实时推送
|
||
|
||
外部:
|
||
POST http://localhost:8000/v1/embeddings # BGE 向量化
|
||
POST http://localhost:3000/v1/chat/completions # LLM 调用
|
||
```
|
||
|
||
## 关键文件
|
||
|
||
```
|
||
~/projects/memoryweave/
|
||
├── WORKLOG.md # 本文件
|
||
├── REPAIR-FULL.md # 修复计划总表
|
||
├── go/
|
||
│ ├── cmd/zhiyid/main.go
|
||
│ ├── internal/
|
||
│ │ ├── api/routes/
|
||
│ │ │ ├── core.go # NewAPI(含 SetPrefetchPusher 接入)
|
||
│ │ │ └── ws_events.go # WSPrefetchAdapter
|
||
│ │ ├── governance/graph_sqlite.go # E1 bug 修复
|
||
│ │ └── storage/
|
||
│ │ └── recall.go # MMR bigram 修复
|
||
```
|
||
|
||
## 下一步
|
||
|
||
- **E4**:图谱推理(图谱真正参与推理:矛盾检测、跨 agent 共享、遗忘决策参考图谱结构)
|
||
- **G7**:遗忘 + 技能系统(forgetter + agent skills)
|
||
---
|
||
|
||
## 2026-05-31 紧急修复:consolidate 服务路径冲突
|
||
|
||
### 问题
|
||
|
||
监控报告 `lancedb` 目录为空,实际数据在 `/var/lib/memoryweave/memories.lance/`(1386 条)。
|
||
|
||
### 根因
|
||
|
||
**两个问题叠加:**
|
||
|
||
1. **系统级 service 文件路径错误**:`/etc/systemd/system/zhiyi-consolidate.service` 指向:
|
||
- binary: `/usr/local/bin/zhiyi-consolidate`(旧 binary,5月29日)
|
||
- data-dir: `/var/lib/memoryweave/lancedb`(空目录)
|
||
|
||
2. **多进程冲突**:同时存在 3 个 consolidate 进程,路径各异
|
||
|
||
### 修复
|
||
|
||
```bash
|
||
# 1. 修复系统 service 文件
|
||
cat > /etc/systemd/system/zhiyi-consolidate.service << 'SERVICE'
|
||
[Unit]
|
||
Description=ZhiYi Consolidation Engine (Rust LanceDB)
|
||
After=network.target
|
||
|
||
[Service]
|
||
Type=simple
|
||
User=muc
|
||
ExecStart=/home/muc/projects/memoryweave/rust/target/release/zhiyi-consolidate --socket /tmp/zhiyi-ipc.sock --data-dir /var/lib/memoryweave
|
||
Restart=always
|
||
RestartSec=5
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
SERVICE
|
||
|
||
# 2. 重载并重启
|
||
sudo -S -p '' systemctl daemon-reload
|
||
sudo -S -p '' systemctl restart zhiyi-consolidate
|
||
```
|
||
|
||
### 验证
|
||
|
||
```
|
||
$ curl -s -H "X-API-Key: zhiyi-dev-key-2026" "http://127.0.0.1:7821/api/v1/stats"
|
||
{"backend":"lancedb (Rust IPC)","data_dir":"/var/lib/memoryweave","tombstone_count":0,"total_episodes":1,"total_memories":1388}
|
||
```
|
||
|
||
**数据完好,1388 条 memories。**
|
||
|
||
### 经验教训
|
||
|
||
- 部署 binary 时**必须同步更新 systemd service 文件**,不能只替换 binary
|
||
- 两个 service 文件需保持同步:`~/.config/systemd/user/zhiyi-consolidate.service` 和 `/etc/systemd/system/zhiyi-consolidate.service`
|
||
- 监控系统检查的路径必须和实际运行的进程路径一致
|
||
|
||
|
||
---
|
||
|
||
## E5.1 Obsidian 插件(2026-06-02)
|
||
|
||
### 实现内容
|
||
|
||
**CORS 中间件**
|
||
- `go/internal/api/middleware/cors.go`: 新增 `CORS()` 函数,支持 `app://obsidian.md` origin
|
||
- `go/internal/api/server.go`: `return middleware.CORS()(middleware.Auth(mux))`
|
||
- 验证: `curl -I -X OPTIONS http://localhost:7821/api/v1/stats -H "Origin: app://obsidian.md"` → 204 + CORS headers ✅
|
||
|
||
**Obsidian 插件 (`plugins/obsidian/`)**
|
||
- `manifest.json`: id=`zhiyi-memory`, name=`织忆`, minAppVersion=`0.15.0`
|
||
- `main.ts`: 注册 ZhiYiPlugin,3 个命令(记忆面板/图谱面板/搜索)+ 设置页
|
||
- `src/api.ts`: fetch 封装,调用 Go API `/api/v1/*` 全部端点,API Key = `zhiy...`(截断)
|
||
- `src/MemoryView.ts`: 侧边栏记忆列表,分页(每页20条),蒸馏队列警告
|
||
- `src/GraphView.ts`: D3.js force-directed graph,ego-network 探索,节点拖拽/缩放
|
||
- `src/SearchModal.ts`: 语义搜索模态框,debounce 300ms,Enter 选择第一条
|
||
- `styles.css`: 全局样式,蒸馏警告高亮
|
||
- `esbuild.config.mjs`: 构建 main.ts → main.js(minified)
|
||
- 构建产物: `main.js` 22KB(已安装至 `~/.obsidian/plugins/zhiyi-memory/`)
|
||
- `README.md`: 安装/使用文档
|
||
|
||
**Makefile 新增目标**
|
||
```makefile
|
||
build-obsidian: cd plugins/obsidian && node esbuild.config.mjs
|
||
install-obsidian: build-obsidian + cp to ~/.obsidian/plugins/zhiyi-memory/
|
||
```
|
||
|
||
**npm 修复**
|
||
- `~/.local/bin/npm` 脚本指向错误路径 `/home/muc/.local/lib/node_modules/npm/bin/npm-cli.js`
|
||
- 实际路径: `/home/muc/.local/lib/npm/bin/npm-cli.js`
|
||
- 修复: `patch` 脚本中的路径后,npm --version 正常(10.9.7)
|
||
|
||
### 验收标准 ✅
|
||
- [x] CORS headers: `Access-Control-Allow-Origin: app://obsidian.md` ✅
|
||
- [x] `make build-obsidian` → main.js 22KB ✅
|
||
- [x] `make install-obsidian` → 文件复制到 `~/.obsidian/plugins/zhiyi-memory/` ✅
|
||
- [x] Go API 1617 记忆正常 ✅
|
||
|
||
### git commit
|
||
```
|
||
E5.1 Obsidian 插件: CORS中间件 + 记忆面板 + 图谱视图 + 搜索模态框
|
||
abef38c
|
||
```
|