ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

知识库编译成Wiki:把检索权交给LLM的工程实践

知识库编译成Wiki:把检索权交给LLM的工程实践

1. 为什么要把知识库“编译”成 Wiki

第一次听到“LLM Wiki”这个词,很多人会下意识地把它理解成“给大模型用的维基百科”。这个理解只对了一半。真正做过知识库落地的人会明白,Wiki 在这里不是指某个具体网站,而是指一种结构化的、可被人和机器同时阅读的知识组织形态。把知识库编译成 Wiki,本质上是把散落在各种文档、表格、聊天记录里的原始素材,转换成一套带层级、带链接、带语义边界的知识节点集合。

我最早接触这个思路,是在处理一个内部技术文档库的时候。当时库里有三千多篇 Markdown、几百个 PDF,还有一堆从聊天工具里导出的问答记录。直接拿去做向量检索,效果惨不忍睹——问“某个接口的超时配置在哪”,检索出来的却是另一篇讲部署流程的文章,因为两篇都出现了“超时”这个词。问题不在于向量模型不行,而在于原始知识本身没有被组织过。向量检索是在一堆没有骨架的肉里找一块特定的肌肉,找不到是正常的。

把知识库编译成 Wiki,解决的正是这个“骨架缺失”的问题。它要求我们在入库之前,先做一轮结构化的整理:把一篇长文档拆成若干语义完整的节点,给每个节点一个稳定的标题和路径,建立节点之间的引用关系,标注每个节点适用的范围和前提条件。做完这一步,知识库才真正具备了被检索的价值。

这里有个关键判断:不是所有知识库都值得编译成 Wiki。如果你的知识库只有几十篇文档,且内容高度同质,直接做全文检索就够了,编译反而是过度工程。但如果你的知识库满足下面任意一条,编译就是必须的:

  • 文档数量超过五百篇,且来源多样
  • 同一个概念在不同文档里有不同表述,甚至互相矛盾
  • 存在大量“前提条件”,比如某个配置只在特定版本下有效
  • 需要支持多轮追问,而不是一问一答

我见过太多团队跳过这一步,直接上向量数据库,结果调了三个月参数,召回率还是上不去。根因不在检索层,在知识层。

1.1 Wiki 形态和普通知识库的本质区别

普通知识库的存储单位是“文档”,Wiki 的存储单位是“节点”。这个区别听起来很小,实际影响巨大。

一篇文档里往往混杂了多个主题。比如一篇讲“服务部署”的文档,前半部分讲环境准备,中间讲配置项,最后讲回滚流程。如果整篇作为一个检索单位,向量会被平均掉,任何一个具体问题的相似度都不高。而 Wiki 形态要求把它拆成三个节点:环境准备、配置项说明、回滚流程。每个节点只讲一件事,向量表达就精准了。

另一个区别是链接。普通知识库的文档之间是孤立的,Wiki 的节点之间是有向图。当 LLM 检索到“配置项说明”这个节点时,它能顺着链接找到“环境准备”和“回滚流程”,从而获得完整的上下文。这一点在 Agent 场景下尤其重要,因为 Agent 需要的不只是一个答案,而是答案所在的完整决策链。

还有一个容易被忽略的区别:Wiki 节点带有明确的边界声明。每个节点会写清楚“本文适用于哪个版本”“不适用于什么情况”。这看起来是负担,实际上是给 LLM 的护栏。没有边界的知识,LLM 会过度泛化,把只在特定条件下成立的结论当成普遍真理。

1.2 编译这个词的准确含义

我用“编译”而不是“整理”或“转换”,是有意为之。编译在计算机里指的是把高级语言翻译成机器能执行的形式,这个过程包含词法分析、语法分析、语义分析、优化、代码生成。知识库编译成 Wiki,流程惊人地相似。

词法分析对应的是切分:把原始文档切成最小语义单元。语法分析对应的是结构识别:判断这些单元之间的层级和顺序关系。语义分析对应的是概念归一:把不同表述的同一概念合并,把同名但不同义的概念区分开。优化对应的是去重和精简:删掉冗余表述,保留核心信息。代码生成对应的是节点输出:生成带标题、路径、链接、边界的 Wiki 节点。

