知识库这道题,答案比想象中多

知识库方案对比

最近半年,找我聊知识库的人明显多了。不只是技术同学,连业务方也开始问:"我们能不能搞一个内部知识库,让AI帮我们查文档?"

这个需求听起来简单——把公司的文档、代码、wiki全喂给AI,问什么答什么,多美好。但真正动手做过的人才知道,"知识库"三个字背后,方案差异大得离谱。

我自己从去年开始陆陆续续试过几种路线,有些效果超出预期,有些踩了不小的坑。趁记忆还新鲜,把目前市面上比较热的路线梳理一下。

最朴素的做法:切片 → 向量化 → 检索 → 生成

这是大部分人入门RAG的方式,也是很多教程里的"标准答案"。把文档切成几百token的小块,用embedding模型转成向量,存进向量数据库,查询的时候找最相似的几块拼到prompt里让模型回答。

这个方案能跑。对于文档量不大、问题比较直接的场景(比如FAQ、简单的产品手册问答),效果还行。

但它有一个根本性的问题:切片会破坏上下文。

举个例子。一份财报里有一段写"营收同比增长12%",被单独切出来之后,它属于哪家公司、哪个季度、跟谁比的——全丢了。用户问"A公司Q3营收增速多少",向量检索可能找到一堆"营收增长"的片段,但答不对。

我们最早做内部知识库时就遇到了这个问题。技术文档里到处都是"该接口"、"这个配置"、"上一节提到的参数"这种依赖上下文的表述,切片之后完全不知道在说什么。

Contextual Retrieval:给每个片段补一句"我是谁"

Anthropic去年提出了一个思路,我觉得挺巧妙的。他们不改变检索架构,而是在入库之前,让模型先给每个片段加一段简短的上下文说明。

比如原来一个片段是"The company's revenue grew by 3% over the previous quarter",入库时会被改成:"This chunk is from an SEC filing on ACME Corp's performance in Q2 2023; the previous quarter's revenue was $314 million. The company's revenue grew by 3% over the previous quarter."

就多了前面那几十个字,检索准确率提升了将近50%。配合BM25做混合检索(语义+关键词匹配),检索失败率能降67%。

这个方案的优点是改动小、兼容性强,可以叠加在其他方案上面。缺点也很明显——每个片段都要调一次模型来生成上下文,文档量大的时候,光这一步的token消耗就不低。Anthropic自己做这个实验用的是Claude的prompt caching来降成本,但换了别的模型,这笔开销得好好算算。

我自己试下来,对中小规模的知识库(几千页以内),这是目前性价比最高的改进方式。但如果文档量到了几十万页的级别,成本就上来了。

GraphRAG:不找片段,找关系

微软研究院的GraphRAG走了一条完全不同的路。它不是把文档切成片段存起来,而是先用LLM从文档里抽取实体和关系,构建一张知识图谱。然后对图谱做社区聚类,给每个社区生成摘要。查询的时候,不直接检索文档片段,而是基于图谱结构和社区摘要来回答。

这个方案在回答"全局性"问题时优势很大。比如"这份数据集里有哪些主题?"、"这几个项目之间有什么关联?"——这类问题需要跨文档的综合理解,传统RAG基本答不上来,GraphRAG可以。

但代价是入库成本非常高。每一批文档都要跑一遍图谱抽取和社区聚类,这个过程需要大量的LLM调用。我们之前在一个中等规模的项目上试,几万篇文档的索引构建花了大半天时间,而且token费用相当可观。

另一个问题是,图谱的质量高度依赖抽取的prompt。如果实体关系抽错了,后面的检索和回答就全歪了。这需要针对你的领域反复调prompt,不是开箱即用的那种方案。

我目前的判断是:如果你的知识库需要回答大量"关联型"问题(比如客户360画像、供应链溯源),GraphRAG值得投入。如果只是做普通的文档问答,有点杀鸡用牛刀。

Corrective RAG:检索完了,先判一下靠不靠谱

CRAG的思路是在检索之后、生成之前,加一个"评估器"。它会判断检索出来的文档质量够不够好——如果够好,就用;如果不好,就触发补救措施,比如用搜索引擎去网上找补充材料,或者对检索结果做二次筛选。

这个方案解决的是"检索到了垃圾怎么办"的问题。在实际业务中,知识库不可能覆盖所有问题,用户问到知识库里没有的内容时,传统RAG会硬凑一个答案出来,幻觉就是这么来的。CRAG至少能在检索不靠谱的时候踩一脚刹车。

