LLM Wiki实战篇:少花token,多沉淀知识

LLM Wiki实战篇:少花token,多沉淀知识

 

动手 LLM Wiki 前,建议你先想明白这些结尾,我提了五个问题:规模天花板、超长文档、成本、冷启动、Lint 幻觉。然后说了 qmd 能解。但 qmd 只是一个搜索引擎——怎么把它接进 LLM Wiki 的工作流里,怎么设计 CLAUDE.md 让 LLM 真正按规矩干活,怎么让 200 页的论文不崩不丢不断,这些才是整套系统真正要解决的部分

时隔两周,我终于把这套方案盘清楚了,今天就来填这个坑

为什么用 qmd

如果只是做一个简单知识库,其实有很多方案。你可以直接用 Obsidian 搜索,可以用 ripgrep,可以用向量数据库,也可以搭一套 RAG。但我这个场景有几个很具体的要求

第一,知识主要以 Markdown 文件存在。原始文章、整理后的 wiki 页面、概念页、实体页、综合页,全部都在本地文件系统里。qmd 对这种文件系统式知识库很顺手,不需要一上来就搭数据库、服务端、API、权限系统。文件放进去,索引建起来,就能搜

第二,我需要混合检索。只用向量检索会遇到一个问题:语义大概能找,但精确词经常不稳。比如CLAUDE.md、raw_sha256、BM25、search-chunks、某个论文标题、某个命令名,这些东西用精确匹配更可靠。qmd 支持 BM25 和向量检索,再加上重排序,刚好适合技术文章、论文、笔记、代码说明这类材料

第三,我需要让 LLM 可以稳定调用。Claude Code 这类工具很适合操作本地文件,但前提是命令要简单、语义要清楚。如果把一堆底层检索参数直接暴露给 LLM,它很容易乱用。qmd 的能力可以被封装成几个稳定命令,比如wiki search、wiki get、wiki find-related、wiki search-chunks,这样 LLM 不用理解所有底层细节,也能稳定完成任务

第四,我需要处理超长文档。很多文章不是三五千字,而是几十页甚至两百页。如果每次都让 LLM 读全文,成本高、上下文容易爆、还会丢细节。qmd 的块级检索可以让 LLM 按主题去找原文中的相关段落,一次只读几个块。这样长文档也能拆开处理

第五,我想要本地、轻量、可迁移。整个知识库就是文件夹,Git 可以管版本,Obsidian 可以看图谱,qmd 管检索,LLM 管编译。没有很重的工程依赖,也不会把系统绑死在某个云服务上

所以 qmd 在这套方案里的定位很清楚:它是本地知识库的检索底座。它不负责替你理解知识,也不负责替你设计知识结构。它只负责一件事:当知识库变大之后,帮 LLM 找到该看的东西

整体架构:四层就够了

整个系统可以拆成四层

  1. 用户层决定读什么、问什么、哪些内容值得沉淀
  2. LLM 层执行 ingest、query、lint,按照 CLAUDE.md 的规矩维护
  3. wikiCLI 层用 bin/wiki 封装 qmd,提供稳定命令文件
  4. 系统层保存 raw 原始文档、wiki 页面、shared 跨域页面、qmd 索引

这里最关键的是 CLI 层。LLM 不直接操作 qmd 原始命令,所有动作都走bin/wiki。原因很简单:qmd 的能力比较底层,参数组合也多,直接让 LLM 调用容易出错。封装之后,LLM 只需要理解几个语义化动作

比如日常查询用:

wiki search “self-attention”

ingest 前找相关页面用:

wiki find-related “Transformer 架构”

长文档按块搜索用:

wiki search-chunks “positional encoding”

读取文档用:

wiki get “wiki/concepts/self-attention.md”

这样一来,LLM 操作知识库时就像在使用一组稳定 API,而不是每次临时拼复杂命令。系统越大,这层封装越重要

目录怎么设计

我把目录分成三块:bin/、shared/、instances/

