ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

拆解RAG与大模型的关系:从检索到生成的协同工作

拆解RAG与大模型的关系:从检索到生成的协同工作

看到这个标题,可能有人会觉得“RAG嘛,就是给大模型外挂一个知识库,检索出来拼到Prompt里再让模型回答”,这话没错,但如果你真的只在做“拼Prompt”这一步,那你很快会撞到RAG的瓶颈:明明知识库里有答案,模型就是答不对;答对了,又经常把不相关的碎片混进来;想加点图片进知识库,又不知道从哪儿下手。这些都很正常,因为RAG和大模型之间远远不是“检索加拼接”这么简单,它们之间更像是一套协作关系,涉及文本切分、向量化、检索排序、上下文窗口利用、模型推理偏好等一系列环节,任何一个环节拧不到位,最终效果都会大打折扣。

这篇文章打算把RAG和大模型之间的“核心关系”彻底讲透:先说RAG到底弥补了大模型的哪些天然短板,再拆一个典型RAG系统的完整流程,然后聊多轮对话和Agent场景下的新问题,接着把大家最关心的瓶颈和排查方法整理出来,最后给一份可以直接照着搭起来的本地RAG知识库实战参考。无论你是刚接触RAG的入门者,还是已经在做项目但效果不理想的实践者,这篇文章都力图让你看完之后不仅知道“RAG怎么用”,更能明白“为什么这么用”和“出了问题到底该查哪里”。

1. 先想明白一件事:RAG到底解决了大模型的什么问题

1.1 大模型不是万能的:三类典型短板

大模型确实很强,能写文章、能总结、能翻译、甚至能写代码,但如果你真的把它当成“全能问答系统”用,很快就会遇到三类很典型的问题。

第一是知识时效性。模型的训练数据有截止日期,模型只知道截止日期之前存在于训练集里的知识。你问它最近刚发布的某个政策、某款新产品的参数、某个内部的规章制度,它大概率会一本正经地编一个看似合理但实际错误的内容,而且它自己并不知道错了。这种“不知道但敢说”的特性,就是基座模型的原生缺陷——你不能指望一个“记忆”固定在某个时间点的模型为你提供“今天”的知识。

第二是知识来源不可控。模型是在海量公开文本上训练的,它的知识是“统计混合体”,无法指定“请只基于《某某管理办法》来回答”,也无法保证引用的内容真实、可追责。对于企业场景,业务数据、内部文档、产品手册这些内容,模型根本没有机会接触,更谈不上准确引用。

第三是上下文窗口的限制。虽然现在的模型上下文窗口越做越大,但把整个知识库一次性塞进Prompt既不现实也不经济。窗口再大,也有容量上限;塞得越多,模型在长上下文中的注意力反而越分散,检索起来更不准确,出错的概率也在上升。我们需要一种机制,让模型“按需获取”最相关的那部分知识,而不是把所有知识都背在身上。

这三类短板恰好就是RAG存在的理由。RAG(Retrieval-Augmented Generation,检索增强生成)不是取代大模型,它是在大模型外部搭了一个“可动态更新的资料架”,需要什么就查什么,查完再让模型组织语言回答。核心思路一句话:把“记忆”从模型参数搬到外部知识库,让模型专注于它真正擅长的事情——理解和生成。

1.2 把RAG理解为“开卷考试”

如果不做RAG,直接拿大模型来做问答,相当于闭卷考试:所有知识都必须“印在脑子里”(参数里),教材里没印到的或者印错的内容,只能靠临场发挥。而RAG相当于开卷考试:允许你带参考资料进考场,遇到不确定的题先翻书,把找到的原文抄到答卷上,再按自己的话组织一遍答案。

这个类比能帮你理解很多RAG系统的关键设计取舍。“翻书”就是检索:你得先知道答案在哪本书的哪一页;“抄原文”就是召回:把命中的段落原封不动地取出来;“组织答案”就是生成:让大模型基于这些段落写一段通顺、完整的回答。开卷考试想考高分,靠的不只是“带书”,还要知道怎么快速定位、怎么筛选有效段落、怎么避免抄了无关内容反而扣分——这正好对应RAG系统中的索引质量、检索精度、排序策略和Prompt组织方式。

