搭建最小 RAG 系统
让大模型回答你公司内部文档、产品手册、规章制度——而不是凭空编一个答案。
RAG 解决什么问题
大语言模型只知道训练数据截止之前公开的内容,问它"我们公司今年的差旅报销标准是什么"它只能瞎猜。RAG(Retrieval-Augmented Generation,检索增强生成)的思路是:先把你的私有文档切成小段、变成可搜索的索引;用户提问时先在索引里找最相关的几段;再把这几段连同问题一起交给模型,让模型"根据资料回答"。模型依然是同一个模型,但它的"参考书"被换成了你给的资料,回答就有了事实依据。
文档怎么切
把整本 PDF 一次性塞给模型既装不下也不高效。需要把它切成 200 到 800 字左右的小块(chunk),每个块尽量保持语义完整(按段落、标题、章节切,而不是按字数硬切)。最朴素的做法是按固定字符数切,更好的做法是按 Markdown 标题或句子边界切,结构化文档效果差异明显。切完后每个块要附上元数据(来源文件名、页码、章节),便于在回答时把引用给到用户。
Embedding 与向量检索
Embedding 模型把一段文字转成一串数字(向量),"意思相近的文字"在数学上距离也近。这一步通常用专门的 Embedding 模型(BGE、M3E、OpenAI text-embedding-3 等),而不是聊天模型。所有文档块转成向量后存进向量数据库(Chroma、Milvus、Qdrant、pgvector 都是常见选择)。用户提问时把问题也转成向量,在库里找"距离最近"的若干块(top-k,通常 3 到 10 个),这就是"检索"的全部过程。
把检索结果交给模型生成答案
拿到 top-k 相关块后,构造一段提示词:"根据以下资料回答问题。资料:[块1] [块2] [块3] 问题:用户原问题。如果资料里没有答案,请说不知道。"连同对话历史一起发给聊天模型,模型就会基于这些资料作答。最后把引用来源(文件名、章节、相关片段 ID)拼到回答里给用户,方便他们点开核对。RAG 系统的质量,七八成取决于文档切分和检索质量,而不是模型本身。
常见的坑
第一是表格和图被切碎——切分时把表格整体保留为一块,不要按行切,否则模型看到一堆零散数字。第二是检索不准——同义词、缩写、跨语言都可能导致向量检索漏掉正确答案,必要时用混合检索(关键词加向量)补救。第三是上下文塞太满——把 10 个块全部塞进提示词成本高、噪声大,应该先重排序(re-rank)只保留最相关的 3 个。RAG 不是装上就好用,它需要持续根据实际查询调优。
虫鱼的AI万花筒