RAG 技术地图:从向量检索到 GraphRAG、LightRAG 与 Agentic RAG

RAG 早已不只是“切块、向量检索、拼进 Prompt”。本文从失败模式出发,梳理混合检索、GraphRAG、LightRAG、Self-RAG、Corrective RAG 与 Agentic RAG 的关系,并给出可落地的选型与评测方法。

本文使用humanizerdocumd-visuals

很多 RAG 教程停在同一个流程:文档切块,生成向量,查询时取回 Top K,再把结果塞进 Prompt。这个流程足以做出 Demo,也很容易让人产生一种错觉:只要换一个更好的 Embedding 模型、把 K 调大一点,回答质量就会稳定上升。

真正上线后,更常见的情况是系统找回了一些相关片段,却不足以回答问题。用户问某项设计为什么调整,系统找回了新方案,却漏掉旧方案的约束;用户要比较三个产品,检索结果集中在其中一个;用户问整个知识库里反复出现的主题,向量检索给出几段局部描述,却无法完成全局归纳。

这些失败不属于同一层。切块破坏上下文是知识组织问题,查询与文档措辞不一致是检索问题,多步问题只搜一次是流程控制问题,拿到错误证据仍然强答则是验证问题。GraphRAG、LightRAG、Self-RAG、Corrective RAG 和 Agentic RAG 之所以同时出现,是因为它们在修补不同环节。

这篇文章不按“第一代、第二代、第三代”给 RAG 排序。我更愿意把它们放到同一张技术地图里,先看系统在哪一层出错,再决定要加哪一种机制。

RAG 从数据、索引、检索到 Agentic 控制与评测的体系图

一、先把 RAG 看成一条知识流水线

RAG 的全称是 Retrieval-Augmented Generation,即检索增强生成。最初的 RAG 工作把参数化知识和外部非参数记忆结合起来:模型负责理解与生成,外部索引负责保存可以更新、可以追溯的知识。这个定义比“向量库问答”宽得多。

一个能长期维护的 RAG 系统至少包含下面几层:

  1. 数据层:原始文档、网页、代码、图片、表格、数据库和 API。
  2. 解析与索引层:清洗、切块、元数据、Embedding、关键词索引、图谱或结构化索引。
  3. 查询层:意图识别、查询改写、过滤、召回、融合和重排。
  4. 上下文层:去重、压缩、证据编排、冲突处理和 Token 预算。
  5. 生成层:根据证据回答、引用来源、表达不确定性或拒绝回答。
  6. 评测与反馈层:记录检索轨迹,区分召回失败和生成失败,并用线上反馈更新测试集。

这几层共同决定效果。换一个向量数据库只改变其中一部分;给流程套上 Agent,也不会自动修好过期文档和错误权限。

更实用的排障方式是把一次失败沿链路反推:

回答错了
  ├─ 证据其实是对的:检查 Prompt、引用约束和生成模型
  ├─ 证据不完整:检查查询拆解、召回、重排和上下文预算
  ├─ 证据本身错误:检查来源、版本、权限和索引更新
  └─ 问题超出知识库:检查拒答、外部搜索和任务路由

只有知道故障在哪一层,技术选型才不会变成追逐名词。

RAG 和微调解决的是两类问题

RAG 与微调经常一起出现在方案讨论里,但它们的落点不同。RAG 把请求和外部知识连接起来,适合更新事实、补充私有资料和提供引用;微调改变模型的行为分布,更适合稳定输出格式、语气、任务习惯或某一类能力。

问题 更适合优先考虑 原因
规则每周变化,需要显示出处 RAG 知识可以独立更新,回答能回到来源
希望模型稳定输出特定 JSON 微调或约束解码 这是行为与格式问题
让模型熟悉私有文档中的最新事实 RAG 不必把易变事实写入参数
让模型学会一种固定分类任务 微调 目标是改变任务行为
既要内部知识,又要固定表达方式 RAG + 微调 两条链路各自负责知识与行为

微调也能让模型记住部分训练材料,但这种记忆不容易精确更新、删除和引用。把它当成知识库,会很快遇到版本和可追溯性问题。反过来,RAG 也不能替代能力训练:给模型检索到再多代码规范,也不保证它会稳定地产出符合规范的代码。

二、基础 RAG:简单,但不是随便切块就够了

基础 RAG 的典型链路是:

离线:文档 → 解析 → 切块 → Embedding → 向量索引
在线:问题 → Embedding → 相似度召回 → Top K → LLM → 回答

RAG 的离线索引与在线查询流程

它适合答案集中在少量局部文本里的问题,例如产品规则查询、API 说明、术语解释和客服 FAQ。知识规模不大、文档结构规整时,基础方案的性价比很高。

基础不等于粗糙。至少有五件事值得在引入复杂框架前做好。

1. 切块要保留结构

固定字符数切块容易把标题、定义、条件和例外拆开。更稳妥的做法是先按 Markdown 标题、HTML DOM、代码符号或 PDF 版面切分,再在过长章节内部递归分块。每个块应携带标题路径、文档版本、来源和权限等元数据。

父子块检索也很实用:用较小的子块做精确匹配,命中后把较完整的父块交给模型。这样既保留召回精度,又不会让一句话脱离所在章节。

常见切块方法可以按语料特点选择:

方法 适合什么内容 容易出现的问题
固定长度 结构弱、需要快速建立基线的纯文本 句子、表格和条件可能被拦腰截断
递归切分 Markdown、普通文档 分隔符规则写得不好时仍会丢层级
结构感知 HTML、代码、带标题的技术文档 依赖解析器质量,复杂 PDF 需要版面识别
语义切分 主题边界明显的长文本 计算更贵,阈值变化会让块不稳定
父子块 既要精确命中,又要保留完整上下文 需要维护块之间的映射和额外读取

PDF 尤其容易踩坑。按页提取看起来省事,但一页可能同时包含上个章节的结尾、下个章节的开头和跨页表格。更可靠的方式是先恢复标题、段落、表格和阅读顺序,再决定切块边界。解析结果应该抽样检查,不能因为文本成功写入向量库就默认它是正确的。

2. Embedding 和向量索引各自负责什么

Embedding 模型把文本和查询映射到向量空间,向量索引负责从大量向量中快速找到近邻。前者决定“什么内容被认为相似”,后者决定“怎样在可接受的延迟里找到这些相似项”。向量数据库不是 Embedding 模型,也不会自动修复表示质量。

相似度可以使用余弦、点积或欧氏距离,具体选择要与模型的训练方式和索引配置一致。向量是否归一化也会影响结果。工程上常见的近似最近邻索引包括 HNSW,以及 IVF、PQ 等压缩或分桶方案:HNSW 通常以更多内存换取较好的召回和查询速度;IVF/PQ 更利于压缩大规模向量,但需要在召回率、训练与查询参数之间取舍。

模型选择不要只看公开榜单。中文比例、专业术语、文本长度和查询类型都会改变效果。最小可行评测集应该来自自己的语料,并至少比较 Recall@K、查询延迟、索引体积和更新速度。

3. 不要只依赖稠密向量

向量擅长语义近似,对订单号、错误码、类名、缩写和罕见专有名词未必稳定。BM25 一类关键词检索正好擅长精确词项。线上常用的混合检索会并行运行两路召回,再通过 Reciprocal Rank Fusion 或学习排序融合结果。

async def hybrid_retrieve(query, filters):
    dense, lexical = await asyncio.gather(
        vector_store.search(query, filters=filters, top_k=30),
        bm25.search(query, filters=filters, top_k=30),
    )
    fused = reciprocal_rank_fusion(dense, lexical)
    return reranker.rank(query, fused)[:8]

这里的 top_k=30 只是候选池,不应直接把 60 个片段交给生成模型。召回负责尽量不漏,重排负责把真正能回答问题的证据放到前面。

4. 召回和重排是两项不同工作

向量召回通常使用 Bi-Encoder:查询和文档分别编码,文档向量可以提前计算,因此适合在大规模索引里快速找候选。它的限制也来自这种分离计算——查询与候选之间没有在编码阶段进行逐词交互,一些细微条件很难辨别。

Cross-Encoder 会把查询和候选一起输入模型,直接预测相关性。它能看到二者的完整交互,排序通常更精细,但无法经济地逐条扫描整个知识库。因此,常见做法是先用向量、BM25 等方法召回几十条候选,再用 Cross-Encoder 重排,最后给生成模型留下少量证据。

混合召回、融合、交叉编码重排与证据包组成的检索漏斗