更关键的是,开卷考试相比闭卷考试有一个巨大优势:参考资料可以随时更新,而模型脑子里那部分“闭卷知识”基本是固定的。企业今天上新了一版产品规格,只需更新知识库里的文档,不需要重新训练模型,就能让线上问答系统立刻知道最新版的内容。这种低频更新的“模型”配合高频更新的“资料架”,才是RAG在工业和商业场景中真正被广泛采用的核心原因。

1.3 RAG与大模型的关系本质:互补,而非替代

在很多人的理解里,“微调和RAG是两条路线,得选一条”。这个说法其实不太准确。RAG负责的是“拿什么资料让模型看”,微调负责的是“让模型学会按什么风格或格式输出”。两者解决的问题维度不同,不是对立关系,甚至在不少项目中是叠加使用的。比如你有一批法律文书,RAG负责把相关法条检索出来喂给模型,微调则让模型学会“援引条文、按判决书格式输出”。可以说,基座模型决定“上限”,RAG负责给它“找素材”,微调负责让它“懂规矩”,三者各管一段。

但要注意,RAG并不能“教会”模型新能力,它只能给模型提供更多信息。如果你的目标是让模型学会一种全新的推理范式、输出特定结构的JSON、适应某种领域术语的表达习惯,单靠RAG可能不够,这时候需要微调配合。理解“RAG解决知识来源问题,微调解决行为对齐问题”,你就不会再纠结“哪个更好”,而是会思考“当前项目的瓶颈到底在知识缺失还是行为不匹配”。

2. 徒手拆开一个RAG系统:从文档到答案,中间发生了什么

一个最典型的RAG流程可以分为三个阶段:索引构建(Indexing)、检索(Retrieval)、生成(Generation)。很多人只用过别人封装好的框架,没看过这两个阶段之间真正发生了什么,遇到问题就会抓瞎。下面把每个环节都展开讲透。

2.1 第一步:文档加载与分块

原始文档五花八门:Word排版混乱、PDF有复杂表格、PPT里大多是碎片文本。RAG系统第一步就是把它们“读”进来,转成纯文本或结构化文本。这个环节看起来简单,实际坑很多。扫描版PDF需要OCR;多层嵌套表格直接抽文本会丢失对应关系;网页正文混着导航和广告……如果这些没处理干净,后面检索到的内容就会“半香半臭”。

文本分块(Chunking)是RAG中最容易被低估的环节。小块文本检索精度高、但上下文信息容易断裂;大块文本上下文完整、但混入噪声的概率也高。市面上常见的策略有两种:固定长度分块和语义分块。固定长度按字符数或Token数切分,最简单但很可能在句子中间“腰斩”,直接破坏语义;语义分块则按段落、标题层级或句子边界切分,保留完整语义单元,但对文档结构有要求。

有一个经验可以分享:分块大小的选择,要同时看两样东西,一是你的Embedding模型对长文本的编码能力,二是你最终用的LLM对上下文的适应能力。如果Embedding是普通的文本模型,超过512个Token之后编码质量会明显衰减,这时候分块就不能太大;而如果LLM上下文窗口很宽、指令遵循能力很强,稍大一点的分块反而能让模型获得更完整的上下文。我见过不少效果差的RAG项目,最后排查下来就是分块策略太粗糙——一个块里塞了三种主题的内容,检索出来之后模型根本不知道用户问的是哪一段。

2.2 第二步:向量化与检索

分完块之后,需要把每个文本块变成向量。这里的关键是Embedding模型。同一个文本,用不同的Embedding模型得到的向量质量差别很大,这直接决定检索的召回效果。比较常见的做法是用通用双语Embedding模型(例如BGE系列)做中英文场景,也可以在领域数据少跑一轮微调,让向量空间更贴合业务术语。

向量化之后,这些向量会存入向量数据库。所谓向量数据库,本质上就是一个专门做“按向量相似度快速检索”的存储引擎。它跟传统关系型数据库最大的不同在于:传统数据库靠精确匹配(比如“用户名等于张三”),向量数据库靠近似度匹配(比如“这段文本和用户问题语义最接近”)。常用的开源方案有Chroma(轻量、适合学习和小项目)、Milvus(分布式、适合生产)、FAISS(底层的向量索引库,本身不是完整数据库,但够快)。选择哪一款,取决于你对数据规模、并发能力和运维成本的要求。个人学习阶段用Chroma完全够,线上环境再考虑更重的方案。

