Skip to content

RAG

检索增强生成(Retrieval-Augmented Generation,RAG)是解决大语言模型幻觉问题、知识更新滞后、私有数据利用等核心挑战的实用方案。纯语言模型虽然能力强大,但存在明显局限:训练数据是静态的,无法获取最新信息;对私有领域知识一无所知;容易生成看似合理但完全错误的内容(幻觉)。RAG 的思路很简单——在生成回答之前,先从外部知识库检索相关文档,然后将检索到的内容作为上下文提供给模型,让模型基于这些材料生成答案。

这个想法的价值在实践中得到了充分验证。企业内部知识库问答是 RAG 的典型应用场景,员工可以向系统提问公司政策、技术文档、项目历史,系统会从内部文档中检索相关信息并生成准确回答。与传统的关键词搜索不同,RAG 能够理解问题语义,整合多个文档的信息,用自然语言给出连贯的答案。客服机器人也是 RAG 的重要场景,基于产品手册、FAQ、历史工单检索,可以给出远超传统规则匹配的答复质量。

RAG 相比微调(Fine-tuning)有独特的优势。微调需要准备训练数据、消耗大量计算资源、且容易出现灾难性遗忘(学到新知识后忘记旧知识)。RAG 则不需要重新训练模型,只需维护可更新的文档库,知识更新成本低且效果可追溯——用户可以查看检索到的文档来验证答案来源。此外,RAG 的答案可以附上引用链接,提升了可信度,这对于医疗、法律等专业领域尤为重要。

核心组件

一个完整的 RAG 系统包含三个核心环节:文档处理、向量检索、生成回答。文档处理将原始文本转换成可检索的表示,向量检索根据问题找到相关文档,生成回答则基于检索结果组织语言输出。

  1. 文档处理的第一步是切分(Chunking)。原始文档通常太长,无法直接作为上下文输入模型(LLM 的上下文窗口有限),而且长文档会稀释关键信息的权重。切分策略直接影响检索质量,最简单的方法是按固定字符数切分(如每 500 字一段),但这样可能在句子中间截断,破坏语义。更优雅的方案是按段落、章节、句子边界切分,或者使用递归字符切分——先尝试按段落切分,如果段落仍然过长,再按句子切分。切分时还要考虑重叠(Overlap),相邻 chunk 之间保留一定重复内容(如 50 字),这样关键词被截断的概率降低,检索召回率会提升。

  2. 切分后的文本需要转换成向量表示才能进行语义检索。传统的关键词搜索无法处理语义相似但表达不同的查询,比如用户问"如何配置网络"和文档中的"网络设置指南"在字面上不重叠,但语义高度相关。向量嵌入模型(Embedding Model)将文本映射到高维向量空间,语义相似的文本在这个空间中距离更近。OpenAI 的 text-embedding-3、Hugging Face 上的 bge-m3e5 系列都是常用的嵌入模型,选择时要考虑语言支持、向量维度、推理性能等因素。

    向量存储需要专门的数据库来支持高效检索。传统关系型数据库无法处理向量相似度计算,向量数据库(Vector Database)通过近似最近邻(ANN)算法在毫秒级完成大规模向量检索。主流选择包括 Milvus、Pinecone、Weaviate、Chroma,或者 PostgreSQL 的 pgvector 扩展。选型时需要考虑数据规模、查询延迟、部署复杂度、运维成本等因素。中小规模应用可以使用轻量级的 Chroma 或 FAISS,大规模生产环境则需要考虑 Milvus 或 Pinecone 这样的专用方案。

  3. 生成回答环节使用大语言模型(LLM)将检索结果转换为自然语言答案。LLaMA、ChatGLM、Qwen 等开源模型都可以部署私有化 RAG 系统,避免数据外传。提示词(Prompt)工程在这里很关键,需要将检索到的文档、用户问题、输出格式要求组合成清晰的指令。基础的 prompt 模板是:"根据以下文档回答问题,不要使用文档外的信息:\n\n文档:{retrieved_docs}\n\n问题:{user_query}\n\n回答:",更复杂的场景会加入多轮对话历史、答案引用要求、不确定性提示等。

检索策略是 RAG 系统的关键设计点。最基础的单路检索(Top-k Retrieval)返回与问题最相关的 k 个文档,通常 k 取 3-5 个。但如果问题涉及多个方面,单路检索可能遗漏相关信息。多路检索(Multi-query Retrieval)将用户问题改写成多个不同表述,分别检索后再合并结果,比如"如何部署服务"可以改写成"部署指南"、"服务配置"等。重排序(Reranking)是另一种优化手段,先用简单的向量检索快速筛选出候选文档(比如前 50 个),再用更精细的重排序模型(如 bge-reranker)精确评分,最终保留前几个最相关的。这种两阶段检索在准确率和性能之间取得了良好平衡。