这个类比不是文字游戏。它意味着知识库编译应该像编译器一样,是一个可重复、可验证、可增量的过程。原始文档更新了,不需要重新编译整个库,只需要重新编译受影响的节点。这一点在知识库规模上去之后,是能不能维护下去的分水岭。

2. 检索权交给 LLM 到底意味着什么

“把检索权交给 LLM”这句话,是这套方法论里最容易被误读的部分。很多人第一反应是:让 LLM 直接去读整个知识库,然后回答问题。这在知识库小的时候可行,一旦超过上下文窗口,就彻底失效。所以这里的“交给 LLM”,不是让 LLM 承担存储和全量扫描,而是让 LLM 承担检索决策。

传统检索的流程是固定的:用户提问 → 向量化 → 相似度匹配 → 返回 Top-K → 拼进 Prompt。这个流程里,LLM 只在最后一步参与,前面全是机械的。问题在于,用户的提问往往不是一次检索能解决的。比如问“为什么我的服务启动失败”,可能需要先检索错误码,再根据错误码检索对应的配置项,再根据配置项检索版本兼容性说明。这是一个多跳过程,固定流程做不到。

把检索权交给 LLM,就是让 LLM 来决定:下一步该查什么。它拿到用户问题后,先判断需要哪些信息,然后生成检索请求,拿到结果后判断信息是否足够,不够就继续查,够了就组织答案。这个过程中,LLM 是检索的调度者,而不是被动的消费者。

2.1 检索权转移的三个层次

我把这个转移分成三个层次,方便你判断自己的项目该做到哪一层。

第一个层次是查询改写。LLM 不直接检索,而是先把用户的口语化问题改写成适合检索的形式。比如用户问“那个超时怎么调”,LLM 改写成“服务调用超时时间配置项”。这一步不需要多跳,但能显著提升召回率。实现成本低,收益明显,适合作为起点。

第二个层次是多跳检索。LLM 根据第一轮检索结果,决定是否需要第二轮、第三轮检索。每一轮的查询词由 LLM 根据已有信息生成。这一步需要 LLM 具备一定的推理能力,且需要给检索工具设计清晰的接口。实现成本中等,但对复杂问题的效果提升很大。

第三个层次是检索策略选择。知识库里可能同时存在向量索引、关键词索引、图索引。LLM 根据问题类型,决定用哪种索引,甚至组合使用。比如事实性问题走向量,关系性问题走图,精确匹配走关键词。这一步实现成本最高,但在知识库结构复杂时是必要的。

大部分项目做到第二个层次就够用了。第三个层次适合知识库规模超过万级节点、且查询类型高度多样的场景。

2.2 为什么不能让 LLM 直接读全库

这里要专门说一下,因为这是最常见的误区。有人会想,既然 LLM 上下文窗口越来越大,那直接把整个知识库塞进去不就行了。

三个现实问题让这条路走不通。第一是成本。每次提问都把全库塞进 Prompt,token 消耗是检索方案的几十倍甚至上百倍。第二是注意力稀释。上下文越长,LLM 对中间部分的注意力越弱,关键信息容易被淹没。第三是更新延迟。知识库一更新,所有缓存全部失效,响应时间不可控。

所以“检索权交给 LLM”的前提,是知识库已经被编译成结构良好的 Wiki 节点。LLM 检索的是节点,不是原始文档。节点足够小,可以精确匹配;节点足够结构化,可以顺着链接跳转。这才是可行的路径。

2.3 检索权和生成权的分离

还有一个设计上的关键点:检索权和生成权要分离。LLM 决定查什么,但查到的内容不能直接由同一个 LLM 无约束地改写。原因很简单,LLM 在生成时会有幻觉,如果它同时负责检索和生成,一旦检索结果不理想,它可能用幻觉来填补。

我的做法是,检索阶段用一个 LLM 实例,只负责生成查询和判断信息充分性,不生成最终答案。生成阶段用另一个实例,只负责基于检索到的节点组织答案,不允许引入节点之外的信息。两个实例的 Prompt 完全不同,职责边界清晰。这样即使生成阶段出现幻觉,也能通过对比检索节点快速定位。