检索这一步,最常见的问题是“Top-K怎么选”。K太小,可能漏掉关键信息;K太大,噪声内容会把模型带偏。比较好的策略是先调大K(比如10左右),然后用重排序(Rerank)模型对召回的结果做一次精细化排序,只保留前2~3个真正相关的片段送入Prompt。重排序本质上就是“粗召回用向量快筛,精排序用交叉编码器细挑”,这相当于先让一个高效检索器把范围从“整个库”缩小到“可能相关的几十段”,再让一个慢但更准的模型挑出最靠谱的几段。这一步非常值得投入,尤其是你的知识库内容之间有较多重叠、互相容易干扰的时候。

2.3 第三步:把检索结果喂给大模型

检索回来的文本块,最终要经过Prompt模板组织后交给大模型。这一步看似只是拼接字符串,实际上决定了模型遵不遵守“只基于资料回答”的约束。很多人直接写一句“请根据以上资料回答”,效果往往不稳定。更好的Prompt模板至少要包含几层约束:

  1. 明确告诉模型:你只能使用资料中的信息作答,资料中不存在的内容要直接说不知道,不能编造。
  2. 告诉模型:回答可能需要结合多段资料进行综合,不要只盯着第一段。
  3. 如果资料中有冲突或部分相关的内容,要求模型以哪个优先级取舍,或者指出信息冲突。
  4. 给模型留一个“退路”:如果检索到的内容与问题完全不相关,要明确说明“没有检索到相关资料”,而不是强行作答。

我还见过一个很实用的做法:在送入Prompt之前,先对召回文本做一轮压缩和去噪。比如用粗提取的方法去掉页眉页脚、去掉重复的空行、合并过度碎片化的句子;如果召回内容太长,还可以让一个小模型先做“要点提取”,只把核心信息传给主模型。这套思路和LangChain里的“Stuff / Refine”等文档处理策略是相通的,本质都是在“信息完整性”和“上下文清洁度”之间找平衡。

2.4 知识库能存图片吗?多模态RAG的几种现实方案

热搜里有个问题特别有意思:“RAG知识库能存图片嘛”。很多人以为RAG只能处理文本,其实不只是这样,但也没有想象中那么丝滑。直接的答案:能,但要看你说的“存图片”是哪种用法。

第一种用法是把图片当作“被检索的素材”。这时候你不能直接把图片丢给文本Embedding模型,需要多模态Embedding模型把图片编码成向量,或者是给图片先做一个“文本描述”,把描述作为索引存入向量库,检索时靠描述匹配,最后把原图或描述一起送入多模态大模型生成回答。这是当前最常见也最省事的可行方案:给图片打标签、写说明,本质上相当于给图片“配文字索引”。

第二种用法是让大模型“看图回答”。如果你的底层模型本身是多模态大模型(比如GPT-4o、Qwen-VL这类),那可以把检索到的图片原始内容通过视觉通道传给模型。这时候RAG管的是“找到哪张图”,真正“看懂并回答”的是多模态大模型。流程上仍然遵循“检索增强生成”的思路,只不过检索的对象换成了“图片文件加它的辅助文本”。

第三种用法是图文混合知识库。这时候文档切分的策略就得调整,比如一个PDF既有文字又有配图,你切割时要尽量把与图片相关的文字绑定在一起,检索的时候才能保证“提到的那张配图”跟“那段解释文字”一起被召回。这块目前各框架的支持参差不齐,我在实践中倾向于用“先提取文本,再用规则或模型为图片生成位置上下文,最后统一入库”的思路,工程实现上更可控。

一句话总结:图片能不能进RAG,不取决于RAG本身,而取决于你有没有多模态编码和生成能力。RAG提供的是“找素材”的骨架,喂进去的是文本还是图片,由你的基础模型决定。

3. 进阶:多轮对话、RAG智能体与知识边界控制

如果只是单轮问答,RAG的结构已经够用。但在真实业务里,用户不会把每句话都问完整。用户先问“这周库存情况怎么样”,再问“为什么会这样”,这里的“这”指代的是上一轮的内容,如果每轮都重新检索,模型根本不知道“这样”指的是哪个对象。多轮对话场景下的RAG,核心问题就是:如何把对话历史中的指代和省略信息利用起来,去构造新的检索Query和新的上下文。

3.1 多轮对话中的检索策略:重写Query而不是拼历史