图里的 30–100 条候选和 5–10 条最终证据只是调试起点。长文档、复杂比较问题可能需要更多证据,短事实问题则可以更少。参数应该由自己的 Recall@K、上下文精度、延迟和回答评测决定。

5. 元数据过滤发生在语义相似之前

时间范围、租户、产品线、语言、权限和文档状态都不适合交给 Embedding 猜测。用户问“当前规则”,旧版本即使语义更接近,也不应排在现行版本前面。

过滤条件最好来自结构化意图,而不是在向量结果返回后用字符串排除:

{
  "intent": "查询当前退款规则",
  "filters": {
    "status": "active",
    "effective_at": "2026-09-30",
    "product": "consumer"
  },
  "must_have_evidence": ["适用条件", "例外", "生效时间"]
}

6. 引用必须映射回原文

RAG 在给模型补知识的同时,还要让回答可以核验。索引阶段需要保留从块到原始文档、页码、标题和版本的映射。经过摘要或压缩的内容也必须保留来源集合,否则最后显示的“引用”可能只是相关页面,并没有支撑具体结论。

7. 给“不知道”留出口

低相关度结果不等于证据。系统需要明确的证据阈值和拒答策略。如果关键条件缺失,可以要求用户补充范围,也可以说明知识库中没有足够材料。强迫模型在每次请求中产出完整答案,会把召回不足伪装成流畅的幻觉。

三、查询改写:同一件事可能有很多说法

用户表达和文档表达不一致,是 RAG 中最常见的召回损失。用户说“登录一直转圈”,文档可能写“认证回调超时”;用户问“为什么这个任务没跑”,运维手册记录的是“调度实例未进入就绪队列”。

查询改写主要有几种做法:

  • 规范化:补全缩写、统一实体名称、修正错别字。
  • 多查询扩展:从不同表述生成多个检索查询,再合并结果。
  • 假设文档生成:先生成一段可能的答案或文档,再用它做向量检索,这类方法常被称为 HyDE。
  • 问题分解:把比较、归因或多跳问题拆成可独立检索的子问题。
  • 反向退一步:先寻找上位概念或通用规则,再回到具体问题。

扩展不是越多越好。每增加一路查询,召回可能提高,噪声、延迟和费用也会增加。一个简单事实问题被拆成十个子问题,通常说明控制策略过度设计。

我倾向于让规划模型输出可审计的结构,而不是要求它暴露一大段自由形式的“思维过程”:

{
  "complexity": "multi_hop",
  "subqueries": [
    "方案 A 的适用条件与限制",
    "方案 B 的适用条件与限制",
    "A 与 B 在更新成本上的差异"
  ],
  "sources": ["docs", "code"],
  "stop_when": "每个比较项至少有一个有效来源"
}

它既方便执行,也方便回放。出现问题时,我们能看到是规划漏了一个比较维度,还是检索没有找回对应证据。

四、模块化 RAG:把固定直线拆成可替换部件

基础 RAG 通常是一条固定直线。生产系统会把这条直线拆成模块:查询经过路由器后进入不同数据源,召回结果经过过滤、融合和重排,必要时重新查询,最后才交给生成模型。

                       ┌→ 关键词索引 ─┐
用户问题 → 查询路由器 ├→ 向量索引   ├→ 融合 → 重排 → 证据包
                       ├→ 图索引     ┤
                       └→ SQL / API ─┘

这种设计有两个直接好处。

一是每个模块可以独立评测。召回率低时不用先怀疑生成模型;重排器更换后也能比较相同候选集上的变化。

二是不同问题可以走不同路径。查询订单状态应该调用业务 API,而不是在文档向量库里寻找一段描述;询问跨文档主题时,可以进入图检索或全局摘要;查错误码时,关键词检索往往比复杂 Agent 更可靠。

模块化 RAG 是后面各种高级路线的共同基础。GraphRAG 改变知识组织与检索方式,Corrective RAG 加入检索质量判断,Agentic RAG 则让路由和循环变得动态。

五、GraphRAG:当问题关心关系和全局结构

向量检索的基本单位是片段。它能判断哪些片段与查询相似,却不会天然建立“人物属于组织”“服务依赖数据库”“政策由哪些历史决策演变而来”这样的显式关系。

