0Pricing
AI Engineering Academy · 课时

生成指标:忠实度与答案相关性

使用 RAGAS 衡量生成的答案是否忠实于检索到的上下文,以及是否真正回答了用户的问题而没有产生幻觉。

生成指标:忠实度与答案相关性 是 CoddyKit 上的免费 AI Engineering Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 AI Engineering Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 AI Engineering Academy 课程共包含 4 节课。

衡量生成阶段

即使检索器找到了完美的文档块,生成阶段仍可能失败。LLM 可能会忽略检索到的上下文,依靠参数记忆作答;可能误解上下文的含义;或者回答与所提问题略有不同的问题。生成指标可以独立于检索来量化这些失败,从而帮助您定位并修复每个问题。两个主要的生成指标是忠实度和答案相关性。

忠实度:定义

忠实度衡量生成答案中的每个陈述是否都能直接追溯到检索到的上下文。忠实的答案不会引入上下文中不存在的信息。忠实度以陈述为单位进行衡量:将答案拆分为单独的原子陈述,然后逐一与上下文核对,确认上下文是否提供支持。忠实度分数就是获得支持的陈述所占的比例。

# Faithfulness = supported_claims / total_claims

example_answer = (
    'Employees receive 15 vacation days per year. '
    'Remote work is allowed on Wednesdays and Fridays. '
    'The CEO is John Smith.'
)
example_context = (
    '15 vacation days are granted annually. '
    'Remote work is permitted on Wednesdays and Fridays.'
)

# Claim 1: 15 vacation days — SUPPORTED
# Claim 2: Remote work Wed+Fri — SUPPORTED
# Claim 3: CEO is John Smith — NOT IN CONTEXT (hallucinated)
# Faithfulness = 2/3 = 0.67

使用 LLM 评审实现忠实度

大规模衡量忠实度最实用的方法,是使用强大的 LLM 作为评审者。向评审 LLM 提示,让它将答案拆分为单独的陈述,然后将每个陈述与上下文进行核对。评审者会返回一个陈述列表,并将每条标记为 SUPPORTED 或 UNSUPPORTED;您可以计算其中获得支持的陈述所占的比例。这种方法每小时可以扩展到数千次评估,每次评估的成本仅为几美分。

import json

def evaluate_faithfulness(answer, context, llm_client):
    prompt = (
        'Task: Evaluate the faithfulness of an answer against a context.\n\n'
        f'Context:\n{context}\n\n'
        f'Answer:\n{answer}\n\n'
        'Steps:\n'
        '1. Break the answer into individual atomic claims.\n'
        '2. For each claim, check if it is supported by the context.\n'
        '3. Return JSON: {"claims": [{"text": "...", "supported": true/false}], "score": 0.0-1.0}'
    )
    response = llm_client.chat.completions.create(
        model='gpt-4o',
        response_format={'type': 'json_object'},
        messages=[{'role': 'user', 'content': prompt}]
    )
    return json.loads(response.choices[0].message.content)

答案相关性:定义

答案相关性用于衡量生成的答案是否真正回答了用户的问题。一个高度忠实的答案仍可能没有切中要点——例如,用户询问“如何重置密码?”,答案却详细解释公司的总体安全策略,却没有提及密码重置流程。答案相关性独立于忠实性:答案可以是忠实的(只陈述上下文中的内容),但也可能不相关(没有回答用户所问的问题)。

衡量答案相关性

RAGAS 使用一种巧妙的反向生成技术来衡量答案相关性:评审 LLM 会生成几个假设性问题,这些问题都可以由生成的回答来回答,然后使用嵌入向量余弦相似度衡量这些生成的问题与原始问题的相似程度。生成的假设性问题与原始问题之间的相似度越高,说明答案相关性越高。

def evaluate_answer_relevance(question, answer, llm_client, embed_fn):
    # Generate hypothetical questions for this answer
    prompt = (
        f'Given this answer: "{answer}"\n\n'
        'Generate 3 questions that this answer would be a good response to.\n'
        'Return as JSON: {"questions": ["...", "...", "..."]}'
    )
    response = llm_client.chat.completions.create(
        model='gpt-4o-mini',
        response_format={'type': 'json_object'},
        messages=[{'role': 'user', 'content': prompt}]
    )
    hyp_questions = json.loads(response.choices[0].message.content)['questions']

    # Measure similarity to original question
    orig_embedding = embed_fn(question)
    hyp_embeddings = [embed_fn(q) for q in hyp_questions]
    similarities = [cosine_similarity(orig_embedding, e) for e in hyp_embeddings]
    return sum(similarities) / len(similarities)