3. 知识库编译成 Wiki 的完整实操流程

前面讲的是思路,这一部分讲具体怎么做。我按实际项目里的顺序,把流程拆成六步。每一步都有踩过的坑,我会标出来。

3.1 第一步:原始素材的盘点与分类

在动手编译之前,先花时间盘点。我见过太多人跳过这一步,直接开始切分,结果切到一半发现素材里有大量重复和矛盾,返工成本极高。

盘点的产出是一张表,记录每个素材的来源、类型、更新频率、可信度。可信度这一列很重要,因为不同来源的素材冲突时,需要有一个优先级。比如官方文档的可信度高于聊天记录,最新版本的高于旧版本。

素材来源类型更新频率可信度处理策略
官方产品文档Markdown季度高全量编译
内部技术方案PDF不定期高全量编译
聊天问答记录文本每日中筛选后编译
历史邮件文本不定期低仅提取结论
外部参考资料网页不定期中人工审核后编译

这张表不是形式主义。它决定了后续编译的优先级和资源分配。可信度低的素材,不要花太多时间做精细切分,提取核心结论就够了。

注意:盘点阶段一定要和素材的维护者确认更新频率。我遇到过一次,某份文档标注是季度更新,实际已经两年没动过,里面的配置项早就废弃了。如果按季度更新来处理,会浪费大量编译精力。

3.2 第二步:语义切分与节点定义

切分是编译里最考验判断力的一步。切得太粗,节点内部主题混杂,检索不准;切得太细,节点之间上下文断裂,LLM 拼不出完整答案。

我的经验是,按“一个节点回答一个问题”来切。具体操作时,先通读文档,在每一个主题转换的地方做标记。主题转换的信号通常有:出现新的小标题、出现“另外”“接下来”“需要注意的是”这类转折词、举例结束回到论述。

切分完之后,给每个节点定义一个稳定的路径。路径的格式建议是“领域/子领域/主题”。比如“部署/环境准备/依赖安装”。路径的作用是给 LLM 一个空间感,让它知道这个节点在知识体系里的位置。

这里有个坑:不要用文档原有的标题作为节点标题。文档标题往往是为了阅读流畅,不是为了检索精确。比如“一些注意事项”这种标题,检索时毫无信息量。要改写成“配置项修改时的三个兼容性注意事项”这种自带语义的标题。

3.3 第三步:概念归一与冲突消解

这一步是编译的核心价值所在。同一个概念在不同文档里可能有不同叫法,比如“超时时间”“超时时长”“timeout”,如果不归一,检索时会漏掉。反过来,同一个词在不同语境下可能指不同东西,比如“节点”在部署语境下指服务器,在图结构语境下指数据点,如果不区分,检索时会混入无关内容。

我的做法是建一张概念表,记录每个标准概念和它的所有别名,以及它的适用语境。这张表在编译时用来做替换和标注,在检索时用来做查询扩展。

冲突消解更麻烦。当两份素材对同一件事给出不同说法时,不能简单取最新的,因为旧说法可能对应旧版本,仍然有效。我的处理方式是保留两个节点,但在节点里明确标注适用版本和适用条件。然后在两个节点之间加一条“互斥”链接,提示 LLM 这两个结论不能同时使用。

提示:冲突消解不要追求一次性做完。知识库是活的,冲突会不断出现。更好的做法是建立一个冲突登记表,每次发现冲突就登记,定期集中处理。这样不会阻塞编译进度。

3.4 第四步:链接建立与图结构生成

节点建好之后,要建立节点之间的链接。链接分三种:层级链接、引用链接、互斥链接。

层级链接是父子关系,比如“环境准备”是“依赖安装”的父节点。引用链接是相关内容之间的跳转,比如“配置项说明”引用“版本兼容性”。互斥链接是前面提到的,标注两个节点不能同时使用。

链接的建立可以半自动化。先用规则匹配,比如两个节点共享超过三个关键词就建立候选链接,然后人工审核。完全自动的链接质量不可控,完全人工的效率太低。半自动是平衡点。

