✅ 评估与测试

普通软件有确定性输出,写断言测试不难。但 Agent 非确定(同输入不同输出)、多步骤、依赖 LLM——怎么测它"好不好"?本章精读 LangChain 的评估体系(EvaluatorCallbackHandler、标准化测试套件、LLM-as-judge),为 RAG Agent 设计可量化的评估方案。

本章目标

  • 理解 Agent 评估为什么难(非确定性、多维度)
  • 掌握 Agent 的核心评估维度(忠实度/相关性/正确性/效率)
  • 精读 EvaluatorCallbackHandler 运行时评估机制
  • 了解 langchain_tests 标准化测试套件
  • 用 LLM-as-judge 实战评估一个 RAG Agent

Agent 评估为什么难

挑战普通软件Agent
输出确定性固定输入→固定输出同输入可能不同输出(温度/模型版本)
正确性标准断言 == 期望值"好回答"是主观的,难定义客观标准
测试维度功能对错忠实度/相关性/有用性/安全/成本...多维度
多步骤单函数调用Agent 走的路径每次不同,中间步骤也要评估
回归测试改代码跑测试改 prompt/换模型,需重新评估全量
💡 核心思路:从"断言"转向"打分"

普通测试是二元的(pass/fail)。Agent 评估通常是连续打分(0-1 的相关性分数)+ 多维评估(同时看忠实度、相关性、有用性)。工具上:LLM-as-judge(用另一个 LLM 评判)是当前主流方案——因为"判断回答好坏"本身就是 LLM 擅长的。

评估维度

忠实度 Faithfulness 答案是否基于 检索文档(防幻觉) 相关性 Relevance 检索的文档 是否切题 正确性 Correctness 答案是否 事实正确 效率/成本 Efficiency token 用量 延迟/步数
图 AD10.1 · Agent 评估的核心维度

EvaluatorCallbackHandler

LangChain 的运行时评估机制——把评估器挂成 callback,每次 run 结束自动评估

📄 tracers/evaluation.py:38 · EvaluatorCallbackHandler python
class EvaluatorCallbackHandler(BaseTracer):
    """运行时评估的桥:把评估器挂成 tracer。

    每个 run 结束时自动用挂载的 evaluators 评估。
    _persist_run (:205) 在 run 完成后用线程池跑 evaluators。
    max_concurrency (:93):并发评估数。
    """

# 本质是"追踪即评估":
# - 普通 tracer 只记录 run(上报 LangSmith)
# - 这个 tracer 额外对 run 做【评估打分】
# - 评估结果也上报,形成"执行+评估"的完整闭环
📌 这与 AD7 的可观测结合

回顾 AD7:callbacks 是可观测基础。EvaluatorCallbackHandler 是特殊的 callback——它不只记录,还评估。所以评估和追踪共享同一套基础设施。这也是为什么评估通常和 LangSmith 深度集成——评估结果可视化在追踪旁边。

标准化测试套件

LangChain 为集成(chat model/embedding/vectorstore/tool)提供标准化测试——保证集成质量一致:

📄 libs/standard-tests/ · 标准化测试体系 python
# langchain_tests 包:每个集成继承对应基类即获一致性测试
# base.py:4 BaseStandardTests —— 根基类

# 按类型分的标准测试:
# chat_models.py:194 ChatModelIntegrationTests
#   - test_invoke (:767)
#   - test_stream (:822)
#   - test_stream_events_v3 (:937)
#   - test_batch (:1130)
#   ... 覆盖所有标准行为

# unit_tests/:单元测试(不需真实 API)
# _langsmith_plugin.py:pytest 插件,自动注入 tracing tags

# 用法:你的 ChatModel 集成继承 ChatModelIntegrationTests
class TestMyChatModel(ChatModelIntegrationTests):
    @pytest.fixture
    def chat_model_class(self):
        return MyChatModel
    # 自动获得几十个标准测试,保证你的实现符合规范
💡 标准化测试的价值

这不是评估"Agent 好不好",而是评估"集成是否符合规范"。比如你写了个新的 ChatModel 集成,继承 ChatModelIntegrationTests 就能验证它是否正确实现了 invoke/stream/batch/stream_events——保证生态质量。这是开源框架维护的关键工程实践。

LLM-as-judge 实战

🚀 用 LLM 评估 RAG Agent

核心思想:用评估 LLM被评估 Agent的输出打分。

📄 ad10_llm_judge.py · RAG 三维评估 python
# pip install langchain langchain-openai pydantic
from langchain_openai import ChatOpenAI
from pydantic import BaseModel, Field
from typing import Literal

judge_model = ChatOpenAI(model="gpt-4o", temperature=0)  # 评判用更强模型,温度0保证稳定

# ============ 定义三个评估维度的打分 schema ============
class FaithfulnessScore(BaseModel):
    """忠实度:答案是否完全基于上下文(有无幻觉)。"""
    score: Literal[0, 1] = Field(description="1=忠实 0=有幻觉")
    reasoning: str = Field(description="判断理由")

class RelevanceScore(BaseModel):
    """相关性:答案是否回答了问题。"""
    score: Literal[0, 1] = Field(description="1=相关 0=跑题")
    reasoning: str

