Ragas Ragas
stable · 中文译文
中文译文 · 原文:https://docs.ragas.io/en/stable/howtos/applications/align-llm-as-judge/ · 许可证 Apache-2.0

如何把 LLM as a Judge 对齐

在本指南中,你将学习如何用 Ragas 系统地评测 LLM-as-judge 指标,并把它与人类专家判断对齐。

  • 构建可复用的评测流水线,用于 judge 对齐
  • 分析 judge 与人类标签之间的分歧模式
  • 迭代 judge prompts,以改进与专家决策的对齐

为什么要先对齐你的 LLM judge?

在运行评测实验之前,重要的是把 LLM judge 对齐到你的具体用例。一个不对齐的 judge 就像指向错误方向的指南针——你基于它的指导所做的每一次改进,都会让你离目标更远。把 judge 对齐到匹配专家判断,能确保你在改进真正重要的东西。这一对齐步骤是可靠评测的基础。

真正的价值:看你的数据

虽然构建一个对齐的 LLM judge 很有用,真正的业务价值来自系统地分析数据并理解失败模式。judge 对齐过程迫使你深入检查边界用例、澄清评测标准,并揭示什么让回复好或坏。把 judge 看作放大你分析能力的工具,而不是替代它。

设置你的环境

我们创建了一个你可以安装并运行的简单模块,这样你可以专注于理解评测过程,而不是创建应用。

uv pip install "ragas[examples]"
export OPENAI_API_KEY="your-api-key-here"

完整代码

你可以在这里查看 judge 对齐评测流水线的完整代码。

理解数据集

我们将使用 EvalsBench 数据集,其中包含对业务问题 LLM 回复的专家标注样例。每一行包括:

  • question:原始提出的问题
  • grading_notes:好的回复应覆盖的关键点
  • response:LLM 生成的回复
  • target:人类专家的二元判断(pass/fail)

下载数据集:

# Create datasets folder and download the dataset
mkdir -p datasets
curl -o datasets/benchmark_df.csv https://raw.githubusercontent.com/vibrantlabsai/EvalsBench/main/data/benchmark_df.csv

加载并检查数据集:

import pandas as pd
from ragas import Dataset

def load_dataset(csv_path: str = None) -> Dataset:
    """Load annotated dataset with human judgments.

    Expected columns: question, grading_notes, response, target (pass/fail)
    """
    path = csv_path or "datasets/benchmark_df.csv"
    df = pd.read_csv(path)

    dataset = Dataset(name="llm_judge_alignment", backend="local/csv")

    for _, row in df.iterrows():
        dataset.append({
            "question": row["question"],
            "grading_notes": row["grading_notes"],
            "response": row["response"],
            "target": (row["target"]),
        })

    return dataset

# Load the dataset
dataset = load_dataset()
print(f"Dataset loaded with {len(dataset)} samples")

数据集中的示例行:

question grading_notes response target
What are the key methods for determining the pre-money valuation of a tech startup before a Series A investment round, and how do they differ? DCF method: !future cash flows!, requires projections; Comp. analysis: similar co. multiples; VC method: rev x multiple - post-$; Founder's share matter; strategic buyers pay more. Determining the pre-money valuation of a tech startup before a Series A investment round is a critical step... (covers DCF, comparable analysis, VC method) pass
What key metrics and strategies should a startup prioritize to effectively manage and reduce churn rate in a subscription-based business model? Churn:! monitor monthly, \<5% ideal. Retention strategies: engage users, improve onboarding. CAC & LTV: balance 3:1+. Feedback loops: implement early. Customer support: proactive & responsive, critical. Managing and reducing churn rate in a subscription-based business model is crucial... (missing specific metrics and strategies) fail

数据集包含对同一问题的多个回复——有些 pass,有些 fail。这帮助 judge 学习可接受与不可接受回复之间的细微区别。

理解你的 ground truth

judge 对齐的质量完全取决于 ground truth 标签的质量。在生产场景中,请让一位 核心领域专家 参与——其判断对你的用例最关键的人(例如心理健康 AI 的心理学家、法律 AI 的律师,或支持聊天机器人的客服总监)。他们一致的判断成为你的 judge 对齐的黄金标准。你不需要给每个例子都打标签——一个有代表性的样本(100-200 个覆盖多样场景的例子)就足以进行可靠对齐。

理解评测方法