图结构生成之后,要做一个连通性检查。如果发现某些节点是孤立的,没有任何链接,要么是切分时漏了关联,要么是这个节点本身冗余,可以考虑合并或删除。

3.5 第五步:节点内容的标准化输出

每个节点最终要输出成标准格式。我用的格式是 YAML 头加 Markdown 正文。YAML 头里放元数据:节点 ID、路径、标题、适用版本、适用条件、最后更新时间、可信度。正文里放具体内容,控制在 300 到 800 字之间。

为什么是 300 到 800 字?太短信息不完整,太长向量表达会被稀释。这个区间是实测下来检索效果最好的。超过 800 字的节点,考虑再切分。

正文的写法也有讲究。第一句必须是这个节点的核心结论,因为检索时第一句的权重最高。后面再展开解释。这样即使 LLM 只读了第一句,也能拿到关键信息。

3.6 第六步:增量编译与版本管理

知识库编译不是一次性的。原始素材更新后,要能增量编译。这就要求每个节点记录它来源于哪个原始素材的哪个版本。素材更新时,对比版本差异,只重新编译受影响的节点。

版本管理用 Git 就够了。每次编译提交一次,节点的新增、修改、删除都有记录。出问题时可以回滚到任意历史版本。这一点在知识库规模大了之后,是救命的。

4. 检索权交给 LLM 的具体实现

编译完成后,知识库变成了一堆结构化的 Wiki 节点。接下来是让 LLM 来检索这些节点。这一部分讲具体实现。

4.1 检索工具的设计

LLM 要检索,得给它工具。工具的设计要遵循一个原则:接口简单,语义清晰。我通常给三个工具。

第一个是search_nodes,输入查询词,返回匹配的节点列表,每个节点返回 ID、标题、路径、摘要。第二个是get_node,输入节点 ID,返回节点完整内容。第三个是follow_link,输入节点 ID 和链接类型,返回关联节点列表。

这三个工具的组合,能覆盖大部分检索场景。LLM 先用search_nodes找到候选,再用get_node读取详情,需要扩展时用follow_link跳转。

工具的返回格式要固定,方便 LLM 解析。我用的格式是 JSON,字段名固定,不返回多余信息。返回内容里不要有自然语言解释,解释由 LLM 自己生成。

4.2 检索循环的控制

LLM 检索时容易陷入两个极端:要么查一次就停,信息不够;要么反复查,停不下来。需要设置控制机制。

我的做法是设置最大检索轮次,通常是 5 轮。每轮结束后,让 LLM 判断信息是否充分。判断的标准写在 Prompt 里:如果已经能回答用户问题,且答案有节点支撑,就停止;如果还缺关键信息,继续查;如果连续两轮没有新信息,停止。

这个判断逻辑要写清楚,不能含糊。含糊的 Prompt 会让 LLM 在该停的时候不停,或者不该停的时候停。

4.3 检索结果的组装

检索结束后,LLM 拿到了一组节点。这些节点要组装成最终答案。组装时要注意三点。

第一,只使用检索到的节点内容,不允许 LLM 引入外部知识。这一点要在 Prompt 里反复强调。第二,标注信息来源,每个结论后面标注来自哪个节点,方便用户核查。第三,处理节点间的冲突,如果检索到的节点有互斥链接,要在答案里说明两种情况的适用条件,让用户判断。

组装后的答案要简洁,不要把所有节点内容都堆上去。LLM 要做的是提炼和综合,不是复制粘贴。

4.4 一个完整的检索示例

假设用户问:“服务启动时报超时错误,怎么排查?”

第一轮,LLM 生成查询“服务启动 超时 错误 排查”,调用search_nodes,返回三个候选节点:超时错误码说明、启动流程配置项、网络连接检查。

第二轮,LLM 调用get_node读取三个节点。发现超时错误码说明里提到“超时可能是依赖服务未就绪导致”,于是生成新查询“依赖服务 就绪检查”,调用search_nodes。

第三轮,找到“依赖服务就绪检查”节点,读取后发现需要检查健康检查接口配置。此时 LLM 判断信息充分,停止检索。