class CorrectnessScore(BaseModel):
    """正确性:答案是否事实正确(对照标准答案)。"""
    score: Literal[0, 1] = Field(description="1=正确 0=错误")
    reasoning: str

# ============ 评估函数 ============
def evaluate_faithfulness(answer: str, context: str) -> FaithfulnessScore:
    """评估忠实度:答案的每个声明是否都能在 context 找到支持。"""
    return judge_model.with_structured_output(FaithfulnessScore).invoke(
        f"上下文:{context}\n答案:{answer}\n"
        f"答案中的每个陈述是否都能从上下文推导出?只回 JSON。"
    )

def evaluate_relevance(answer: str, question: str) -> RelevanceScore:
    return judge_model.with_structured_output(RelevanceScore).invoke(
        f"问题:{question}\n答案:{answer}\n答案是否切题回答了问题?"
    )

def evaluate_correctness(answer: str, ground_truth: str) -> CorrectnessScore:
    return judge_model.with_structured_output(CorrectnessScore).invoke(
        f"标准答案:{ground_truth}\n待评答案:{answer}\n两者意思是否一致?"
    )

# ============ 评估数据集(离线评估)============
eval_dataset = [
    {
        "question": "LCEL 是什么?",
        "context": "LCEL 是 LangChain 的表达式语言,用 | 组合组件...",
        "ground_truth": "LCEL 是 LangChain 的管道组合语法",
    },
    # ... 更多评估样本
]

# ============ 运行评估 ============
def run_evaluation(agent, dataset):
    results = []
    for item in dataset:
        answer = agent.invoke(item["question"])  # 被评估 Agent 的输出
        results.append({
            "faithfulness": evaluate_faithfulness(answer, item["context"]).score,
            "relevance": evaluate_relevance(answer, item["question"]).score,
            "correctness": evaluate_correctness(answer, item["ground_truth"]).score,
        })

    # 汇总
    n = len(results)
    print(f"=== 评估报告({n} 个样本)===")
    print(f"忠实度: {sum(r['faithfulness'] for r in results)/n:.1%}")
    print(f"相关性: {sum(r['relevance'] for r in results)/n:.1%}")
    print(f"正确性: {sum(r['correctness'] for r in results)/n:.1%}")

# 改 prompt / 换模型 / 调 RAG 策略后,重跑评估对比分数
# 这就是 Agent 的"回归测试"
⚠️ LLM-as-judge 的局限

用 LLM 评估 LLM 有自身偏差:①评判模型可能偏好某风格;②强模型评判弱模型更准,反过来不行;③对长答案/复杂推理可能判断不稳。缓解:用比被评估模型更强的评判模型、温度设0、多评判取平均、结合人工抽检。LLM-as-judge 是当前最实用方案,但不是完美方案

RAG 专项评估指标

RAG 有成熟的评估框架(如 RAGAS),核心指标对应 AD4 的反思点:

指标衡量什么计算方式
Faithfulness答案忠实于文档(防幻觉)答案声明能否在文档找到支持
Answer Relevance答案切题答案是否回答了问题
Context Precision检索精度检索的文档里相关的比例
Context Recall检索召回需要的文档是否都检索到

注意 Context Precision/Recall 评估的是检索质量(AD3),Faithfulness/Relevance 评估的是生成质量。分离评估能定位问题在检索还是生成。

在线评估 vs 离线评估

维度离线评估在线评估
时机发布前,固定数据集运行时,真实流量
目的回归测试、对比方案监控质量、发现退化
成本可控(固定样本)高(每个请求都评)
实现评估脚本EvaluatorCallbackHandler
典型本章的 run_evaluationLangSmith 在线评估

与生产实践对照

评估概念OpenCode 对应
LLM-as-judge 自动评估无(依赖人工使用反馈)
标准化测试套件effect-drizzle-sqlite 测试基建
EvaluatorCallbackHandler 运行时OTel span + 事件流
评估数据集无标准化评估集
成本/效率监控session.ts getUsage 成本统计
🧭 评估是 Agent 工程的薄弱环节

对比可观测/容错/部署(都有成熟方案),Agent 评估至今仍是开放难题——没有银弹,业界还在探索。LangChain 提供了工具(EvaluatorCallbackHandler、standard-tests、LangSmith 评估),但如何定义"好"、如何构建评估集、如何应对非确定性仍需大量人工设计。这恰恰说明:掌握评估能力,是高级 Agent 工程师的稀缺技能。

进阶阶段完成!

🎉 第五阶段(进阶)完成!

恭喜完成全部 10 个进阶章节。回顾四大主题:

  1. 多 Agent 协作(AD1-2)—— Supervisor/层级拓扑、Handoff、子图通信
  2. 高级 RAG(AD3-4)—— 检索策略、CRAG/Self-RAG 自我反思
  3. 记忆系统(AD5-6)—— Checkpoint 深度、Store 语义长期记忆
  4. 可观测/生产(AD7-10)—— 追踪、容错、部署、评估

从"会用框架"到"精通原理与生产工程",你已掌握构建生产级 Agent 系统的完整知识体系。

小结

教程全部完成

全部 35 章(3 基础 + 8 LangChain + 8 LangGraph + 6 OpenCode + 10 进阶)已完成!回到 首页 看进度,或重温 OC6 概念对照表 巩固。你已经具备从理论到生产的完整 Agent 工程能力。🚀