评估 Agent 表现:比你想象的要难十倍

Agent 定在明早九点上线,老李把腿翘在会议桌上,保温杯搁在一旁,看着小王在键盘上敲敲打打。

“我觉得差不多了,”老李语气轻松,“这两天我随手试了十几个问题,回答都挺像那么回事。明天直接上吧。”

小王头也没抬:“老李,你知道‘随手试了十几个问题’这句话里有多少坑吗?”

“能有什么坑?我问他‘今天的服务器负载怎么样’,他查了监控API,告诉我 CPU 75%,内存 60%,这不挺靠谱?”

“那是因为你只看了结果。你有没有看过他是怎么查的?他用的是哪个工具?参数传对了没?中间有没有走过弯路?有没有调了一个不该调的有写权限的API?如果只看最终结果,你永远不知道他是在走钢丝还是在跳舞。”

老李把腿放下来,保温杯端到嘴边又停住:“那你的意思是,光看着行还不够?”

“差太远了。Agent 的评测,比 LLM 难十倍。LLM 你只要看回答对不对。Agent 你不仅要看结果,还要看过程、看效率、看安全性——相当于你不仅要看期末考试分数,还要看他是自己做的还是抄的,中间有没有作弊,做完花了多长时间。”


三个维度:结果、过程、效率

小王走到白板前,画了三条线。

“结果质量”——这是最直观的,任务最终完成了吗?报告写了没?数据查对了没?但这个维度会骗人。就像刚才那个例子,Agent 可能确实拿到了 CPU 数据,但如果他调用的是一个不该用的写权限 API,只是碰巧参数没写坏,那这次‘成功’就是一颗定时炸弹。

“过程正确性”——Agent 的思考轨迹(Thought)是否合理?选择的工具是否恰当?工具参数是否正确?有没有跳过必要步骤?比如你让他查服务器负载,他却去调了用户数据库,虽然最终也拿到了一个数字,但这条路本身就是错的。

“效率”——用了多少步?花了多少 Token?有没有反复调同一个工具做无用功?如果一个任务平均 3 步就能完成,你的 Agent 却跑了 12 步,说明他的规划能力或工具使用策略有问题,这在批量处理时会直接反映到成本和延迟上。

老李若有所思:“所以评测不是出一道题看答案,而是把 Agent 的‘脑子’全程录像,然后逐帧分析?”

“精准。这叫轨迹评测。你要保存每次运行的完整日志——每一步的 Thought、Action、Observation——然后逐条分析。这比端到端评测麻烦得多,但能帮你定位问题到底出在推理层还是工具层还是执行层。”

图:Agent 评测的两个层次——只看结果 vs 细看过程


一个评测脚本,发现 30% 的隐藏问题

“我给你看个实际的。”小王打开终端,调出一段评测脚本。他前一周偷偷准备了 100 个测试用例,覆盖了查询、计算、预约、报告生成四类任务,每道题都标注了期望的工具选择和参数范围。

python
# Agent 评测示例:检查工具调用是否正确
def evaluate_tool_usage(test_cases, agent):
    results = []
    for case in test_cases:
        # 运行 Agent 并记录完整轨迹
        trajectory = agent.run_with_trace(case["instruction"])
        
        # 检查是否使用了预期的工具
        expected_tool = case["expected_tool"]
        actual_tools = [step["action"] for step in trajectory if step["type"] == "action"]
        
        tool_correct = expected_tool in [a["name"] for a in actual_tools]
        
        # 检查参数是否正确(简化:检查关键参数是否存在)
        param_correct = all(
            p in str(actual_tools) for p in case.get("expected_params", [])
        )
        
        # 检查是否有多余的危险操作
        dangerous_actions = [a for a in actual_tools if a["name"] in case.get("forbidden_tools", [])]
        
        results.append({
            "instruction": case["instruction"],
            "tool_correct": tool_correct,
            "param_correct": param_correct,
            "dangerous": len(dangerous_actions) > 0,
            "steps": len(actual_tools)
        })
    
    # 统计
    accuracy = sum(r["tool_correct"] and r["param_correct"] for r in results) / len(results)
    danger_rate = sum(r["dangerous"] for r in results) / len(results)
    avg_steps = sum(r["steps"] for r in results) / len(results)
    
    return {"accuracy": accuracy, "danger_rate": danger_rate, "avg_steps": avg_steps}