第四轮,LLM 组装答案:先说明超时的常见原因,再给出排查步骤,每一步标注来源节点。答案里包含错误码说明、配置项检查、依赖服务检查三个部分,逻辑完整。

这个示例里,LLM 做了三次检索决策,每次决策都基于上一轮的结果。固定流程做不到这一点,因为固定流程不知道第一轮之后该查什么。

5. 常见问题与排查技巧实录

这一部分是我在实际项目里踩过的坑,整理成速查表。每个问题都附了排查思路和解决方法。

问题现象可能原因排查方法解决方法
检索结果总是无关节点切分过粗,主题混杂随机抽 10 个节点,看是否只讲一件事重新切分,按“一个节点一个问题”原则
检索结果重复概念未归一,同一概念多个节点搜索同一概念的不同叫法建立概念表,合并重复节点
LLM 检索停不下来停止条件不明确查看检索日志,看每轮是否有新信息明确停止条件,设置最大轮次
答案有幻觉生成阶段引入了外部知识对比答案和检索节点强化 Prompt,禁止引入节点外信息
节点更新后检索失效增量编译未触发检查素材版本和节点版本建立版本对比机制,自动触发重编译
多跳检索断链链接建立不完整检查节点连通性补充引用链接,做连通性检查
检索速度慢节点数量过大,索引未优化查看检索耗时分布分层索引,先粗筛再精排

除了表里的问题,还有几个经验性的技巧。

技巧一:给节点加“反例”字段。有些节点讲的是“什么情况下适用”,但 LLM 容易过度泛化。加一个“不适用情况”字段,明确写出这个节点不适用于什么场景,能有效减少误用。

技巧二:检索日志要保留。每次检索的查询词、返回节点、LLM 的决策过程都要记录。出问题时,日志是唯一的排查依据。我通常保留最近一个月的日志,定期分析高频查询和失败查询。

技巧三:定期做检索质量评估。准备一组标准问题,每个问题有标准答案和标准来源节点。定期跑一遍,看召回率和准确率。质量下降时能及时发现。

技巧四:节点标题要包含同义词。比如“超时配置”这个标题,可以在后面加括号写上“超时时长、timeout”。这样检索时命中率更高。标题是检索的第一入口,值得多花心思。

技巧五:不要追求一次编译完美。知识库编译是迭代过程。先编译一版能用的,上线跑起来,根据实际检索效果再优化。我见过团队花三个月做完美编译,结果上线后发现用户的问题类型和预期完全不同,白费功夫。

6. 工具选型与工程化建议

最后说一下工具选型。这部分不是必须的,但能帮你少走弯路。

编译阶段,我用 Python 脚本加 LLM API。脚本负责切分、归一、链接生成,LLM 负责语义判断和内容改写。为什么不全部用 LLM?因为切分和链接生成有大量规则性工作,用脚本更快更稳定。LLM 只用在需要语义理解的地方。

存储阶段,节点用 Markdown 文件存 Git,索引用轻量级向量库。不建议一上来就用重型向量数据库,节点数量在万级以下时,轻量级方案完全够用,且更容易调试。

检索阶段,LLM 的选型要看任务复杂度。查询改写用轻量模型就够,多跳检索和答案组装用能力更强的模型。分开选型能控制成本。

工程化方面,最重要的是可观测性。每次检索的输入输出、每轮决策、耗时、token 消耗都要记录。没有可观测性,出了问题只能猜。我通常用一个简单的日志表,记录这些字段,定期分析。

还有一个建议:先做小规模验证。选一个子领域的知识库,比如只编译“部署”相关的文档,跑通全流程,验证效果。效果达标再扩展到全库。全库编译的复杂度是子领域的十倍以上,直接上全库容易失控。

这套方法我在几个项目里跑过,知识库规模从几百节点到几万节点都有。规模越大,前期编译的投入回报越明显。小规模时可能感觉不到优势,但一旦超过某个临界点,没有编译的知识库会迅速变得不可维护。这个临界点,我的经验是五百个节点左右。低于这个数,怎么搞都行;高于这个数,不编译就是给自己挖坑。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进