ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

RAG与大模型的关系及本地知识库搭建实战

RAG与大模型的关系及本地知识库搭建实战 最近这半年几乎每周都有人拿RAG的问题来找我要么是“RAG和大模型到底是不是一回事”要么是“我手里一堆PDF和Word能不能用RAG快速做个公司内部问答机器人”。说真的这些问题放在一年前还比较好答但现在RAG这个名字被塞进了太多概念里RAG智能体、RAG框架、本地RAG知识库、Dify接入本地大模型、LangChain里的Easy RAG……术语一多人反而容易懵。所以这篇我想把RAG和大模型的核心关系彻底掰开揉碎讲清楚它们俩是谁依赖谁、怎么配合、跑起来以后会踩哪些坑以及当你手头只有一台普通电脑的时候怎么从零搭一个能用、能复现、能逐步调优的RAG知识库。1. RAG到底和大模型是什么关系1.1 先给关系下一个准定义如果非要用一句话解释那就是大模型是大脑RAG是给大脑配的外部记忆册。大模型本身有参数记忆你问它“李白是哪个朝代的”它能靠训练时背下来的知识回答。可你要是问“公司上季度华东区的销售额是多少”“这份合同第五页第三条写的什么”它大概率只能瞎编因为公开语料里根本没有这些内容。RAG要做的事情就是补上这一环先把私有文档切碎、向量化、存进一个能快速检索的“记忆库”用户提问时先从库里找到最相关的几段内容再把“用户问题检索到的片段”一起交给大模型生成答案。所以RAG不是另一个模型它是围绕大模型搭建的一套检索-增强-生成完整流程。1.2 大模型的三个死穴恰好是RAG的切入点第一个死穴是知识截止。训练一次大模型成本非常高知识基本停留在一个固定的时间点。教科书级别的静态常识没问题但遇到上个月刚上线的产品、昨天刚更新的政策文件、同事上周写的项目方案它天然不知道。第二个是私域知识盲区。企业的财务数据、研发文档、客服话术、运维手册这些内容不会出现在任何公开训练集里可业务场景偏偏最依赖这些。你不可能指望一个开源模型靠“通用知识”回答出你的内部专属问题。第三是幻觉。模型在不确定答案的时候倾向于用一种自信十足的语气胡说八道而且听起来还挺像那么回事。RAG的价值在于它把来自真实文档的证据文本喂给模型把回答从“猜测”拉到“查证”的轨道上。1.3 谁依赖谁其实谁都不能少很多人有个误解以为RAG是把“检索”包装了个新名字。如果只有检索没有大模型那它就是搜索引擎输出的是原文片段而不是“组织好的答案”反过来只有大模型没有RAG那就是一个记忆残缺但能聊天的专家。真正形成合力的方式是检索端负责“找到正确答案在哪里”生成端负责“把证据变成人话”。再往下拆一层你会发现一个很有意思的结论RAG的质量瓶颈几乎从来不在生成端而在检索端。大模型只要拿到了正确的上下文哪怕是一个很小的7B模型也能写出有模有样的回答。真正让人抓狂的问题是“该找到的内容没被找到”或者“找到了但被排在后面”。1.4 RAG的核心价值也就是它存在的理由我觉得可以总结成三个关键点知识更新成本极低。文档改了一版库里删掉旧chunk、插入新chunk当天就能生效完全不需要重新训练模型。可追溯、可解释。回答可以标注“这部分内容参考自文档2第3段”用户能沿着证据链路倒查回去。这个特性在企业合规、风控场景里几乎等于刚需。门槛低、见效快。不需要高端GPU做大规模训练一台配置尚可的消费级电脑就能把一套私有知识库跑起来。2. RAG完整工作流三段式原理拆解2.1 第一阶段文档的拆解与入库RAG的源头是文档。不管你的知识库载体是PDF、Markdown、Excel还是网页链接第一次接入系统时都有一个绕不开的环节切块Chunking。为什么必须切大模型的上下文窗口是有限的哪怕现在很多模型宣称能支持128K甚至200K tokens你也不可能把整个知识库塞进去。所以需要把长文档切成若干个小块每一块独立向量化、独立存储检索的时候按“块”召回。切块这件事看起来简单其实非常讲究。切太细比如按每200字硬切会破坏段落语义一句话被拦腰截断检索结果会非常碎切太粗比如把整个章节塞成一个块检索时会召回大量无关内容召回精度直接滑坡。我比较常用的策略是先按标题结构拆成一个个大章节再对超过阈值的章节做滑动窗口切分每块控制在500到800字之间块与块之间保留约10%到15%的重叠防止关键句正好落在边界上被割裂。2.2 第二阶段向量化与检索匹配文档切块之后下一步是把每个块变成一个向量。这里要用到另一类模型——嵌入模型Embedding Model比如常见的bge-m3、text2vec、nomic-embed-text。它们做的事情说来也直白把一段文本映射到一个高维空间里的坐标点语义上相似的两句话会在空间里距离更近。提问时同样把用户问题向量化然后在向量库里做近似最近邻搜索找出距离最近的前K个块。这个“K”是个需要反复调的超参数K太小容易漏掉有用信息K太大无关内容会污染上下文。我一般从K5开始调但实际最优值跟文档质量、切块大小都密切相关。这里有个非常容易忽略的细节向量检索只擅长语义匹配不擅长精确关键词匹配。比如用户问“甲方的验收标准是什么”文档里写的是“业主方确认验收合格的条件”语义上确实相关向量检索大概率能命中但如果用户问的是某个精确的编号比如“合同编号HT-2024-038”向量检索反而可能表现得很糟糕。所以专业一点的RAG方案都会做混合检索向量检索主打语义再加一层BM25这类传统关键词检索最后把两路结果合并去重再做一次重排。2.3 第三阶段生成与答案融合检索完成之后系统会把“用户问题检索到的若干文本块”拼接成一个大提示词交给大模型生成答案。这一段的功夫全在提示词设计上。我处理这个环节时会注意三件事。第一是明确告诉模型“只能依据给定材料回答”材料中没有的内容直接说不知道不要强行补充。这一步对抑制幻觉非常有效。第二是给每段材料加编号生成时要求模型在答案里标注“根据材料3”后面排错和追证据都方便。第三是控制输入材料的顺序通常把最相关的片段放在最前面因为不少模型对距离较远的内容关注度会下降。生成完之后一个完整的RAG系统通常还有后处理环节比如答案的内容去重、引用来源整理、敏感信息过滤。企业级落地时往往还会接一个“答案评估”步骤用规则或另一个模型判断当前回答是否命中了知识库内容如果没有就回退到“抱歉我无法从现有资料中找到答案”避免硬答。3. 本地RAG知识库零基础完整实操3.1 工具选型普通电脑也能跑起来我知道很多人看到RAG的第一反应是“这得上GPU吧”。其实不然。一套能用的本地RAG硬件要求远没有微调大模型那么夸张。我推荐的最小可靠组合是组件推荐方案说明大模型Ollama Qwen2.5 7B / Llama 3.1 8B7B到8B的量化模型16GB内存的电脑就能跑嵌入模型bge-m3 或 nomic-embed-text中英文效果都比较稳体积也不大向量数据库Chroma / FAISS单机轻量场景首选无需单独部署服务端编排框架LangChain / LlamaIndex方便串流程但初期也可以直接手写可视化平台Dify / AnythingLLM对不想写代码、想快速验证的用户非常友好这里面我尤其想提一下Dify。它是当前接入本地大模型非常顺手的工具社区版可以对接Ollama里已经拉下来的本地模型再做知识库上传、分段、召回的整套配置。如果你想要的是“开箱即用”的本地RAG而不是自己从零写代码Dify是当前的性价比选择。3.2 动手搭建一个可直接复制的流程为了方便说明我用“Ollama Chroma Python”这套组合搭一个简易本地RAG知识库整个过程不需要GPU服务器一台有16GB内存的笔记本就能完成。第一步安装Ollama并拉取模型。Ollama同时支持大模型和嵌入模型在终端里执行两条命令ollama pull qwen2.5:7b ollama pull bge-m3执行完后可以测试一下模型是否正常响应ollama run qwen2.5:7b 你好请简单介绍你自己第二步准备知识文档并做切块。我习惯把文档放到一个docs目录下用Python写一个简单的切块器。这里给一个基础的递归字符切分代码from langchain_text_splitters import RecursiveCharacterTextSplitter splitter RecursiveCharacterTextSplitter( chunk_size500, chunk_overlap50, separators[\n\n, \n, 。, , , , , ] ) with open(docs/project.md, r, encodingutf-8) as f: text f.read() chunks splitter.split_text(text) print(f切分完成共 {len(chunks)} 块)第三步生成向量并写入Chroma。这里的逻辑是遍历每个chunk用bge-m3生成向量再把向量和对应的文本、来源信息一起存到向量数据库里。import chromadb from langchain_community.embeddings import OllamaEmbeddings from langchain_community.vectorstores import Chroma embedding OllamaEmbeddings(modelbge-m3) vectorstore Chroma.from_texts( textschunks, embeddingembedding, persist_directory./chroma_db ) print(向量库创建完成)第四步检索并拼接提示词。用户输入问题以后先从Chroma里检索出前K个文本块然后把它们拼成上下文提示词交给Ollama里的大模型生成答案from langchain_community.chat_models import ChatOllama results vectorstore.similarity_search(项目截止日期是什么时候, k5) context \n\n.join([f【材料{i1}】\n{doc.page_content} for i, doc in enumerate(results)]) prompt f请基于以下材料回答问题材料中没有的信息不要编造。 如果材料不足以回答请直接说“资料中未找到相关信息”。 {context} 问题项目截止日期是什么时候 llm ChatOllama(modelqwen2.5:7b) response llm.invoke(prompt) print(response.content)这个流程跑通以后你就拥有一个最简但五脏俱全的本地RAG系统了。3.3 效果验证怎么判断RAG到底“行不行”跑通和跑好是两码事。搭完之后我强烈建议花一点时间做效果验证而不是看到能回答就认为大功告成。我会准备三类测试问题第一类是事实型问题答案必须来自某篇特定文档第二类是综合型问题需要跨多个文档拼接信息比如“对比A方案和B方案的成本差异”第三类是边缘型问题知识库里根本没有答案用来测试系统会不会不懂装懂。我给自己的验收标准很简单事实型问题准确率至少在80%以上综合型问题能给出部分正确的结构边缘型问题必须老实说“不知道”。如果前两项不达标先回去检查切块策略和检索K值如果第三项不达标就是提示词没有约束好幻觉。4. RAG和微调怎么选别再傻傻分不清4.1 两种手段解决的是两类问题RAG和大模型微调这组词经常被摆在一起但它们的定位完全不同。微调是改变模型本身通过额外的训练数据让模型的权重发生变化让它学会某种风格、某种格式或者掌握某一窄领域的推理模式。RAG是不改变模型通过动态注入外部知识来增强回答的准确性和实时性。如果知识库的内容是高频变动的比如客服话术、产品FAQ、实时政策文件RAG是唯一合理的选择因为每次更新只需要替换文档重新向量化如果目标是让模型稳定地按特定格式输出比如永远用一套JSON结构回复、永远模仿某个角色的文风那微调更合适因为仅靠提示词很难保证一百次里有九十九次都严格遵守格式。4.2 实际项目里两者经常混着用我在真实项目里看过一种很常见的组合打法先微调模型让它学会这套业务的语言习惯和输出格式再在推理阶段挂上RAG从实时更新的知识库里检索业务细节。微调负责“让它像这个行业的人”RAG负责“让它知道今天的具体情况”。举个例子一个法律咨询系统可以先用大量判决书微调模型让它熟悉法言法语和文书结构上线后接一个包含最新司法解释和内部案例库的RAG知识库这样新法规一发布只要把新文档投入库里系统当天就能回答相关问题而不用重新训练。微调管“风格和底子”RAG管“信息和时效”两者并不互相排斥。4.3 资源成本对比别一上来就烧GPU我自己在评估技术方案时会特别看重成本。微调的硬件门槛很高即使是LoRA这类参数高效微调通常也需要一块不错的大显存GPU而RAG的核心开销在文档向量化的算力上一次处理完就基本固定了日常问答阶段其实是最普通的CPU和内存就能扛住的。所以我的建议很直接大多数企业内部知识库场景先上RAG别一上来就考虑微调。只有当RAG已经把召回准确率调到极限、结果还是不能满足业务要求时才值得考虑用微调或者RAG微调组合来兜底。4.4 一个容易忽略的窗口期问题还有个细节得提醒一下。现在很多模型的上下文窗口做得越来越大有人开始觉得“那干脆把资料全塞进提示词还要RAG干嘛”。想法可以理解但你要知道长上下文不等于高质量关注模型对几万token中间的细节注意力是分散的加上巨大的计算开销响应速度和成本都会吃掉长窗口的红利。RAG的核心价值就在于**“只取最相关的少量片段”**让模型的注意力集中在关键证据上。所以哪怕上下文窗口再大检索增强的思路也依然有意义。5. RAG的常见瓶颈与避坑指南5.1 检索召回的“灯下黑”RAG项目里最常见的现象是知识库里明明有答案但系统就是答不出来。这类问题九成出在检索环
返回列表