上下文召回率:我们检索到足够的信息了吗?

上下文召回率用于衡量检索到的上下文是否包含正确回答问题所需的足够信息。它会逐句检查标准答案:每个句子是否都能归因于某个检索到的片段?上下文召回率高,说明检索器找到了所有必要信息。上下文召回率低,说明检索到的片段缺少关键信息,因此即使生成效果完美,LLM 也不可能正确回答。

def evaluate_context_recall(ground_truth_answer, retrieved_contexts, llm_client):
    prompt = (
        f'Ground truth answer:\n{ground_truth_answer}\n\n'
        f'Retrieved context:\n{",".join(retrieved_contexts)}\n\n'
        'For each sentence in the ground truth answer, determine if it '
        'can be attributed to the retrieved context.\n'
        'Return JSON: {"sentences": [{"text": "...", "in_context": true/false}], "recall": 0.0-1.0}'
    )
    response = llm_client.chat.completions.create(
        model='gpt-4o',
        response_format={'type': 'json_object'},
        messages=[{'role': 'user', 'content': prompt}]
    )
    return json.loads(response.choices[0].message.content)

上下文精确率:检索到的片段相关吗?

上下文精确率用于衡量检索到的片段是否确实有助于回答问题。上下文精确率高,说明检索到的片段与问题高度相关。上下文精确率低,说明许多检索到的片段都是偏离主题的噪声,LLM 必须阅读并丢弃这些内容,从而增加混淆风险。上下文精确率通过检查哪些检索到的片段实际被生成的答案使用或引用来衡量。

def evaluate_context_precision(question, answer, retrieved_contexts, llm_client):
    precision_scores = []
    for i, context in enumerate(retrieved_contexts, 1):
        prompt = (
            f'Question: {question}\n\n'
            f'Context chunk {i}: {context}\n\n'
            f'Answer: {answer}\n\n'
            'Was this context chunk useful in generating the answer? '
            'Return JSON: {"useful": true/false, "reason": "..."}'
        )
        response = llm_client.chat.completions.create(
            model='gpt-4o-mini',
            response_format={'type': 'json_object'},
            messages=[{'role': 'user', 'content': prompt}]
        )
        result = json.loads(response.choices[0].message.content)
        precision_scores.append(1.0 if result['useful'] else 0.0)
    return sum(precision_scores) / len(precision_scores)

同时使用 RAGAS 衡量所有指标

RAGAS 库在一个统一框架中实现了 RAG 的四项核心指标——上下文精确率、上下文召回率、忠实性和答案相关性。它会在内部处理 LLM 评审调用。传入包含问题、生成答案、检索上下文和标准答案的数据集,即可获得综合评分报告。RAGAS 还支持异步评估,因此您可以并行评估数百个示例。

from ragas import evaluate
from ragas.metrics import (
    faithfulness, answer_relevancy,
    context_precision, context_recall
)
from datasets import Dataset

# Build evaluation dataset
eval_samples = [
    {
        'question': item['question'],
        'answer': item['generated_answer'],
        'contexts': item['retrieved_texts'],
        'ground_truth': item['expected_answer']
    }
    for item in test_results
]

eval_dataset = Dataset.from_list(eval_samples)
results = evaluate(eval_dataset,
    metrics=[faithfulness, answer_relevancy, context_precision, context_recall]
)
results.to_pandas().to_csv('eval_results.csv', index=False)

通过指标组合进行诊断

指标组合可以揭示具体的系统问题。忠实性低 + 上下文精确率高 → LLM 忽略了上下文并产生了幻觉(请修复提示词)。上下文召回率低 + 忠实性高 → 检索器遗漏了关键片段,但 LLM 忠实地报告了它找到的内容(请改进分块或嵌入)。答案相关性低 + 忠实性高 → 检索到的片段只有间接相关,LLM 忠实地讨论了这些片段,却遗漏了问题本身(请改进检索过滤或查询重写)。