在本指南中,我们评测数据集中预先存在的回复,而不是生成新回复。这种方法确保跨评测运行的结果可复现,让我们聚焦于 judge 对齐而不是回复生成。

评测工作流是:数据集行(question + response)→ Judge → 与人类 target 比较

定义评测指标

对于 judge 对齐,我们需要两个指标:

主指标:accuracy(LLM judge) - 评测回复并返回带 reason 的 pass/fail 决策。

对齐指标:judge_alignment - 检查 judge 的决策是否与人类专家的 verdict 匹配。

设置 judge 指标

定义一个简单的基线 judge 指标,对照 grading notes 评测回复:

from ragas.metrics import DiscreteMetric

# Define the judge metric with a simple baseline prompt
accuracy_metric = DiscreteMetric(
    name="accuracy",
    prompt="Check if the response contains points mentioned from the grading notes and return 'pass' or 'fail'.\n\nResponse: {response}\nGrading Notes: {grading_notes}",
    allowed_values=["pass", "fail"],
)

对齐指标

对齐指标把 judge 的决策与人类 verdict 比较:

from ragas.metrics.discrete import discrete_metric
from ragas.metrics.result import MetricResult

@discrete_metric(name="judge_alignment", allowed_values=["pass", "fail"])
def judge_alignment(judge_label: str, human_label: str) -> MetricResult:
    """Compare judge decision with human label."""
    judge = judge_label.strip().lower()
    human = human_label.strip().lower()

    if judge == human:
        return MetricResult(value="pass", reason=f"Judge={judge}; Human={human}")

    return MetricResult(value="fail", reason=f"Judge={judge}; Human={human}")

实验函数

实验函数 编排完整评测流水线——用 judge 评测回复并测量对齐:

from typing import Dict, Any
from ragas import experiment
from ragas.metrics import DiscreteMetric
from ragas_examples.judge_alignment import judge_alignment  # The metric we created above

@experiment()
async def judge_experiment(
    row: Dict[str, Any],
    accuracy_metric: DiscreteMetric,
    llm,
):
    """Run complete evaluation: Judge → Compare with human."""
    # Step 1: Get response (in production, this is where you'd call your LLM app)
    # For this evaluation, we use pre-existing responses from the dataset
    app_response = row["response"]

    # Step 2: Judge evaluates the response
    judge_score = await accuracy_metric.ascore(
        question=row["question"],
        grading_notes=row["grading_notes"],
        response=app_response,
        llm=llm,
    )

    # Step 3: Compare judge decision with human target
    alignment = judge_alignment.score(
        judge_label=judge_score.value,
        human_label=row["target"]
    )

    return {
        **row,
        "judge_label": judge_score.value,
        "judge_reason": judge_score.reason,
        "alignment": alignment.value,
        "alignment_reason": alignment.reason,
    }

运行基线评测

执行评测流水线并收集结果

import os
from openai import AsyncOpenAI
from ragas.llms import llm_factory
from ragas_examples.judge_alignment import load_dataset

# Load dataset
dataset = load_dataset()
print(f"Dataset loaded with {len(dataset)} samples")

# Initialize LLM client
openai_client = AsyncOpenAI(api_key=os.environ.get("OPENAI_API_KEY"))
llm = llm_factory("gpt-4o-mini", client=openai_client)

# Run the experiment
results = await judge_experiment.arun(
    dataset,
    name="judge_baseline_v1_gpt-4o-mini",
    accuracy_metric=accuracy_metric,
    llm=llm,
)

# Calculate alignment rate
passed = sum(1 for r in results if r["alignment"] == "pass")
total = len(results)
print(f"✅ Baseline alignment: {passed}/{total} passed ({passed/total:.1%})")

📋 输出(baseline v1)

2025-10-08 22:40:00,334 - Loaded dataset with 160 samples
2025-10-08 22:40:00,334 - Initializing LLM client with model: gpt-4o-mini
2025-10-08 22:40:01,858 - Running baseline evaluation...
Running experiment: 100%|████████████████████████| 160/160 [04:35<00:00,  1.72s/it]
2025-10-08 22:44:37,149 - ✅ Baseline alignment: 121/160 passed (75.6%)

初始表现分析

评测会生成全面的 CSV 结果,包含所有输入(question、grading_notes、response)、人类 targets、带推理的 judge 决策,以及对齐比较。

分析错误与失败模式

