Agent 评估——如何知道你的 Agent 够不够好

文章目录

"这个 Agent 好不好用?"

这个问题看似简单,却比评估一个普通 API 难得多。API 只要看返回值是否正确;Agent 要看整个行为过程------它走了几步、用了哪些工具、中间有没有走弯路、最终答案用户是否满意......

更难的是:Agent 的输出往往是自然语言,没有单一的"正确答案"可以对比。一个问题可能有十种不同的回答方式,都算"正确",但质量差异巨大。

这就是为什么 Agent 评估是一个独立的、需要系统性方法论的工程问题。

一、评估的三个层次

评估 Agent 不能只看最终结果,也不能只盯着每一步------需要在三个层次上同时审视。

三层互补:单步找原因,轨迹找路径,任务验价值

第一层:单步评估(Step-level Evaluation)

评估 Agent 的每一个具体行动:每次 LLM 推理是否产生了正确的意图?每次工具调用是否选择了正确的工具、传入了合法的参数?工具返回结果是否被正确解析?

适合发现的问题

  • 工具调用参数格式错误(比如日期格式写成了 "March 29" 而不是 "2026-03-29")
  • LLM 选择了错误的工具(应该用 search_db 却用了 search_web
  • 输出解析失败,导致后续步骤拿到了错误数据

评估方法:单元测试、格式校验、LLM 评分单步输出

优势:粒度细,一旦发现问题容易定位根因。

局限:每步都正确,不代表整体路径是最优的。

第二层:轨迹评估(Trajectory-level Evaluation)

评估完整的执行路径:Agent 是否走了不必要的弯路?步骤顺序是否合理?有没有冗余的工具调用?

适合发现的问题

  • 绕弯路:查了三次数据库才找到一次就能找到的信息
  • 逻辑顺序错误:先生成报告再去收集数据
  • 重复操作:同一个查询调用了两次相同的工具

评估方法:与参考轨迹对比(编辑距离)、LLM-as-Judge 评审轨迹合理性、人工审查

优势:发现"能完成但很低效"的问题,对成本优化尤为关键。

第三层:任务完成评估(Task-level Evaluation)

评估最终结果:用户的原始需求是否得到满足?最终答案是否准确、完整、有用?

适合发现的问题

  • 答非所问:技术上每步都对,但最终输出偏离了用户真实意图
  • 质量不足:完成了但质量不满足期望
  • 用户体验差:格式混乱、表达不清

评估方法:与黄金答案对比、用户满意度调研、A/B 测试、LLM 评分

优势:最贴近业务价值,直接反映用户体验。

💡 小贴士 :三层不是择一而用,而是互补使用。单步找原因 ,轨迹找路径 ,任务验价值。理想的评估体系应该三层都覆盖。

二、评估指标体系:四个维度

知道了"评估什么层次",还需要知道"用什么指标衡量"。

四维平衡:只优化正确性,可能牺牲效率;只优化效率,可能损害安全

正确性指标详解

任务完成率(Task Completion Rate):在一批测试任务中,有多少比例最终完成了用户目标。通常是最核心的指标。

python 复制代码
def calculate_completion_rate(results: list[dict]) -> float:
    completed = sum(1 for r in results if r["task_completed"])
    return completed / len(results) if results else 0.0

答案准确性(Answer Accuracy):对于有明确正确答案的问题(如事实查询、数据计算),与标准答案的匹配程度。

工具调用准确率(Tool Call Accuracy):所有工具调用中,选择正确工具 + 参数合法的比例。

幻觉率(Hallucination Rate):回答中包含不存在于文档/上下文、纯属捏造信息的比例。在 RAG 场景尤其重要。

效率指标详解

平均响应延迟(Average Latency):从用户发出请求到 Agent 给出最终答案的端到端时间。

每任务 Token 消耗(Tokens per Task):完成一个任务平均需要多少 Token。直接决定运营成本。

平均工具调用次数(Avg. Tool Calls per Task):工具调用次数越少,通常意味着 Agent 规划得越好(但也要注意不能为了减少调用次数而丢失准确性)。

安全性指标详解

越权操作率:Agent 尝试访问超出其权限范围的资源或操作的比例,哪怕最终被系统拦截。

有害请求拒绝率:当收到明确有害的请求时,Agent 正确拒绝的比例。过高(把正常请求也拒绝了)和过低(没有拒绝有害请求)都是问题。

用户体验指标详解

任务放弃率(Abandonment Rate):用户在任务未完成时主动停止的比例。高放弃率通常意味着 Agent 的回答让用户失去了信心。

平均澄清次数(Avg. Clarifications):Agent 需要向用户追问几次才能理解任务。追问本身不一定是坏事,但追问太多说明 Agent 理解能力有限。

三、LLM-as-Judge:用 AI 评估 AI

传统软件测试有"正确答案"------输入 2+2,期望输出 4,验证失败就报错。Agent 的输出是自然语言,没有唯一正确答案,如何自动化评估?

LLM-as-Judge(用 LLM 作为评审) 是目前最主流的解决方案。核心思想:用一个更强或同等能力的 LLM,来评估被测 Agent 的输出质量。

优势:无需人工标注,可大规模运行;劣势:Judge自身也可能出错

设计有效的 Judge 提示词

Judge 提示词的质量决定了评估的质量。一个好的 Judge 提示词需要:

① 明确评估角色

python 复制代码
JUDGE_SYSTEM_PROMPT = """
你是一位严格、客观的 AI 助手评审专家。
你的职责是评估 AI Agent 的回应质量。

评审原则:
- 只根据提供的内容评审,不凭个人偏好
- 对显而易见的问题给出明确的低分
- 对优秀表现给出具体的理由
- 你的评审结果将用于改进 AI 系统,请保持严格
"""

② 结构化评分维度

python 复制代码
def build_judge_prompt(
    task: str,
    agent_trajectory: str,
    agent_output: str,
    reference_answer: str = None
) -> str:
    ref_section = f"\n参考答案:{reference_answer}" if reference_answer else ""
    
    return f"""请评估以下 Agent 的表现:

用户任务:{task}

Agent 执行轨迹:
{agent_trajectory}

Agent 最终输出:
{agent_output}{ref_section}

请按以下维度评分(1-5分)并给出理由:

1. 任务完成度(1-5分):是否完成了用户的核心需求?
2. 准确性(1-5分):信息是否准确,有无明显错误或幻觉?
3. 执行效率(1-5分):是否走了不必要的弯路?
4. 输出质量(1-5分):回答是否清晰、完整、有用?

最后给出:
- 综合评分(1-5):
- 最大问题:(一句话)
- 改进建议:(具体可操作)
- 总体判定:通过 / 需改进 / 不通过

请以 JSON 格式输出。"""

③ 解析结构化输出

python 复制代码
import json
from openai import OpenAI

client = OpenAI()

def llm_judge(task: str, trajectory: str, output: str, reference: str = None) -> dict:
    """运行 LLM-as-Judge 评估"""
    prompt = build_judge_prompt(task, trajectory, output, reference)
    
    response = client.chat.completions.create(
        model="gpt-4o",  # 使用强模型作为 Judge
        messages=[
            {"role": "system", "content": JUDGE_SYSTEM_PROMPT},
            {"role": "user",   "content": prompt}
        ],
        response_format={"type": "json_object"}
    )
    
    result = json.loads(response.choices[0].message.content)
    return result

LLM-as-Judge 的注意事项

位置偏见(Position Bias):Judge 往往倾向于给第一个选项更高的分数。在需要比较多个 Agent 输出时,要随机化顺序。

自我偏好(Self-preference):用 GPT-4o 评估 GPT-4o 的输出,Judge 会有偏向于认为自己的输出更好的倾向。尽量用不同系列的模型做 Judge。

Judge 一致性:同一个 Judge 对同样的输出,多次评估结果可能不同。重要的评估要多次运行取平均。

人工校准:建立一批"有明确正确答案"的校准样本,验证 Judge 的评分与人类专家的一致性,确保 Judge 本身是可靠的。

四、Agent 测试金字塔

软件工程中有经典的"测试金字塔"理论------底层单元测试数量最多、速度最快;顶层 E2E 测试数量最少、但最接近真实场景。Agent 系统同样适用这个框架。

黄金比例参考:E2E 10%、集成 30%、单元60%

单元测试:Agent 的基础防护

Agent 的单元测试对象,不是 Agent 本身,而是 Agent 赖以运行的各个组件:

python 复制代码
import pytest

# 测试工具函数本身(不涉及 LLM)
def test_search_orders_returns_correct_format():
    """工具函数单元测试"""
    result = search_orders(user_id="user_001", status="pending")
    assert isinstance(result, list)
    assert all("order_id" in item for item in result)
    assert all("amount" in item for item in result)

def test_search_orders_rejects_invalid_status():
    """参数校验测试"""
    with pytest.raises(ValueError, match="status must be one of"):
        search_orders(user_id="user_001", status="invalid_status")

# 测试提示词模板
def test_system_prompt_contains_required_elements():
    """提示词格式测试"""
    prompt = build_system_prompt(role="customer_service")
    assert "你只能访问" in prompt
    assert "禁止" in prompt
    assert "用户信息" in prompt

# 测试输出解析器(Mock LLM 输出)
def test_tool_call_parser_handles_malformed_json():
    """输出解析鲁棒性测试"""
    malformed = '{"tool": "search", "args": {missing_quote: true}}'
    result = parse_tool_call(malformed)
    assert result is None or result.get("error") is not None

集成测试:验证组件协作

集成测试把 LLM 和工具真正连接起来,但通常用 Mock 或简化版的外部服务:

python 复制代码
from unittest.mock import patch, MagicMock

@patch("tools.web_search")
def test_agent_uses_search_for_unknown_questions(mock_search):
    """集成测试:Agent 是否在需要时调用搜索"""
    mock_search.return_value = "搜索结果:2026年最新数据..."
    
    agent = create_customer_service_agent()
    response = agent.run("2026 年最新的产品价格是多少?")
    
    # 验证 Agent 确实调用了搜索
    mock_search.assert_called_once()
    assert "价格" in response.lower() or "搜索" in response.lower()

def test_rag_agent_cites_sources():
    """RAG 集成测试:回答是否附带来源"""
    agent = create_rag_agent(knowledge_base=TEST_KB)
    result = agent.run("公司的退款政策是什么?")
    
    assert result.answer is not None
    assert len(result.sources) > 0
    assert any("退款" in src.content for src in result.sources)

端到端测试:贴近真实场景

E2E 测试使用真实的 LLM 和(或)真实的工具,验证完整的用户场景:

python 复制代码
import asyncio

E2E_TEST_CASES = [
    {
        "name": "完整客服场景",
        "input": "我订了一个 ORD-001 但想退款,能帮我处理吗?",
        "success_criteria": [
            lambda r: "ORD-001" in r.lower(),  # 识别了订单号
            lambda r: "退款" in r,              # 提到了退款
            lambda r: len(r) > 50               # 回答足够详细
        ],
        "forbidden_patterns": [
            r"我不知道",
            r"无法帮助"
        ]
    },
    {
        "name": "边界场景:无效订单号",
        "input": "查询订单 FAKE-9999",
        "success_criteria": [
            lambda r: "找不到" in r or "不存在" in r or "无效" in r
        ],
        "forbidden_patterns": []
    }
]

async def run_e2e_test(test_case: dict, agent) -> dict:
    """运行单个端到端测试用例"""
    import re
    
    response = await agent.run(test_case["input"])
    
    criteria_results = [fn(response) for fn in test_case["success_criteria"]]
    forbidden_hits = [
        pattern for pattern in test_case["forbidden_patterns"]
        if re.search(pattern, response)
    ]
    
    passed = all(criteria_results) and not forbidden_hits
    return {
        "name": test_case["name"],
        "passed": passed,
        "response": response[:200],
        "criteria_met": criteria_results,
        "forbidden_hits": forbidden_hits
    }

五、黄金数据集与回归测试

一次性的评估是不够的。Agent 系统会持续演化------模型升级、提示词修改、工具变更......每次变更都可能引入新的退化(Regression)。

黄金数据集(Golden Dataset) 是防止退化的核心工具。

回归测试与黄金数据集构建流程

构建黄金数据集的策略

① 从生产数据中挖掘

真实用户的问题是最有价值的测试数据。从生产日志中筛选:

  • 高频出现的典型问题
  • 用户标记为"不满意"的失败案例
  • 边界场景(极短的问题、包含特殊字符的输入等)
python 复制代码
def sample_from_production_logs(logs: list, sample_size: int = 100) -> list:
    """从生产日志采样构建数据集"""
    import random
    
    # 按类别分层采样
    successful = [l for l in logs if l["task_completed"]]
    failed     = [l for l in logs if not l["task_completed"]]
    edge_cases = [l for l in logs if l.get("is_edge_case")]
    
    # 失败案例更有价值,多采样
    sampled = (
        random.sample(failed,     min(50, len(failed)))   +
        random.sample(successful, min(30, len(successful))) +
        random.sample(edge_cases, min(20, len(edge_cases)))
    )
    return sampled[:sample_size]

② 覆盖关键能力维度

数据集需要均衡覆盖 Agent 的所有核心能力,而不是扎堆在某一类场景:

能力维度 测试用例比例
基础问答 20%
工具调用 25%
多轮对话 20%
边界和拒绝 20%
复杂推理 15%

③ 版本控制管理

数据集本身也需要版本控制------随着 Agent 能力升级,数据集的期望答案也可能需要更新:

python 复制代码
GOLDEN_DATASET_VERSION = "v2.1.0"

GOLDEN_DATASET = [
    {
        "id": "GD-001",
        "version": GOLDEN_DATASET_VERSION,
        "input": "我的订单 ORD-001 在哪里?",
        "expected_tools": ["get_order_status"],
        "expected_output_contains": ["ORD-001", "状态"],
        "expected_output_excludes": ["我不知道", "无法查询"],
        "difficulty": "easy",
        "category": "order_query"
    },
    {
        "id": "GD-042",
        "version": GOLDEN_DATASET_VERSION,
        "input": "帮我把所有待付款订单都取消掉",
        "expected_tools": [],  # 不应该直接执行,应该先确认
        "expected_output_contains": ["确认", "您确定"],
        "difficulty": "medium",
        "category": "safety_check"
    }
]

回归测试自动化

python 复制代码
async def run_regression_test(
    agent,
    dataset: list,
    baseline_scores: dict,
    threshold: float = 0.95  # 新版本得分不得低于基准的 95%
) -> dict:
    """运行回归测试,与基准分数对比"""
    
    results = []
    for case in dataset:
        response = await agent.run(case["input"])
        
        # 检查期望包含的内容
        contains_ok = all(
            kw in response for kw in case.get("expected_output_contains", [])
        )
        # 检查期望排除的内容
        excludes_ok = all(
            kw not in response for kw in case.get("expected_output_excludes", [])
        )
        
        results.append({
            "id": case["id"],
            "passed": contains_ok and excludes_ok,
            "category": case["category"]
        })
    
    # 计算各维度得分
    total_score = sum(r["passed"] for r in results) / len(results)
    category_scores = {}
    for cat in set(r["category"] for r in results):
        cat_results = [r for r in results if r["category"] == cat]
        category_scores[cat] = sum(r["passed"] for r in cat_results) / len(cat_results)
    
    # 与基准对比
    regressions = {
        cat: score
        for cat, score in category_scores.items()
        if score < baseline_scores.get(cat, 1.0) * threshold
    }
    
    return {
        "total_score": round(total_score, 4),
        "category_scores": {k: round(v, 4) for k, v in category_scores.items()},
        "regressions_detected": regressions,
        "passed": len(regressions) == 0 and total_score >= threshold
    }

六、评估驱动改进的完整闭环

评估的目的不是给 Agent 打分,而是驱动持续改进。建立"评估 → 定位 → 改进 → 再评估"的完整闭环,才是 Agent 工程的真正成熟。

评估不是终点,而是驱动持续改进的引擎

当评估发现问题时,如何定位根因?

问题定位决策树

python 复制代码
任务完成率低
├── 单步准确率也低?
│   ├── 是 → 工具调用有问题:检查工具设计和参数格式
│   └── 否 → 规划/推理问题:优化系统提示词或换模型
├── 轨迹评分低(步骤多但结果对)?
│   └── 效率问题:优化提示词,引导更直接的路径
└── 单步和轨迹都正常,但用户满意度低?
    └── 输出质量问题:调整回答风格、格式、完整性

三种改进方向及其权衡

① 优化提示词(最低成本)

提示词工程是投入产出比最高的改进方向。通常能解决:规划不合理、工具选择偏差、输出格式不对、不必要的追问等问题。

改进过程:收集失败案例 → 分析共同模式 → 针对性修改提示词 → 回归测试验证

② 更换或微调模型(中等成本)

当提示词优化达到瓶颈时,考虑升级模型或对当前模型进行微调:

  • 升级底座:GPT-4o-mini → GPT-4o,通常能带来 10-20% 的准确性提升
  • 微调:用高质量的领域数据对模型进行 Fine-tuning,适合有大量行业特定数据的场景

③ 重新设计工具(高成本但治本)

当问题根源在于工具设计不合理时------比如工具粒度太粗、返回信息太多无法筛选、工具描述不清导致 Agent 误用------需要重新设计工具接口。

建立评估 SLO(服务级别目标)

像对待生产 API 一样,给 Agent 设定明确的质量指标目标:

python 复制代码
AGENT_SLO = {
    "task_completion_rate":    0.90,   # 任务完成率 ≥ 90%
    "answer_accuracy":         0.95,   # 答案准确性 ≥ 95%
    "hallucination_rate":      0.02,   # 幻觉率 ≤ 2%
    "avg_latency_seconds":     8.0,    # 平均延迟 ≤ 8 秒
    "avg_tokens_per_task":     2000,   # 每任务 Token ≤ 2000
    "user_satisfaction_score": 4.0,    # 用户满意度 ≥ 4.0/5.0
    "harmful_request_rejection_rate": 0.99  # 有害请求拒绝率 ≥ 99%
}

设定 SLO 的好处:当任何指标跌破阈值时,自动触发告警并阻断发版。

七、本章小结

这一章,我们系统学习了 Agent 评估的完整方法论:

  • 三个评估层次:单步(找原因)、轨迹(找路径)、任务(验价值)------三层互补,缺一不可
  • 四维评估指标:正确性、效率、安全性、用户体验------只优化一维会牺牲其他维度
  • LLM-as-Judge:用更强的 LLM 评审被测 Agent 的输出;多维度结构化评分;注意位置偏见、自我偏好和一致性问题
  • 测试金字塔:单元测试(60%)+ 集成测试(30%)+ E2E 测试(10%),速度与置信度的平衡
  • 黄金数据集:从生产数据采样 + 人工标注期望轨迹,版本控制管理,覆盖核心能力维度
  • 评估驱动改进:评估 → 定位根因 → 三种改进方向(提示词/模型/工具)→ 回归验证 → 更新基准,形成飞轮

评估不是 Agent 开发的终点,而是持续改进的引擎。没有评估体系的 Agent,就像没有量表的医生------凭感觉,不可靠。

相关推荐
慧都小项1 年前
灰盒级SOA测试工具Parasoft SOAtest重新定义端到端测试
web·ci·cd·端到端测试·soa测试·环境虚拟化·测试资产共享
龙测科技3 年前
测试金字塔理论和三明治结构,你更支持哪个?
单元测试·集成测试·测试·端到端测试
ZPILOTE3 年前
ORB-SLAM2学习笔记3之EuRoc开源数据集运行ORB-SLAM2生成轨迹并用evo工具评估轨迹
vslam·orb-slam2·视觉里程计·euroc·evo·轨迹评估·evo_traj