实现上不复杂,一个分类器就能搞定。但它增加了一次模型调用,延迟会涨。而且那个"评估器"本身也需要训练或调prompt,效果取决于你对"什么是好检索"的定义有多清晰。

Agentic RAG:让Agent来决定怎么找

这是最近讨论比较多的一个方向。与其写死一套检索流程(切片→检索→拼接→生成),不如让AI Agent自己决定:这个问题需要查哪些数据源?检索结果够不够?要不要换个关键词再查一次?要不要交叉验证?

好处是灵活。不同的问题走不同的检索路径,复杂问题可以分多步拆解,还可以同时调用向量检索、全文搜索、SQL查询、API调用等多种工具。相当于把检索策略从"固定管线"变成了"动态决策"。

但这也意味着系统的不可预测性增加了。Agent可能在一个简单问题上绕很多圈才给答案,也可能在复杂问题上偷懒只查了一次就下结论。调试起来比传统管线复杂得多,而且每次查询可能触发多次LLM调用,成本和延迟都不好控制。

我自己的观察是,Agentic RAG在"复杂研究型问题"上效果很好——比如竞品分析、技术选型调研这种需要多源交叉验证的场景。但对大部分内部知识库问答来说,有点过头了。

LLM Wiki:让AI替你维护知识库

今年4月,Andrej Karpathy发了一个GitHub Gist,提出了一个挺有意思的思路:大部分RAG系统让模型每次从零检索答案,知识从来不积累。更好的做法是让模型增量构建并维护一个持久的、互相链接的结构化知识库——知识被"编译"一次并持续更新,而不是每次查询都重新推导。

这个gist在Hacker News上拿了近300分,催生了不少开源实现,其中一个跨平台桌面应用5个月冲到了1.9万星。

LLM Wiki的核心类比很直觉:RAG是外卖员——你饿了才去取货,每次从原材料仓库里现找现拼。LLM Wiki是农场主——在你饿之前就把食材种好、加工好、分类存好。

它把知识库分成三层。最底层是原始资料——文章、论文、代码、文档,只读不改,作为事实来源。中间层是Wiki——完全由LLM拥有和维护的一堆Markdown文件,实体页、概念页、摘要页、综合页,互相用链接串起来。最顶层是Schema——一份规则文档,告诉LLM wiki怎么组织、有什么页面类型、按什么流程维护。

这个模式跟传统RAG的区别在于处理时机。RAG是查询时实时检索,LLM Wiki是文档写入时就预编译。RAG解决"精准召回",LLM Wiki解决"知识质量"。两者不互斥——最佳实践是LLM Wiki提供高质量语料,RAG负责精准定位。

腾讯有个数据团队在直播数据场景中落地了这套方案,据说血缘查询时间从30分钟降到2分钟,SQL生成时间从半天降到10分钟。不过这是他们的特定场景,效果能不能复制到其他领域还需要验证。

局限也很明显。首先是成本——每次文档摄入都是多次LLM调用(分析→生成→交叉引用→更新目录),token消耗远高于朴素RAG索引。其次是规模天花板——索引导航在100个来源、几百个页面左右表现不错,再往上就不太好说了。另外整个wiki由LLM维护,质量上限取决于模型能力,所以需要额外的校验机制来防止LLM幻觉污染知识库。

OpenViking:给Agent用的上下文数据库

火山引擎开源的OpenViking走的是另一条路。它不是给人用的知识库,而是给AI Agent用的"上下文存储基础设施"。