多轮对话最简单的处理方式是把最近的几轮对话拼在检索Query前面一起向量化检索,但这样做效果往往一般,因为历史太长会把检索重点稀释掉。更推荐的做法是引入“查询重写”环节:让大模型基于对话历史整理出一个独立的检索语句。比如用户前一轮问“上个月的销量数据”,后一轮说“平均单价呢”,经过查询重写后输出“上个月销量数据的平均单价是多少”,再去检索。这一步看似多花了一次模型调用,但对最终的检索命中率提升非常明显。

在这里有一个实操细节:做查询重写的Prompt要简洁明确,避免让模型把历史里的噪声也带进来。我常用的模板很简单:“请根据用户和助手的对话历史,写出用户当前问题对应的独立检索语句,只输出检索语句,不要输出其他内容。”实测下来,一个几十Token的Prompt就够,不需要特别复杂的推理链。

多轮对话还会出现一个全新的问题:已召回内容可能已经回答过上一轮了,当前轮重复检索可能出现“原地打转”。这时可以做一层“已回答内容排除”:把前几轮已经使用过的文档标识记录在对话状态里,当新一轮检索的Top-K结果中有大量与之前重复的片段时,要么降低它们的权重,要么强制让模型基于新的知识回答。这个逻辑在框架里很少被默认支持,需要自己在状态管理里加。

3.2 RAG智能体:从被动问答到主动检索

RAG再往前走半步,就是Agent化。传统的RAG是一次“检索-生成”的线性流程,用户问题来了就检索,检索完了就生成,中间没有判断、没有计划、没有工具。而Agent化的RAG会在生成之前加入“判断”:这个问题是否需要检索?需要检索哪个知识库?一次检索够不够?如果当前检索结果不足以回答,是继续扩大检索还是问用户澄清?这套流程说白了就是把原来固定不变的RAG管线变成了一个可以自主决策的循环。

具体落地时,我建议不要一开始就把整套Agent框架搬上来,而是从“带工具调用的RAG”开始。意思是你给大模型预留一个或多个检索工具,让模型自己决定“要不要搜、搜什么”。比如用户问“我们上次谈的那份合同什么时候到期”,如果单纯走RAG,这个检索Query大概率会命中一些不太相关的内容;而如果让模型先判断“这需要去合同知识库检索”,再配合查询重写,召回的准确率会高很多。

再往后才是完整Agent:多轮调用、多工具组合、任务规划。但我要提醒一句,Agent化并不是越多越好。每一层自主决策都意味着更高的失败概率和更长的延迟。能用一条规则判断要不要检索的地方,就不要让模型去做决策;能用一步检索解决的,就不要跑三步循环。RAG智能体真正该做的,是在“固定流程解决不了、值得动态探索”的问题上发挥作用。

3.3 知识边界控制:让模型敢说“不知道”

很多RAG项目上线之后,最头疼的问题不是答不上来,而是“明明没有资料,模型却硬答”。这本质上是一个“知识边界控制”问题。语言模型天然倾向于给出看起来合理的回答,不回答对它来说是一种“失败”,所以它会想方设法编造。

知识边界控制可以从三个层面来做。第一层是检索层面的置信度判断:如果召回结果的相似度分数全都低于某个阈值,直接判定为“无相关知识”,不等生成就开始走兜底逻辑。第二层是生成层面的Prompt约束:明确要求模型“如果资料中没有答案,直接回复‘知识库中未检索到相关信息’,不要猜测”,并且不允许它使用自己的常识补充。第三层是输出层面的校验:可以用一个小模型或基于规则的模块对模型回答做“来源检查”,比如判断回答中的关键数字、名称是否确实出现在检索到的资料里,如果发现“无中生有”,则重新走一遍检索或直接拒绝回答。

这三层分别对应“检索端”“生成端”“输出端”。很多团队只在第二层做约束,效果不稳定,因为Prompt约束对于强大的模型来说往往只是“软约束”,它在对抗性问题上还是会忍不住调用内部知识。把三层都做上之后,“敢说不知道”的能力才会有质的提升。

4. RAG的瓶颈到底在哪里:一份排查清单

RAG经过了这几年的实践,核心瓶颈大家基本有了共识:不是模型不够聪明,而是“检索到的素材”不够给力。很多人兴致勃勃地搭了一个RAG系统,效果却不如直接让大模型闭卷回答,就是因为没意识到RAG的整体效果,是由最弱环节决定的。下面把最常见的三类瓶颈和排查方法展开讲。