bin/里放统一的 wiki CLI。shared/放跨域共享的页面,比如实体、跨域概念、桥接页面。instances/下面放不同知识域,每个域有自己的 raw、wiki 和 CLAUDE.md

大概结构是这样:

qmd_llm_wiki/

├── bin/

│ └── wiki

├── shared/

│ ├── entities/

│ ├── concepts/

│ └── bridges/

└── instances/

├── formal/

├── natural/

├── technical/

├── mental/

├── social/

└── philosophy/

每个实例里面的结构基本一致:

technical/

├── raw/

│ ├── articles/

│ ├── papers/

│ └── assets/

├── wiki/

│ ├── sources/

│ ├── entities/

│ ├── concepts/

│ ├── synthesis/

│ ├── _wip/

│ └── log.md

└── CLAUDE.md

raw/放原始文档,原则是只读不改。wiki/放 LLM 维护后的页面。sources/是来源摘要,concepts/是概念页,entities/是人物、组织、产品这类实体页,synthesis/是综合分析,_wip/用来保存超长文档 ingest 进度,log.md记录知识库操作历史

这个结构的好处是清楚。原始资料和整理结果分开,单篇文章和跨文章概念分开,当前域和共享层分开。后面做检索、lint、维护都会轻很多

qmd 初始化时要做什么

qmd 的核心概念是 Collection,可以理解成一组被索引的文件。我们要做的第一步,就是把不同目录注册成不同 Collection

不要把整个 wiki 文件夹粗暴注册成一个集合。因为 source 页面、concept 页面、entity 页面、raw 原文的用途完全不同。查询时,你可能只想搜整理后的 wiki;ingest 时,你可能想找相关 concept;查证据时,你可能只想搜 raw;长文档处理时,你还需要搜 raw 的块级索引

所以更好的做法是按用途注册,比如:

technical-sources → technical/wiki/sources/*.md

technical-concepts → technical/wiki/concepts/*.md

technical-entities → technical/wiki/entities/*.md

technical-synthesis → technical/wiki/synthesis/*.md

technical-raw → technical/raw/**/*.md