核心思路是把Agent需要的记忆、资源、技能统一组织成一个虚拟文件系统(用viking://协议寻址),Agent像操作文件一样操作上下文。它有分层加载机制——L0是基础信息,L1是相关上下文,L2是深度细节——Agent根据任务需要逐层加载,避免一次性把太多无关信息塞进上下文窗口。

它甚至有个ov compile命令,可以把资料编译成类似wiki的结构。但跟LLM Wiki的区别在于,OpenViking是面向Agent检索优化的,人一般不直接浏览它的内容。

如果你在搭建一个需要长期记忆的Agent系统(比如一个能跨多轮对话持续工作的编码助手),OpenViking值得关注。但如果你只是想给团队做个文档问答系统,它的复杂度有点过了。

Mem0:Agent的记忆层

Mem0解决的是一个更聚焦的问题:让AI记住用户和对话历史。它会自动从对话中提取关键信息(用户偏好、历史决策、上下文状态),存成一个结构化的记忆层,下次对话时自动检索相关记忆注入上下文。

跟LLM Wiki的区别很清晰:LLM Wiki是"Agent从你的文档中学到的东西",Mem0是"Agent记得关于你的事"。一个面向知识,一个面向用户。两者可以互补——知识库用RAG/LLM Wiki提供领域知识,Mem0提供用户个性化记忆。

实际场景中,我觉得Mem0更适合面向C端的AI产品(比如一个能记住你习惯的私人助理),而不是内部知识库。

长上下文暴力塞入:有时候最简单的方案够用

说实话这个方案有点不好意思单独拿出来说,因为它太"暴力"了——如果你的知识库足够小,直接把所有文档塞进模型的上下文窗口就行,什么检索都不需要。

现在有些模型已经支持200k甚至更长的上下文了。配合prompt caching(把常用prompt缓存起来,后续调用直接复用),延迟和成本都可以接受。Anthropic之前的测试显示,对于200k token以内的知识库(大约500页),暴力塞入的效果并不比RAG差。

当然这个方案有明显上限。知识库超过了上下文窗口就没办法了,而且每次请求都发送完整的知识库,即使有cache,带宽成本也不低。但对于一些特定场景——比如一个产品的FAQ、一个小团队的操作手册、一个项目的核心文档——简单粗暴反而是最优解。

Self-RAG:模型自己学会什么时候该查

学术界还有一种思路,通过训练让模型自己判断"这个问题我需要检索吗"以及"检索到的内容跟我的回答相关吗"。模型在生成过程中会产出一种叫"reflection token"的特殊标记,用来表达对自己输出的反思。

这个方向的研究意义很大,但工程落地还比较远。需要专门fine-tune模型,而且reflection token的质量依赖训练数据。目前更像是一种"未来的可能性",而不是今天就能拿来用的方案。

Late Chunking:先编码再切片

Jina AI提出的Late Chunking跟传统流程正好反过来。传统做法是先切片再编码,它先把整篇文档送进一个长上下文embedding模型做编码,然后再把embedding向量按chunk切分。这样每个chunk的向量实际上包含了整篇文档的上下文信息。

这个方案的好处是检索质量高,因为向量本身就编码了全局上下文,不会出现"片段不知道自己属于哪篇文档"的问题。缺点是对embedding模型有要求——需要支持足够长的上下文输入,而且长文档编码的计算成本不低。

目前这个方向还在演进中,Jina的长上下文embedding模型能处理到8k token。对于大部分文档来说够用了,但如果是特别长的技术文档或法律合同,可能还是会有截断。

怎么选?我的一些直觉

聊了这么多方案,说几点我自己的判断。不一定对,供参考。

如果知识库在500页以内,先试试暴力塞入。长上下文模型 + prompt caching,工程成本接近于零,效果往往不差。

如果是几千页到几万页的规模,朴素RAG + Contextual Retrieval + 混合检索(向量+BM25)是目前最稳的组合。改动小、效果可验证、成本可控。

如果文档之间有大量关联关系需要推理,可以考虑叠加GraphRAG或LLM Wiki。前者更偏"查询时建图",后者更偏"入库时建图"。GraphRAG适合回答全局性问题,LLM Wiki适合需要持续积累、知识越来越丰富的场景。

如果你在搭建一个需要长期记忆的Agent,OpenViking和Mem0值得关注——一个管上下文存储,一个管用户记忆,可以组合使用。

如果面对的是复杂研究型问题(竞品分析、技术选型调研),Agentic RAG可能更适合。但这基本是在搭建一个Agent系统了,知识库只是它的数据源之一。

这些方案之间不是互斥的。我自己目前在用的组合是Contextual Retrieval做入库增强 + 混合检索做查询 + CRAG做兜底,同时在一个小范围项目里试点LLM Wiki。效果在我们的场景下还不错。

不过说实话,知识库这件事,技术方案只占一半。另一半更难的问题在于:数据质量、文档更新频率、用户预期管理。文档本身就是过时或错误的,再好的检索方案也救不了。

每个团队的场景不一样,照搬别人的方案不如搞清楚自己的问题在哪。先把"用户最常问什么类型的问题"这件事想明白,方案自然就出来了。我这篇梳理只是帮你缩小选择范围,最终决策还得你自己来。

Total votes: 11

添加新评论