# Diagnostic matrix
diagnostics = [
    {
        'condition': 'Low faithfulness + High context precision',
        'cause': 'LLM ignoring context, answering from parametric memory',
        'fix': 'Strengthen system prompt: "Answer ONLY from the provided context"'
    },
    {
        'condition': 'Low context recall + High faithfulness',
        'cause': 'Retriever missing relevant chunks',
        'fix': 'Improve chunking strategy, embedding model, or increase top-k'
    },
    {
        'condition': 'Low answer relevance + High context recall',
        'cause': 'Retrieved context is off-topic; LLM is answering wrong question',
        'fix': 'Add query rewriting or improve metadata filters'
    }
]

通过人工评估进行校准

LLM 评审指标与人工判断相关,但并不完全一致。请让 3 名人工评分者使用 1 到 5 分的量表,对随机抽取的 50 个输出的忠实性和答案相关性进行评分,以此校准自动化指标。计算 LLM 评审结果与人工平均评分之间的一致性。如果 LLM 相对于人工评分系统性地偏高或偏低,请应用修正因子。经过校准的自动化指标可以让您确信,分数提升确实反映了质量提升。

from scipy.stats import spearmanr

def calibrate_judge_vs_humans(samples):
    '''samples: [{"llm_score": 0.9, "human_score": 4.2}, ...]'''
    llm_scores = [s['llm_score'] for s in samples]
    human_scores = [s['human_score'] / 5.0 for s in samples]  # normalize to 0-1

    correlation, pvalue = spearmanr(llm_scores, human_scores)
    print(f'LLM-Human Spearman correlation: {correlation:.3f} (p={pvalue:.4f})')

    mean_llm = sum(llm_scores) / len(llm_scores)
    mean_human = sum(human_scores) / len(human_scores)
    bias = mean_llm - mean_human
    print(f'LLM bias vs humans: {bias:+.3f}')
    return correlation, bias

为生产环境设定指标目标

在将 RAG 系统部署到生产环境之前,请定义系统必须达到的最低指标阈值。常见的生产目标包括:忠实性 > 0.90(答案主张中产生幻觉的比例低于 10%)、答案相关性 > 0.80(至少 80% 的答案确实回答了问题)、上下文精确率 > 0.60(大多数检索到的片段都相关),以及上下文召回率 > 0.75(检索到的上下文包含大多数关键事实)。未达到这些阈值的系统不应在进一步改进前部署。

PRODUCTION_THRESHOLDS = {
    'faithfulness': 0.90,
    'answer_relevancy': 0.80,
    'context_precision': 0.60,
    'context_recall': 0.75
}

def check_production_readiness(metrics):
    ready = True
    print('Production readiness check:')
    for metric, threshold in PRODUCTION_THRESHOLDS.items():
        score = metrics.get(metric, 0)
        status = 'PASS' if score >= threshold else 'FAIL'
        print(f'  {metric}: {score:.2f} (>= {threshold}) -> {status}')
        if status == 'FAIL':
            ready = False
    print(f'Overall: {"READY" if ready else "NOT READY"}')
    return ready

快速检查

请检验您对本课 AI 工程概念的理解。

课程回顾

在本课中,您学习了:将忠实性作为逐条主张的指标,用于检查答案中的每个陈述是否都受到检索上下文的支持;将答案相关性作为衡量答案是否回答实际问题的指标;使用上下文召回率和上下文精确率从生成结果的角度衡量检索质量;以及使用RAGAS 库进行自动化多指标评估。接下来,我们会将这些指标组合成一个自动化评估工具,您可以在每次变更时运行它。

常见问题解答

「生成指标:忠实度与答案相关性」课时是免费的吗?

是的 — 「生成指标:忠实度与答案相关性」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 AI Engineering Academy 课程的其余内容,请升级到 CoddyKit PRO。 AI Engineering Academy 课程共包含 4 节课。

「生成指标:忠实度与答案相关性」这节课中我会学到什么?

使用 RAGAS 衡量生成的答案是否忠实于检索到的上下文,以及是否真正回答了用户的问题而没有产生幻觉。 你通过在浏览器中直接运行的动手代码来练习 AI Engineering Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 AI Engineering Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 AI Engineering Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「生成指标:忠实度与答案相关性」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 AI Engineering Academy 课中编写并运行代码吗?

能。每节 AI Engineering Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 为什么 RAG 中的评估很重要
  2. 检索指标:命中率、MRR 与 NDCG
  3. 生成指标:忠实度与答案相关性
  4. 构建自动化评估工具
← 返回 AI Engineering Academy