RAG 相关概念
AI 学习笔记系列的第九篇,介绍 RAG 相关的基本概念,包括 RAG 基本流程、优化点、常见检索方式和融合方法,以及一个具体示例、常见问题和解决方法。
检索增强(Retrieval Augmentation)
大语言模型并不总能只靠参数记忆解决问题,否则下面的问题很难解决 / 缓解:
- 幻觉(Hallucination):模型生成了不正确或不真实的信息
- 新事件的更新不够及时
- 稀有信息掌握不够好
- 错误修正难以实现
因此很多时候大模型需要访问外部数据。
检索增强即先从文本集合或数据库中检索信息,再以某种方式把这些信息用于生成过程。
所谓检索(Retrieval),最常见的做法是计算数据库条目与输入某种表示向量之间的相似度。 像查询向量数据库时,查询通常就是用向量 / 嵌入(Embedding)来表示的。
从交互方式看,检索增强方法大致可以分成三种通用形式:
- 并行交互(Parallel Interaction),典型代表是 K 近邻思路,如 kNN-LM,它不是简单把检索结果塞进 Prompt,而是把检索本身当作语言模型的一部分并做模型集成
- 单次交互(Sequential Single Interaction),也就是先检索一次,再把结果用于生成,这类方法里,一个常见思路是基于检索提供示例,比如 Retrieval ICL 会在训练数据中找最相关示例并放入 Prompt,RAG、REALM、RETRO 也都可以放在这类思路下理解
- 多次交互(Sequential Multiple Interaction),也就是生成过程中多次检索、动态补充信息,代表性方法如 FLARE
至于检索结果最终怎么被用到生成里,也有多种方案:
- 把检索本身当语言模型并做模型集成
- 把检索内容放进 Prompt
- 交互式的方法(与 Agent 相关)
检索增强生成(RAG)
RAG(Retrieval-Augmented Generation)是一种现代常用的检索增强方法,它的核心思想是在生成回答之前,先从外部知识库中检索相关信息,再把这些信息作为上下文提供给生成模型,用来辅助生成答案。
在一个 RAG 系统中,检索到的文档最常见的用途,是作为 Prompt 的附加上下文。 当然,也可以像 kNN-LM 那样,更深地与模型输出结合。 使用 RAG 时,我们计算相似度,本质上是在比较查询和数据库中每一段文本,目的就是找出与当前问题最相关的内容,再把这些外部信息提供给模型,帮助它在生成答案时减少幻觉、补充新知识,并提高准确性。
后文将基于现代 RAG 系统的基本流程,介绍一些相关概念和方法。
RAG 的基本流程
现代 RAG 系统的基本流程包括以下几个步骤:
- 嵌入(Embedding):把查询和文档都表示成向量。这样系统就可以通过向量之间的距离或相似度,判断它们在语义上是否接近。它解决的是怎样把文本变成可检索的表示这个问题
- 切块(Chunking):把长文档切成较小的片段,方便检索和放入上下文。块太大,主题可能混杂;块太小,又容易丢失上下文。它本质上是在检索精度和上下文完整性之间做平衡
- 索引(Index / Indexing):把文档块组织成可高效检索的结构。常见做法是先把 chunk 编码成向量,再写入向量索引或向量数据库。它解决的是如何在大规模文档中快速找到相关内容
- 检索(Retrieval):根据用户查询,从索引中找出最相关文档块的过程。通常先把查询编码成向量,再取回 top-k 个候选结果。它决定了模型后面能看到哪些外部知识
- 重排(Rerank / Reranking):在初步检索之后,对候选文档再做一次更精细的排序。检索负责先召回一批可能相关的内容,重排再从中挑出更适合当前问题的部分。它通常能显著提高最终上下文质量
- 生成(Generation):模型基于用户问题和检索结果生成最终回答的过程。最常见的做法是把检索到的文档作为附加上下文放进 prompt。它是把外部知识真正转化为答案的最后一步
RAG 的优化点
- Top-k:检索阶段最终取回多少个候选文档块。取太少,可能漏掉关键信息;取太多,又会引入噪声、浪费上下文窗口。它本质上是在召回率和噪声之间做权衡
- 块大小(Chunk Size):每个文档块切多大。它直接影响检索粒度、上下文完整性和最终生成效果。这个参数没有固定最优值,通常需要结合任务和文档类型一起调整
- 混合检索(Hybrid Search):把多种检索方式结合起来,最常见的是向量检索 + 关键词检索。语义检索擅长找意思相近的内容,关键词检索擅长精确术语匹配。两者结合,通常比单一路线更稳
- 查询改写(Query Rewriting):在检索前先改写用户问题,让它更适合搜索。因为用户的表达往往口语化、模糊,直接拿去检索效果未必最好。改写后的查询通常更完整,也更利于召回相关文档
- 引用(Citation):在回答中标出信息来源,例如引用了哪些文档或片段。它能提高答案的可验证性,让用户知道模型是根据什么得出结论的。对高可信场景来说,citation 往往非常重要
- 评估(Evaluation):对 RAG 系统效果的评估。因为 RAG 包含检索、重排、生成等多个环节,所以不能只看最终答案对不对。一个好的评估体系,还需要关注检索质量、引用质量、忠实性、延迟和成本等因素
备注:查询改写和重排都可以由模型完成,也可以用规则或轻量方法实现。
检索方式
常见的检索方式有:
- TF-IDF:根据词频和逆文档频率给每个词打分,用于衡量词在文档中的重要性
- BM25:根据查询词是否出现在文档里、出现了多少次、这个词在整个语料里是否稀有,以及文档是否过长,给每个文档打一个相关性分数
- 向量检索 / 语义检索:按 embedding 相似度找文档,擅长说法不同但意思相近的情况。
备注:BM25 往往被视为 TF-IDF 的改进版本,考虑了文档长度和词频饱和等因素,因此在很多场景下表现更好。混合检索里通常就是向量检索 / 语义检索和 BM25 配合。
检索融合方法
常见的检索融合方法有:
- 倒数排名融合(RRF,Reciprocal Rank Fusion):看同一篇文档在不同结果列表里的名次,然后按一个倒数公式把这些名次加起来,最后得到融合后的总分
- 线性加权融合(Convex Combination):直接对不同检索器的分数做加权求和
重排模型(Reranker)
重排往往用一个专用的模型来做,输入是查询和候选文档块,输出是一个相关性分数。 这个模型最常见的是交叉编码器(Cross-Encoder),也可以是其他排序模型或基于规则的方法。 重排模型通常比初步检索更精细,可以捕捉更复杂的语义关系,从而提高最终上下文的质量。
知识库(Knowledge Base)
知识库是一个已经过整理、切分、索引化,能够被系统高效检索的外部知识集合。
RAG 里使用知识库一般分两条链路:
- 离线 ingest
- 收集原始文档
- 清洗和解析文档
- 切块
- 生成 embedding
- 建索引(向量索引、BM25 索引等)
- 写入向量数据库或检索系统
- 在线 query
- 查询改写
- 查询 embedding
- 检索
- 重排
- 生成回答
备注:Ingest 通常指文档的预处理入库过程,也就是把原始文档解析、切块、向量化并写入检索系统。
因为 Ingest 的成本较高,所以通常会用离线 Ingest 的方式来构建知识库,定期更新。 而在线 Query 则是用户提问时的实时检索和生成过程。 但也有一些场景会用在线 Ingest,比如用户上传了一个文档,系统需要立刻把它切块、生成 embedding 并写入索引,以便后续检索使用。
股票财报 RAG 示例
下面以股票财报 RAG 为例,按完整流程梳理一个现代 RAG 系统会如何构建知识库、检索信息、生成答案,并在新财报发布后持续更新知识库。
- 离线 ingest 构建知识库
- 收集原始文档:收集各个公司的财报、会议纪要、投资者演示文稿,以及券商整理过的摘要笔记等
- 文档解析与清洗:把 PDF、网页、会议纪要等格式统一解析成可处理文本,去掉无关噪声,保留标题、页码、季度、公司名、发布时间等元数据
- 切块:把长文档切成适合检索的文本块,比如按标题、小节、发言人或问答轮次切分。块太大容易主题混杂,块太小又容易丢失上下文
- 确定块大小:这是切块时最重要的参数之一,要在检索精度和上下文完整性之间平衡
- 生成 embedding:把每个文档块编码成向量表示,后续就可以按语义而不只是按关键词来检索
- 构建索引:把文档块及其 embedding 写入向量索引,同时为原文或文档块建立 BM25 索引,用于关键词检索
- 形成知识库:这里的知识库不只是原始文档集合,还包括切好的 chunks、embeddings、向量索引、BM25 索引,以及各种元数据
- 用户发起查询
- 用户提问:
英伟达这季度咋样,后面怎么看? - 查询改写:原始问题偏口语化、模糊,系统可以先把它改写成更适合检索的形式,例如:
总结英伟达最近一个财季的营收增长、数据中心业务表现,以及管理层对下季度的指引和展望 - 查询 embedding:把改写后的查询也编码成向量,这样就可以和知识库中的文档块向量做相似度比较
- 用户提问:
- 检索候选内容
- 向量检索:用查询向量去向量索引里查找语义上最相关的文档块,例如能找到“指引”“数据中心”“营收增长” 等相关段落
- 关键词检索:同时用 BM25 去搜精确术语、数字、产品名、业务线名称等,因为财报场景里这些强关键词非常重要
- 混合检索:把向量检索和 BM25 检索结合起来,而不是只用其中一种
- 结果融合:将两路检索结果按排序进行融合,兼顾语义相关性和关键词命中能力,比如用 RRF 等方法来综合两路结果的排名,得到一个更稳健的候选列表
- 设定 top-k:决定最终先取回多少个候选文档块,取太少可能漏掉关键内容,取太多又会引入噪声
- 对候选结果进一步筛选
- 重排:对初步召回的候选块再做一次更精细排序,把当前季度、最相关、最关键的内容排到前面,把旧季度或背景性较强的内容放后面
- 去重与过滤:去掉重复内容、明显过时内容,以及和本次问题弱相关的片段,避免占用上下文窗口
- 选择最终上下文:从重排后的结果里选出最值得送进模型的若干块,例如本季度财报、会议纪要中谈到数据中心和指引的片段
- 组织上下文并生成答案
- 上下文拼装:把用户问题和选中的财报片段一起组织进 prompt,必要时加上公司名、季度、来源等说明
- 生成:让大模型基于用户问题和检索证据生成答案,例如总结本季度营收表现、数据中心业务驱动因素,以及下季度展望
- 引用:在回答中标出信息来源,例如该结论来自财报、会议纪要的哪个部分,这样答案不仅可读,也可核查
- 结果评估与持续优化
- 评估:不能只看最终答案像不像样,还要拆开看检索是否召回了正确季度的内容、重排是否把关键段落排在前面、生成是否忠实于原文、引用是否准确
- 调整 top-k:如果经常漏掉“后面怎么看”这类展望信息,可能需要适当提高 top-k;如果噪声太多,则可能需要降低
- 调整 chunk size:如果答案总是缺上下文,可能块切得太小;如果检索总是不准,可能块切得太大
- 优化 hybrid search:继续调 BM25、向量检索和 RRF 的组合方式,让财报里的精确术语和语义表达都能被更稳定地召回
- 优化 query rewriting:如果用户问题很口语化或省略很多信息,改写质量会直接影响召回效果
- 优化 citation:让引用更准确、更细粒度,提升用户对系统的信任
- 更新知识库
- 监控新文档:当公司发布新的财报、会议纪要或投资者演示文稿时,系统需要及时发现并纳入处理流程
- 增量 ingest:对新文档重复执行解析、清洗、切块、embedding 和索引构建,把新增内容写入现有知识库,而不是每次全量重建
- 元数据更新:为新文档补充公司名、季度、发布时间、文档类型、页码等信息,保证后续检索和过滤仍然准确
- 索引刷新:更新向量索引和 BM25 索引,让系统能够优先检索到最新季度内容
- 旧内容管理:必要时对旧季度内容做降权、归档或版本区分,避免系统把历史信息误当成当前结论
- 知识库时效性维护:如果知识库不及时更新,系统即使检索流程再完整,也可能基于过时材料回答问题
- 最终回答用户问题:
英伟达本季度营收继续高增长,数据中心业务仍是核心驱动;管理层对下季度给出了较强指引,因此市场通常会关注需求是否延续、供给是否跟上,以及高增长能否维持。
可以看到,这个答案不是模型单靠参数记忆出来的,而是基于提前 ingest 的财报知识库,经过这一整套 RAG 流程得到的。
GraphRAG
GraphRAG 是一种图结构化的检索增强生成方法:它先把非结构化语料组织成图,再基于实体关系、图遍历或社区摘要进行检索与生成,因此比普通基于 chunk 的 RAG 更适合处理需要关系推理、跨文档整合和全局总结的问题。
GraphRAG 的优点是更会连关系、看全局,缺点是更重、更贵、更复杂,因此它更适合知识关系复杂、需要多跳推理或全局总结的场景,而不是默认替代普通 RAG。
常见问题和解决方法
- 图片怎么处理:很多知识并不只在正文里,还在图表、流程图、截图、表格截图、财报里的柱状图和折线图里。只做纯文本解析会直接丢信息。常见做法是做多模态处理:对图片做 OCR、图表理解、视觉描述,或者直接用多模态 embedding / 多模态模型,把图片内容转成可检索的文本或向量,再和正文一起入库(也可以直接把图片用 base64 传给多模态模型,并结合上下文理解图片,但 base64 只是传输格式,不是检索或理解方案)
- 表格怎么处理:表格往往是最重要的信息载体,但普通切块会把行列关系打散。常见做法是尽量保留表格结构:把表格转成结构化 JSON/CSV,再按表格整体、行、列或单元格组织检索;必要时结合专门的表格问答模型
- PDF 解析不稳定怎么办:很多 PDF 的阅读顺序、标题层级、页眉页脚、双栏排版都会把内容解析乱。解决方法通常是使用更稳的文档解析流水线,加入版面分析、标题识别、去噪和按版面块切分,而不是直接把 PDF 粗暴转成纯文本
- 元数据怎么利用:很多问题不只是语义相关,还和时间、来源、作者、公司、季度、页码有关。解决方法是给 chunk 补充元数据,并在检索、过滤、排序时把这些信息用起来,比如优先最新季度、优先权威来源、优先当前公司的文档
- 时效性怎么保证:知识库很容易过期,尤其是新闻、财报、产品文档、政策类内容。解决方法是建立增量更新机制:持续监控新文档、自动 ingest、更新索引,并对旧内容做版本区分、降权或归档
- 多跳问题怎么处理:有些问题不是一段文档就能回答,而是要把多个来源的信息拼起来。常见做法包括问题拆解、多轮检索、GraphRAG,或者 agent 式检索流程(像一个 agent 一样边想边查),让系统先拆问题再逐步找证据
- 长上下文噪声怎么控制:检索回来太多内容时,模型不一定更准,反而可能被噪声干扰。解决方法通常是更好的 rerank、上下文压缩、去重、摘要化,只把最关键的证据送进生成阶段
- 查询太口语化或太短怎么办:用户的问题常常很模糊。解决方法是做查询改写、查询扩展、补全上下文,必要时结合会话历史把省略的信息补回来
- 召回和精度冲突怎么平衡:取回太少会漏,取回太多会脏。解决方法就是联合调 top-k、chunk size、混合检索、rerank 等环节,不要只盯某一个参数
- 幻觉和误引怎么处理:即使检索到了对的文档,模型也可能乱总结、错归因。常见做法是强制基于证据回答、要求 citation、做 grounding 检查(模型回答能否在检索到的文档里找到依据),甚至在生成后再跑一轮验证
- 权限和数据隔离怎么做:企业场景里,不是所有人都应该看到所有文档。解决方法是把权限控制接进检索层,而不是只放在应用层展示阶段,否则可能在检索阶段就泄露了不该看的内容
- 成本和延迟怎么控制:RAG 很容易变成每一步都加模型,最后又慢又贵。常见做法是分层设计:便宜的召回、较贵的重排、只在必要时用大模型生成,同时配合缓存、批处理和增量更新
- 怎么评估到底哪一步出了问题:RAG 是多阶段系统,答案差不一定是模型差,也可能是切块、召回、重排、上下文构造有问题。解决方法是做分阶段评测,分别看检索质量、重排质量、引用准确率、答案忠实性,而不是只看最终回答
- 多语言和术语漂移怎么处理:同一个概念在不同语言、不同团队里叫法可能不一样。常见做法包括多语言 embedding、术语表、同义词扩展,以及针对特定领域做检索模型适配
- 非结构化与结构化数据怎么混合:很多问题既要查文档,又要查数据库、指标表、知识图谱。解决方法是做混合知识源 RAG:文本库负责解释性信息,结构化查询负责精确数值,再在生成阶段统一融合