GraphRAG 把文档转换为实体和关系图,再在图上构建社区及社区报告。以微软开源实现的标准索引流程为例,它会从文本单元中抽取实体、关系和可选的声明,运行社区检测,并为不同层级的社区生成摘要。查询时主要有两种思路:

  • Local Search 从某个实体出发,组合相邻实体、关系、原始文本和其他上下文,适合“某个对象与谁相关”“一次变更影响哪些组件”。
  • Global Search 读取社区报告,以 map-reduce 方式汇总多个社区的局部回答,适合“整个语料中有哪些主要主题”“各类观点怎样分布”。

这解决了普通 Top K 检索很难处理的全局问题。一个主题可能分散在数十份文档中,没有任何单块文本与问题高度相似;社区摘要却能先在离线阶段把分散信息组织起来。

GraphRAG 的代价同样明确:

  1. 实体与关系抽取需要额外模型调用,索引成本明显增加。
  2. 实体消歧会影响整张图。“RAG”“检索增强生成”和某个内部简称可能被错误地当成三个实体。
  3. 图中的关系来自文本抽取,不等于经过验证的业务事实。
  4. 社区结构和报告需要维护,文档变化不再只是向量索引追加。
  5. 全局查询读取大量社区报告,延迟和 Token 消耗可能高于普通检索。

早期介绍经常把 GraphRAG 写成“完全不能增量更新”。这个说法已经不准确。当前官方 CLI 提供 update 命令和 update 类索引方法。不过,有更新入口不代表维护成本等同于向量库追加一个块。新增实体可能改变社区归属,下游摘要和报告也可能需要重新计算。工程上应该评估实际更新范围、删除一致性与报告刷新延迟。

所以,GraphRAG 适合关系密集、跨文档和全局归纳问题较多的知识库。FAQ、产品手册或答案集中在单个段落里的场景,先做好混合检索和重排往往更划算。

六、LightRAG:用双层检索连接局部实体与全局主题

LightRAG 也使用图结构,但它不是简单把 GraphRAG 的某些步骤删掉。它重新设计了索引和查询方式,希望同时保留细粒度实体关系与较高层主题语义,并降低更新成本。

在索引阶段,文档被切成块,模型从中抽取实体及关系,相关描述被合并。系统同时保存图结构和可用于检索的键值信息。新文档可以独立抽取后再与已有节点和边合并,不必每次从头重建完整索引。

查询时,LightRAG 从问题中提取两类关键词:

  • 低层关键词 更接近具体实体、属性与关系,适合局部事实查询。
  • 高层关键词 表达主题和概念,适合较抽象的整体问题。

检索模式可以只关注局部、只关注全局,也可以组合两者。相关实体、关系和原始文本共同组成生成上下文。它与纯向量检索最大的区别,是检索对象不再只有“相似片段”,还包括由实体关系连接起来的知识结构。

LightRAG 的优势也不能只看论文名称里的 “Light”。实际系统仍然需要处理实体抽取质量、同名实体合并、图存储、向量存储、文档删除和模型版本迁移。它的增量机制减少了全量重建压力,但错误实体也可能随着增量合并进入图中。

如果知识持续更新,又确实存在大量实体关系和多跳问题,LightRAG 值得验证。验证的重点不应只是最终答案,还要单独观察实体召回、关系路径、索引更新时间和删除后残留。

LightRAG 的公开实现提供四种常见查询模式:

模式 主要检索对象 适用问题
naive 文本块 用作普通向量检索基线
local 低层关键词对应的实体与关系 某个对象的属性、关联和局部事实
global 高层关键词对应的关系与主题 较宽泛的主题和整体问题
hybrid 低层与高层信息组合 同时需要具体实体和整体背景的问题

这些名称不能直接套用成 GraphRAG 的同名机制。GraphRAG 的 Global Search 建立在社区报告及其 map-reduce 汇总上;LightRAG 的 global 模式来自它自己的高层关键词和图检索设计。比较方案时,要看实际索引产物和查询路径,不能只对照模式名称。

GraphRAG 与 LightRAG 在索引、全局知识、查询和更新上的对比

增量更新还有一个容易被忽略的时序问题。假设旧文档写“服务使用方案 A”,新文档改成“服务已迁移到方案 B”。如果系统只把新实体和关系并入图,A 与 B 可能同时存在。查询时出现的不是简单重复,而是互相冲突的事实。生产系统至少要保存来源版本、valid_from / valid_to、删除记录和抽取模型版本,并在上下文编排阶段明确处理冲突。能追加数据,不等于已经解决知识更新。

