From f4313a40efcb129166e1b64bb4fb216214140036 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E5=94=AF?= Date: Thu, 2 Jul 2026 00:23:04 +0800 Subject: [PATCH] docs: add implementation plans for P0/P1/P2 features --- docs/p0-fallback-plan.md | 61 ++++++++++++++++++++++++++++ docs/p1-autoinject-plan.md | 83 ++++++++++++++++++++++++++++++++++++++ docs/p2-trustscore-plan.md | 69 +++++++++++++++++++++++++++++++ 3 files changed, 213 insertions(+) create mode 100644 docs/p0-fallback-plan.md create mode 100644 docs/p1-autoinject-plan.md create mode 100644 docs/p2-trustscore-plan.md diff --git a/docs/p0-fallback-plan.md b/docs/p0-fallback-plan.md new file mode 100644 index 0000000..48fc614 --- /dev/null +++ b/docs/p0-fallback-plan.md @@ -0,0 +1,61 @@ +# P0: Recall 降级策略 — 织忆 Go daemon + +## 目标 +当 bge-embed (8000) 或 Rust IPC sidecar 不可用时,recall 自动降级到 graph.db 关键词搜索,不返回 500 错误。 + +## 修改文件 + +### 1. `/tmp/memoryweave/go/internal/governance/graph_sqlite.go` +新增方法 `FallbackTextSearch(query, namespace, limit)`: + +```go +func (gs *SQLiteGraphStore) FallbackTextSearch(query, namespace string, limit int) []map[string]interface{} { + // 1. 从 edge properties 中搜索 content 字段(JSON 内 text 字段) + // 2. LIKE '%query%' 模糊匹配 nodes 的 name + // 3. 按 pagerank DESC 排序 + // 4. LIMIT limit +} +``` + +sqlite-go 通过 CGo 操作,参考已有 queryRows 函数(行 1037)。 +类似 SearchNodes(行 865)的模式,但搜索 edges 的 properties 字段。 + +### 2. `/tmp/memoryweave/go/internal/storage/recall.go` +在 `RecallPipeline` 结构体新增 `GraphStore` 字段: + +```go +type GraphExpander interface { + // ... existing methods +} +``` + +不用改 interface。在 `Recall` 方法末尾(当前行 149 return nil 之前),如果 candidates 为空且 lanceDB 搜索失败,尝试从 GraphStore 的 FallbackTextSearch 获取结果。 + +### 3. `/tmp/memoryweave/go/internal/api/routes/core.go` +在 `Recall` handler(行 209-293)中,当 `a.Pipeline.Recall()` 返回 err 时(行 240),不直接 500,而是调用 graph store 的 fallback 搜索: + +```go +if err != nil { + // Fallback: graph.db keyword search + fallbackResults := a.GraphStore.FallbackTextSearch(req.Query, req.Namespace, req.Limit) + if len(fallbackResults) > 0 { + // Convert fallback results to RecallResult format + results = convertFallbackResults(fallbackResults) + // return with 200 + warning header + } else { + respondError(w, 500, "recall failed: "+err.Error()) + return + } +} +``` + +## 验证方法 +```bash +# 正常状态能搜到 +curl -s -X POST -H "X-API-Key: zhiyi-dev-key-2026" \ + -d '{"query":"小唯","top_k":3}' \ + http://localhost:7821/api/v1/recall | python -c "import json,sys;d=json.load(sys.stdin);print(f'count: {d.get(\"count\",0)}')" + +# 模拟 bge-embed 挂了 +# curl 应该仍返回结果(从 graph.db 关键词搜索) +``` diff --git a/docs/p1-autoinject-plan.md b/docs/p1-autoinject-plan.md new file mode 100644 index 0000000..c6acc48 --- /dev/null +++ b/docs/p1-autoinject-plan.md @@ -0,0 +1,83 @@ +# P1: 自动注入钩子 — 织忆 Hermes 插件 + +## 目标 +增强 Hermes 织忆插件的 prefetch/queue_prefetch,实现: +1. queue_prefetch 缓存下一轮记忆(异步预取) +2. 社交关闭检测(skip trivial messages) +3. 新增 [织忆] 标记注入格式,与 hermes 原生记忆区分 +4. 更好的话题重叠检测(避免同一轮注入重复上下文) + +## 修改文件 + +### `~/.hermes/hermes-agent/plugins/memory/zhiyi/__init__.py` + +#### 1. 新增社交关闭检测(参考 Memory-OS hooks.py:251-268) +```python +_SOCIAL_CLOSERS = frozenset({ + "ok", "好的", "👍", "👌", "✅", "谢谢", "感谢", "知道了", + "明白", "嗯", "好", "行", "yes", "yep", "thanks", "thx", + "no", "不用", "没事", "可以", "done", "完成", +}) + +def _is_social_close(text: str) -> bool: + text = text.strip().lower() + if text in _SOCIAL_CLOSERS: + return True + if len(text) < 6 and not any(c in text for c in "://.@#$_?"): + return True + return False +``` + +#### 2. 实现 queue_prefetch(原为 pass) +```python +def queue_prefetch(self, query: str, *, session_id: str = "") -> None: + """异步预取:本轮对话结束后立即查询织忆,下一轮 prefetch 直接返回缓存。""" + if not self._client or not query or len(query.strip()) < 2: + return + if _is_social_close(query): + return + # 后台线程查询并缓存 + def _async_prefetch(): + results = self._client.recall(query.strip(), top_k=3) + notes = self._client.search_notes(query.strip(), max_hops=2, max_notes=3) + with self._prefetch_lock: + self._prefetch_cache["queue"] = { + "results": results, + "notes": notes, + "timestamp": time.time() + } + threading.Thread(target=_async_prefetch, daemon=True).start() +``` + +#### 3. 增强 prefetch 方法 +```python +# 在 prefetch 入口处: +if _is_social_close(query): + return "" # 关闭消息不触发预取 + +# 优先从 queue_prefetch 缓存取 +with self._prefetch_lock: + queued = self._prefetch_cache.pop("queue", None) + if queued and (time.time() - queued["timestamp"]) < 30: + # 用缓存结果 + pass + +# 输出格式改成带 [织忆] 标记 +blocks = ["[织忆 Memory — relevant past context]"] +for r in results: + blocks.append(f" [{score:.2f}][{cat}] {content[:500]}") +``` + +## 验证方法 +```bash +cd ~/.hermes/hermes-agent && python3 -c " +from plugins.memory.zhiyi import HermesZhiYiMemoryProvider +p = HermesZhiYiMemoryProvider() +# 测试 prefetch +result = p.prefetch('织忆记忆系统架构', session_id='test') +print('prefetch result:', result[:200] if result else 'empty') +# 测试 social closer +result2 = p.prefetch('好的', session_id='test') +print('social closer prefetch:', repr(result2)) +" +``` diff --git a/docs/p2-trustscore-plan.md b/docs/p2-trustscore-plan.md new file mode 100644 index 0000000..2d3f20d --- /dev/null +++ b/docs/p2-trustscore-plan.md @@ -0,0 +1,69 @@ +# P2: 信任评分 — 织忆 Go daemon + +## 目标 +给 graph.db 的 edges 表加信任评分字段,新增反馈 API 端点。 + +## 修改文件 + +### 1. `/tmp/memoryweave/go/internal/governance/graph_sqlite.go` + +#### a) Upgrade SQL 迁移(在 migrate() 中追加) +```sql +ALTER TABLE graph_edges ADD COLUMN trust_score REAL DEFAULT 0.5; +ALTER TABLE graph_edges ADD COLUMN retrieval_count INTEGER DEFAULT 0; +ALTER TABLE graph_edges ADD COLUMN helpful_count INTEGER DEFAULT 0; +``` +注意:ALTER TABLE ADD COLUMN 要先检查列是否存在,用 sqlite3 的 `PRAGMA table_info(graph_edges)` 检查。 + +#### b) 新增方法 +```go +// AddEdgeFeedback 记录边反馈 +func (gs *SQLiteGraphStore) AddEdgeFeedback(edgeID string, helpful bool) error +// 实现:UPDATE graph_edges SET helpful_count = helpful_count + 1 WHERE id = ? +// 如果不是 helpful: UPDATE graph_edges SET retrieval_count = retrieval_count + 1 WHERE id = ? + +// UpdateEdgeTrustScores 批量更新信任评分(定时或触发) +func (gs *SQLiteGraphStore) UpdateEdgeTrustScores() error +// 实现:UPDATE graph_edges SET trust_score = +// CASE +// WHEN retrieval_count > 0 THEN CAST(helpful_count AS REAL) / retrieval_count +// ELSE 0.5 +// END + +// IncrementEdgeRetrieval 递增边的检索计数(在 ExpandFromResults 里调用) +func (gs *SQLiteGraphStore) IncrementEdgeRetrieval(edgeID string) error +``` + +#### c) 在 ExpandFromResults(行 679-733)中,每条被检索的边调用 IncrementEdgeRetrieval + +### 2. `/tmp/memoryweave/go/internal/api/routes/core.go` +新增端点: + +```go +// POST /api/v1/graph/edge/feedback +func (a *API) EdgeFeedback(w http.ResponseWriter, r *http.Request) { + // body: { edge_id: string, helpful: bool } + // 调用 a.GraphStore.AddEdgeFeedback(edgeID, helpful) +} +``` + +### 3. `/tmp/memoryweave/go/internal/api/server.go` +注册新路由: +```go +mux.HandleFunc("/api/v1/graph/edge/feedback", api.EdgeFeedback) +``` + +### 4. `/tmp/memoryweave/go/internal/api/routes/core.go` +在 Recall handler 中,当结果返回时(行 292),遍历每条结果的 edge ID,递增 retrieval_count。 + +## 验证方法 +```bash +# 提交反馈 +curl -s -X POST -H "X-API-Key: zhiyi-dev-key-2026" \ + -H "Content-Type: application/json" \ + -d '{"edge_id":"e_xxx","helpful":true}' \ + http://localhost:7821/api/v1/graph/edge/feedback + +# 验证 trust_score 更新 +sqlite3 /var/lib/memoryweave/graph.db "SELECT id, trust_score, retrieval_count, helpful_count FROM graph_edges LIMIT 5" +```