乐于分享
好东西不私藏

Obsidian插件自动建 Wiki:obsidian-llm-wiki

Obsidian插件自动建 Wiki:obsidian-llm-wiki

最近在看一个 Obsidian 插件,obsidian-llm-wiki,基于 Andrej Karpathy 的 LLM Wiki 概念,把笔记自动转成结构化的 Wiki 知识库。

这类工具我看了不少。Hermes、OpenHuman 里的 LLM-Wiki 实现,我自己也在做。但一圈比下来,都不如这个扎实。

做 Wiki 时最头疼的几个问题:概念怎么拆、实体和概念怎么分、同义不同名怎么处理、断链怎么修、提问能不能反哺笔记——它都覆盖了,而且方法很讲究。目前看来,这是我见过最好的 Karpathy LLM Wiki 实现。

1 代码量与结构

目前(260604)整个项目约 1.9 万行代码,业务代码 81%,测试 19%。

核心在 src/wiki/,5064 行,占 33%:

  • wiki-engine.ts
    (1017 行):总编排,跑通 ingest → extract → create → link
  • query-engine.ts
    (888 行):对话式查询,基于知识库做 RAG
  • lint-fixes.ts
    (832 行)+ lint-controller.ts(762 行):修死链、去重、处理孤儿页
  • page-factory.ts
    (515 行):实体/概念页面的增删改查和合并
  • source-analyzer.ts
    (359 行):迭代批量提取,性能关键
  • prompts/
    (855 行):LLM 提示模板,覆盖生成、摄取、合并、Lint、对话

国际化也做得重,支持 8 种语言。v1.14.0 还拆出一批纯函数核心模块 src/core/,摆脱了 Obsidian 运行时依赖,可以独立测试。

2 如何定义概念

这是做 LLM Wiki 最困难的地方,也因人而异。

2.1 提示词设计

提示词本体在 src/wiki/prompts/ingestion.ts,粒度和语言控制在 src/wiki/system-prompts.ts,执行 orchestration 在 src/wiki/source-analyzer.ts

核心提示词的几个要点:

  • 输入变量:{{content}}{{batch_context}}{{granularity_instruction}}{{batch_size}}
  • Task 0:首轮提取标题 + 200 字摘要(后续省略)
  • Task 1:每轮必须输出 entities 和 concepts 数组
  • Task 2:可生成 1-2 个别名,防止后续重复提取
  • 字段要求:name(必须用源语言,禁止翻译)、type(实体 7 类 / 概念 4 类)、summary(4-6 句)、原文引用(2-4 句)、相关实体/概念
  • Entity vs Concept 有一套 12 步判定流程,第 12 步默认归 concept
  • 重要规则:wiki-link 测试(不值得被链接的不提取)、禁止重复

2.2 去重机制

去重分三层:

  1. 同文件内去重(source-analyzer.ts
  2. 创建页面时精确去重(page-factory.tsconflict-resolver.ts),基于 slug + alias
  3. LLM 语义去重(ingestion.ts:resolveEntityDedup

2.3 迭代提取

摄入文件时,右上角会提示 analyzing batch n/5...

这里的 Batch 是多轮迭代提取。一个文件可能包含大量 entity/concept,一次 LLM 请求 token 不够,所以分多轮:

  • Batch 1:提取最核心的 20 个(重要程度由模型判断)
  • Batch 2:在剩余内容中提取下一批,同时告诉 LLM 已提取项,避免重复
  • Batch 3...
  • 停止条件:返回空数组、达到 maxBatches 上限、或达到 maxTotalItems 上限

轮数计算:

123maxBatches = Math.min(  maxBatchesBase × 3,           // fine=36, standard=18, coarse=9, minimal=3  max(2, contentLength/2000 + 2) // 约每 2000 字符 +1 轮

总 Input Tokens ≈(全文 Tokens + 系统指令 + batch_context)× 轮数。

3 查询反哺

查询反哺由 ingestConversation() 实现。它会先判断对话主题和 Wiki 已有内容是否相似。如果 LLM 返回 fully_redundant,只会弹提示,不会创建新文件。如果有新内容,就创建 {wikiFolder}/sources/{语义标题}.md,并更新 concept、entity、索引和 log。

4 自定义规则

schema/config.md 是专门留给用户自定义的。可以随时修改,定制知识库的组织和输出风格。每次摄入新内容,LLM 都会参考这个 Schema 生成统一格式的页面。

它包含:

  • 实体分类规则(如 type: persontype: project
  • 概念分类规则(如 type: theorytype: method
  • 各类页面的模板结构(必须包含哪些章节)
  • 维护策略(何时标记页面需要审查)

用户可以手动编辑,也可以让模型根据当前知识库内容给出调整建议,再看 suggestions.md 决定是否应用到 config.md

5 维护与修复

执行后会扫描整个 Wiki(排除索引和日志),检测这些问题:

  • 重复页面:同一概念/实体被创建多个页面(支持跨语言检测,如「精力管理」和「Energy Management」)
  • 死链:页面中引用了不存在的 [[链接]]
  • 空页面:内容过少的 stub 页面(<50 字符实质内容)
  • 孤立页面:没有任何其他页面链接过来的页面
  • 别名缺失:Entity/Concept 页面缺少 aliases 字段
  • 路径污染:文件名中出现路径前缀重复,如 entities-entities-X.md
  • 双层嵌套链接:内容中出现 [[entities/entities/X|X]] 这类错误格式
  • 矛盾:不同页面对同一事实的描述相互矛盾

5.1 什么时候用

  • 摄入大量新内容后,检查重复和断链
  • 每周定期跑一次,保持 Wiki 整洁
  • 查询结果异常时,排查 Wiki 结构问题

5.2 Token 消耗

维护 Wiki 混合了本地检测和 LLM 检测。费 token 的主要是修复阶段。

重复检测、LLM 健康分析、修改阶段需要 LLM 处理。只看不修很省 token,重复检测的候选筛选也比较聪明,只有高置信度候选才走 LLM 验证,不会把全 Wiki 发过去。真正费 token 的是点「修复」之后的各个动作。

6 使用体验

提取质量没问题,但风格偏官方 Wiki。整个摄入过程是多轮迭代提炼的,相对费 token、费时间。在设置中设为 "Custom" 会省一些。我的个人体会是:没必要把所有文档都扔进 Wiki。全量摄入花的时间和 token 都太多,只针对某些文件、某些目录做 Wiki,性价比更高。如果你也在折腾 LLM Wiki,这个插件值得参考。不是因为它功能最全,而是因为它把很多你迟早会踩的坑,都处理得比较到位。