七、Self-RAG 与 Corrective RAG:检索之后还要判断证据

固定 RAG 有两个隐含假设:每个问题都需要检索;检索回来的内容都值得使用。这两个假设都不成立。

Self-RAG:按需检索并反思输出

Self-RAG 的论文提出让模型通过特殊的反思标记学习何时检索,并对检索片段的相关性、回答的支撑程度和输出质量做判断。它关注的是模型如何在生成过程中自适应地使用检索,而不是简单固定取回若干段落。

严格来说,论文里的 Self-RAG 包含专门训练,不等于在 Prompt 末尾加一句“请反思”。工程实践中可以借鉴它的控制思想,但不要把普通的二次提示包装成同一种方法。

Corrective RAG:检索质量差时走修正分支

Corrective RAG(CRAG)在检索结果和生成之间加入评估器。评估器判断当前证据可信、模糊还是不可靠,再触发不同动作:直接使用,进一步精炼,或者转向外部搜索。原论文还使用分解再重组的方式,从文档中保留有用内容并过滤干扰信息。

一个简化的工程版本可以写成:

evidence = retrieve(query)
grade = retrieval_grader(query, evidence)

if grade == "sufficient":
    context = compress(evidence)
elif grade == "ambiguous":
    context = retrieve(rewrite(query))
else:
    context = trusted_web_search(query)

return answer_with_citations(query, context)

真正难的部分是 retrieval_grader。如果它与生成模型有相同偏见,就可能给相关但无答案的片段打高分。生产环境需要用人工标注的失败样本校准阈值,并保留“证据仍不足”的终止状态。

Self-RAG 与 CRAG 都在处理一件常被忽略的事:检索是一种有风险的输入。错误资料放进上下文后,模型往往会因为它“看起来像证据”而更加确信。

八、Agentic RAG:让检索成为一个有状态的决策过程

Agentic RAG 没有唯一固定实现。它通常指让 Agent 的规划、工具调用、反思和状态管理进入 RAG 流程,使系统可以根据中间结果决定下一步,而不是从查询到回答只执行一次固定管线。

一个典型过程是:

理解任务
  ↓
判断是否需要外部知识
  ↓
拆分子问题并选择数据源
  ↓
执行检索 / SQL / API / 网页搜索
  ↓
检查证据覆盖与冲突
  ├─ 不足:改写查询、换工具或继续检索
  └─ 足够:组织证据并生成回答
  ↓
验证引用与终止

它适合下面几类请求:

  • 需要多跳证据,后一步查询依赖前一步结果;
  • 数据分布在文档、数据库、代码仓库和外部网页中;
  • 用户任务不只问答,还包括比较、调查、生成报告或执行操作;
  • 系统需要根据证据质量动态重试或切换数据源;
  • 不同子问题需要不同权限和工具。

例如用户问“为什么昨晚的任务失败,这个问题是否影响今天的数据”。系统要先查任务状态,再根据错误码检索手册,随后查询上游数据状态,最后判断影响范围。一次向量 Top K 很难覆盖这条链路,Agent 的工具路由和状态机更合适。

不过,Agentic RAG 的灵活性来自更多运行时决策,也意味着更多不确定性:

  • 查询可能越拆越多,形成没有收益的检索循环;
  • Agent 可能选错工具,或对一次失败不断重试;
  • 多轮结果持续进入上下文,早期噪声会影响后续判断;
  • 延迟与费用从固定值变成分布,尾延迟更难控制;
  • 权限边界从“能读哪个索引”扩展为“能调用哪些工具并携带哪些数据”。

因此,Agentic RAG 不能只靠一个无限循环。至少需要显式状态和预算:

class RetrievalState(TypedDict):
    question: str
    plan: list[dict]
    evidence: list[dict]
    unresolved: list[str]
    attempts: int
    token_budget: int
    tool_budget: int

def should_stop(state):
    return (
        evidence_complete(state)
        or state["attempts"] >= 4
        or state["tool_budget"] <= 0
    )

停止条件、工具白名单、每个数据源的超时、证据去重和最大预算,都是 Agentic RAG 的核心能力。没有这些约束,它只是一个可以反复检索的 Prompt。

九、这些 RAG 不是一条升级路线

把常见方案放在一起比较,会发现它们优化的是不同维度。

