Post

RAGAS 指标体系拆解:RAG 质量评估的工程实现

从 30 余个评估指标出发,拆解 RAGAS 质量评估体系的内部运作机制,揭示检索增强生成系统的性能测量逻辑。

RAGAS 指标体系拆解:RAG 质量评估的工程实现

指标体系总览:四层架构

RAGAS 将 RAG 系统拆解为四个测量层面:

graph TB
    subgraph "输入层"
        Q[Question]
        R[Retrieved Contexts]
        GT[Ground Truth]
    end
    
    subgraph "生成层"
        A[Answer]
    end
    
    subgraph "评估层"
        C1[Context Quality]
        C2[Answer Quality]
        C3[Faithfulness]
        C4[Alignment]
    end
    
    Q --> R
    Q --> A
    R --> A
    
    R --> C1
    A --> C2
    R -.-> C3
    A -.-> C3
    GT --> C4
    A --> C4
    
    style C1 fill:#e1f5ff
    style C2 fill:#fff4e1
    style C3 fill:#ffe1f5
    style C4 fill:#e1ffe1

每层对应特定的测量目标:

  • Context Quality:检索模块返回的上下文片段是否准确、完整、无冗余
  • Answer Quality:生成答案是否切题、连贯、符合语义
  • Faithfulness:答案是否严格基于检索上下文,无幻觉
  • Alignment:答案与标准答案的对齐程度

核心工作流:指标如何运转

1. 答案质量层:双通道验证

AnswerCorrectness:加权融合机制

这个指标将两个独立通道的信号融合:

\[\text{Score} = w_1 \cdot F_{\beta}(\text{TP}, \text{FP}, \text{FN}) + w_2 \cdot \text{CosineSim}(\vec{A}, \vec{R})\]

其中:

  • 第一通道:LLM 将答案与参考答案拆解为原子陈述(statements),计算 TP/FP/FN
  • 第二通道:嵌入模型计算语义向量的余弦相似度
  • 默认权重 $[0.75, 0.25]$ 意味着事实准确性主导,语义相似性辅助

工作流如下:

sequenceDiagram
    participant R as Reference
    participant A as Answer
    participant LLM
    participant Emb as Embedding Model
    
    R->>LLM: 拆解为原子陈述
    A->>LLM: 拆解为原子陈述
    LLM->>LLM: 计算 TP/FP/FN
    LLM-->>A: F-Score (0.75权重)
    
    R->>Emb: 生成向量
    A->>Emb: 生成向量
    Emb->>Emb: 计算余弦相似度
    Emb-->>A: Cosine (0.25权重)
    
    A->>A: 加权融合得分

AnswerRelevancy:反向验证机制

不直接判断”答案是否切题”,而是生成反向问题:

  1. LLM 基于答案生成 $n$ 个反向问题(默认 $n=3$)
  2. 计算每个反向问题与原始问题的相似度
  3. 取平均值
\[\text{Relevancy} = \frac{1}{n} \sum_{i=1}^{n} \text{CosineSim}(Q_{\text{orig}}, Q_{\text{gen}_i})\]

这种设计避免了直接打分的主观性。如果答案偏题,生成的问题必然偏离原问题。

AnswerSimilarity:纯语义测量

直接计算嵌入向量的余弦相似度,不涉及事实核查:

1
2
3
from ragas.metrics import AnswerSimilarity

metric = AnswerSimilarity(threshold=0.8)  # 可选的二值化阈值

适用于开放域问答,答案表述多样但语义等价的场景。

2. 上下文质量层:精确率与召回率的解耦

ContextPrecision:相关片段的排序质量

计算逻辑:

\[\text{Precision@K} = \frac{\sum_{k=1}^{K} \left( \text{Relevant}_k \times \sum_{j=1}^{k} \text{Relevant}_j \right)}{\sum_{k=1}^{K} \text{Relevant}_k}\]

其中 $\text{Relevant}_k$ 为二元信号(LLM 判断第 $k$ 个上下文片段是否对回答问题有用)。

关键特性:

  • 如果无关片段排在前面,分母增加但分子不变,得分下降
  • 本质是信息检索中的 Mean Average Precision (MAP) 的变体

ContextRecall:覆盖参考答案的完整度

将参考答案拆解为陈述集合 $S_{\text{ref}}$,检查每条陈述能否从检索上下文中推断:

\[\text{Recall} = \frac{|\{s \in S_{\text{ref}} \mid \text{Attributable}(s, \text{Contexts})\}|}{|S_{\text{ref}}|}\]