运行基线评测后,我们可以分析不对齐模式,了解 judge 在何处与人类专家不一致。

基线表现:75.6% 对齐(121/160 正确)

让我们检查错误分布

📋 代码

import pandas as pd

# Load results
df = pd.read_csv('experiments/judge_baseline_v1_gpt-4o-mini.csv')

# Analyze misalignments
false_positives = len(df[(df['judge_label'] == 'pass') & (df['target'] == 'fail')])
false_negatives = len(df[(df['judge_label'] == 'fail') & (df['target'] == 'pass')])

print(f"False positives (judge too lenient): {false_positives}")
print(f"False negatives (judge too strict): {false_negatives}")

📋 输出

False positives (judge too lenient): 39
False negatives (judge too strict): 0

关键观察: 全部 39 个不对齐(24.4%)都是 false positives——judge 说 "pass" 但人类专家说 "fail" 的情况。基线 judge 过于宽松,漏掉了省略 grading notes 中关键概念的回复。

失败用例样本

下面是 judge 错误地通过了缺失关键概念的回复的例子:

Grading Notes Human Label Judge Label What's Missing
*Valuation caps*, $, post-$ val key. Liquidation prefs: 1x+ common. Anti-dilution: *full vs. weighted*. Board seats: 1-2 investor reps. ESOP: 10-20%. fail pass Response discusses all points comprehensively but human annotators marked it as fail for subtle omissions
*Impact on valuation*: scalability potential, dev costs, integration ease. !Open-source vs proprietary issues. !Tech debt risks. Discuss AWS/GCP/Azure... fail pass Missing specific discussion of post-money valuation impact
Historical vs. forecasted rev; top-down & bottom-up methods; *traction evidence*; !unbiased assumptions; 12-24mo project... fail pass Missing explicit mention of traction evidence

错误中的常见模式:

  1. 缺失 grading notes 中的 1-2 个具体概念,同时覆盖了其他概念
  2. 隐含 vs 显式覆盖 - judge 接受隐含概念,我们希望显式提及
  3. 缩写术语 没有被正确解码(例如 "mkt demand" = market demand,"post-$" = post-money valuation)
  4. 忽略关键标记 - 标有 * 或 ! 的点往往是必要的

改进 judge prompt

基于错误分析,我们需要创建一个改进后的 prompt,它:

  1. 理解 grading notes 中使用的 缩写
  2. 识别关键标记(*、!、具体数字)
  3. 要求所有概念 都存在,而不仅仅是大多数
  4. 接受语义等价物(同一概念的不同措辞)
  5. 平衡严格程度 - 既不太宽松也不太严格

创建改进后的 v2 prompt

用全面的评测标准定义增强的 judge 指标:

from ragas.metrics import DiscreteMetric

# Define improved judge metric with enhanced evaluation criteria
accuracy_metric_v2 = DiscreteMetric(
    name="accuracy",
    prompt="""Evaluate if the response covers ALL the key concepts from the grading notes. Accept semantic equivalents but carefully check for missing concepts.

ABBREVIATION GUIDE - decode these correctly:

• Financial: val=valuation, post-$=post-money, rev=revenue, ARR/MRR=Annual/Monthly Recurring Revenue, COGS=Cost of Goods Sold, Opex=Operating Expenses, LTV=Lifetime Value, CAC=Customer Acquisition Cost
• Business: mkt=market, reg/regs=regulation/regulatory, corp gov=corporate governance, integr=integration, S&M=Sales & Marketing, R&D=Research & Development, acq=acquisition
• Technical: sys=system, elim=elimination, IP=Intellectual Property, TAM=Total Addressable Market, diff=differentiation
• Metrics: NPS=Net Promoter Score, SROI=Social Return on Investment, proj=projection, cert=certification

EVALUATION APPROACH:

Step 1 - Parse grading notes into distinct concepts:

- Separate by commas, semicolons, or line breaks
- Each item is a concept that must be verified
- Example: "*Gross Margin* >40%, CAC, LTV:CAC >3:1" = 3 concepts

Step 2 - For each concept, check if it's addressed:

- Accept semantic equivalents (e.g., "customer acquisition cost" = "CAC")
- Accept implicit coverage when it's clear (e.g., "revenue forecasting" covers "historical vs forecasted rev")
- Be flexible on exact numbers (e.g., "around 40%" acceptable for ">40%")

Step 3 - Count missing concepts:

- Missing 0 concepts = PASS
- Missing 1+ concepts = FAIL (even one genuinely missing concept should fail)
- Exception: If a long list (10+ items) has 1 very minor detail missing but all major points covered, use judgment

CRITICAL RULES:

1. Do NOT require exact wording - "market demand" = "mkt demand" = "demand analysis"

2. Markers (* or !) mean important, not mandatory exact phrases:
   - "*traction evidence*" can be satisfied by discussing metrics, growth, or validation
   - "!unbiased assumptions" can be satisfied by discussing assumption methodology

3. Numbers should be mentioned but accept approximations:
   - "$47B to $10B" can be "$47 billion dropped to around $10 billion"
   - "LTV:CAC >3:1" can be "LTV to CAC ratio of at least 3 to 1" or "3x or higher"

4. FAIL only when concepts are genuinely absent:
   - If notes mention "liquidation prefs, anti-dilution, board seats" but response only has board seats → FAIL
   - If notes mention "scalability, tech debt, IP" but response never discusses technical risks → FAIL
   - If notes mention "GDPR compliance" and response never mentions GDPR or EU regulations → FAIL

5. PASS when ALL concepts present:
   - All concepts covered, even with different wording → PASS
   - Concepts addressed implicitly when clearly implied → PASS
   - Minor phrasing differences → PASS
   - One or more concepts genuinely absent → FAIL

Response: {response}

Grading Notes: {grading_notes}

Are ALL distinct concepts from the grading notes covered in the response (accepting semantic equivalents and implicit coverage)?""",
    allowed_values=["pass", "fail"],
)