4.1 分块粒度带来的“语义碎片化”问题

分块太小,则每个文本片段包含的信息量太少,检索出来之后模型需要“拼图”,拼图过程中很容易脑补,甚至在片段衔接处产生幻觉。分块太大,则一个片段里混合了多个主题,检索相似度会被“稀释”,导致模型不知道该重点用哪段。这就是“语义碎片化”和“信息稀释”的两难。

排查方法是做一个“命中测试”:找一批有标准答案的问题,把检索结果打印出来,人工看Top-3的检索片段是否包含了正确答案。如果命中的片段经常只有半句话、需要模型拼凑上下文,说明分块需要结合文档结构适当放大或采用段落级切分;如果命中片段中包含很多无关信息,说明块需要切得更细。我见过不少团队在这个环节就开始调模型、调Prompt,其实问题根本在分块,先确认好“检索命中质量”再谈“生成质量”。

4.2 检索质量:向量检索的天花板在“语义相关性”

向量检索本质是“语义近似匹配”,但“近似”不等于“准确”。很多问题涉及否定、条件、对比、时序等逻辑关系,向量相似度很难捕捉。比如“当前不支持的支付方式有哪些”和“支付方式的支持范围”在语义上接近,但答案几乎是相反的。仅靠向量检索,这类问题很容易召回错误。

提高检索质量有两种常见路径。一种是用“混合检索”弥补向量检索的短板:把“关键词精确匹配”(BM25)和“向量语义检索”的结果做合并,再交给重排序模型统一排序。这样,用户如果问了一个包含明确专有名词的问题,关键词匹配能先精确命中,向量语义匹配做补充,两者结合能覆盖更多查询类型。另一种路径是细化索引:对检索文本做实体识别、生成标签,用结构化标签辅助向量检索。这两种方式都值得尝试,尤其在前者中,用重排序模型处理合并后的召回结果,是把“粗召回”变成“精检索”的关键一步。

4.3 上下文污染:召回了但用不好

有些项目拿出检索结果一看,前几个片段确实和问题相关,但模型回答还是不对。排查发现,很多情况下是召回结果中混入了高度相关但不同主题的多个片段,模型在“综合归纳”的时候,把不属于答案的噪声信息也编了进去。这属于“上下文污染”。

上下文污染的解决办法可以从两个方向下手。一个方向是减少输入噪声:在重排序之后,只保留与问题最相关的1~2个片段,放弃“给模型更多信息让它自己判断”的偷懒思路。另一个方向是打标:对每个片段来源标注文档名、章节标题、更新时间,让模型能识别“这些内容来自不同文档”,并分别引用。很多框架默认不输出片段来源,导致模型根本无法区分“A文档说可以”和“B文档说不可以”之间的冲突关系。加上来源标注之后,模型在处理冲突信息时会谨慎很多,也会更倾向在答案中说明“存在不同来源之间说法不一致”。

4.4 RAG排查速查表

下面这张表整理了我在项目中反复使用的一套排查顺序,每次RAG效果不佳,我就按这个顺序往下捋。

排查维度常见症状检查方法常用解法
数据清洗检索到乱码、页眉页脚、无关重复内容打印Top-3片段肉眼检查加清洗规则、去模板化、过滤低质量段
分块方式命中片段信息不完整或混入多种主题用标准问答集测试命中率按文档结构切分、按语义段落切分
Embedding模型语义相关但检索排序不准对比不同模型在同一测试集的召回率更换更强Embedding模型或在领域数据上微调
检索策略专有名词命中差、同义表述召回不全拆开混合检索单独看效果引入BM25+向量混合检索
重排序Top-1片段不够准,总有噪声排前面观察重排前后排序变化加入交叉编码器Rerank模型
Prompt模板模型不遵循资料约束、强行作答检查回复是否包含资料之外内容强化边界约束、加“不知道”兜底指令
多轮历史指代问题导致检索Query偏移打印重写后的Query检查加入查询重写环节,单独建模对话Query

这套排查表的价值在于:它能帮你把“RAG效果不好”这个大问题,拆成一个一个可以单独验证的小问题。每调整一个环节,都能用测试集快速验证,而不是同时改五六处,最后出了问题也不知道是哪一步引起的。

5. 实战:从零搭一个本地RAG知识库,可以复制的最小方案