提供三种实现:

  • LLMContextRecall:LLM 逐条判断可归因性
  • NonLLMContextRecall:字符串模糊匹配(Rouge-L)
  • IDBasedContextRecall:直接比较文档 ID

ContextEntityRecall:实体粒度的覆盖率

从参考答案 $GT$ 和检索上下文 $C$ 中提取命名实体:

\[\text{EntityRecall} = \frac{|\text{Entities}(C) \cap \text{Entities}(GT)|}{|\text{Entities}(GT)|}\]

适用场景:知识图谱问答、事实核查等需要精确实体匹配的任务。

ContextUtilization:利用率测量

检查生成答案时实际使用了多少检索上下文:

graph LR
    C1[Context 1] -->|未使用| X1[✗]
    C2[Context 2] -->|部分使用| P1[~]
    C3[Context 3] -->|完全使用| Y1[✓]
    
    X1 --> Score[利用率 = 1.5/3]
    P1 --> Score
    Y1 --> Score

低利用率意味着检索返回了过多冗余信息。

3. 忠实度层:幻觉检测的三种策略

Faithfulness:陈述级可归因性

工作流:

  1. 将答案拆解为独立陈述 ${s_1, s_2, \ldots, s_n}$
  2. LLM 逐条判断是否可从上下文推断
  3. 计算可验证陈述的比例
\[\text{Faithfulness} = \frac{\sum_{i=1}^{n} \mathbb{1}[\text{Supported}(s_i, \text{Contexts})]}{n}\]

实现细节:

1
2
3
4
5
6
7
8
9
10
# 陈述拆解示例
answer = "Python 发布于 1991 年,由 Guido van Rossum 创建。"
statements = [
    "Python 发布于 1991 年",
    "Python 由 Guido van Rossum 创建"
]

# LLM 逐条验证
for stmt in statements:
    supported = llm_judge(stmt, contexts)  # True/False

FaithfulnesswithHHEM:专用模型加速

使用 HuggingFace 预训练的二分类模型 vectara/hallucination_evaluation_model

  • 输入:<context> [SEP] <answer>
  • 输出:幻觉概率 $p_{\text{halluc}} \in [0,1]$
  • 支持批处理,速度比 LLM 推理快 10 倍以上

性能对比:

方法速度精度成本
Faithfulness (GPT-4)~800ms~$0.02/样本
FaithfulnesswithHHEM~80ms中高~$0.0001/样本

MultiModalFaithfulness:跨模态对齐验证

针对图文混合输入,检查答案是否得到文本与图像双重支撑

1
2
3
4
faithful = (
    verify_text_support(answer, contexts) 
    and verify_image_support(answer, images)
)

返回布尔值(0.0 或 1.0)。

4. 对齐层:标准答案的多维度匹配

指标匹配粒度技术路线适用场景
BleuScoren-gram 重叠统计匹配机器翻译、格式化输出
RougeScore最长公共子序列统计匹配摘要生成
AnswerSimilarity语义向量嵌入模型开放域问答
FactualCorrectness事实三元组LLM 提取+比对知识型问答

FactualCorrectness:事实三元组比对

工作流:

  1. LLM 从参考答案提取事实三元组:(主体, 关系, 客体)
  2. 从生成答案提取事实三元组
  3. 计算三元组匹配的 F1 分数

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
# 参考答案:"巴黎是法国的首都,人口约 220 万。"
ref_triples = [
    ("巴黎", "是首都", "法国"),
    ("巴黎", "人口", "220万")
]

# 生成答案:"巴黎是法国首都,约有 2百万居民。"
gen_triples = [
    ("巴黎", "是首都", "法国"),
    ("巴黎", "居民", "2百万")
]

# 匹配:1个完全匹配,1个部分匹配(语义等价但表述不同)

工程权衡:速度、成本、精度的三角

实现策略对比

graph LR
    A[测量需求] --> B{是否需要语义理解}
    B -->|否| C[统计指标]
    B -->|是| D{是否有标注数据}
    
    C --> C1[BleuScore<br/>RougeScore<br/>ExactMatch]
    C1 --> C2[速度: ~1ms/样本<br/>成本: 0]
    
    D -->|无| E[无参考指标]
    D -->|有| F[有参考指标]
    
    E --> E1[AnswerRelevancy<br/>Faithfulness<br/>ContextRelevance]
    E1 --> E2[速度: ~500ms/样本<br/>成本: ~0.01刀/1K样本]
    
    F --> F1[AnswerCorrectness<br/>ContextPrecision<br/>ContextRecall]
    F1 --> F2[速度: ~800ms/样本<br/>成本: ~0.02刀/1K样本]
    
    style C2 fill:#90EE90
    style E2 fill:#FFD700
    style F2 fill:#FF6347

