Repository navigation
Closed
Labels
bug功能异常、崩溃、数据错误(agent 诊断 → 人工确认)功能异常、崩溃、数据错误(agent 诊断 → 人工确认)
Description
#3 的跟进问题
环境
- dsh-mneme 0.3.3(0.2.x ~ 0.3.x 均存在)
- 配置:
embedProvider: local(ONNX / transformers.js,离线本地语义) - 平台:Windows 11,dsh web profile
现象
Local 模式下,记忆内容被更新(工具写入 / 人工编辑合并 / 冲突三路合并)后,
该记忆的 embedding 向量被清空,但不会重新生成。后果:
- 语义检索对该条记忆静默失效,只能靠 keyword 兜底;
- 旧向量未保留,也无法恢复,只能手动 reindex(
/api/dsh-mneme/vector-reindex)。
根因(代码级)
lib/service.js 的 scheduleEmbed() 依赖 embedder.schedule(memory):
function scheduleEmbed(memory) {
if (txDepth > 0) return; // deferred to the transaction's commit
if (embedder && memory?.id) {
try { embedder.schedule(memory); } catch { /* ignore */ }
}
}但 LocalEmbedder 与 OllamaEmbedder 都没有实现 schedule 方法:
| Embedder | 文件 | 有 embed/embedSingle |
有 schedule |
|---|---|---|---|
| LocalEmbedder | lib/local-embedder.js |
✅ | ❌ |
| OllamaEmbedder | lib/local-embedder.js |
✅ | ❌ |
| OpenAIEmbedder | lib/embedding.js |
✅ | ✅(第 68 行) |
因此 Local/Ollama 模式下,每次 update 后的实际执行链是:
store.update将embedding置空(无新向量传入时,existing.embedding因toRow剥离恒为undefined→null);scheduleEmbed调用embedder.schedule(...)→undefined is not a function→ TypeError;- 被
catch {}静默吞掉 → 重建从未发生。
即:"清空 + 重建"的设计闭环,在 Local/Ollama 模式下只有"清空"生效。
补充:v0.3.3 为
mergeHumanEdits等路径补了scheduleEmbed调用
(issue #3),但受限于上述根因,对 Local/Ollama 用户仍无效。
复现步骤
-
配置
embedProvider: local,确认记忆库有向量(/api/dsh-mneme/semantic的index.embeddedCount > 0); -
通过工具更新某条记忆的 content(触发
service.update→store.update+scheduleEmbed); -
等待数秒后查库:
SELECT COUNT(*) FROM memories WHERE embedding IS NOT NULL AND embedding != '';
该条记忆的向量已为空;
-
对该条记忆做语义搜索(
mode=vector),无向量命中,仅 keyword 命中。
影响
- Local/Ollama 模式下,任何记忆更新都会静默丢失该条向量,语义检索逐步退化;
- 与 OpenAI 模式行为不一致(OpenAI 有
schedule,能异步重建); - 用户感知为"语义搜索越来越不准 / 结果变少",且无任何日志提示。
修复建议(二选一)
方案 A:给 LocalEmbedder / OllamaEmbedder 实现 schedule(memory)
与 OpenAI 版语义一致:收到 memory 后异步调用 embedSingle 写入新向量。
方案 B:让 scheduleEmbed 对无 schedule 方法的 embedder 走通用重嵌
function scheduleEmbed(memory) {
if (txDepth > 0) return;
if (embedder && memory?.id) {
try {
if (typeof embedder.schedule === "function") {
embedder.schedule(memory);
} else if (typeof embedder.embedSingle === "function") {
// fire-and-forget 通用重嵌(Local/Ollama 兜底)
const text = [memory.title, memory.content].filter(Boolean).join("\n");
embedder.embedSingle(text)
.then((v) => { if (v?.length) store.setEmbedding(memory.id, v); })
.catch(() => { /* 重嵌失败不阻断主流程 */ });
}
} catch { /* ignore */ }
}
}Metadata
Metadata
Assignees
Labels
bug功能异常、崩溃、数据错误(agent 诊断 → 人工确认)功能异常、崩溃、数据错误(agent 诊断 → 人工确认)
Activity
Anans-Amarre commentedon Aug 16, 2026
感谢深挖!@heptaspirit 你定位得非常准——
scheduleEmbed假设所有 embedder 都有schedule,但 Local/Ollama/OpenAI 新路由都没有,导致向量清空后不重建(静默 no-op)。这个比 issue #3 更隐蔽,赞。已在 v0.3.5 修复:
scheduleEmbed加能力检测:有schedule走原路径;否则用embedSingle拼 title+content 生成向量 →store.setEmbedding重建logger.warn发布:npm @modusensus/[email protected],429 测试全绿。欢迎复验!
heptaspirit commentedon Aug 16, 2026
@Anans-Ivresse
跟进:
启动时回灌重建仍会失败(Local 模式启动竞态)
已在 v0.3.5 验证,运行中的 update+重建已正常 ✅,但启动时的 mergeHumanEdits 回灌路径仍有问题:
现象:
人工编辑 md 镜像 → 重启 dsh → content 正常合并回库,但该条向量被清空后重建失败(embeddedCount 减 1,该条无向量)。
根因:
时序问题
mergeHumanEdits 在插件 apply 的同步段执行(index.js 读取 md → 合并),而 embedder.init() 是异步的(init().catch(...),模型加载约 0.3~0.9s)。回灌触发 scheduleEmbed → embedSingle 时,extractor 尚未就绪 → 抛错被 logger.warn 记录 → 重建未发生。
建议:
让启动回灌的重建等待 embedder 就绪——
复现:
改一条 md → 重启 → 查 SELECT COUNT(*) FROM memories WHERE embedding IS NOT NULL 比重启前少 1。
Anans-Amarre commentedon Aug 16, 2026
感谢你非常精确的复现和时序分析,root cause 定位得很准——启动阶段 mergeHumanEdits 在同步段触发 embedSingle,而 embedder.init() 尚未完成,错误被吞导致静默失败,这个判断完全正确。
对应你提出的两个方向,我们已在 v0.3.7 中一并修复:
请升级到 npm @modusensus/[email protected] 后复验一下启动场景。如果仍有异常,欢迎继续反馈。感谢你对社区的贡献!
heptaspirit commentedon Aug 16, 2026
@Anans-Ivresse 0.3.7 已确认修复所有相关问题