理论讲了一大堆,接下来给一份能直接照着做的最小方案。这个方案的目标是:在你自己电脑上,跑通一个“文档进库,提问回答”的本地RAG知识库,不依赖任何付费API,适合零基础的朋友。用到的核心组件是三块:一个本地大模型作为生成端、一个Embedding模型处理文本向量化、一个轻量向量数据库做检索存储。

5.1 技术选型:本地部署路线怎么走

生成端我推荐用Ollama。它可以帮你快速跑起来Qwen2.5、Llama3、Phi系列等开源大模型,一条命令就能完成部署。之所以强调本地路线,是因为它可控、免费、数据不出机器,适合学习和企业内部原型验证。Embedding模型同样可以跑在Ollama上,常见的如bge-m3、nomic-embed-text等都能直接使用,省去自己写推理代码的麻烦。

向量数据库选Chroma就够了。它不需要独立服务,一个本地目录就能存所有向量及相关元数据,Python调用也极其简单,很适合零基础学习者。这套组合的好处是:全部组件都能离线运行,你只需要有一台能跑得动4~8B模型的电脑(优先带显卡,没有显卡苹果M系列芯片或者纯CPU跑小模型也能凑合,就是慢一些),就能完整体验RAG全流程。

5.2 最小流程:从文档入库到回答问题的完整代码

为了方便你直接“抄作业”,我用最直白的方式写了一个简化流程。假设你有一些Markdown或TXT文档放在docs/目录下,目标是回答基于这些文档的问题。

from langchain_community.document_loaders import DirectoryLoader, TextLoader from langchain_text_splitters import RecursiveCharacterTextSplitter from langchain_community.embeddings import OllamaEmbeddings from langchain_community.vectorstores import Chroma from langchain_community.chat_models import ChatOllama from langchain_core.prompts import ChatPromptTemplate # 1. 加载文档 loader = DirectoryLoader("docs", glob="**/*.txt", loader_cls=TextLoader) docs = loader.load() # 2. 切分文本 splitter = RecursiveCharacterTextSplitter( chunk_size=800, chunk_overlap=100, separators=["\n\n", "\n", "。", "!", "?", ";", ";", " ", ""], ) chunks = splitter.split_documents(docs) # 3. 构建向量库 embedding = OllamaEmbeddings(model="bge-m3") vectorstore = Chroma.from_documents(documents=chunks, embedding=embedding, persist_directory="./chroma_db") # 4. 初始化本地大模型 llm = ChatOllama(model="qwen2.5:7b", temperature=0.2) # 5. 检索 + 组装Prompt retriever = vectorstore.as_retriever(search_kwargs={"k": 4}) prompt_template = ChatPromptTemplate.from_messages([ ("system", "你是一个严谨的问答助手,只能依据以下资料回答问题。" "如果资料中没有相关信息,请明确回复:知识库中未找到相关内容。" "禁止编造答案,禁止使用你自己的常识补充。"), ("human", "资料:\n{context}\n\n问题:{question}"), ]) def ask(question: str) -> str: hits = retriever.invoke(question) context = "\n\n".join([doc.page_content for doc in hits]) messages = prompt_template.format_messages(context=context, question=question) response = llm.invoke(messages) return response.content # 6. 测试 print(ask("我们文档里规定了哪些支付方式?"))

这段代码的核心逻辑很简单:读文档、切块、向量化入库、检索、生成。跑通之后,你可以自己替换文档内容,逐步体会“为什么切分粒度不同效果不一样”“为什么加了这个Prompt约束它就不乱说了”。

5.3 本地部署的注意事项

本地部署最需要关注的是模型大小和硬件资源匹配。Ollama上模型的命名后面带参数规模,比如qwen2.5:7b是70亿参数版本。7B规模模型建议至少有8GB显存,如果没有独立显卡,纯CPU跑起来速度会很慢,一个回答可能要等几十秒甚至更久。作为学习用途可以接受,但如果你想部署成一个小服务给团队用,建议至少准备一块16GB显存以上的显卡,或者用量化更狠的模型(比如4bit量化版)。

模型选择上,生成端如果追求中文效果,Qwen2.5系列是市面上开源模型里很省心的一个;Embedding端,bge-m3对中文的支持也比较成熟,可以直接用。注意安装依赖的时候不要一股脑全装,只需要langchain、langchain-community、chromadb这几个核心库,再加Ollama本体就够了。