成本优化策略

  1. 分层测试:先用统计指标快速筛选,再用 LLM 指标精测
  2. 批处理:FaithfulnesswithHHEM 支持批处理,可降低 GPU 空转损耗
  3. 缓存机制:对重复出现的 (question, context) 对缓存嵌入向量

实现示例:

1
2
3
4
5
6
7
8
9
10
11
12
from functools import lru_cache
import hashlib

@lru_cache(maxsize=10000)
def cached_embedding(text: str):
    return embedding_model.encode(text)

def compute_similarity(q1, q2):
    # 使用哈希避免直接传递大对象
    h1 = hashlib.md5(q1.encode()).hexdigest()
    h2 = hashlib.md5(q2.encode()).hexdigest()
    return cosine_sim(cached_embedding(h1), cached_embedding(h2))

特定场景:指标组合的最佳实践

RAG 系统:四阶段测量

测量目标:检索精度 → 幻觉控制 → 答案质量 → 鲁棒性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from ragas.metrics import (
    ContextPrecision,
    ContextRecall,
    Faithfulness,
    AnswerCorrectness,
    NoiseSensitivity
)

# 阶段 1:检索质量
retrieval_metrics = [
    ContextPrecision(),  # 排序质量
    ContextRecall()      # 信息覆盖
]

# 阶段 2:幻觉检测
hallucination_metric = Faithfulness()

# 阶段 3:答案质量
answer_metric = AnswerCorrectness(weights=[0.75, 0.25])

# 阶段 4:鲁棒性测试
robustness_metric = NoiseSensitivity(mode="irrelevant")

指标依赖关系图

graph TD
    Q[Question]
    C[Contexts]
    A[Answer]
    GT[Ground Truth]
    
    Q --> AR[AnswerRelevancy]
    A --> AR
    
    Q --> CP[ContextPrecision]
    C --> CP
    GT --> CP
    
    GT --> CR[ContextRecall]
    C --> CR
    
    A --> F[Faithfulness]
    C --> F
    
    A --> AC[AnswerCorrectness]
    GT --> AC
    
    Q --> CU[ContextUtilization]
    C --> CU
    A --> CU
    
    style Q fill:#e1f5ff
    style C fill:#fff4e1
    style A fill:#ffe1f5
    style GT fill:#e1ffe1

快速决策树

graph TD
    Start{有标注数据?}
    Start -->|有| HasGT{检测幻觉?}
    Start -->|无| NoGT{检测幻觉?}
    
    HasGT -->|是| GT_Faithful[Faithfulness +<br/>AnswerCorrectness +<br/>ContextRecall]
    HasGT -->|否| GT_NoFaithful[AnswerCorrectness +<br/>ContextPrecision +<br/>ContextRecall]
    
    NoGT -->|是| NoGT_Faithful[Faithfulness +<br/>AnswerRelevancy +<br/>ContextUtilization]
    NoGT -->|否| NoGT_NoFaithful[AnswerRelevancy +<br/>ContextRelevance]
    
    GT_Faithful --> Cost{预算限制?}
    NoGT_Faithful --> Cost
    
    Cost -->|严格| Fast[替换为 RougeScore +<br/>FaithfulnesswithHHEM]
    Cost -->|宽松| Keep[保持 LLM 指标]

完整指标速查表

指标需要 GT需要 Context需要 LLM输出范围主测维度
AnswerCorrectness0-1事实+语义
AnswerRelevancy0-1切题性
AnswerSimilarity0-1语义相似
ContextPrecision0-1检索排序
ContextRecall✓/✗0-1信息覆盖
ContextEntityRecall0-1实体覆盖
ContextUtilization0-1上下文利用
Faithfulness0-1幻觉检测
FaithfulnesswithHHEM0-1幻觉检测
BleuScore0-1n-gram 匹配
RougeScore0-1LCS 匹配
SummarizationScore0-1摘要质量
ToolCallAccuracy0-1工具调用
ToolCallF10-1工具调用
AgentGoalAccuracy可选0/1目标达成
TopicAdherence0-1对话一致性
NoiseSensitivity0-1鲁棒性
AspectCritic0/1自定义规则
RubricsScore可选1-5领域评分
MultiModalFaithfulness0/1多模态对齐
SQLSemanticEquivalence0/1SQL等价
DataCompyScore0-1表格比对
This post is licensed under CC BY 4.0 by the author.