RAG 的本质
剥开包装
RAG(Retrieval-Augmented Generation)是 LLM 应用领域包装最过度的概念之一。围绕它构建的框架、工具链和最佳实践文档,让人误以为 RAG 是一个需要专门技术栈来支撑的独立范式。
剥开框架的外衣,RAG 的核心操作不过是:在调用 LLM 之前,把相关信息塞进上下文。
def rag_in_ten_lines(query: str, documents: list[str]) -> str:
# 1. 检索:找到与查询相关的文档
relevant_docs = retrieve(query, documents, top_k=3)
# 2. 增强:将检索结果注入上下文
context = "\n\n".join(relevant_docs)
prompt = f"根据以下参考资料回答问题。\n\n参考资料:\n{context}\n\n问题:{query}"
# 3. 生成:调用 LLM
return call_llm(prompt)这十行代码包含了 RAG 的全部本质。后续的一切——向量数据库、embedding 模型、chunk 策略、reranking——都是对这三个步骤的优化。
理解了这个本质,你就能判断什么时候该用 RAG,什么时候不该用。如果你的"相关信息"可以通过简单的关键词匹配获取,你不需要向量检索。如果你的文档总量可以塞进一次上下文窗口,你不需要 RAG——直接把所有文档放进 prompt 就行。RAG 解决的是一个特定问题:当相关信息的总量超过上下文窗口,且需要动态选择哪些信息放入上下文时。
检索质量决定一切
RAG 系统的质量瓶颈几乎从来不在生成端——只要上下文够充分,LLM 通常能给出合理的回答。瓶颈在检索端:你塞进上下文的信息是否真的与问题相关。
这是一个被框架抽象掩盖的关键判断。当开发者使用 LangChain 或 LlamaIndex 搭建 RAG pipeline 时,大量精力花在框架的配置和调优上——选择哪个向量数据库、用哪个 embedding 模型、chunk size 设多大。但真正决定系统质量的问题是:给定用户的查询,检索出的文档片段是否包含了回答该查询所需的信息。
如果检索到了无关文档,LLM 要么忽略它们(浪费了上下文窗口的宝贵空间),要么被它们误导(生成基于无关信息的回答)。如果检索遗漏了关键文档,LLM 只能基于不完整的信息回答——这比没有 RAG 更危险,因为用户以为系统"查阅了资料"。
所以开发 RAG 系统时,检索质量的评估是最重要的环节。常用指标包括:
- 召回率:在所有相关文档中,检索到了多少比例。
- 精确率:在检索到的文档中,有多少比例是真正相关的。
- MRR(Mean Reciprocal Rank):第一个相关文档的排名位置。
这些指标与 LLM 无关——它们衡量的纯粹是信息检索系统的质量。RAG 首先是一个检索问题,其次才是一个生成问题。
Chunk 策略的工程权衡
将长文档切分为 chunk 是 RAG 中最关键的工程决策之一。切分策略直接影响检索质量和生成质量。
Chunk 太大:语义信噪比低。一个 2000 token 的 chunk 可能只有两三句话与查询相关,其余内容是噪声。同时,大 chunk 占用更多上下文窗口空间,限制了可以放入的 chunk 数量。
Chunk 太小:上下文碎片化。一个 100 token 的 chunk 可能丢失了段落级别的语义完整性。一个论点的前提在一个 chunk 中,结论在另一个 chunk 中——如果只检索到其中一个,LLM 获得的是不完整的信息。
这个权衡没有普适的最优解,因为最优 chunk size 取决于文档的结构和查询的粒度。技术文档(层级结构清晰、段落自包含)适合按段落或小节切分;叙事性文档(上下文依赖强)需要更大的 chunk 或重叠切分。
一条实用的经验法则是:chunk 的边界应该对齐语义的边界。 按段落切分优于按固定 token 数切分,按章节标题切分优于按段落切分。这意味着 chunk 策略应该利用文档的结构信息(标题层级、列表结构、代码块边界)。
RAG 不是万能的
RAG 被过度使用了。以下场景中,RAG 不是正确的解决方案:
实时数据查询。 RAG 的检索源是预先索引的文档库。如果用户需要的是实时数据(当前股价、最新新闻、实时系统状态),RAG 无法提供——应该直接调用相应的 API,将结果注入上下文。
精确计算。 用户问"过去三个月的总销售额"。即使 RAG 检索到了包含月度销售数据的文档,LLM 的加法也不可靠。应该用代码计算,结果注入上下文。
全量分析。 用户要求"分析所有客户反馈的共同主题"。RAG 的 top-k 检索意味着你只看到了一个子集,无法做全量分析。应该先用传统方法(聚类、主题模型)处理全量数据,再用 LLM 解释结果。
知识已在模型中。 用户问的是常识性问题或模型训练数据大概率覆盖的知识,RAG 检索可能引入噪声。判断标准:如果不用 RAG 时 LLM 的回答质量已经足够好,加入 RAG 只会增加延迟和成本。
先判断问题是否适合用 RAG,再去优化 RAG 的实现细节。