ARTICLE · INTELLIGENCE

战地情报 · 详情页

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

从RAG到KAG与CAG:大模型知识接入路线对比与选型

从RAG到KAG与CAG:大模型知识接入路线对比与选型 1. 从RAG说起为什么检索这件事这么难大概从2023年开始RAG这个词就成了大模型落地绕不开的关键词。做文档问答、私域知识库、企业内部助手几乎所有人第一反应就是用RAG。它的思路听起来非常简单用户问一个问题系统先从知识库里检索出相关片段再把片段连同问题一起丢给大模型生成答案。这就像考试时先翻书翻到对应章节再作答而不是闭卷硬写。但真正上手之后你会发现检索这件事远比想象中复杂。原因很简单——大模型本身不接受文档只接受token。你要把知识库切碎、向量化、存进数据库然后靠相似度计算把看起来相关的内容捞出来。这里的每一个环节都可能成为瓶颈。检索丢给模型的片段对不对、全不全、有没有噪音直接决定了生成质量。很多RAG项目最后效果不佳问题往往不在生成端而在检索端要么召回了一堆不相关的内容要么漏掉了最关键的证据要么把十几段碎片塞进去模型根本不知道该信哪一段。我见过太多团队把大量时间花在调prompt上最后发现瓶颈根本不在prompt而在召回质量。这也是为什么后来出现了KAG和CAG这两条新路线。它们都是冲着RAG的软肋去的只不过一个选择用知识图谱来重构知识组织方式另一个干脆选择不检索了直接全量塞进上下文。这三条路线放在一起看其实代表了三种截然不同的落地哲学值得认真拆一拆。这篇文章就围绕RAG、KAG、CAG三条路线展开聊聊它们各自解决什么问题、卡在什么地方、适合什么场景最后再说说我在Mac上搭RAG项目时的一些实操记录以及怎么根据你的业务场景选路线。2. RAG的典型架构与真实瓶颈2.1 标准RAG的四个核心环节RAG的标准流程可以拆成四个环节切分、向量化、召回、生成。切分指的是把原始文档按段落、按固定长度或者按语义边界切成小块也就是所谓的chunk。这个环节看似简单却是很多RAG项目翻车的第一个雷区。切得太小信息被截断模型看到的都是碎片切得太大语义冗余向量相似度计算容易被噪声干扰召回精度下降。我见过有人直接按256个字符硬切结果一句话被拦腰截断召回出来以后上下文全是半截句子生成效果可想而知。向量化环节把一个chunk变成一串向量本质上是在做语义压缩。这步的关键在于embedding模型的选择。通用领域的bge、m3e、text-embedding这类模型处理常见文本问题不大但碰上专业术语密集的垂直领域效果会直线下降。比如医疗、法律、机械图纸这类内容通用embedding模型经常把漏电保护器和熔断器当成一回事召回结果自然跑偏。我自己的习惯是先拿一小批领域文档跑一轮召回测试看top-k结果里有多少是真正有用的如果准确率不到六成基本可以判定这个embedding模型不适合你的场景应该考虑微调或者换垂直模型。召回环节就是算相似度通常的做法是对问题的向量和库里所有向量做余弦相似度计算取top-k。这里有个隐藏问题向量相似不等于语义相关。两个句子用词相近但含义相反的情况经常出现比如这个功能很好用和这个功能不是很好用向量距离可能非常近。所以成熟的RAG系统一般不会只靠向量召回至少要加一层关键词召回做融合再用重排模型打一次分把最相关的几个结果排在前面。这个重排环节很多人会跳过但在实测中它对最终效果的影响相当大。最后是生成环节把用户问题加上检索到的chunk一起拼进context交给大模型生成。这步的痛点在于“噪音淹没信号”如果召回了8个chunk真正相关的可能只有2个模型就容易被另外6个带偏。很多人会试图用prompt让模型忽略无关内容实测下来效果有限——模型很难区分无关和相关的边界尤其是在chunk本来就切得比较碎的情况下。2.2 我理解的三类RAG瓶颈把上面这些现象归纳一下RAG的瓶颈大致可以分成三类召回瓶颈、知识单元瓶颈、生成组织瓶颈。召回瓶颈最直观。文档里的信息密度不均匀同样的chunk大小一段可能是完整的结论加理由另一段可能全是背景铺垫。向量检索是一视同仁的它无法判断这段chunk承载了多大信息量所以关键结论被淹没的情况特别常见。想要缓解这个问题就得在切分策略上做文章比如按Markdown标题结构切、按语义完整性切而不是死守固定长度。知识单元瓶颈指的是chunk粒度和知识粒度不匹配的问题。一个知识点往往分散在多个chunk里用户问的问题需要跨越多个段落甚至多份文档才能回答但向量检索通常只能召回孤立的chunk。你问这个产品的定价策略和市场反馈相关的内容可能一半在产品文档的第三页另一半在销售周报的某个表格里两个chunk之间没有关联模型拼不出完整答案。这类跨文档推理问题是标准向量RAG的天然短板。生成组织瓶颈则是前两个问题叠加的结果。召回内容不完整模型就只能脑补或者给出片面的答案召回了太多噪声模型又容易跑题。很多RAG项目上线后被人说一本正经地胡说八道十有八九是卡在这三个环节的某一个上。3. KAG知识图谱如何补齐RAG的短板3.1 从向量检索到知识推理的转变KAG的全称是Knowledge-Augmented Generation核心思路一句话概括把知识组织成图谱让模型在知识结构上推理而不是在文本碎片里检索。我在实际了解这个思路时有很强的共鸣因为RAG的很多问题本质上都出在它把知识当成文本来处理而KAG换了一个视角把知识当成实体和关系来处理。举个例子你有一个汽车维修知识库里面记录着各种故障码对应的维修方案。传统RAG的方式是把这些维修方案切成chunk存进向量库用户问P0301故障码通常是什么原因系统就去检索包含P0301的chunk。KAG的方式则是先在知识库里抽取出一个图谱节点是故障码P0301点火线圈火花塞氧传感器边是属于导致排除方法。用户提问时系统不只是找到P0301相关的文本而是沿着图谱里的关系路径把点火线圈故障和P0301的因果链路一起找出来再组织成答案。这两种方式的差异在问题越复杂、越需要多跳推理时体现得越明显。KAG能把这种推理做起来靠的不只是知识图谱本身还有一套逻辑推理机制。它会把大模型生成的答案拆成一组逻辑表达式再结合图谱上的证据做校验。比如模型说P0301是点火线圈问题系统会去图谱上找这条结论是否与已知的实体关系一致如果图谱里只有点火线圈老化会导致P0301这个关系那这条结论就能通过校验如果图谱里记录的是火花塞间隙过大也会导致P0301而模型漏掉了这一点系统就会把这个缺失给补出来。这是标准RAG做不到的——它只能把检索到的文本原样塞给模型无法对答案做知识层面的完整性检查。所以KAG本质上做的不是换个检索方式而是换一套知识表示。把知识库变成了一个可以被逻辑引擎操作的结构化网络大模型变成了这个网络上一个负责自然语言理解和生成的接口推理和校验的工作交给了图谱和规则引擎。这个分工方式让它能在复杂知识问答场景里做到比RAG更可靠的输出。3.2 ontology预设与知识抽取的工程实操KAG落地时有一个绕不开的环节知识抽取和本体设计。所谓ontology可以理解成知识图谱的schema它定义了实体有哪些类型、关系有哪些类型、属性有哪些字段。比如一个企业知识库的ontology可以是部门、员工、项目、文档、会议关系可以是成员属于部门项目由部门负责文档关联项目。ontology设计得越清晰知识抽取的目标就越明确图谱的质量也越可控。在实际操作中我建议大家不要一开始就追求完美的ontology。先从业务的核心问题出发圈出一组最小的实体和关系集合跑通闭环再逐步迭代。因为ontology太细抽取规则就复杂很容易在初期消耗大量精力在怎么抽而不是抽出来的东西有没有用上。反过来ontology太粗图谱结构就稀疏做多跳推理时路径太少能力发挥不出来。一般我会用用户问的最多的20个问题作为seed分析这些问题涉及哪些实体和关系据此设计第一版ontology——用问题驱动ontology设计比凭空拍脑袋要靠谱得多。知识抽取环节通常是由大模型完成的。把原始文档切片丢给大模型让它按照ontology抽取实体、关系、属性输出成结构化格式再经过清洗和校验后写入图数据库。这个环节有两个容易踩的坑一个是实体对齐同一个实体在不同文档里叫法不同比如总部和总公司需要做归一化另一个是关系置信度大模型抽取的关系不一定是对的最好是加一个人工抽检的环节按比例抽一批结果让领域专家过目错了就回炉调整prompt。3.3 KAG的场景适配与工程成本KAG不是银弹它适合的场景有明确的特征一是知识结构化程度高实体关系清晰二是问题需要多跳推理比如某个项目里有没有参与过同类项目的成员这种问题需要跨多个实体才能答出来三是持续迭代知识库内容会不断更新图谱可以增量维护。反过来如果你的知识库是大量语义模糊的散文、对话记录、图片资料KAG的价值就比较有限——因为抽取出来的图谱本身就是模糊的后面的推理也就无从谈起。工程成本方面KAG比标准RAG高出一个量级。知识抽取要跑大量大模型调用图数据库要部署维护ontology要反复设计调整推理链路的测试也要专门投入。我在和一些团队交流时发现很多人对KAG的理解停留在换一种存储方式上实际上它是换一种系统设计思路这个成本不吃透的话项目很容易做砸。4. CAG取消检索直接信任长上下文4.1 CAG的工作逻辑与适用边界CAG也就是Cache-Augmented Generation这个思路我第一次看到的时候觉得有点像偷懒但细想之后觉得它确实切中了RAG的一个核心痛点检索本身就是有成本的而且这个成本会随着精度要求上升而急剧放大。CAG干脆取消了检索这个环节把相关资料全部拼进上下文一次性交给模型让模型自己去找答案。听起来很暴力但它的底气来自大模型上下文窗口的快速增长。GPT-4系列、Claude系列动辄128K、200K甚至更长的上下文窗口这意味着你可以在一次请求里塞进几十万字。既然模型读得完为什么还要费劲去检索这个思路在特定场景下确实成立。CAG的典型做法是这样的事先把相关知识库的内容全部整理成一段文本在启动对话时一次性加载到prompt里做预填充模型在这个完整的知识上下文里回答用户问题。这里的缓存体现在两个层面一是文本层面的上下文缓存避免每次都重新提交同样的长文本二是KV Cache层面的缓存把预填充部分的计算缓存下来用户提问时不需要重新编码长上下文节省了大量计算时间。CAG最适合的场景是知识库规模可控、内容相对固定、问题范围集中在一个封闭域内的情况。比如你做一个产品使用手册问答助手手册一共几百页全部塞进去能放得下用户问题的答案一定在这几百页里CAG就是完全可以工作的方案。实测下来只要上下文能装下CAG的回答一致性往往比RAG好——因为模型看到了全部信息不会因为检索遗漏而出现知识盲区。4.2 CAG的上下文窗口与成本陷阱CAG的限制也很明显。第一个是上下文窗口的物理限制你可以用128K窗口塞一本手册但塞不下一个企业全量的知识库。第二个是中间丢失现象模型对长上下文中间部分的信息关注度是下降的资料一长模型容易读过但是忘了。第三是成本长上下文的token费用远高于短上下文虽然KV Cache能省一部分计算但存储和带宽成本依然不低。我在实际测试CAG时发现一个比较实用的策略是分层接入先在CAG模式下运行如果用户的提问明显超出了预填充知识的范围再动态切换到RAG或者触发新的预填充。这种混合方案做起来并不复杂但能同时享受两种策略的优点也避开了各自的短板。另外预填充文本的排版也很重要我是用目录章节标题正文的组织形式每一节内容独立分段标题用清晰的层级格式标注。这样模型在长文本里定位信息的难度会显著下降回答质量会好不少。5. 三条路线怎么选一张对照表与几个判断标准5.1 按知识特征匹配技术路线前面分别聊了三条路线这里把它们的核心差异整理成一个对照表方便决策时一眼看清维度RAGKAGCAG知识表示文本chunk实体关系图谱完整上下文文本核心机制向量检索重排知识推理逻辑校验长上下文直接读取最适合的场景知识库规模大、内容松散、查询简单实体关系清晰、需要多跳推理知识库规模有限、内容相对固定主要成本向量库搭建、embedding模型调优知识抽取、ontology设计、图数据库长上下文token费用、缓存空间主要风险召回不精准、跨文档推理弱知识抽取质量不达标、工程成本高上下文窗口限制、中间丢失对模型要求通用即可需要较强指令跟随能力需要超长上下文支持用这个表格对照你的业务场景选择路径会清晰很多。如果是做客服问答知识库是FAQ加产品文档内容不会经常变动CAG最省心如果是做企业内部知识管理文档种类繁杂、查询模式丰富RAG是更稳妥的起点如果业务要求严格的事实校验比如法律条款咨询、医疗建议问答KAG提供的逻辑推理能力就无法替代。要特别注意规模临界点这个问题。知识库的大小决定了CAG是否可行但这不只是一个塞不塞得下的问题。即便塞得下还要考虑业务对响应延迟和成本敏感度。知识库越大预填充时间越长用户等待也就越久。我的一个判断标准是如果CAG预填充后的用户平均等待时间超过3秒或者单次请求成本超过RAG方案的3倍就值得考虑切换方案。5.2 先跑通RAG再做迭代对大多数团队来说我不太建议一上手就梭哈KAG或CAG。更现实的做法是先用标准RAG跑通一个最小闭环把流程理顺再根据实际效果判断瓶颈出在哪里。如果发现模型答错了但检索结果确实也烂那问题在召回策略可以尝试调整chunk、加关键词召回、加重排这些都是RAG内部可以优化的空间未必需要换路线。如果这些问题优化到位之后发现知识关联性和推理能力还是跟不上这时候再考虑引入KAG的知识图谱增强。如果发现知识库规模并不大但在RAG模式下频繁出现该答的没答出来的情况那大概率是检索精度还不够高这时候CAG往往能以很小的改动拿到更好的效果。5.3 混合架构是常态我做过的项目里几乎没有单纯靠一种策略打天下的。成熟的系统往往是混合架构把高频问题对应的知识组织成CAG用的预填充知识包把需要多跳推理的问题交给KAG的图谱链路剩下的兜底场景再走RAG的召回生成。三层策略按请求特征分流虽然架构复杂度会增加但每一层的效果都在可控范围内。举个例子我之前做一个设备维修知识库高频的故障代码查询直接走CAG预填充十几万个故障码对应的维修建议做成结构化数据走KAG图谱查询文档类的深度阅读问答走RAG召回。这样用户问P0301故障码怎么处理CAG秒回问换过点火线圈之后还有P0301下一步该排查什么这样的延伸问题KAG能沿着图谱路径给出推理而问结合这篇维修手册解释一下氧传感器的作用RAG负责从文档里捞原文。三种路径各司其职体验比单一方案好很多。6. 实操参考在Mac上从零搭一个RAG最小项目6.1 环境准备与工具选型Mac上搭RAG项目现在生态已经很成熟了。我自己常用的一套组合是Ollama跑本地模型LangChain做流程编排ChromaDB做向量存储Embedding用Ollama自带的nomic-embed-text或者bge-m3。这台组合的好处是全部本地运行不需要API key数据不出机器隐私安全有保障而且安装过程足够简单。环境准备分三步。第一步装Ollama在官网下载Mac版安装包装完后在终端执行ollama pull qwen2.5:7b拉取一个7B参数的模型再执行ollama pull nomic-embed-text拉取embedding模型。第二步装Python依赖包建议用Conda建一个干净环境执行pip install langchain chromadb pypdf。第三步准备测试文档我建议先拿几篇自己的Markdown笔记或PDF试跑别一上来就上大量文档不然排查问题时会分不清是文档问题还是代码问题。6.2 最小化RAG代码实现搭建阶段的核心代码其实不长。下面这段是我实测可跑通的版本逻辑非常直白读文档、切块、向量化、存库、召回、生成。用LangChain的DirectoryLoader和RecursiveCharacterTextSplitter做文档加载和切分ChromaDB做向量存储和召回最后调用Ollama的模型做生成。完整流程大约80行Python就能跑通非常适合用来理解RAG的每个环节。from langchain_community.document_loaders import DirectoryLoader from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain_community.embeddings import OllamaEmbeddings from langchain_community.vectorstores import Chroma from langchain_community.chat_models import ChatOllama # 1. 加载文档 loader DirectoryLoader(./docs, glob**/*.md) docs loader.load() # 2. 切块按Markdown标题结构优先切再按长度兜底 splitter RecursiveCharacterTextSplitter( chunk_size512, chunk_overlap80, separators[\n## , \n### , \n\n, \n, 。, , ] ) chunks splitter.split_documents(docs) # 3. 向量化与入库 embeddings OllamaEmbeddings(modelnomic-embed-text) vectorstore Chroma.from_documents(chunks, embeddings, persist_directory./chroma_db) # 4. 召回 retriever vectorstore.as_retriever(search_kwargs{k: 4}) # 5. 生成 llm ChatOllama(modelqwen2.5:7b) def ask(question): context_chunks retriever.invoke(question) context \n\n.join([c.page_content for c in context_chunks]) prompt f请基于以下资料回答问题。如果资料中没有相关答案请直接说明。 资料 {context} 问题{question} return llm.invoke(prompt).content6.3 实操中的踩坑记录与参数调优心得这套最小项目能跑通但从能跑到好用之间还有不少路要走。我自己实测下来最值得说的有三个点。切块策略真的不能照抄默认值。我刚开始用LangChain的默认参数chunk_size1000在测试一份带表格的PDF时效果很差表格被切得七零八落模型回答问题时经常说根据资料无法找到相关信息。后来改成把表格单独识别出来用chunk_overlap80保留上下文衔接回答质量才有明显提升。我的心得是chunk_size不要迷信固定值而是要结合你的文档类型来定。如果是技术手册这类标题层次清晰的文档建议优先按标题切一个标题下不管多少字算一个chunk如果是聊天记录这类无结构文本才用固定长度加overlap兜底。overlap的作用是避免切分点恰好把语义截断但不宜设太大否则一个chunk里重复内容过多向量表示的区分度会下降。embedding模型最好做一轮本地评测再定。我在换用bge-m3之前用默认的all-MiniLM-L6-v2跑了50个测试问题发现几个高频词比如退货和退款的召回结果经常混淆后来换成bge-m3效果改善了很多。如果你做的是垂直领域知识库建议专门准备20到30个典型问题人工标注正确答案对应的文档片段跑一遍召回测试按recallk这个指标评估一下。recallk的含义是前k个召回结果里有多少是真正有用的。如果低于0.6就该考虑换embedding模型或者调整切分策略了。检索结果一定要做重排。Top-4召回结果里往往只有一两条是真正相关的。你可以先用向量召回20条再用一个reranker模型比如bge-reranker-base在本地重排取前4条作为最终上下文。这个步骤增加的耗时大约在100毫秒到200毫秒换来的是回答可靠性的明显提升。如果不想引入重排模型退而求其次的做法是在prompt里让模型对上下文做一遍证据筛选把不相关的内容先挑出来忽略掉但实测这种方式的稳定性不如真正的重排。7. 最后再聊几句回头再看RAG、KAG和CAG这三条路线我最直观的感受是它们不是三个互相竞争的技术方案而是知识接入大模型这条主线上三个不同位置的解法。RAG在检索精度上死磕KAG在知识结构上重建CAG在上下文利用上另辟蹊径。理解了各自的出发点和边界你看到新的技术概念时就不会被名词绕晕而是能一眼看出它到底在优化哪个环节。我个人在实际操作中的体会是不要把路线选择当成一次性的技术决策。业务在变知识库在涨模型能力在迭代今天的KAG适用场景半年后可能因为上下文窗口翻倍而变得更适合CAG今天只能在RAG里解决的基础问答明天搭上知识图谱后就能做多跳推理。保持架构上的可替换性比纠结于选哪条路线更重要。组件层面做接口隔离数据层面做统一清洗这样换路线时不需要重写全部代码只需要替换中间环节的实现。另外一个小建议是不管走哪条路线都一定要沉淀一套评测集把典型问题和期望答案固化下来。没有评测集的迭代都是盲人摸象你根本不知道改动是变好了还是变坏了。这句话应该能帮你省下不少盲目折腾的时间。
RELATED READING

延伸阅读

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