如果你最近在关注大模型应用开发,肯定绕不开一个词:RAG(Retrieval-Augmented Generation,检索增强生成)。说白了,它就是给大模型装上一个“外挂知识库”——先检索再回答,而不是让模型硬着头皮猜。这篇指南我尽量用大白话把RAG讲透,从原理到实操,从踩坑到调优,覆盖一条完整的学习路径。不管你是刚入门的技术新手,还是被业务方逼着做知识库问答的开发者,这篇文章应该都能给你一些启发。
我自己做RAG相关项目已经有一段时间了,踩过的坑比走过的路还多。刚开始以为RAG就是“把文档喂给大模型”,后来才发现这里面藏着大量细节:文档怎么切、向量怎么存、检索怎么排、上下文怎么塞,每一步都直接影响最终回答质量。这篇内容不是教科书式的概念堆砌,而是结合我实际操作经验写出来的学习笔记,希望能帮你少走几个月的弯路。
1. 先搞明白:RAG到底是在解决什么问题
1.1 大模型不是真的“全知全能”
很多小白第一次接触大模型的时候,都会有一个误解:既然大模型能写代码、能写诗、能翻译,那它应该什么都知道吧?
实际上差得远。大模型的知识来源是预训练阶段“读”过的数据,这意味着两个天然的限制:
第一,知识有截止时间。一个去年发布的模型,它可能完全不知道这个月刚发生的行业新闻、最新政策、公司内部制度。你问它“我们公司最新的报销流程是什么”,它只能根据历史数据猜测,然后一本正经地给你编一个。
第二,知识是压缩过的。大模型在训练时不会把原文一字不差地背下来,而是学习数据背后的统计规律。这个压缩过程会丢失大量细节。比如你问它一本专业手册里某个参数的具体取值范围,它很可能答不上来,或者答个大概,但关键部分却是错的。
这个现象有个专业名词叫“幻觉”(Hallucination),就是模型在生成内容时,产出看似流畅但实际错误、甚至完全虚构的信息。做知识库问答的人对这四个字应该深恶痛绝——用户问“老王的电话号码是多少”,模型答出来一个号码,看起来逻辑通顺,但那个号码根本不存在,这在实际场景中是绝对不能接受的。
1.2 RAG的思路:把闭卷考试变成开卷考试
要理解RAG,你只需要做一道类比。
传统的直接用大模型回答问题,相当于“闭卷考试”:考生只能凭自己脑子的记忆来作答,遇到不会的题就只能瞎编。而RAG相当于给了考生一份参考资料,并且允许他一边翻书一边答题。
这道题的官方定义是:RAG在模型生成回答之前,先从外部知识库中检索与用户问题最相关的文档片段,把这些片段注入到模型的输入上下文中,模型参考这些片段生成答案。
这就带来了三个非常明显的优势:
- 回答有依据:模型不是凭空回答,而是基于检索到的文档片段来组织语言,幻觉概率大幅降低。
- 知识可实时更新:外部知识库可以随时增删改。公司制度变了,把新文件放进去,系统马上就能答出最新版本。不需要重新训练模型。
- 可溯源:回答完问题之后,你可以展示“我是参考了哪几份文档得出的结论”,用户看到了出处,信任度会高很多。
这个优势是微调(Fine-tuning)很难替代的。微调是把新知识“练进”模型参数里,成本高、周期长、更新麻烦,而且你依然无法控制模型在哪个环节产生幻觉。所以现在业界做企业知识库、客服机器人、文档问答类应用的常规方案,基本都是RAG,微调更多用来调整模型的语气和行为习惯,而不是给它塞新知识。
1.3 RAG和微调的边界,别搞混
这里我想多提醒一句:RAG和微调不是对立关系,它们各管一段。
你完全可以“先RAG后微调”:用RAG解决知识更新的问题,用微调解决模型输出风格和任务能力的问题。比如做一客服机器人,RAG负责从售后手册里找答案,微调负责让模型用更亲和的语气回答。
但优先级上,凡是涉及“事实性回答”“最新信息查询”的场景,优先考虑RAG。因为微调本质上是让模型“背新书”,背得快也忘得快,而且你很难保证它背得准。RAG才是让模型“翻开书查”的正确姿势。
2. 拆解RAG的完整工作流程:从文档到回答要经过哪些关卡
一个标准的RAG系统,可以简单拆成两条线:离线索引管线和在线检索生成管线。
离线索引管线负责把文档预处理成可检索的格式,在线管线负责接收用户问题、检索相关片段、生成回答。我把每一步拆开讲清楚。
2.1 文档加载与切分:最容易被低估的一步
很多新手第一步就把注意力放在模型和向量数据库上了,但真正决定RAG系统上限的,往往是文档加载和切分这一步。
文档加载本身没什么技术含量,就是从PDF、Word、Markdown、网页、数据库里把文本抽出来。但这里有个很隐蔽的坑:PDF文本提取经常会出现乱码、表格错位、段落顺序混乱的问题。我见过不少项目,索引建得漂漂亮亮,结果检索出来的内容是一堆断裂的乱码,原因就是PDF解析阶段就没处理好。
切分(Chunking)是更关键的一步。你需要把长文档切成一个个小块,每一块后续会被向量化并存入索引。切分粒度直接决定了检索的召回效果。
这三点是切分时最常问的问题:
- 切太碎(比如一句话一切):语义不完整,检索可能召回一句无关紧要的话,缺少上下文。
- 切太大(比如整章一切):向量表示会被稀释,检索到的片段可能包含太多不相关内容,还容易超出模型的上下文窗口。
- 切分重叠(Overlap):相邻块之间保留一定的重叠字符,可以避免关键内容恰好被切到边界上而丢失。
我目前比较常用的切分策略是这样的:通用文本,每个块大概300到500个token,重叠50到100个token;如果文档有明显章节结构,先按章节切,再对超长章节做二次切分。但这个数值不是死的,它跟你的文档类型、模型上下文长度、用户提问方式都有关系,后面第三部分实操里我会再说调优思路。
2.2 向量化与向量数据库:文本怎么变成“坐标”
切好的文本片段,机器是没法直接理解的。你要做的是把这些片段转换成向量的形式。
向量你可以简单理解为“一堆数字组成的坐标”。比如一条文本“猫是毛茸茸的动物”,经过嵌入模型(Embedding Model)处理后,会变成一个几百维的浮点数组。这个数组被映射到一个高维空间中,语义相近的文本在这个空间里的距离也相近。“猫是毛茸茸的动物”和“猫是可爱的宠物”这两条文本的向量距离会很近,而和“火箭发射原理”的向量距离会很远。
这个能力来自于嵌入模型在大量语料上的训练。常见的选择有很多,但核心思路一致:把句子变成语义坐标。
向量化完成之后,这些向量需要一个存放和检索的地方,也就是向量数据库。它和其他数据库最大的区别在于:它天然支持“按向量相似度查最近邻”的能力。
我常用的方案有两类:
- 轻量级嵌入式:适合个人项目和中小规模数据,部署零成本,直接写在代码里,数据量大时性能会下降。
- 服务级向量数据库:适合生产环境,支持分布式、高并发、数据过滤、多租户,真正企业级的方案基本都在这类里选。
选型上我的建议很简单:先跑通最简单的方案,等数据量和并发上来之后,再迁移到更重量级的方案。一开始就上复杂的分布式部署,容易把自己劝退。
2.3 检索与重排序:从“找到”到“找得准”
当用户提出一个问题,系统会先把问题转换成向量,然后在向量数据库里做最近邻搜索,找出最相似的Top K个片段。
但这里有个常见的问题:向量相似度和“相关性”未必完全画等号。有时候检索回来的片段词面很像,但语义离题;有时候真正的答案因为措辞不同,反而排在后面。
所以生产级RAG系统几乎都会加一道“重排序”(Rerank)的工序:向量检索先粗召回Top 50或Top 100个候选片段,交给重排序模型精排,从中挑出Top 3到Top 5个最相关的片段,再送给大模型。
重排序模型也是机器学习模型,但它对内容相关性的判断通常比纯向量距离准确得多。加了这一道工序之后,回答质量会有肉眼可见的提升。代价是多一次模型调用,速度和成本略有增加,但整体上非常值得。
另外,不少团队会做混合检索:一边用向量检索找语义相似的,一边用关键词检索(比如BM25)找出直接命中查询词的文档,再把两边的结果合并去重。混合检索的好处是能兼顾“语义”和“字面”,尤其在专业文档、人名、编号、产品型号等场景下效果更明显。
2.4 上下文注入与生成:大模型是怎么“看着资料答题”的
检索完成之后,系统会把命中的文本片段拼接到Prompt(提示词)里,格式大概长这样:
“你是知识库问答助手,请仅根据下面提供的参考文档回答问题。如果参考文档中没有相关信息,请直接说明不知道,不要编造答案。参考文档:……”然后模型就在这个上下文的约束下生成回答。
这里有几个实践要点:
- 上下文拼接顺序会影响模型注意力的分布。核心结论:把最相关的片段尽可能放在靠前或者靠后的位置,中间位置的内容容易被模型“忽略”,业内有人管这叫“lost in the middle”。如果你能控制答案片段的位置,尽量利用这一点。
- 要明确给模型“不知道的边界”。在Prompt里加上“如果参考文档中找不到答案,请直接说不知道”,这个约束能显著减少幻觉。模型有时候不是想骗你,它是真的不知道该怎么承认自己不知道。
- 答案长度和内容也要在Prompt里控制。你让一个客服机器人回答“怎么退换货”,它如果给你写一篇论文,那是你自己的Prompt设计有问题。
到了这一步,一个简化版的RAG系统其实已经闭环了。但离真正好用,还差大量的工程细节和调优工作。
3. 小白实操:从零搭建一个能跑的RAG系统
这部分我直接给出一套能跑的流程。我假设你已经安装好了Python环境,并且有一个可以调用的大模型接口(无论是云端还是本地部署的都可以)。为方便演示,我会用一个轻量级的开源向量存储方案,以及一个可以直接运行的嵌入模型。
3.1 环境准备与依赖安装
先安装以下核心依赖:
pip install langchain pip install chromadb pip install sentence-transformers pip install pypdf pip install faiss-cpu这里有另一个很常见的建议:不要一上来就装太多、太复杂的依赖。很多初学者被冗长的依赖列表搞到崩溃,最后还没开始就放弃了。我建议你先装这五个库,跑通流程,后面缺什么再补什么。刚开始就上全家桶,反而会让你不知道每层是怎么工作的。
如果你使用的是云端大模型接口,还需要安装对应的SDK;如果你用的是本地部署的模型,确保你已经能通过API或本地协议调用它。
3.2 构建索引:从文档到向量数据库
下面是整个离线索引流程的核心代码,我加了比较详细的注释。
from langchain_community.document_loaders import PyPDFLoader from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain_community.embeddings import HuggingFaceEmbeddings from langchain_community.vectorstores import FAISS # 1. 加载文档 loader = PyPDFLoader("company_manual.pdf") documents = loader.load() # 2. 切分文档 text_splitter = RecursiveCharacterTextSplitter( chunk_size=400, chunk_overlap=80, separators=["\n\n", "\n", "。", "!", "?", " ", ""], ) chunks = text_splitter.split_documents(documents) # 3. 向量化 embeddings = HuggingFaceEmbeddings( model_name="your-embedding-model-name", model_kwargs={"device": "cpu"} ) # 4. 构建向量索引并保存 vectorstore = FAISS.from_documents(chunks, embeddings) vectorstore.save_local("faiss_index")这个流程里有几个细节值得展开说。
切分器我用的是递归字符切分器(RecursiveCharacterTextSplitter),它的工作方式是:尽量按照我给的分隔符优先级去切分,如果发现切出来的块还是太大,就用下一个分隔符继续切。这个策略比较智能,能尽量保留自然段落和语义边界。
嵌入模型这里写的是your-embedding-model-name,你需要替换成你实际使用的模型。选择嵌入模型有一个很朴素的判断标准:嵌入模型的参数量越大,语义理解能力通常越强,但推理速度越慢、占用资源越多。如果你的文档内容是中文为主,建议选择在中文语料上训练效果较好的模型,这一点非常关键。我踩过的坑就是用了一个英文效果不错但中文效果很差的嵌入模型,检索召回率一度惨不忍睹。所以在实际项目中,嵌入模型选型值得你花时间做几个测试样本验证。
device参数可以根据你的硬件设置成"cpu"或者"cuda"。如果文档规模比较小(几百页以内),CPU跑嵌入完全够了,构建索引是离线完成的,慢个几分钟无所谓。
3.3 在线检索与生成:把答案“组装”出来
索引建好之后,在线流程的代码看起来更加简洁。
from langchain_community.vectorstores import FAISS from langchain_community.embeddings import HuggingFaceEmbeddings from langchain.chains import RetrievalQA # 加载之前保存的索引 embeddings = HuggingFaceEmbeddings(model_name="your-embedding-model-name") vectorstore = FAISS.load_local("faiss_index", embeddings, allow_dangerous_deserialization=True) # 创建检索器 retriever = vectorstore.as_retriever( search_type="similarity", search_kwargs={"k": 4} ) # 创建问答链 qa_chain = RetrievalQA.from_chain_type( llm=your_llm, retriever=retriever, chain_type="stuff", ) # 提问 response = qa_chain.invoke("公司对员工请假天数有上限要求吗?") print(response["result"])这一步在概念上很简单:检索器拿到问题,在向量数据库里找出最相似的4个片段,问答链把这些片段拼进Prompt,交给大模型生成回答。
但我要提醒你两个容易忽视的点。
第一个是allow_dangerous_deserialization=True这个参数。新版FAISS加载本地索引时默认禁止反序列化,很多人在这个参数上卡了半天。如果你是自己生成的索引文件,信任数据来源,可以打开这个开关;如果你下载了来路不明的索引文件,千万别开,这个参数本质上是让代码能够执行索引文件里潜在的可执行代码,有安全风险。
第二个是chain_type。代码里用的是stuff,意思是把检索到的所有片段一次性都塞进Prompt。这在片段少、上下文短的场景下没问题。但如果你的检索结果很多、或者每个片段很长,容易把Prompt撑爆,这时候就需要考虑其他处理方式,比如map_reduce(对每个片段分别问一遍再汇总)或者refine(逐段精修答案)。它们能处理长上下文,但代价是更多的模型调用次数和更长的响应时间。
3.4 关键参数调优:决定回答质量的隐藏旋钮
我刚开始做RAG的时候,以为跑通流程就万事大吉了。结果拿一个问题去测试,答案要么答非所问,要么啰里啰嗦。排查了一圈才发现,问题出在几个参数设置上。
这里给大家列一张我常用的参数调优速查表:
| 参数 | 作用 | 常见问题 | 调优建议 |
|---|---|---|---|
| chunk_size | 切块大小 | 太小丢失上下文,太大稀释语义 | 300-500(通用),按文档类型调整 |
| chunk_overlap | 块间重叠 | 过小导致边界信息丢失 | 50-100,或chunk_size的10%-20% |
| top_k | 检索返回片段数 | 太少漏信息,太多塞无关内容 | 3-5起步,越复杂的问题可以适当调大 |
| embedding模型 | 语义理解能力 | 中文场景用英文模型效果差 | 针对领域和语种实测对比 |
| 检索类型 | 相似度 / MMRA | 纯相似度可能缺少多样性 | 复杂问题可尝试mmr(最大边际相关) |
| 重排序 | 精排相关度 | 不加重排,召回质量不稳定 | 预算允许时一定加 |
以top_k为例。k值设太小,比如只有1,那模型只能看一段话,如果这段恰好不是答案所在的位置,回答就废了。但k值设太大,比如到了10,会把一堆不相关的片段也塞进Prompt,模型反而容易被噪声干扰,回答质量也会下降。合理的方式是先设一个中等值(比如4),跑一批测试问题,看召回结果反馈哪些片段被命中,再根据情况调整。
chunk_size的调整逻辑更直观:如果文档里有大量表格、代码块、结构化文字,建议适当增大chunk_size并配合重叠;如果文档是连续的自然语言,中等大小的chunk通常效果最好。
4. 实战疑难排查:检索不到、答错、延迟高怎么办
代码能跑通很简单,要让它稳定地输出高质量回答很难。我把在实际项目中遇到的问题和排查思路整理成了一份速查表,都是真实踩过的坑。
4.1 检索结果答非所问
现象:用户问“合同中的违约金比例是多少”,系统返回的却是一段无关的合同综述。
排查思路:
第一步先看看向量数据库召回的原文片段到底是啥。我一般会在日志里把top_k个片段的文本内容打出来。如果召回内容本身就牛头不对马嘴,说明问题出在检索端;如果召回内容正确但模型回答错了,说明问题出在生成端的Prompt设计或上下文处理上。
检索端最常见的原因,是切分不当。比如一个长段落被拦腰切断,违约金比例是在前一个块里,但你切出的块只包含后半段,这样当然检索不到。解决办法是调大chunk_overlap,或者用按语义段落优先的切分策略。
另一个原因是检索阀值不敏感。有时候向量数据库确实召回了包含答案的片段,但它的相似度得分偏低,被其他不相关的片段挤出了Top K。这时候可以在检索器里调高K值,或者加一重排序模型,把真正相关的片段精排上来。
还有一种情况很隐蔽:用户问题的说法和文档原文完全不同。比如文档里写的是“解约赔偿条件”,用户问的是“毁约了要赔多少钱”。纯向量检索对同义改写有一定的鲁棒性,但遇到表达差距很大的提问,召回效果仍然可能崩。混合检索在这个场景下能起到不少帮助,关键词命中的机制往往能在语义匹配失效时兜底。
4.2 模型仍在“幻觉”,回答内容明显编造
现象:参考文档里根本没有相关信息,模型还是回答了一个看起来像模像样的答案。
排查思路:
第一个可能性是Prompt约束不强。很多模型接到问题后,会习惯性地利用内部知识来“补全”答案。你必须在Prompt里把约束说得非常明确,比如“如果参考文档里没有信息,只回复‘当前知识库中未找到相关资料’,不要自行回答”。
第二个可能性是检索到了完全不相关的内容,模型把它们误认成了正确答案。这里我会建议在代码里加一个召回内容相关性判断的环节。最简单的方法是对相似度得分设一个阈值,低于阈值的片段直接丢弃,最后只保留真实相关的部分。如果所有片段都低于阈值,就返回“未找到相关资料”。
第三个可能性是处理表格和图片时出问题了。文档里的表格被PDF解析成乱序文本,或者关键信息藏在图片里,检索时自然就丢了。解决思路有两个:表格类文档先用专门的表格解析工具将结构还原成可读文本,再走切分;图片类内容接入多模态能力,对图片做描述后建索引,再参与检索。这个投入不小,但做知识库问答迟早会遇到。
4.3 系统响应太慢,生产环境撑不住
现象:单机玩的时候挺流畅,一上了业务场景,并发一拥而入,每个请求要等十几秒。
排查思路:
RAG的响应链路是:向量检索 + 重排(可选) + 大模型推理。向量检索在大规模数据集上会有延迟,大模型推理是响应大头,两者优先级不一样。
我给的优化顺序是:先做缓存,再做并发,最后考虑模型量化。
缓存的意思是:热门的、重复的问题直接缓存答案,没必要每次重新调用大模型。这个优化简单粗暴,带来的延迟降低却最明显。建议对重复提问做个哈希去重,相同或高度相似的问题直接命中缓存。
并发优化更多是工程层面的。比如多个用户同时提问时,向量数据库的并发查询能力是否够用;大模型API是否支持异步请求;如果用的是本地模型部署,推理服务有没有开足显存和批处理。我见过不少项目是卡在没有做异步和批处理上,大量请求在排队。
最后的模型量化方案是:把大模型从16位量化到8位甚至4位,推理速度能提升不少,但回答质量可能略有下滑。这个方案在本地部署场景下是性价比最高的,建议先拿量化模型跑一批测试,评估回答质量还能不能接受。
5. 从Demo到生产:进阶路线图
跑通Demo容易,落地到生产才是硬仗。我个人的经验是:一个生产级RAG系统至少需要解决三个问题——数据质量、检索质量、效果评估。
5.1 构建面向检索的文档预处理
生产环境里,文档来源五花八门:Word、PPT、扫描件、网页、图片、手写笔记。如果数据质量参差不齐,整个RAG的上限就不会太高。
我现在处理文档流程是:先分类(文本型 / 表格型 / 图片型),再针对类型选择解析方案,最后做一次清洗。清洗包括去除页眉页脚、提取表格结构、统一编码格式、处理超链接等。这一步很枯燥,但对检索质量的提升是决定性的。
额外提一句:如果你做的是跨语言的文档知识库,建议在嵌入和检索阶段就做好语言适配。比如中英混合文档,答案可能一半中文一半英文,这时候切片和嵌入模型都需要对双语文档有不错的处理能力。
5.2 引入评估体系:别再“肉眼调参”了
很多RAG项目停在一个尴尬的阶段:改一个参数,试了几个问题觉得OK,上线一段时间又开始被用户投诉。这里的问题在于没有建立一个足够客观的评估体系。
业界常用的做法是准备一组带标准答案的评测集,比如50到200个问答题对,每次改动之后,跑这组评测集,看回答的自动评估指标变化。常见的指标包括:忠实度(回答是否依据检索文档)、相关性(回答是否正确回答了问题)、检索命中率(正确答案片段是否被召回)。
评估方式可以采用人工评估,前期样本少、只管几个核心场景,人工评估最可靠;也可以借助大模型当裁判,对多个候选回答做对比打分,效率高,适合迭代调优。
我个人的习惯是:初期人工评估20个典型问题来摸底,之后用一个评测集配合自动指标跑回归测试,每次调参都记录配置和指标结果,这样才能从“我觉得改好了”变成“数据证明改好了”。
5.3 多轮对话与状态管理
很多知识库不是一问一答就完事的,用户会连续追问:“那退换货要几天?”——你得知道这里的“这”指的是上一轮说的某个商品。
多轮RAG处理起来比单轮复杂得多。核心方案是对用户的原始问题进行“改写补全”:先让大模型根据对话历史,把当前问题补全成一个完整的、独立的查询,然后再走检索流程。比如用户前一轮问“你们家的椅子是什么材质”,下一轮问“能用水擦吗”,改写环节会先把问题改成“刚才提到的那个材质能用水擦吗”,再进行检索,效果会好很多。
状态管理方面的细节是:每轮检索的片段要留存,保证后续追问可以引用;对话历史不要无限堆积,超过一定轮数就裁剪或做摘要,避免上下文超出模型窗口、也避免早期无关信息干扰判断。
5.4 生产环境的SRE意识
最后聊一点偏工程运维的内容。RAG系统上线之后,你至少要关注三类指标:缓存命中率、调用成功率和端到端延迟。缓存命中率能看出哪些问题是用户热问,调用成功率能暴露上游链路的问题,端到端延迟决定了用户体验。
日志里一定要把检索到的片段ID、相似度分数、模型输入输出都记录下来。这是事后排查的关键。我挨过一次比较惨的教训:线上系统某个回答错了,结果日志里只有最终答案,完全没有中间检索过程和Prompt内容,排了两天都没找到原因。从那以后,凡是RAG请求,我一定会在日志里留全链路的快照。
安全层面也要注意:RAG系统有可能检索出超出权限范围的文档,比如某个用户提问时命中了内部机密文件。这时候要做的是在检索阶段就做权限过滤,根据用户身份限制其能访问的文档范围,而不是等检索结果出来之后再做处理。这属于“在设计索引时就考虑多租户隔离”的范畴,越早做,后期越省心。
6. 写在最后:一些学习上的建议
RAG这个方向,入门不难,但要做出真正能落地的产品,需要补的知识维度确实不少。我把自己的学习路径和踩坑心得分享在下面,供你参考。
第一,先把基本流程跑通,再研究优化。不要一上来就纠结用哪个向量数据库、用哪个重排模型。先用最简单的工具链,让一个Demo能回答出基本正确的问题,再逐步替换组件。换组件你会知道自己要解决什么具体问题,而不是为了用新技术而用新技术。
第二,掌握评估方法比掌握调参技巧更重要。如果只有“凭感觉”这一个评估手段,你很难判断一次改动是好是坏。花一两天时间建一个小的评测集,后续的迭代效率会成倍提升。
第三,做RAG要多读别人分享的Case Study,不要只看纯理论教程。检索失败的现实原因千奇百怪——PDF解析乱码、嵌入模型跑偏、Prompt约束不够、切分边界切断答案……这些在教科书里不会写清楚,只有在真实的故障复盘里才有人讲。
我还想分享一个很细节的体验:一个好的RAG系统,不只是“搜到”和“答对”就够了,还要懂得“不答”。当知识库里没有答案时,能诚实地告诉用户“我没有找到相关资料”,比硬编一个错误答案要重要得多。这个行为是在Prompt里约束的,也是需要在系统设计时贯彻的。
我的实现经验里有很多细节,并不是调试一两次就能沉淀下来的。比如切分参数最好看召回样本中命中的位置来微调,而不是全凭经验给一句话;嵌入模型在领域数据上的评测,用20条和业务强相关的问题就能暴露一半的问题;重排序模型加上之后,大部分场景下效果都有明显提升,这个投入产出比是非常值的。
如果这篇文章能让你对RAG有了一个更立体的理解,并且愿意动手搭一个自己知识库的Demo,我就觉得值了。把代码跑起来,把问题抛出来,再去对比别人踩过的坑,你会发现RAG的学习曲线远没有想象中那么陡。
最后送给你一个我在实践中反复验证过的结论:RAG项目的成败,多半不在模型本身,而在数据准备和检索质量。这两个环节花再多精力都不为过。希望你能在自己的RAG项目里,少走一些我走过的弯路。