
最近在看一个 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 → linkquery-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 去重机制
去重分三层:
同文件内去重( source-analyzer.ts)创建页面时精确去重( page-factory.ts、conflict-resolver.ts),基于 slug + aliasLLM 语义去重( 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: person、type: project)概念分类规则(如 type: theory、type: 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,这个插件值得参考。不是因为它功能最全,而是因为它把很多你迟早会踩的坑,都处理得比较到位。
夜雨聆风