18 KiB
织忆五步实施计划
创建时间:2026-05-30 状态:E1/E2/E3/E4 已完成,E5 规划完成,准备实施 禁止:偷懒、随意更改变动设计语言
总览
| 阶段 | 内容 | 优先级 | 预计工期 | 状态 |
|---|---|---|---|---|
| E1 | 图谱导航激活 | 🔴 高 | 1-2 天 | ✅ 完成 |
| E2 | 多 agent 命名空间激活 | 🔴 高 | 1 天 | ✅ 完成 |
| E3 | 增量 embedding | 🟡 中 | 1 天 | ✅ 完成 |
| E4 | 图谱推理 | 🟡 中 | 2-3 天 | ✅ 完成 |
| E5 | 产品 UI | 🔵 低 | 长期 | ⏳ |
E1:图谱导航激活
目标
改造 /recall 链路,向量搜索后接图谱 BFS 扩展,让搜索结果融合结构化知识。
现状
- 图谱数据:1269 节点 / 31248 边(
graph/stats确认) navigate.goBFS 导航代码已写好,但/recall没调用/recall当前纯语义搜索,不走图谱
实施步骤
E1.1 确认 navigate.go 接口
- 找到
navigate.go的函数签名和参数 - 确认 BFS 扩展是 1 跳还是 2 跳
- 确认输出格式(节点列表还是边列表)
E1.2 改造 recall 链路
修改 internal/api/routes/recall.go:
语义搜索 → 向量 top-K →
图谱 BFS 扩展(navigate 1跳邻居)→
合并去重 → bge-reranker 重排 →
返回最终结果
E1.3 测试验证
# 验证图谱有数据
curl http://localhost:7821/api/v1/graph/stats
# 验证 recall 走图谱(找有图谱关联的记忆)
curl "http://localhost:7821/api/v1/recall?query=织忆图谱导航&top_k=5"
# 对比:图谱激活前 vs 激活后的召回结果差异
# 激活后应该出现更多 1 跳邻居相关结果
验收标准
graph/statsnode_count > 1000(已有,确认不变)- recall 结果中包含图谱扩展内容(通过日志或响应标记确认)
- 延迟 < 500ms(可接受范围)
E2:多 agent 命名空间激活
目标
Hermes 和 OpenClaw 使用独立 namespace,数据物理隔离,互不串味。
现状(2026-05-31 验证)
- ✅ Hermes:
agent_id="hermes-a06"→namespace="hermes-main"(GoderiveNamespace自动推导) - ✅ OpenClaw:
agent_id="openclaw",namespace="openclaw-main"(zhiyi client 显式传递) - ✅ Rust sidecar:
search()/scan_all()均有only_if("namespace = '{}'", ns)namespace 过滤 - ✅ 验证:同一 query 在 hermes-main 和 default-main 返回不同 ID 的记忆,隔离生效
- ℹ️ 历史数据(
agent_id=default)在default-main,与 hermes-main/openclaw-main 物理隔离
实施步骤
E2.1 确认当前 namespace 配置(已验证)
- Hermes 插件:
agent_id="hermes-a06"硬编码于ZhiYiClient.commit/recall(~/.hermes/plugins/zhiyi/__init__.py) - OpenClaw 插件:
agent_id="openclaw",namespace="openclaw-main"硬编码于ZhiYiClient(/persistent/.../memory-zhiyi/src/client.ts)
E2.2 验收(2026-05-31 通过)
# Hermes recall → hermes-main
curl -X POST http://localhost:7821/api/v1/recall \
-H "X-API-Key: zhiyi-dev-key-2026" \
-d '{"query":"牧尘 小唯","top_k":3,"namespace":"hermes-main"}'
# → 返回 hermes-main 专属记忆
# OpenClaw recall → openclaw-main
curl -X POST http://localhost:7821/api/v1/recall \
-H "X-API-Key: zhiyi-dev-key-2026" \
-d '{"query":"牧尘 小唯","top_k":3,"namespace":"openclaw-main"}'
# → 返回 openclaw-main 专属记忆
验收标准
namespace=hermes-main查询不到namespace=openclaw-main的记忆namespace=openclaw-main查询不到namespace=hermes-main的记忆- Rust sidecar 在 commit/recall 时正确使用 namespace 过滤
E3:增量 embedding
目标
commit 时同步调用 vLLM embedding,不等 Rust sidecar batch,延迟从分钟级降到毫秒级。
现状(2026-05-31 验证)
- ✅ 已实现:Go
core.go:79在Commit()中调用a.Embedder.EncodeSingle(req.Content) - ✅ BGE HTTP:连接
localhost:8000/v1/embeddings,17ms/条,L2 归一化 - ✅ IPC 传输:Go 将 vector + 文本一起发往 Rust
lancedb_insert,Rust 直接存储(不重编码) - ✅ 验证:commit 后立即 recall 测试记忆排第一(score=0.843),无需等待 batch
- ℹ️ embedder.go 有
MOLIFANG_API_KEYfallback(当前未启用,环境无此 key)
实施步骤
E3.1 确认当前 embedding 流程(已验证)
- Go
core.go:79→a.Embedder.EncodeSingle(req.Content)→ BGE HTTP 8000 → 1024-dim vector - Go
core.go:123→Vector: vector写入models.MemoryRecord - Go
core.go:129→a.LanceDB.InsertMemory(mem)→ IPClancedb_insert发送到 Rust - Rust
lancedb_ops.rs:160-163→ 从 JSON 读取 vector,直接写入 LanceDB FixedSizeListArray
E3.2 验证结果(2026-05-31)
# commit 后立即 recall
curl -X POST http://localhost:7821/api/v1/commit \
-H "X-API-Key: zhiyi-dev-key-2026" \
-d '{"content":"E3增量embedding测试:验证commit时同步生成vector","namespace":"default-main"}'
# → memory_id: mem_1780211630617301197
curl -X POST http://localhost:7821/api/v1/recall \
-H "X-API-Key: zhiyi-dev-key-2026" \
-d '{"query":"E3增量embedding测试","top_k":3,"namespace":"default-main"}'
# → mem_1780211630617301197 排第一,score=0.843 ✅
验收标准
- commit 响应包含 memory_id(写入成功)
- commit 后立即 recall 能搜到(无需等待 Rust sidecar batch)
- recall 得分 > 0.8(证明向量有效,非零向量)
E4:图谱推理
目标
图谱真正参与推理:矛盾检测、跨 agent 共享、遗忘决策参考图谱结构。
现状
- 图谱存了 1269 节点/31248 边,只搜不用(2026-05-31 修复了 fmt.Printf debug)
- E4.1: Commit 路径已接入 ConflictDetector,检测率依赖 dedup 搜索覆盖
- E4.2: Recall 结果 < 3 时自动补充 shared namespace
- E4.3: Forgetter.ShouldForget 支持 graphDegree 可变参数
实施步骤
E4.1 矛盾检测(✅ 已实现,2026-05-31)
实现位置:
governance/governance.go:IsContradiction()+DetectContradiction()方法(导出供 routes 包调用)routes/core.go:API: 添加ConflictDetector字段,构造函数签名更新server.go: ConflictDetector 提到 NewAPI 之前创建(避免作用域错误)
Commit 流程:
Commit() → dedup 搜索 top-5 相似记忆
→ 3a: exact match → merge
→ 3b: near-dup (cos ≥ 0.98) → merge
→ 3c: 对其余相似记忆运行 DetectContradiction()
→ 有矛盾 → {"status":"ok","conflicts":["矛盾内容"]}
限制:依赖 dedup 搜索结果的覆盖率。语义相反的陈述在向量空间中未必是 top-5 最近邻。2026-05-31 修复了 IsContradiction 中文感知问题(原用 strings.Fields 对中文无效,改用 unicode.Han 字符级切分 + containsNegCN 否定词检测)。
E4.2 跨 agent 知识共享(✅ 已实现,2026-05-31)
实现位置:routes/core.go:Recall() — pipeline.Recall() 结果 < 3 时,补充 shared namespace 搜索
流程:
Pipeline.Recall(query, ns, limit) → len < 3 && ns != "shared"
→ EncodeSingle(query) → LanceDB.Search("memories", vec, 5, "shared")
→ 去重已出现在 own ns 的记忆 → 追加到 results,Score 降权 0.5
E4.3 遗忘决策参考图谱(✅ 已实现,2026-05-31)
实现位置:governance/governance.go:ShouldForget()
逻辑(向后兼容,不传 graphDegree 则行为不变):
// 节点度 > 5 时,每超 1 度 + 0.03 保留分
if len(graphDegree) > 0 && graphDegree[0] > 5 {
score += float64(graphDegree[0]-5) * 0.03
}
调用方待接入:routes/admin.go:71、server.go:904 — 需要在遗忘循环中查 GraphStore.GetEntityDegree() 注入 graphDegree 参数。
验收标准
- E4.1: Commit 响应包含
conflicts字段(如有矛盾)— ✅ 逻辑已接入 - E4.2: Recall < 3 结果时自动补充 shared — ✅ 已实现
- E4.3: ShouldForget 签名支持 graphDegree — ✅ 已实现,调用方待接
E5:产品 UI
规划版本:v1.0 | 2026-06-02 目标:给织忆构建三层可视化入口(Obsidian 插件 / 增强 CLI / Web UI),覆盖日常快速查询和图谱深度探索两种场景。
E5.1:Obsidian 插件(优先级最高)
为什么先做 Obsidian
- 牧尘的笔记和记忆本来就在 Obsidian 里,界面切换成本最低
- 插件形式天然接入 vault 工作流,不需要另外打开窗口
- 图谱可以直接嵌入笔记界面,实体关系和笔记内容联动
目标功能
- E5.1.1 插件骨架:
manifest.json+main.ts+styles.css,Obsidian 加载并注册ZhiYiPlugin - E5.1.2 记忆侧边栏面板:展示最近记忆列表,支持按 namespace 过滤,支持分页
- E5.1.3 实体图谱视图:基于 D3.js force-directed graph,从
/api/v1/graph/entity/{entity}/neighbors获取数据,节点颜色区分 category,hover 显示关系标签 - E5.1.4 记忆搜索模态框:输入查询词调用
/api/v1/search/recall,显示 top-20 结果,点击跳转到记忆详情 - E5.1.5 实体详情视图:选中图谱节点后,从
/api/v1/memories/by-entity/{entity}获取关联记忆列表 - E5.1.6 蒸馏状态面板:展示
/api/v1/distill/status和/api/v1/distill/quota,队列为非空时高亮提醒
技术方案
- 开发目录:
~/projects/memoryweave/plugins/obsidian/ - 插件通过
fetch()调用 Go API(端口 7821),Go 服务需添加 CORS 头(Access-Control-Allow-Origin: app://obsidian.md) - 图谱渲染:D3.js v7 从 CDN 加载(
https://cdn.jsdelivr.net/npm/d3@7/dist/d3.min.js),不用本地打包 - 构建:esbuild 打包
main.ts→main.js(npx esbuild main.ts --bundle --outfile=main.js) - Obsidian 开启「第三方插件」后,插件文件夹挂载到
~/.obsidian/plugins/zhiyi-memory/
CORS 适配(Go 服务改动)
// api/middleware/cors.go — 新增
func CORS() gin.HandlerFunc {
return func(c *gin.Context) {
c.Header("Access-Control-Allow-Origin", "app://obsidian.md")
c.Header("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
c.Header("Access-Control-Allow-Headers", "X-API-Key, Content-Type")
if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(204)
return
}
c.Next()
}
}
// server.go — 注册 middleware
server.Use(apiMiddleware.CORS())
文件结构
plugins/obsidian/
├── manifest.json # Obsidian 插件清单
├── styles.css # 插件样式
├── main.ts # 插件入口,注册侧栏、图谱视图、搜索模态框
├── src/
│ ├── api.ts # 调用 Go API(fetch 封装,baseURL = http://localhost:7821)
│ ├── MemoryView.ts # 记忆侧边栏面板
│ ├── GraphView.ts # D3 图谱渲染
│ └── SearchModal.ts # 搜索弹窗
├── esbuild.config.mjs # 构建配置
└── README.md
验收标准
- Obsidian 加载插件后,左侧出现「织忆」侧边栏
- 侧边栏显示最近 20 条记忆(namespace=default),点击展开内容
- 图谱视图能渲染至少 3 层邻居节点,节点可拖拽
- 搜索模态框输入关键词返回结果(<500ms)
- 蒸馏队列非空时侧边栏顶部出现红色提示
E5.2:增强 CLI(第二优先级)
目标功能
- E5.2.1
zhiyi tree命令:树形展示 namespace 下记忆结构,按 category 分组,每条记忆显示前 60 字符摘要 - E5.2.2
zhiyi graph命令:ASCII art 渲染 ego-network 图谱(中心节点 + 一跳邻居 + 关系标签) - E5.2.3
zhiyi recall <query>命令:语义搜索,返回 top-10 结果,显示 relevance score 和摘要 - E5.2.4
zhiyi stats命令:显示记忆总数、namespace 分布、今日新增、蒸馏队列状态 - E5.2.5
zhiyi entity <name>命令:查询实体详情(出现次数、关联实体列表、记忆片段)
技术方案
- CLI 命令入口:
~/projects/memoryweave/go/cmd/zhiyi-cli/ - 使用
cobra或原生flag解析子命令 - 图谱 ASCII 渲染:用 Unicode box-drawing 字符(
┌─┬┐│├┼┤└┴┘),中心节点用◉,邻居用○ - 调用现有 Go API 端点,不直接操作存储
文件结构
go/cmd/zhiyi-cli/
├── main.go
├── cmd/
│ ├── root.go
│ ├── tree.go
│ ├── graph.go
│ ├── recall.go
│ ├── stats.go
│ └── entity.go
└── output/
├── ascii_graph.go # ASCII 图谱渲染
└── formatter.go # 格式化输出
验收标准
zhiyi tree输出格式正确(树形、分组、摘要)zhiyi graph <entity>渲染 ASCII 图谱,实体数 ≥ 5 时换行正确zhiyi recall输出 relevance score 排序正确zhiyi stats显示记忆数、namespace 分布、蒸馏配额(used/limit)
E5.3:Web UI(第三优先级)
目标功能
- E5.3.1 React 项目骨架:Vite + React + TypeScript,路由
/memories/graph/search/distill - E5.3.2 记忆列表页:分页表格(每页 20 条),列:id / content_preview / category / created_at / namespace,支持点击展开完整内容
- E5.3.3 图谱探索页:全屏 D3.js force-directed graph,支持缩放/拖拽/筛选(category / namespace),点击节点弹出详情 drawer
- E5.3.4 语义搜索页:输入框 + 实时结果(debounce 300ms),显示 relevance 和摘要,高亮匹配片段
- E5.3.5 蒸馏监控页:进度条显示 daily used / limit,队列列表(episode_id / category / content_preview)
- E5.3.6 响应式布局,支持 1280px+ 宽屏
技术方案
- 项目目录:
~/projects/memoryweave/web-ui/ - 技术栈:Vite + React 18 + TypeScript + TailwindCSS + D3.js v7
- API 层:Axios 调用 Go API,响应式状态用 React Query 管理缓存
- 图谱:与 E5.1 共用
/api/v1/graph/navigate和邻居接口,数据结构一致 - 部署:Go 服务新增静态文件中间件(
/static/*→web-ui/dist/),make build-web构建后自动同步
文件结构
web-ui/
├── index.html
├── package.json
├── vite.config.ts
├── tailwind.config.js
├── src/
│ ├── main.tsx
│ ├── App.tsx
│ ├── api/
│ │ └── zhiyi.ts # API 客户端封装
│ ├── pages/
│ │ ├── MemoriesPage.tsx
│ │ ├── GraphPage.tsx
│ │ ├── SearchPage.tsx
│ │ └── DistillPage.tsx
│ └── components/
│ ├── GraphCanvas.tsx # D3 图谱组件
│ ├── MemoryTable.tsx
│ └── DistillStatus.tsx
└── dist/ # 构建输出,由 Go 静态中间件托管
Go 服务静态文件中间件
// api/middleware/static.go — 新增
func StaticFile(root string) gin.HandlerFunc {
fs := http.FileServer(http.Dir(root))
return func(c *gin.Context) {
if _, err := os.Stat(filepath.Join(root, c.Request.URL.Path)); err == nil {
fs.ServeHTTP(c.Writer, c.Request)
c.Abort()
} else {
c.Next()
}
}
}
// server.go — 注册
if opt.Mode == "dev" {
server.Use(apiMiddleware.StaticFile("../web-ui/dist"))
}
验收标准
- Web UI 能加载并显示记忆列表(分页正常)
- 图谱页渲染实体节点 ≥ 10 个,缩放拖拽流畅
- 搜索页输入关键词后 1 秒内显示结果,高亮匹配文字
- 蒸馏监控页显示正确的 used/limit 进度条
- 各页面在 1920×1080 和 1366×768 下布局正常
E5 总体依赖关系
E5.1 (Obsidian 插件)
└── Go API 需添加 CORS 中间件
└── 构建系统需新增 esbuild 步骤
E5.2 (增强 CLI)
└── 复用 E5.1 的 CORS 无关紧要
└── 直接调用 Go API(无需其他依赖)
E5.3 (Web UI)
└── 复用 E5.1 的 CORS 中间件
└── Go 服务新增静态文件中间件
└── 需要独立的 Vite 构建流程
实施顺序
第一波(E5.1 Obsidian 插件)
- 添加 Go CORS 中间件,构建部署
- 创建
plugins/obsidian/目录结构 - 实现
ZhiYiPlugin骨架,注册侧边栏 - 实现 MemoryView(记忆列表)
- 实现 GraphView(D3 图谱)
- 实现 SearchModal(搜索)
- 本地测试:Obsidian 加载插件,验证全部功能
- 提交,WORKLOG 同步
第二波(E5.2 增强 CLI)
- 创建
go/cmd/zhiyi-cli/项目结构 - 实现 tree / graph / recall / stats / entity 命令
- 本地测试所有子命令
- 提交,WORKLOG 同步
第三波(E5.3 Web UI)
- 初始化 Vite + React + TypeScript 项目
- 实现 MemoriesPage
- 实现 GraphPage(基于 E5.1 相同的 D3 数据源)
- 实现 SearchPage
- 实现 DistillPage
- Go 服务添加静态文件中间件
make build-web集成到 Makefile- 完整测试,提交
附录:外部调研(GitHub 开源参考)
| 方向 | 参考项目 | 关键技术 |
|---|---|---|
| Obsidian 插件 | obsidianmd/obsidian-sample-plugin |
manifest.json, Plugin class, CustomView |
| 图谱可视化 | react-force-graph (底层 D3) |
force-directed layout, zoom/pan |
| Web UI 图谱 | vis-network / react-vis |
alternative to raw D3 |
| CLI 图谱 | dogmap(Mastodon ASCII 工具) |
box-drawing 字符布局 |
阶段推进规则
- 必须按顺序完成:E1 → E2 → E3 → E4 → E5
- 每个阶段必须测试验证后才能进入下一阶段
- 禁止跳过测试验证步骤
- 禁止偷懒:实施步骤必须逐条执行
- 禁止随意更改变动设计语言:阶段目标和验收标准锁定
- 如有阻塞,记录到 BLOCKED 章节,继续下一个阶段
BLOCKED(阻塞记录)
| 时间 | 阶段 | 阻塞原因 | 尝试方案 |
|---|---|---|---|
| - | - | 无阻塞 | - |
进度追踪
| 阶段 | 开始时间 | 完成时间 | 状态 |
|---|---|---|---|
| E1 图谱导航激活 | 2026-05-30 | 2026-05-30 | ✅ |
| E2 多 agent 命名空间 | 2026-05-30 | 2026-05-30 | ✅ |
| E3 增量 embedding | 2026-05-30 | 2026-05-30 | ✅ |
| E4 图谱推理 | 2026-05-31 | 2026-05-31 | ✅ E4.1/E4.2/E4.3 已实现,E4.3 调用方已接入(extractTopEntityDegree) |
| E5 产品 UI | 2026-06-02 | - | 🔨 |
最后更新:2026-06-02(E5 规划完成)