开发流程

构建 RAG 系统的典型开发流程包含数据准备、原型验证、性能优化、生产部署四个阶段。

  1. 数据准备阶段需要收集领域文档,清洗格式问题(去除无关字符、统一编码、修复乱码),然后进行文档切分和向量化存储。这个阶段的工作量往往被低估,实际项目中 60%-70% 的时间可能花在数据处理上,高质量的文档库是 RAG 系统成功的基石。

  2. 原型验证阶段快速验证技术方案的可行性。可以使用 LangChain、LlamaIndex 等 RAG 框架快速搭建原型,这些框架封装了常见的组件和流程,开发者只需配置数据源、选择嵌入模型、指定 LLM,就能得到可工作的系统。原型阶段的核心目标是验证检索质量——用一组典型的测试问题,检查检索结果是否相关,如果检索就不准确,再好的 LLM 也无法生成正确答案。这个阶段通常会暴露出文档切分不合理、嵌入模型选择不当等问题,需要针对性调整。

  3. 性能优化阶段关注准确率和响应速度。准确率方面,可以尝试不同的检索策略(重排序、多路检索)、调整切分参数(chunk size、overlap)、优化 prompt 模板。响应速度方面,可以缓存常见问题的答案、使用更小的嵌入模型、优化向量数据库索引。这个阶段需要建立评估体系,不能仅凭主观判断。一种实用的方法是准备一批标准问题及其参考答案,计算生成答案与参考答案的相似度(可以用 BLEU、ROUGE 等指标,或者用另一个 LLM 给答案打分),有量化的指标才能进行 A/B 测试和迭代优化。

  4. 生产部署阶段需要考虑工程实践问题。并发处理能力是首要考虑,RAG 系统的响应链路包括嵌入计算、向量检索、LLM 生成,任意一个环节成为瓶颈都会影响整体性能。可以采用异步处理、请求队列、水平扩展等策略提升吞吐量。监控和日志也很重要,需要记录每次查询的检索结果、生成答案、用户反馈,这些数据既能用于问题排查,也能持续优化系统。安全性方面,要确保文档访问权限控制、敏感信息脱敏、防止提示词注入攻击。

常见挑战

RAG 系统开发中会遇到一些共性难题。

检索不精准是首要问题,用户问题表述模糊、领域术语歧义、文档覆盖不足都会导致检索失败。解决思路包括优化 prompt 引导用户更清晰地描述问题、扩充文档库覆盖更多场景、使用更强大的嵌入模型和重排序策略。

另一个挑战是上下文窗口限制,检索到的内容可能超过 LLM 能处理的长度,这时需要对检索结果进行摘要或过滤,只保留最相关的部分。

答案质量不稳定也经常出现。有时 LLM 会忽略检索到的内容,编造文档外的信息(幻觉问题);有时答案过于笼统,没有给出具体细节;有时答案格式不符合预期(如要求列出要点却生成段落)。这些问题的缓解方法是仔细设计 prompt,明确告诉 LLM 只使用提供的信息、规定输出格式、给出示例(Few-shot Learning)。更高级的方案是使用微调过的模型,专门训练 LLM 遵循 RAG 任务的模式,但成本较高。

多轮对话是 RAG 的进阶挑战。用户的问题可能依赖对话历史,比如先问"公司的远程办公政策是什么",再追问"那加班呢",第二个问题中的"那"指的是远程办公场景下的加班,需要结合上下文理解。处理多轮对话需要维护对话状态,将历史问题和检索结果整合到新的查询中。常用的方法是将前几轮对话的问题和检索到的文档拼接起来,与当前问题一起输入嵌入模型,或者让 LLM 根据对话历史重写当前问题,使其成为独立完整的表述。

框架与工具

LangChain 是目前最流行的 RAG 开发框架,它提供了从文档加载、切分、嵌入、存储到检索、生成的完整工具链。LangChain 的抽象层级较高,适合快速原型,但抽象也意味着灵活性受限,定制化需求可能需要绕过框架直接实现。LlamaIndex 是另一个选择,更专注于数据索引和检索,在处理大规模文档库时性能更好。

对于追求极致性能和灵活性的场景,可以直接使用底层库构建系统。嵌入计算可以用 Hugging Face 的 sentence-transformers,向量检索可以用 FAISS 或 Milvus SDK,LLM 调用可以用 Transformers 库或 vLLM 推理引擎。这种方式的开发成本较高,但能够针对具体需求优化每个环节,适合大规模生产环境。

RAG 是大模型落地最成熟的方案之一,它不需要重新训练模型就能让 LLM 掌握私有知识,而且答案可追溯、易于更新。随着向量数据库和嵌入模型的技术进步,RAG 系统的准确率和性能还在持续提升。对于企业应用而言,投入资源构建高质量的文档库和检索系统,比盲目追求更大的模型更有价值。