路线 主要改变 更擅长的问题 主要代价
基础 RAG 向量召回文本块 局部事实、单文档问答 措辞敏感,跨块能力弱
混合 RAG 关键词、向量、过滤与重排 专有名词、错误码、通用知识问答 调参与融合更复杂
模块化 RAG 可组合的路由与处理模块 多数据源、不同查询类型 需要明确接口和可观测性
GraphRAG 实体关系、社区及社区报告 全局主题、关系密集、跨文档归纳 索引和维护成本高
LightRAG 图与向量结合的双层检索 局部实体与全局主题、多跳问题 抽取和图一致性仍需治理
Self-RAG 按需检索与生成反思 需要自适应检索的生成任务 原方法涉及训练与反思控制
Corrective RAG 检索质量评估与修正分支 召回质量波动、需要外部补充 评估器本身可能误判
Agentic RAG 动态规划、工具路由和循环 多步骤、多工具、调查型任务 延迟、成本和行为更难预测

一个系统完全可以同时使用多种机制:Agent 负责把复杂问题拆开;明确事实走混合检索;跨文档关系走 LightRAG;全局归纳走 GraphRAG;检索后再由评估器检查证据是否足够。组合的前提是每个模块都有清晰收益,而不是把所有新名词装进一条链路。

十、一套更现实的生产架构

如果从零建设,我会优先采用“共享证据协议 + 多种检索器 + 受控编排”的结构。

1. 统一证据格式

无论结果来自向量库、图、SQL 还是 API,都转换为统一证据对象:

{
  "content": "用于回答的内容",
  "source_id": "doc-173",
  "source_type": "document",
  "uri": "/docs/refund-policy",
  "version": "2026-09-18",
  "retrieval_mode": "hybrid",
  "score": 0.86,
  "permissions": ["employee"],
  "supports": ["退款时限", "例外条件"]
}

统一协议让融合、去重、引用和评测不再绑定某个数据库。图检索可以额外记录关系路径,SQL 可以记录查询与结果版本,但都必须回答“这条证据来自哪里”。

2. 用路由器选择最低成本的有效路径

路由不必一开始就由大模型完成。错误码、订单号和明确的数据查询可以用规则识别;只有复杂语义问题才调用规划模型。

明确事实 / 专有名词       → 混合检索
实体关系 / 多跳           → 图检索或 LightRAG
语料级主题 / 全局归纳     → GraphRAG Global Search
实时状态 / 精确数值       → SQL 或业务 API
开放世界且内部证据不足    → 可信网页搜索
复合调查任务              → Agentic 编排以上工具

“先用最便宜的方法”不是单纯节省费用。固定管线通常更容易测试,也更容易给出稳定延迟。只有问题确实需要动态规划时,才进入 Agent 循环。

3. 把证据覆盖写进终止条件

不要只用“模型觉得可以回答了”作为结束判断。规划阶段可以声明必需证据,运行时逐项填充:

{
  "required_evidence": [
    {"name": "当前规则", "status": "found"},
    {"name": "历史变更原因", "status": "found"},
    {"name": "影响范围", "status": "missing"}
  ]
}

预算耗尽但仍有关键项缺失时,系统应该输出部分结论和缺口,而不是把“未找到”自动补成一个听起来合理的答案。

4. 让权限跟随检索和生成

权限过滤应在召回阶段生效,不能先取回全部内容,再要求模型“不要泄露”。Agent 调用多个工具时,还要限制结果能否流入其他工具、日志和长期记忆。最终引用也要经过权限校验,避免正文可以显示,点击来源却越权,或反过来暴露隐藏文档标题。

5. 记录完整检索轨迹

线上日志至少要包含:原始问题、路由结果、改写查询、过滤条件、各路候选、重排结果、最终证据、工具耗时、模型版本、回答引用和终止原因。敏感内容需要脱敏或只保留标识,但不能只记录最后答案。

没有轨迹,用户点一个“踩”之后,团队仍然不知道是索引没更新、路由选错、重排漏掉证据,还是模型没有遵守证据。

十一、评测要把检索和生成拆开

RAG 最容易出现的评测误区,是只让另一个大模型给最终回答打一个总分。总分下降时无法定位问题,分数上升也可能只是回答更流畅。

检索评测

测试集应该标注回答需要哪些证据,而不仅是参考答案。常见指标包括:

  • Recall@K:必要证据是否出现在前 K 个结果中;
  • MRR / nDCG:有效证据是否排在更靠前的位置;
  • Context Precision:提供给模型的上下文中有多少真正相关;
  • 证据覆盖率:复合问题的各个子结论是否都有材料;
  • 版本与权限正确率:是否命中有效且允许访问的来源。

