关于 loreweave
loreweave 是面向 Markdown 笔记库的本地知识与记忆引擎,供需要检索笔记的用户和 AI Agent 使用。它结合时间事实、图谱检索和可读的追加式记忆,核心功能不依赖大模型。
主要功能
- 01双时态事实与时间线
- 02关键词、嵌入与图谱混合检索
- 03按使用和衰减管理记忆
- 04笔记库整理报告
- 05确定性事实查询与聚合
- 06命令行与 15 个 MCP 工具
适用场景
- 01通过关联概念检索笔记
- 02还原特定日期已知的信息
- 03为 Agent 提供持久笔记记忆
- 04发现过时、重复或孤立笔记
MCP 相关
向 MCP 客户端提供 15 个类型化工具,用于搜索、读取、查询和更新笔记库记忆。Agent 写入的事实会以可读 Markdown 追加到 lore 目录。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
Loreweave
面向 Markdown 知识库的时态知识引擎。
它可在本地对你拥有的文件进行索引、关联、记忆、遗忘和梦境处理。
快速开始 · 功能介绍 · CLI · Agent 记忆 · 基准测试 · 工作原理 · 研究
大多数知识工具都是只写不读。你认真记录,知识库不断增长,六个月后却找不到自己明明写过的内容——因为检索只是对散文进行关键词搜索,内容不会自动重新浮现,也没有机制发现你去年写下的内容如今已不再属实。
Loreweave 正是解决这个问题的那一层。指定一个 Markdown 文件夹(Obsidian 知识库或普通文件夹均可),它就会基于你的笔记构建知识图谱、双时态事实存储和记忆模型——再通过 CLI 提供给你,并通过 MCP 提供给你的 AI Agent。
以下三项保证由代码强制落实,而非空口承诺:
- 你的文件优先。 用户的 Markdown 文件绝不会被修改;引擎只会追加内容,且仅限于
lore/下。知识库才是事实来源——索引只是缓存,你可以随时删除,并且可以完全一致地重新构建(这点有测试验证)。 - 核心部分不使用任何大模型。 索引和检索不消耗任何 Token,也不会发起任何网络请求。同一知识库、同一查询,答案永远相同。
- 记忆清晰可读。 Agent 存储的每条事实都是一行 Markdown,你可以打开、编辑并使用
git diff查看差异。
快速开始
npm i -g --allow-scripts=better-sqlite3 loreweave # the flag is for npm 12: see Requirements
cd ~/my-vault
lore init # creates .lore/
lore index # incremental sync; one changed note: 32 ms at 1k notes, 656 ms at 20k (see Scale)
lore search "why did we drop the queue design"
lore ask "what's the status of project atlas"
lore dream # what's duplicated, contradicted, stale, unlinked
无需配置,也无需联网:开箱即用,使用 BM25 和知识图谱扩散激活。需要时可添加本地嵌入:
// .lore/config.json
{ "embedding": { "provider": "ollama", "model": "mxbai-embed-large" } }
追求质量可选择 mxbai-embed-large(670 MB);更看重磁盘占用和索引速度时可选择 nomic-embed-text(274 MB)。这两种模型以及 E5、BGE 和 Arctic 系列所需的任务前缀都会自动应用。两者实测效果差异见基准测试。如果不配置嵌入提供方,系统会使用词法检索与图谱检索,功能依然完整。
支持非英语知识库:中文、日文和韩文文本会按字符切分,以便进行搜索;其他文字系统则按原样建立索引。
功能
1. 知识带有时间线。 事实具有双时态属性:它们在现实世界中生效的时间(valid_from/valid_until),以及系统获知它们的时间(recorded_at)。相互矛盾的事实会被取代,而非覆盖,因此历史始终可查询。
$ lore assert "Ledger Format" status draft --valid-from 2026-01-01
$ lore assert "Ledger Format" status final --valid-from 2026-08-01
✓ Ledger Format :: status :: final
superseded: "draft" (now valid until 2026-08-01)
journal: lore/journal/2026-08-01.md
(lore 和 loreweave 是同一个二进制文件——全局安装会同时提供二者;
npx --allow-scripts=better-sqlite3 loreweave 无需安装即可运行。)
两条时间轴都可查询,这正是它具有双时态而不仅仅是历史记录的原因。--as-of 会询问当时实际为真的内容;--as-known-at 会询问当时所相信的内容。只有在事后才获知某些信息时,两者才会出现分歧——而这恰恰是你最需要还原过去的决策实际依据的时刻:
$ lore facts --subject Vendor --as-of 2024-06-01
Vendor :: reliability :: poor — outage postmortem (2024-01-01 → now)
$ lore facts --subject Vendor --as-known-at 2024-06-01
Vendor :: reliability :: good (2024-01-01 → 2024-01-01) [superseded]
哪条事实胜出由确定性规则决定(较新的有效时间优先,来源作为次级判定依据),绝不会询问大模型哪条看起来更新。查看任何内容的完整历史只需一条命令——按时间顺序合并每次值变更,以及提及这些变更的带日期文本:
$ lore timeline Project Atlas
2024-01-15 status: planning (until 2024-09-01)
2024-02-10 • [[Project Atlas]] kicked off with a three-person crew. [kickoff.md]
2024-09-01 status: planning → active
2025-06-20 • The [[Project Atlas]] midpoint review went long but well. [review.md]
时序图谱系统会在摄取每份文档时运行大模型来构建这些信息。而这里的取代链一直都在维护,因此只需在读取时进行联接:无需大模型,无需联网,每次答案都相同。
2. 检索遵循关联,而不只是词语。 查询会融合 BM25、稠密相似度(若已配置)以及基于知识库自身图谱的个性化 PageRank——包括 wiki 链接、共享实体、标签和共现信息。即使两跳内的邻居与查询没有共享词汇,也能被检索出来,而且每条结果都会说明原因:
• data/glacier-dataset.md#@0 (0.0327) ⟨via amara osei⟩
The Glacier Dataset holds meltwater sensor readings from 2019-2024.
3. 具有动态变化的记忆。 每段内容都带有 FSRS 风格的稳定性和可提取性指标——遵循幂律遗忘曲线。真正被使用(而不只是检索到)的内容衰减更慢;重要但逐渐淡忘的知识会被提出来供复习,而不是悄然腐朽。内容永远不会被删除。
4. 它会做梦。 lore dream 是一种空闲时执行的整合流程,会检查知识库并报告重复段落、相互矛盾的事实、过时知识、明显相关的笔记之间缺失的链接,以及孤立内容。使用 --apply 时,它会写入摘要和待审核队列——仅追加,位于 lore/ 下。它绝不会重写你的文本:由大模型驱动的整文件重写是一种已有记录的失败模式——每次重写都会悄然丢失细节,直到文件变得杂乱无章——因此架构上禁止这样做。
5. 回答检索无法回答的问题。 计数、分组和日期范围查询会对事实存储执行确定性的 SQL,而不是对嵌入向量凭感觉作答:
$ lore count --predicate trip_to --since 2025-01-01 --until 2025-12-31
2 Japan
1 Kenya
6. 事实来自你的笔记,而非表单。 没有人会手动编写 - [fact] X :: y :: z,因此提取器会挖掘知识库中已有的约定:
status: shipped # frontmatter
- owner:: Priya # Dataview inline field
- [location] Hyderabad # Basic Memory observation
只有明确无歧义的字段语法才会自动接受。像 - **Owner:** Priya 这样的行文格式,在实体笔记中很准确,在报告笔记中却会产生噪声,因此默认关闭(facts.extract: "all")——或者,Agent 可以通过 lore_propose_facts 审核候选项并确认真实事实。判断过程不会进入索引。
7. 时间指事件发生的时间,而非文件保存的时间。 --since 和 --until 会按内容时间进行筛选——包括 frontmatter 日期、带日期的文件名(2025-03-14-standup.md)或正文中的日期;只有在笔记没有自身日期时,才会回退到文件修改时间。lore watch 会保持索引最新,因此你无需记得重新索引。
8. 专为 Agent 打造。 MCP 服务提供 15 个类型化工具,让 Claude Code、Cursor 或任何 MCP 客户端都能将你的知识库用作持久记忆。会话连续性通过查询实现,而非改述——lore resume 会根据记录时间计算并准确返回自 Agent 上次连接以来的所有变更:
$ lore resume
since 2026-08-11 15:55
~ lore/journal/2026-08-11.md
+ Project Atlas :: status :: shipped (since 2026-08-11)
± Project Atlas :: status: active → shipped
$ lore resume
since 2026-08-11 15:56
nothing changed
其他方案会用大模型概述上一会话的内容,从而引入改述;这则是确定性的差异对比。完整设置说明见Agent 记忆。
命令行
| 命令 | 功能 |
|---|---|
lore init | 使用默认配置创建 .lore/ |
lore index [--full] [--no-nlp] [--rebuild-similar] | 将知识库增量同步到索引 |
lore search <q> [-k] [--since] [--until] [--tag] [--folder] [--json] | 带来源信息的混合检索 |
lore ask <q> | 提取式回答:当前事实 + 相关度最高的段落(无需大模型) |
lore facts [--subject] [--predicate] [--as-of] [--as-known-at] [--history] [--limit] | 查询事实存储(默认 200 行;若 --limit 指定其他数量,则按指定数量显示;达到上限时会说明省略的行数) |
lore timeline <entity> [--since] [--until] | 按时间顺序查看历史:事实变更与有日期的提及合并显示 |
lore resume [--since] | 查看上次回顾后的变更:笔记、事实和取代记录 |
lore review [--threshold] [--limit] | 查找重要但逐渐淡忘、值得重新查看或归档的知识 |
lore assert <s> <p> <o…> [--valid-from] | 记录事实(写入日志,并取代旧事实) |
lore invalidate <s> <p> | 关闭某个槽位中的当前事实 |
lore count [--predicate] [--group-by] [--since] | 汇总事实历史 |
lore capture <text…> | 将带时间戳的行追加到 lore/inbox.md |
lore dream [--apply] | 执行整合流程 + 可选生成摘要或审核队列 |
lore watch | 随知识库变更自动重新建立索引 |
lore mark-used <note> [anchor] | 强化已证明有用的段落 |
lore graph export --format json|graphml|dot | 导出图谱 |
lore doctor | 健康检查:损坏的链接、完整性、覆盖情况 |
lore stats | 知识库统计信息和热门实体 |
lore serve --mcp | 通过标准输入输出启动 MCP 服务 |
将其用作 Agent 记忆(MCP)
// Claude Code: .mcp.json (or claude_desktop_config.json)
{
"mcpServers": {
"loreweave": {
"command": "npx",
"args": ["--allow-scripts=better-sqlite3", "-y", "loreweave",
"--vault", "/path/to/vault", "serve", "--mcp"]
}
}
}
--allow-scripts 参数适用于 npm 12;Requirements 说明了这一点,以及如何清除 npx 已经在未使用该参数的情况下完成的安装。
| 工具 | Agent 能获得什么 |
|---|---|
lore_search | 带有来源信息和时间筛选条件的混合检索 |
lore_context_pack | 一次调用获取会话上下文:相关段落 + 当前事实 + 最近变更 |
lore_read_note | 按路径读取笔记全文 |
lore_assert_fact / lore_invalidate_fact | 写入/关闭事实——保留日志记录、以新事实取代旧事实,绝不破坏性删除 |
lore_query_facts | 查询特定时间点的事实(asOf、asKnownAt、历史记录) |
lore_timeline | 合并某个实体的事实与文本,形成时间线 |
lore_resume | 准确显示自 Agent 上次连接以来发生的变更 |
lore_review | 值得重新呈现的重要但逐渐淡忘的段落 |
lore_aggregate_facts | 对事实历史进行计数/分组 |
lore_capture | 向收件箱追加带时间戳的一行内容 |
lore_mark_used | 强化信号:该段落确实起到了帮助作用 |
lore_propose_facts | 提取候选事实,供 Agent 审核并确认 |
lore_dream_report | 整理报告(重复项、矛盾项、过时项、孤立项) |
lore_index | 触发重新索引 |
通过 MCP 确认的事实会以易读的 Markdown 写回 lore/journal/YYYY-MM-DD.md,因此 Agent 的记忆可以打开、编辑,也可以使用 git diff 查看差异:
- [fact] Ledger Format :: status :: final {valid_from=2026-08-01, confidence=0.9, source=stated}
删除 .lore/ 并重新索引——每条事实和关联都会从这些文件中重建。
任何笔记中的 - [fact] 行都会被重放,但只有在 lore/journal/ 下才会读回 source= 属性;这是 loreweave 唯一会写入的路径。普通笔记中的同一行仍会记录该事实,但会标记为 extracted——笔记可以陈述某件事,但不能声称是你说的。
与托管记忆服务相比(Mem0、Zep):这些服务会在写入时运行大模型,将内容提取并总结到自己的存储中;loreweave 的核心不运行任何模型,将记忆保存在你自己的文件中并纳入版本控制,同时确保每次检索都可复现。代价是:它们会进行抽象式总结,而该引擎有意不这样做。与它们已公布的基准相比,检索质量较低——但需注意的是,大多数已公布的 Agent 记忆数据衡量的是由大模型完成的端到端问答,而这与检索衡量的并非同一指标。
基准测试
这些第三方基准测试使用的相关性标签并非由我们选择。所有 loreweave 数值都是检索指标——它负责找到证据,而不负责撰写答案——因此无法与在检索后接入语言模型的系统所报告的端到端问答准确率相提并论。复现任意数值:
docs/benchmarks.md。包含注意事项的横向比较:
docs/scoreboard.md。
LongMemEval_S(ICLR 2025)——500 个问题,每个问题约有 50 段聊天历史会话;需要找到包含证据的会话。会话级召回率,共 500 个问题:
| 配置 | R@1 | R@5 | R@10 |
|---|---|---|---|
| 无模型(无嵌入、无网络) | 0.552 | 0.899 | 0.943 |
| + 嵌入与 8 轮分块 | 0.590 | 0.959 | 0.983 |
同一任务的第三方基准测试报告称,BM25 单独使用时 R@5 为 86.2%,BM25+向量混合检索为 95.2%,仅向量系统为 96.6%。比较之前需要注意一点:他们的指标只要检索到任意一个黄金会话,就给问题计 1 分;我们的指标则计算找到的黄金会话比例——我们的定义更严格,因此跨系统差距小于一个百分点时,应视为噪声。说明这一点后:loreweave 达到 95.9%,超过混合检索,仅略低于向量系统,且使用本地模型、无需网络,并配有可回退使用的词法索引。
BEIR / SciFact——5 183 篇科学摘要、300 条论断,按 nDCG@10 评分(排序质量:相关文档排名越靠前,得分越高):
| 配置 | nDCG@10 | Recall@10 |
|---|---|---|
| BM25 基线(BEIR 论文,Anserini) | 0.665 | — |
| loreweave,无模型 | 0.681 | 0.817 |
| loreweave + nomic-embed-text | 0.727 | 0.865 |
| loreweave + mxbai-embed-large | 0.742 | 0.884 |
LoCoMo——10 段长对话、1 982 个带证据标签的问题,按轮次计算召回率。不存在可比较的第三方检索数据(已发表的 LoCoMo 结果是大模型问答准确率),因此这里的数据作为目标值,而非比较结果:
| R@1 | R@5 | R@10 | R@20 | |
|---|---|---|---|---|
| 无模型 | 0.337 | 0.538 | 0.610 | 0.656 |
| + 嵌入 | 0.318 | 0.532 | 0.627 | 0.705 |
直白地说,这些数字说明了什么。 召回率很强,但排名第一是短板——LongMemEval 的 R@10 为 0.983,而 R@1 为 0.590——因此这里的数值均按 R@5 报告,使用这些结果的 Agent 应查看前 5 条,而不是只相信排名第一的结果。已测得的最大质量提升来自嵌入模型本身:在文档(BEIR)和会话(LongMemEval)检索中,mxbai 相比 nomic 带来的提升超过所有下游调优的总和;而在 LoCoMo 的单轮片段上,效果持平,因此这是规模效应,并非魔法。可使用交叉编码器重排器(在配置中设为 rerank),但它只适用于不使用嵌入、关注排名第一结果的场景——与嵌入一起使用时,它会降低两个公开基准的召回率,因此除非你愿意接受这种取舍,否则应将其关闭。完整分析,包括失败的实验和基准测试发现的缺陷:
docs/evaluation.md。
Loreweave 还附带一套内部回归基准测试(npm run eval),覆盖三个专门构建的知识库——其中包括一项时间扰动测试,随附配置的一致性得分为 100%,而 BM25 为 0%;每次推送都会在 CI 中执行这一测试。内部语料适合用于回归测试,却毫无证明力,因此详情请见
docs/evaluation.md,而非此处。
规模
与质量数据一样,规模数据也经过了实测——运行 npm run scale,即可在你自己的
计算机上复现(合成知识库,每篇笔记 3 个块,密集互连):
| 笔记数 | 块数 | 实体数 | 边数 | 完整索引 | 增量更新 | 搜索 p50 | p95 | 梦境 | 堆内存 |
|---|---|---|---|---|---|---|---|---|---|
| 1 000 | 3 000 | 2 766 | 17 k | 1.2 s | 32 ms | 3 ms | 4 ms | 0.2 s | 63 MB |
| 5 000 | 15 000 | 13 766 | 85 k | 6.1 s | 165 ms | 9 ms | 12 ms | 1.0 s | 145 MB |
| 20 000 | 60 000 | 55 016 | 339 k | 22.5 s | 656 ms | 38 ms | 53 ms | 4.8 s | 333 MB |
从 5 k 到 20 k,完整索引的耗时按**每篇笔记 0.93×**增长——呈线性或更优,
中间没有隐藏的超线性增长。“增量更新”指一篇发生变更的笔记,这正是
lore watch 全天实际处理的情况。以上所有操作都在一个进程中、使用一个 SQLite 文件完成,
无需守护进程——搜索的 p50 为 3-38 ms,足够快,可以放进 Agent 循环中运行。
工作原理
vault/*.md ──parse──▶ notes · blocks · wiki-links · tags · entities
│ (incremental: mtime + content hash)
▼
SQLite .lore/index.db ── disposable cache, rebuildable
│
┌───────────────────┼────────────────────┐
▼ ▼ ▼
graph (CSR) retrieval facts
blocks ∪ entities BM25 + dense + PPR bitemporal, supersession,
2-iteration PPR → weighted RRF deterministic freshness,
α = 0.5 → FSRS boosts aggregates
└─────────┬─────────┴──────────┬─────────┘
▼ ▼
dream (idle-time) CLI · MCP
代码强制执行的设计规则:
- 文件优先。 用户的 Markdown 永远不会被修改。引擎只会追加内容,且只追加到
lore/下。 - 不变量由代码保障,而非提示词。 Schema、迁移、图构建和 取代逻辑都有类型定义、版本管理和测试——运行时无需 LLM 重新定义。
- 核心功能完全不需要 LLM。 索引和检索不消耗任何 token。 语言模型是此引擎的使用者,而非其依赖项。
- 所有内容都可重新推导。 完整重建会生成字节级一致的派生状态 (已有测试验证)。
研究脉络
每项重要设计选择都有 2024-2026 年的研究作为依据;综述见
docs/research/。
| 选择 | 来源 |
|---|---|
| 密集-稀疏融合 + 使用密集重置概率的 PPR | HippoRAG 2 (ICML 2025),2502.14802 |
| 浅层 2 次迭代 PPR、异构节点 | NodeRAG (2025),2504.11544 |
| 无关系图——不使用 LLM 提取三元组 | LinearRAG (ICLR 2026),2510.10114 |
| 不在索引时进行社区摘要 | LazyGraphRAG (Microsoft, 2024) — 以 0.1% 的索引成本达到相同质量 |
| 路由/融合,而非将所有内容都交给图处理 | GraphRAG-Bench (ICLR 2026),2506.05690 |
| 双时间事实,失效但永不删除 | Zep/Graphiti (2025),2501.13956 |
| 幂律遗忘、使用门控强化 | FSRS;RMM (ACL 2025),2503.08026 |
| 将整合作为空闲时段的工作 | Sleep-time compute (Letta, 2025),2504.13171 |
| 绝不让 LLM 重写整个记忆文件 | ACE (2025),2510.04618 |
| 可计算事实用于聚合 | User as Code (2026),2606.16707 |
| 细粒度索引 + 增添事实的键 | LongMemEval (ICLR 2025),2410.10813 |
库的使用
import { openContext, indexVault, search, assertFact, queryFacts, dream } from 'loreweave';
const ctx = openContext('/path/to/vault');
await indexVault(ctx.store, ctx.root);
const hits = await search(ctx, 'streaming compaction', { k: 5 });
assertFact(ctx, { subject: 'Atlas', predicate: 'status', object: 'shipped', validFrom: '2026-08-01' });
const asOfMarch = queryFacts(ctx.store, { subject: 'Atlas', asOf: '2026-03-01' });
const report = dream(ctx);
ctx.close();
开发
npm install
npm run build # the stdio-server tests run the built CLI, and skip without it
npm test # 546 tests
npm run eval # retrieval benchmark vs BM25 baseline
npm run typecheck
要求
Node 22 或更高版本。在 Linux、macOS 和 Windows 上,针对 Node 22、24 和 26 进行了 CI 测试。唯一的原生依赖 better-sqlite3 在 Node 22、24、25 或 26 上可在 macOS、Linux 和 Windows 上通过预编译二进制文件安装,无需编译器。Node 23 没有预编译二进制文件,因此 npm 会从源代码编译,这需要 C++ 工具链。
npm 12 不再默认运行依赖项的安装脚本,而 better-sqlite3 会在安装脚本中获取其二进制文件:如果没有使用 --allow-scripts=better-sqlite3,安装会成功,但任何打开索引的命令都会报错,显示“Could not locate the bindings file”。Node 22、24 和 26 附带的 npm 10 和 11 无需额外操作,并且接受 npm i -g 和 npx 使用此标记。
npm i -g和npx接受此标记,具体用法见快速入门和 MCP 配置。- 即使之后添加了此标记,npx 仍会重复使用此前未带标记安装的版本:使用
npm cache npx ls找到该安装,再用npm cache npx rm <key>将其移除。 - 在项目中——无论是你自己的项目,还是克隆的本仓库——npm 12 都会拒绝此标记,Node 24 和 26 附带的 npm 11(从 11.16 开始)也会拒绝。npm 11 不带此标记也会运行该脚本。在 npm 12 上,改用
npm approve-scripts better-sqlite3批准此脚本,该命令会在 package.json 的allowScripts中记录此项,然后运行npm rebuild better-sqlite3。
许可证
MIT © Ambuj Upadhyay
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。