shared-entities → shared/entities/*.md

shared-concepts → shared/concepts/*.md

shared-bridges → shared/bridges/*.md

这样后面命令就可以非常清楚。wiki search默认搜当前域的 wiki 页面,wiki search –raw搜原始文档,wiki search-cross搜所有域和 shared 层,wiki search-chunks专门搜 raw 里的文档块

初始化时还要给每个 Collection 加 context description,也就是告诉 qmd 和重排序模型:这个集合里装的是什么。比如 source 页面是一篇文档的摘要,concept 页面是概念解释,raw 是不可修改的原始资料。这个信息会影响检索质量,因为系统不仅要知道“哪些文本相似”,还要知道“用户这个问题更应该去什么类型的页面里找”

初始化完成后,执行 reindex,让 qmd 建索引和向量嵌入。后面每次新增或修改文件,都需要按需重新索引,否则检索结果可能滞后

wiki CLI 要封装哪些命令

CLI 不需要做得很复杂,核心命令够用就行。我的思路是把命令分成六类

第一类是初始化和维护:wiki init、wiki reindex、wiki status、wiki collections。新建知识库时先 init,再 reindex,然后用 status 看状态。新会话开始时也建议先跑 status,让 LLM 了解当前库的规模和最近变化

第二类是检索:wiki search、wiki search-cross、wiki search-lex、wiki search-vec。日常大多数问题用wiki search就够了。跨域问题用wiki search-cross。遇到专有名词、命令名、文件名,用wiki search-lex。遇到模糊问题,用wiki search-vec

第三类是 ingest 专用检索:wiki find-related。这个命令的参数应该比普通 search 更宽松,比如返回更多结果、阈值更低。因为 ingest 时宁可多看几条候选页面,也不要漏掉一个应该更新的旧概念

第四类是超长文档:wiki search-chunks、wiki wip-list、wiki wip-done。长文档不能全文读,要按主题搜块。WIP 文件负责记录处理进度

第五类是文档取回:wiki get、wiki bulk。wiki get用来读取单个页面或 docid,wiki bulk用来批量读取某一类页面,比如 lint 时批量检查 sources 或 concepts

第六类是日志和版本:wiki log、wiki log-recent、wiki save。每次 ingest、修复、综合分析,都应该写日志。知识库是长期资产,必须能回头看自己做过什么

这套 CLI 的设计原则是:命令数量不要太多,每个命令的语义要稳定,LLM 能看懂,用户也能看懂

CLAUDE.md 才是系统的操作手册

qmd 解决检索,CLI 解决调用,CLAUDE.md 解决行为规范。它告诉 LLM:你是谁,你能做什么,不能做什么,遇到不同任务怎么走流程,页面应该怎么写,什么时候需要问用户

每个域都应该有自己的 CLAUDE.md。里面至少包含几块内容

第一,角色定义。你要告诉 LLM,它是这个知识库的维护者,用户负责决定读什么、问什么,LLM 负责摘要、交叉引用、归档和维护。这里一定要写两条红线:不要修改 raw 下的原始文档,不要改写 log.md 的历史记录。raw 是事实来源,log 是审计记录,这两个地方不能乱动

第二,知识库定位。这个部分很重要。比如技术域就要写清楚:它关注人工系统的构造方法,以有效性为评价标准。算法的具体实现归技术域,算法的可计算性证明归形式域,技术的社会影响归社会域或哲学人文域。边界越清楚,LLM 越不容易乱放内容

第三,新会话启动流程。LLM 每次开始工作时应该先运行wiki status、wiki log-recent、wiki wip-list。这样它知道当前知识库状态、最近做过什么、有没有没完成的长文档任务。否则每个新会话都像失忆重来

第四,Ingest 流程。标准流程可以设计成:先读取 raw 文档,再用wiki find-related找已有相关页面,然后和用户确认重点,再写 source、concept、entity、synthesis,写完立刻wiki get验证,最后wiki log和wiki save。这个流程写进 CLAUDE.md 后,LLM 就不会每次自由发挥

第五,Query 流程。用户提问时,先 search,再根据结果 get 关键页面,需要原始证据时搜 raw,需要跨域时 search-cross,回答时标注依据和不确定性。这样回答会更稳

第六,页面格式。source 页面怎么写,concept 页面需要哪些字段,entity 页面怎么维护,synthesis 是否要写反面证据,wikilink 怎么命名,这些都要写清楚。LLM 最怕抽象要求,最好给具体模板

CLAUDE.md 的维护方式也很简单:一开始不用追求完美,先写一版能跑的。ingest 第一篇文章后,看哪里不满意,就把规则补进去。不要一次改很多条,一次改一条,改完用下一篇文章测试

Ingest 一篇普通文章怎么跑

普通文章,也就是几页到几十页以内,可以按这个流程走

第一步,把文章转成 Markdown,放进raw/articles/。raw 里的文件尽量保持原样,不要让 LLM 改它

第二步,让 LLM 读取原文:

wiki get “raw/articles/xxx.md”

如果文章比较长,可以先读 snippet

第三步,让 LLM 提炼文章主题,然后找已有相关页面:

wiki find-related “文章核心主题”

这一步很关键。没有这一步,LLM 很容易每篇文章都新建一堆页面,最后知识库变成碎片堆。先找相关页面,才能判断哪些概念要更新,哪些实体已经存在,哪些内容需要合并

第四步,让 LLM 先给你一个 ingest 计划。它应该说清楚:这篇文章会生成哪个 source 页面,可能更新哪些 concept,是否需要 entity,是否值得写 synthesis,有哪些地方需要你判断重点。你确认方向后,再让它写

第五步,写入 wiki 页面。source 页面保存这篇文章的摘要、关键论点、证据、提取出的概念和实体。concept 页面保存跨来源积累的概念理解。entity 页面保存人物、组织、产品等实体信息。synthesis 页面保存多篇文章之间的综合判断

第六步,写完就验证。让 LLM 用wiki get把刚写的页面读回来,检查 frontmatter、wikilink、内容完整性。如果有问题,当场修

第七步,记录日志并保存版本:

wiki log ingest “文章标题”wiki save “ingest: 文章标题”

这套流程一开始看起来比“直接问 LLM 总结文章”麻烦,但差别在于:总结是一次性输出,ingest 是把文章变成知识库的一部分。后面你再问相关问题,这篇文章会和其他页面一起参与检索和推理

200 页论文怎么处理

长文档是这套系统最值得设计的地方。一个简单原则:超过一定长度的文档,不要全文塞给 LLM

处理长文档应该分三步

第一步,先做准备。让 LLM 读取文档摘要、目录或者前几段,判断这篇文档应该拆成哪些主题。比如一篇 Transformer 论文,可能拆成 self-attention、multi-head attention、positional encoding、encoder-decoder、training strategy、evaluation、和 RNN 的对比

然后创建一个 WIP 文件,放在wiki/_wip/里。这个文件记录文档路径、主题列表、已完成主题、待处理主题、已创建页面、已更新页面。它的作用很简单:防止跨会话断掉之后不知道做到哪里

第二步,按主题处理。每次只处理一个主题,用:

wiki search-chunks “self-attention” -n 5

qmd 会在 raw 文档的块级索引里找最相关的几个片段。LLM 读这些片段后,更新对应 wiki 页面。处理完一个主题,马上更新 WIP,把这个主题从 pending 移到 completed。不要等所有主题都读完再写,因为长文档 ingest 很容易中途被上下文、网络、会话长度打断。每处理完一个主题就落盘,系统就可恢复

第三步,全部主题处理完后,再做汇总。让 LLM 搜一下这些主题之间的关系,必要时写 synthesis 页面。最后用wiki wip-done标记任务完成,再写日志

这套流程解决的核心问题是稳定性。长文档最怕三件事:上下文爆、处理中断、读了前面忘了后面。分块检索加 WIP 续传,可以把一个大任务拆成多个小任务,每个小任务都能独立完成、验证、保存

Lint 怎么做

Lint 的目标不是让 LLM 判断内容真伪。内容真伪需要来源、证据和人的判断。Lint 主要抓结构问题

比如:

  • YAML frontmatter 缺字段
  • wikilink 指向不存在的页面
  • 页面正文太短,像没写完
  • 两个 concept 页面太相似,可能重复
  • raw 文件被意外修改
  • 页面太久没复查
  • 命名格式不统一

这些问题应该用程序检查,不要让 LLM 自己凭感觉看。wiki lint可以自动跑一遍结构检查,生成报告。报告出来后,LLM 可以协助修复,但是否合并、是否重命名、是否删除重复页面,最好由用户确认

这里最重要的一项是 raw 完整性。source 页面里可以记录原始文件的 SHA-256。如果 raw 文件后来被改了,lint 就能发现。因为 raw 是整套系统的事实底座,一旦被污染,后面的 wiki 页面都不可靠

六域分类只是我的方案

我这套系统用了六域分类:形式域、自然域、技术域、心智域、社会域、哲学人文域。这个分类的核心想法是按“命题”分,不按“学科”分

比如一篇讲 AlphaFold 的文章,按学科分会很纠结:它到底算 AI、计算机、生物学、化学,还是科学哲学?按命题分会清楚一些。模型架构和工程实现属于技术域,蛋白质折叠机制属于自然域,科学发现方式的变化可能属于哲学人文域,产业影响可能属于社会域

六域的大概判断是这样的:

  1. 形式域:真值由公理推演决定,比如数学、逻辑、可计算性理论
  2. 自然域:描述客观物质过程且可证伪,比如物理、化学、生物、神经机制
  3. 技术域:描述人工系统怎么构造,以有效性评价,比如工程、软件、AI 系统实现
  4. 心智域:描述个体主体的功能性经验和行为规律,比如认知、注意力、情绪、心理机制
  5. 社会域:描述多主体互动形成的结构、规则和事件,比如经济、政治、制度、历史
  6. 哲学人文域:处理意义创造和元反思,比如哲学、文学、艺术、宗教、文化研究

但这只是我自己的分类方案,不一定适合所有人。有人可能更适合按项目分,有人适合按业务线分,有人适合按写作主题分,有人适合按“产品、技术、商业、认知、社会”这种更轻的方式分。重点不在于一定要用六域,重点在于你要有一套稳定的分类边界,让 LLM 知道内容该放哪里

如果你不想一开始就搞复杂,可以只建一个 technical,或者只建一个 personal。等内容多了,再拆域。知识库分类最好从你的真实使用场景长出来,不要为了完整而完整

shared 层怎么用

只要你有多个域,就会遇到跨域问题。比如 OpenAI 这个实体,在技术域会出现,在社会域会出现,在哲学人文域也可能出现。再比如信息熵,在形式域、自然域、技术域都有不同含义。重复写三遍会乱,硬塞到某一个域也会别扭

shared 层就是为了解决这个问题。它可以放三类页面

第一类是 shared entities,比如 OpenAI、Claude、Transformer、某个作者、某个机构。第二类是 shared concepts,比如信息熵、复杂性、反馈、系统、模型这类跨域概念。第三类是 bridges,用来记录两个域之间的连接

bridge 页面不需要写得很复杂,它只要说明:A 域的哪个概念和 B 域的哪个概念有关,它们为什么有关,相似在哪里,差异在哪里,各自链接到哪些页面

这样做的好处是,跨域关系不会污染单个域的边界,也不会丢失。你在 Obsidian 里看图谱时,也能看到不同知识区域之间的桥

Obsidian 和 Git 的角色

Obsidian 在这套系统里更像 IDE。你可以用它看 wiki 页面、看 wikilink、看图谱、做人工编辑。qmd 负责搜,LLM 负责维护,Obsidian 负责可视化和人工阅读

Git 负责版本控制。每次 ingest、lint 修复、synthesis 更新,都可以提交一次。这样你能回看知识库的变化过程。如果 LLM 哪次改坏了,也可以回滚

这两个工具都很朴素,但很重要。知识库不是聊天记录,不能只存在会话里。它应该落到文件系统里,能被搜索,能被版本管理,能被人打开阅读

怎么从零搭建

如果你想自己做一套,最小版本可以这样来

第一步,安装 qmd

npm install -g @tobilu/qmd

第二步,建目录。先不要追求六域完整,选一个你最常用的领域,比如 technical。目录里放 raw、wiki、CLAUDE.md。wiki 下面建 sources、concepts、entities、synthesis、_wip、log.md

第三步,写一个最简单的bin/wiki。先只封装几个命令:init、reindex、search、get、find-related、search-chunks、log、status。不要一开始就写 580 行,先让核心流程跑起来

第四步,注册 qmd Collection。把 raw、sources、concepts、entities、synthesis 分开注册。给每个 Collection 写清楚 context description

第五步,写 CLAUDE.md。先写角色、禁区、ingest 流程、query 流程、页面模板、新会话启动流程。规则不要太抽象,尽量用具体例子

第六步,找三篇最近读过的文章试跑。第一篇主要用来暴露问题,第二篇用来调整 CLAUDE.md,第三篇看流程是否稳定。这个阶段不要追求知识库规模,重点是把 LLM 的行为调顺

第七步,加 lint。先检查最简单的:frontmatter、broken wikilink、stub 页面、raw 文件是否被改。后面再慢慢加重复概念、过期页面、跨语言重复这些检查

第八步,处理长文档。等普通文章流程稳定后,再加search-chunks和 WIP 机制。不要一开始就拿 200 页论文测试,会让你很难判断问题出在流程、分类、命令还是文档本身

这个顺序很重要。先做最小闭环,再扩展能力。最小闭环就是:放入文章 → LLM ingest → qmd 检索 → 更新 wiki → log 记录 → 下次能搜到

这套方案解决了什么

回到开头的五个问题

  1. 规模天花板怎么解?靠 qmd 检索。知识库大了之后,LLM 不再扫描全量文件,而是先 search,再 get 相关页面
  2. 超长文档怎么解?靠 search-chunks 和 WIP。长文档按主题拆开,每次只读几个相关块,处理完一个主题就落盘
  3. 成本怎么降?靠检索前置。查询时不读全库,ingest 时不扫全量页面,长文档不读全文。LLM 的成本花在真正需要理解和写作的地方
  4. 冷启动怎么过?靠 CLAUDE.md 和前三篇文章调校。先写一版规则,拿真实文章跑,发现问题立刻补规则。不要幻想一开始就完美
  5. Lint 幻觉怎么处理?内容判断不要交给 lint,结构问题交给程序。broken link、frontmatter、stub、raw hash、重复页面,这些都可以自动查

这五个问题都没有被“自动消灭”。更准确地说,这套架构给了它们一个可控的处理方式。知识库系统很难一劳永逸,关键是每个问题出现时,你知道它属于哪一层,该用什么机制处理

写在最后

这套 LLM Wiki 的核心,其实可以用一句话概括:把读过的东西,编译进一个长期可维护的知识系统里

qmd 负责让 LLM 找得到资料,CLAUDE.md 负责让 LLM 按规矩办事,CLI 负责把操作变稳定,文件系统负责让知识真正落地,Obsidian 和 Git 负责让它可视化、可回滚、可长期维护。它们各自只做一件事,但组合起来,就能形成一个比较完整的个人知识编译系统

如果你只是想临时问答,普通 RAG 或文档问答工具已经够用。把文档丢进去,问几个问题,拿到答案,这种场景没必要搞得太重。但如果你想把长期阅读、研究、写作沉淀成自己的知识资产,希望一篇文章读完之后,不只是生成一次总结,而是能进入你的概念体系、问题体系和写作素材库,那这套方案会更适合

当然,六域分类只是我自己的设计,不需要照搬。有人适合按学科分,有人适合按项目分,有人适合按业务线分,也有人适合按“技术、产品、商业、认知、写作”这种更贴近日常使用的方式分。真正值得参考的不是六域本身,而是背后的实现思路:原始资料和整理页面分层,检索和写作分层,规则和执行分层,短文档和长文档分流程,人工判断和程序检查分工

所以刚开始不用想太复杂。选一个你最常读的领域,找三篇最近读过的文章,先把 ingest 跑通。第一篇用来暴露问题,第二篇用来调整 CLAUDE.md,第三篇基本就能看出这套流程适不适合你。知识库不是搭出来就完成的东西,它会随着你的输入持续生长。真正重要的不是第一版多完美,而是它能不能在你持续阅读、持续提问、持续写作的过程中,一直长下去

这篇没有把所有代码逐行贴出来,因为代码本身不是重点,重点是把完整的构建思路讲清楚:为什么用 qmd,目录怎么拆,CLI 怎么封装,CLAUDE.md 怎么设计,普通文章怎么 ingest,长文档怎么续传,Lint 怎么检查,分类方案怎么调整。理解了这些,你完全可以按自己的使用习惯搭一套

作者:秋孝隱

扫一扫 微信咨询

联系我们 青瓜传媒 服务项目

商务合作 联系我们

本文经授权 由青瓜传媒发布,转载联系作者并注明出处:https://www.opp2.com/381715.html

《免责声明》如对文章、图片、字体等版权有疑问,请联系我们广告投放 找客户 找服务 蘑菇跨境
企业微信
运营大叔公众号
运营宝库
运营宝库H5