图检索还要评估实体识别、关系路径和社区摘要是否丢失关键限定。Agentic RAG 则需要观察工具选择正确率、平均循环次数、无效调用率和预算耗尽率。

生成评测

生成阶段更关心:

  • 结论是否正确;
  • 每个事实是否得到证据支持;
  • 引用是否真的支撑相邻结论;
  • 是否遗漏关键条件和反例;
  • 证据不足时能否正确拒答;
  • 多个来源冲突时是否说明冲突,而不是静默选边。

LLM Judge 可以扩大评测规模,但不应独立决定质量。评审模型可能偏爱更长、更自信或措辞更接近参考答案的回答。需要用人工标注集校准,并定期抽查高分样本中的引用。

测试集要按失败模式组织

一套只包含“能在文档里直接找到答案”的测试集,无法评价高级 RAG。至少要覆盖:

  1. 单段事实问题;
  2. 专有名词和精确标识查询;
  3. 跨文档多跳问题;
  4. 时间、版本和权限约束;
  5. 全局主题与归纳问题;
  6. 多来源冲突;
  7. 知识库不存在答案;
  8. 需要 SQL、API 或外部搜索的任务。

每次线上失败都应该归类后进入回归集。评测集因此会逐渐贴近真实业务,而不是长期停留在上线前准备的几十道理想问题上。

十二、怎样选择:从失败样本开始,而不是从框架开始

如果当前系统还是一个基础向量检索,我会按下面的顺序推进。

第一步:把朴素 RAG 做扎实

整理文档版本与权限,改进结构化切块,加入关键词和向量混合召回,再用重排器控制最终上下文。建立带证据标注的测试集,同时记录线上检索轨迹。

很多“需要 GraphRAG”的问题,到这里已经能解决一大半。原因并不神秘:原系统可能连精确词项、有效版本和标题层级都没有正确使用。

第二步:针对明确故障增加模块

  • 查询表述不稳定:增加改写、多查询或 HyDE。
  • 长文上下文破碎:使用父子块、章节摘要或层次检索。
  • 检索结果质量波动:加入证据评分和 Corrective 分支。
  • 多数据源问题:增加查询路由和统一证据协议。
  • 多跳问题:先尝试问题分解,再评估图结构是否带来稳定收益。

第三步:小范围验证图检索

选一个关系密集、答案确实跨文档的子语料,对比混合 RAG、GraphRAG 和 LightRAG。除了答案质量,还要记录索引费用、更新时间、删除一致性、查询延迟和人工维护量。

图检索如果只在演示问题上更好,却让日常文档更新变成昂贵批任务,它就还没有成为生产方案。

第四步:只给复杂任务启用 Agentic RAG

先定义工具边界、状态、预算和停止条件,再让 Agent 动态规划。简单问答继续走固定管线。复杂任务可以逐步开放更多工具,并通过回放确认 Agent 为什么选择某条路径。

Agentic RAG 的成熟度不体现在循环次数,而体现在它能否用有限步骤拿到足够证据,并在无法完成时清楚地停下来。

十三、我对这套体系的理解

RAG 为一次回答提供可获取、可验证、可更新的依据,重点已经从模型的参数记忆转向外部证据。不同技术路线可以归到三个问题:

  1. 知识怎样被保存:文本块、关键词索引、向量、实体关系、社区摘要或结构化表。
  2. 证据怎样被找到:相似度、关键词、过滤、重排、图遍历、全局归纳或工具调用。
  3. 流程怎样被控制:固定管线、质量修正、自反思,或带预算和状态的 Agent。

GraphRAG 和 LightRAG 主要改变前两个问题,Agentic RAG 主要改变第三个问题。它们可以组合,却不互相替代。图里没有正确的数据,Agent 再聪明也只能规划出一条通向错误证据的路线;检索已经稳定的问题,增加自主循环反而会扩大成本和方差。

最值得优先建设的能力仍然很朴素:可信的数据、清晰的版本、可追溯的证据、分层的评测和能够复盘的运行轨迹。有了这些底座,新的检索方法可以被准确比较;没有这些底座,系统只能靠几个成功案例判断“好像变聪明了”。

参考资料