小王把这个脚本跑了一遍,结果投射在屏幕上:工具选择正确率只有 72%,有 8% 的测试用例 Agent 调用了不该使用的工具,平均步数 5.3 而期望是 3.1。

老李的脸僵住了:“也就是说,我看着挺聪明的 Agent,其实每四次任务就有一次选错了工具?”

“而且你根本没发现,因为选错工具之后它自己‘圆’回来了,最终输出看着合理。这就是只看结果的盲区。”


评测数据集:别拿“随手试”当标准

“这 100 道题你哪来的?”老李问。

“一部分来自 AgentBench 和 WebArena 这些公开的 Agent 评测基准,一部分是我根据咱们内部业务场景手工设计的。”小王打开一个表格,“公开基准给你提供了一个客观的标尺,知道你的 Agent 在业界大概什么水平。但业务特定的场景,必须自己设计——比如‘查询工单系统中老李今天处理的工单数’,这种题公开数据集里不可能有。”

他补充道:“设计评测用例有个黄金法则——覆盖边界和异常。不要只出‘今天的天气’这种简单查询,要出‘如果 API 返回超时怎么办’、‘如果用户同时要求查两个冲突的数据怎么办’、‘如果工具返回空结果怎么办’。Agent 的鲁棒性,就是在这些边界用例上体现的。”

老李沉默了一会儿,把保温杯里的枸杞水喝完,然后说:“你刚才说那个安全违规检测,具体怎么做的?”


持续评测:每次改 Prompt 都是一次冒险

“安全违规检测就是检查 Agent 是否调用了不该用的工具,或者是否以不该用的参数调用了工具。”小王打开另一段代码,“比如我们禁止 Agent 直接执行数据库写操作。评测脚本里有一个黑名单工具列表,一旦轨迹里出现,直接标红。”

python
# 安全检测:扫描轨迹中的违规操作
FORBIDDEN_ACTIONS = ["delete_record", "execute_sql_write", "grant_permission"]

def check_safety(trajectory):
    violations = []
    for step in trajectory:
        if step["type"] == "action":
            if step["action"]["name"] in FORBIDDEN_ACTIONS:
                violations.append(step)
    return violations

“但这只是事后检测。”老李皱眉,“难道不能事前拦截?”

“可以,那是护栏系统做的事。但护栏可能有漏洞,评测脚本是最后一道验证——确保护栏真的起作用了。万一你改了 Prompt 导致护栏被绕过,评测会立刻发现。”

小王接着强调:“更重要的是持续评测。你不能上线前测一次就以为永远没问题。每次你调整了系统提示词、换了模型版本、加了新工具,Agent 的行为都会微妙地变化。必须把评测脚本接入 CI 流水线——每次变更自动跑一遍完整的测试集,指标低于阈值就阻断部署。”

老李靠在椅背上,沉默了好一会儿。然后他站起来,把白板上那三条线描了又描。

“行。明早的上线延期两天。你先把这 100 个用例跑成绿灯,工具正确率提到 90% 以上,违规率降到零。评测脚本接进 Jenkins。”

他走到门口,转过身来,语气明显缓和:“那什么……你刚才说的 AgentBench,它在评测 Agent 的时候是只给最终答案打分,还是也检查过程?如果我想对比咱们的 Agent 和开源方案,该怎么跑?明天下午你给我演示一下。”

小王咧嘴笑了。老李端着保温杯走出会议室,枸杞在杯里晃晃悠悠,像那些刚被评测脚本揭开的隐藏问题——不再被表面的“看着挺好”所掩盖。

代码生成 Agent:你的新"初级开发工程师"?
多 Agent 系统:当一个小弟不够用,你需要一个团队