还有一个容易被忽略的点:路径和编码。Windows环境下中文路径偶尔会有编码问题,建议所有文档路径尽量用英文字母命名,文档内容保存为UTF-8编码,避免导入时出现乱码。这个坑在本地项目中遇到的人很多,提前注意可以省下不少排查时间。

6. RAG vs 微调:到底该怎么选,两者如何配合

在聊RAG的时候,永远绕不开“微调”这两个字。很多人的困惑是:我已经打算用大模型了,为什么还要搞一套复杂的RAG流程?直接拿业务数据微调一个模型不是更省事吗?答案取决于你面对的问题是什么类型。

6.1 一张对比表看清差异

对比维度RAG微调(Fine-tuning)
知识时效性动态更新库即可,无需重训模型新知识需要重新训练,周期长、成本高
知识来源可追溯可标注引用来源,可审计、可追责知识固化在参数中,无法定位出处
实现难度中等,涉及分块、检索、排序多个环节需要数据准备、训练配置、评估流程,门槛高
成本主要为存储和高频检索调用,相对较低训练GPU成本高,且模型越大越贵
适用场景问答、私域知识库、实时资料查询输出风格对齐、特定格式生成、领域术语理解
知识密度单条知识可精细到段落级甚至句子级知识是以权重形式混合存储的,不可细粒度控制
幻觉控制通过Prompt约束和检索边界控制,相对可控无法从机制上阻止幻觉,只能通过训练数据间接影响

这张表已经说得很清楚:RAG擅长“给模型喂新知识”,微调擅长“教模型按新规则输出”。两者的分工并不重叠,所以在实际项目里完全可以在做一个RAG系统的同时,对底层模型做一次针对性的轻量微调,让它更适应你的业务表达习惯。

6.2 实际项目中我如何判断

我的经验是,先问自己三个问题。第一,业务知识多久变一次?如果每天都在变,比如商品信息、公告政策、内部制度,就是RAG的天下,因为你可以随时把新文档丢进知识库,当天生效,而微调做不到。第二,回答需不需要引用来源?如果是客服问答、企业知识库、合规审核这类需要“有据可查”的场景,RAG天然具备优势,因为你可以让模型在回答末尾标注用的是哪份文档的哪个段落。第三,输出格式是不是核心难点?比如要模型输出指定的JSON Schema、固定的报告模板、专业的公文措辞,这一块RAG帮不上忙,微调或者强指令模型更合适。

如果三个问题中有两个以上指向RAG,那就不必犹豫,先做RAG。如果模型“输出格式完全不受控、术语表达总是不对”,那再考虑微调。最理想的架构往往是先有一个通用能力不错或微调过的基座模型,在此基础上套一层RAG体系——基座负责“会说话、懂格式”,RAG负责“有资料、有依据”,两者叠加才能最大限度地发挥大模型在业务场景中的价值。我在实际项目里也越来越倾向于用这个组合方案,而不是在两条路线之间做单选。

7. 最后聊点实际体会

这篇文章从头到尾都在强调一句话:RAG和大模型的核心关系,不是“用RAG替代大模型”,也不是“把大模型变成检索工具”,而是“用外部知识与生成能力协作,各取所长”。我对这句话的理解也经历了几个阶段,刚开始做RAG时只关心“检索准不准”,后来发现“检索准”只是及格线,真正的差距在于分块、重排、Prompt约束、多轮Query重写这些细节是否真的打磨到位。

给你几个可以直接带走的小建议:第一,上线前一定要准备一套至少50条问题的评测集,不要只靠质感判断好坏,RAG系统的效果波动比你想的大得多,必须有量化数据兜底。第二,每次只改一个变量,改了分块就只评估分块,改了重排就只评估重排,不然你永远不知道真正起作用的是哪一步。第三,不要迷信大模型,上下文窗口再大也救不了“检索返回了一堆垃圾”这个现实,把更多精力花在“怎么找到最合适的那一段”,而不是“怎么让模型从一堆噪声里挑答案”。

RAG的下一步一定会朝着多模态、智能体编排、更精准的知识边界控制这几个方向继续演进,但无论技术怎么变,它和大模型之间的协作逻辑不会变:大模型负责思考和表达,RAG负责为它提供真实、可靠、可追溯的知识素材。理解清楚这对关系,你后面不管是用现成框架、还是自己写流程,都会少走很多弯路。

返回列表