用 LLM 优化 prompts

在你清晰识别错误模式之后,可以用 LLM 优化 prompts。你也可以用 LLM 识别错误,但务必审阅它们,确保与 ground truth 标签对齐。你还可以使用像 Cursor、Claude Code 这样的编码 agent,或像 DSPy 这样的框架,系统地优化 judge prompts。

用改进后的 prompt 重新运行评测

用增强的 v2 prompt 再次运行评测(设置与基线相同,只替换指标):

# Use the same dataset and LLM setup from the baseline evaluation above
results = await judge_experiment.arun(
    dataset,
    name="judge_accuracy_v2_gpt-4o-mini",
    accuracy_metric=accuracy_metric_v2,  # ← Using improved v2 prompt
    llm=llm,
)

passed = sum(1 for r in results if r["alignment"] == "pass")
total = len(results)
print(f"✅ V2 alignment: {passed}/{total} passed ({passed/total:.1%})")

📋 输出(improved v2)

2025-10-08 23:42:11,650 - Loaded dataset with 160 samples
2025-10-08 23:42:11,650 - Initializing LLM client with model: gpt-4o-mini
2025-10-08 23:42:12,730 - Running v2 evaluation with improved prompt...
Running experiment: 100%|██████████| 160/160 [04:39<00:00,  1.75s/it]
2025-10-08 23:46:52,740 - ✅ V2 alignment: 139/160 passed (86.9%)

显著改进! 对齐率从 75.6% 提升到 86.9%。

如果你需要进一步迭代:

  • 分析剩余错误以识别模式(它们是 false positives 还是 false negatives?)
  • 连同标签一起标注你的推理——这在改进 LLM Judge 时会有帮助,你也可以把这些作为 few shot 例子加入。
  • 使用更聪明的模型 - 更有能力的模型如 GPT-5 或 Claude 4.5 Sonnet 通常作为 judges 表现更好
  • 利用 AI 助手 - 本指南是用 Cursor AI agents 分析失败并迭代 prompts 创建的。你可以使用 AI 编码 agents(Cursor、Claude 等)或像 DSPy 这样的框架,系统地优化 judge prompts
  • 当对齐在 2-3 次迭代中趋于平稳,或达到你的业务阈值时停止

你已经完成了什么

你已经用 Ragas 构建了一个系统化的评测流水线,它:

  • 用清晰指标对照专家判断测量 judge 对齐
  • 通过结构化错误分析识别失败模式
  • 用可复现实验跟踪跨评测运行的改进

这个对齐后的 judge 成为可靠 AI 评测的基础。有了一个你可以信任的 judge,你现在可以自信地评测 RAG 流水线、agent 工作流或任何 LLM 应用——并知道指标上的改进会转化为质量上的真实改进。