AI Agent 开发(27):评测与可观测

QuibblerAgentQuibblerAgent 2026-10-25 约 20 分钟 3 次阅读

模块五的收官篇看过了前沿形态:Deep Research 一跑几十分钟,Computer Use 直接上手操作浏览器。形态越炫,一个朴素的追问越响——它凭什么进生产?demo 的标准是"当着你的面成功一次",生产的标准是"没人盯着也天天对"。从 demo 到生产,中间隔着三道质检:调试靠 trace,质量靠 evals,成本靠监控。

本篇是《AI Agent 开发》系列第 27 篇,第六模块"生产化"开篇,工具主线仍是第 2 篇开通过的 LangSmith(LangChain 官方 SaaS,2026-10 上线了新的自助定价),代码基于 langsmith SDK 与 openevals、agentevals 两个官方评估包(2026-10 基线)。全文按"为什么观测 → 深读 trace → 数据集与回归 → 评估器选型 → 判官的坑 → CI 门禁 → 成本监控"推进,依赖一条命令装齐:uv add langsmith openevals agentevals。

1、Agent 为何更依赖观测

传统软件是确定性的:同样的输入走同样的分支,单测覆盖住路径,bug 就能复现、定位、回归。Agent 破坏了这个前提——模型输出是概率性的,同一个问题问三遍可能得到三种工具选择。更麻烦的是三个变量随时在动:模型供应商悄悄更新权重、你改了一行提示词、某个工具的返回格式变了,任何一项都足以让上周稳定的 Agent 这周开始抽风。

所以 Agent 的"测试"要换思路:单次执行的输赢说明不了什么,要看统计意义上的质量;而统计的前提,是每一次执行都留下完整现场。观测由此分成三层:

层 回答的问题 手段
trace 这一次执行到底发生了什么 LangSmith 追踪树
数据集统计 改动之后质量涨了还是跌了 evals 回归实验
成本监控 一次会话、一天烧掉多少钱 usage 与成本聚合

trace 解释个案,evals 证明趋势,成本决定这个 Agent 能不能开着跑。 三层缺一不可:没有 trace,evals 分数下跌了你不知道为什么;没有 evals,你只能靠用户投诉发现质量滑坡;没有成本监控,一个失控循环一夜能烧掉一个月预算。

不想把数据送 SaaS 的团队,开源侧有 Langfuse 与 Arize Phoenix 两个成熟的自托管替代,本文的概念与流程全部平移,下文以 LangSmith 为例。

2、深读 trace 树形结构

第 2 篇配好 LANGSMITH_TRACING=true 后,每次执行自动上报成一条 trace。会开开关不等于会读现场,先讲树形结构的读法。LangGraph Agent 的 trace 分四层:最外层是图 run(一次完整执行的根节点),往下是节点 run(agent 节点、tools 节点),节点里挂着模型 run 与工具 run,用了子图或多 Agent 还会再嵌套一层。每层都带输入输出、耗时、token 消耗与错误信息,点的层级越深,细节越多。

定位"哪一步出错",推荐一套固定流程:先看根节点的最终输出,把错误归类,再按类下钻:

症状 下钻位置 常见根因
没调工具,答案靠编 agent 节点里模型 run 的输入 prompt 被长对话稀释、工具描述含糊
调错工具或参数错 模型 run 的 tool_calls docstring 没写清边界
工具调对了答案还错 ToolMessage 与下一轮输入 工具返回异常或上下文被截断

这套流程的本质,是把"Agent 出错了"翻译成"某一层 run 的哪个字段不对"。翻译完成,修复方向自然浮出。

trace 除了看,还能打标。给坏 trace 打上标记,就是后面数据集的进货渠道,SDK 一行搞定:

from langsmith import Client

client = Client()
# run_id 从 trace 详情页的 URL 里复制
client.create_feedback(
    run_id="0cf9d8a1-7f2b-4b1e-9c3a-5e8f1a2b3c4d",
    key="human-review",
    score=0,  # 0 差评 / 1 好评
    comment="检索回来的文档和问题无关,答案疑似编造",
)

打完标的 trace 在 UI 里按 feedback 筛选,攒下的差评现场就是下一节评测集的第一批原料。量大了可以用 Annotation Queue 把待标注的 trace 排队分给团队成员,标注流程就产品化了。

3、数据集与实验回归

单条 trace 是个案。要知道一次改动是改良还是劣化,得把真实 case 固化成数据集,改动前后各跑一遍对比分数——这套流程就是 evals,本质是给 Agent 写回归测试。数据集由若干 example 组成,每条 example 是两个 dict:inputs 是给 Agent 的输入,outputs 是参考答案(reference outputs),供评估器对比用。

用第 2 节攒下的坏 case 建集,核心两步:

from langsmith import Client

client = Client()
dataset = client.create_dataset(dataset_name="客服 Agent 回归集")

client.create_examples(
    dataset_id=dataset.id,
    examples=[
        {
            "inputs": {"question": "我的订单 8823 到哪了"},
            "outputs": {"tools": ["get_order_status"], "answer": "报出物流状态"},
        },
        {
            "inputs": {"question": "你好,在吗"},
            "outputs": {"tools": [], "answer": "直接寒暄,不调任何工具"},
        },
    ],
)

字段名完全自定义:这里的 tools 写期望的工具调用序列,answer 写参考答案,评估器按同名字段取值。批量写法需要 langsmith 0.3.13 以上,装最新版即可。

数据集就位,写一个目标函数把被测 Agent 包进去,交给 evaluate 跑实验:

def agent_target(inputs: dict) -> dict:
    result = agent.invoke({"messages": [("user", inputs["question"])]})
    called = [
        c["name"]
        for m in result["messages"]
        if getattr(m, "tool_calls", None)
        for c in m.tool_calls
    ]
    return {"answer": result["messages"][-1].content, "tools": called}

experiment = client.evaluate(
    agent_target,                             # 被测系统:进 inputs,出 outputs
    data="客服 Agent 回归集",                    # 数据集名或 id
    evaluators=[tool_match, answer_quality],  # 评估器,下一节展开
    experiment_prefix="gpt-5-mini",
    max_concurrency=4,                        # 并行跑例,加速回归
)

agent_target 里那段推导把轨迹里实际调过的工具名抽出来,与参考答案同字段对齐——评估比的是结构化字段,不是整段自由文本,字段对不齐,评估器再准也没用。跑完 LangSmith 生成一条 experiment 记录,改一版提示词再跑一条,UI 里两条实验并排,分数与成本全部可视。旧教程里的 run_on_dataset 是这个方法的历史名字,新代码直接用 evaluate,参数细节见 LangSmith 评估指南。

4、评估器选型

评估器决定"什么算对",是 evals 的核心。三类按成本与可靠度排开:确定性判断(精确匹配、包含判断)便宜且完全可复现;LLM 判官灵活但有方差;轨迹评估评判工具调用序列,是 Agent 特有的维度。

4.1、精确与包含判断

评估器就是普通函数,签名固定收三个 dict,返回布尔值:

def tool_match(inputs: dict, outputs: dict, reference_outputs: dict) -> bool:
    return outputs["tools"] == reference_outputs["tools"]

def answer_contains(inputs: dict, outputs: dict, reference_outputs: dict) -> bool:
    return reference_outputs["answer"] in outputs["answer"]

inputs 是这条 case 的输入,outputs 是 Agent 实际输出,reference_outputs 是数据集里的参考答案。这两个评估器零 token 成本、结果完全确定——只要能写成明确规则(工具白名单、答案必含某关键词),就优先用它。

4.2、LLM 判官

答案开放、没法写规则时,请一个模型当裁判。openevals 仓库提供工厂函数:

from openevals.llm import create_llm_as_judge
from openevals.prompts import CORRECTNESS_PROMPT

answer_quality = create_llm_as_judge(
    prompt=CORRECTNESS_PROMPT,   # 内置评分标准,可换自定义 rubric
    feedback_key="correctness",  # 实验结果里的分数列名
    model="openai:gpt-5-mini",   # 判官模型
)

工厂返回的评估器与上一节的自定义函数同构,直接塞进 evaluators 列表即可。判官拿到的同样是 inputs、outputs、reference_outputs 三段,按 prompt 里的标准打分。判官模型选便宜的就行,但有一条禁忌:别用被测模型自评,原因下一节讲。

4.3、轨迹评估

最终答案对了,不代表过程对:Agent 可能绕了十步冤枉路,也可能调用了不该碰的写工具。这类问题只有轨迹评估抓得住——被评对象不是答案,是整条消息轨迹(含 tool_calls)。agentevals 仓库提供判官版与确定性版两条路,先看判官版:

from agentevals.trajectory.llm import (
    create_trajectory_llm_as_judge,
    TRAJECTORY_ACCURACY_PROMPT,
)

trajectory_judge = create_trajectory_llm_as_judge(
    prompt=TRAJECTORY_ACCURACY_PROMPT,
    model="openai:gpt-5-mini",
)

# outputs 传实际消息轨迹,reference_outputs 传期望轨迹(可省略)
verdict = trajectory_judge(outputs=messages, reference_outputs=expected)

判官版按"工具用得对不对、顺序合不合理"给轨迹打分,不带参考轨迹也能判"合理但不完美"这类相对结论。要零成本就换 create_trajectory_match_evaluator,四种模式 strict、unordered、subset、superset 确定性比对工具调用序列:subset 要求实际调用是参考序列的子集,少调可以、名单外的工具一个不许碰;superset 相反,参考工具必须全调到、多调不究。模式细节见轨迹评估指南。

三类对比一张表收口:

评估器 token 成本 可复现性 适用场景
精确/包含 零 完全确定 有白名单或标准答案
LLM 判官 每例一次调用 有方差 开放式回答质量
轨迹评估 零或一次调用 分模式 过程对不对、路绕不绕

5、LLM 判官的偏差与缓解

LLM 判官把打分外包给了模型,模型自带的偏差也一起进场。三个最常见:

  • 位置偏差:比较两个候选答案时,偏向先出现的那个
  • 自我偏好:判官偏爱与自己风格一致的输出,同模型自评显著偏高
  • 评分漂移:同一个答案今天 4 分明天 3 分,温度与模型版本更新都会移动标尺

判官不是免费的午餐:它把"评估输出"的问题,换成了"评估判官"的问题。

对应的缓解手段,按性价比排:

  • 换位打分:A/B 两个顺序各判一次,结论矛盾就判平局,位置偏差即被中和
  • 锚定评分标准:rubric 里给最低分与最高分各配一个具体示例,分数贴着锚点走
  • 固定判官:锁模型版本、temperature=0,判官不随被测系统升级
  • 分数粗档化:五分制漂移明显,改 0/1 两档或 0/0.5/1 三档

还有终极一招:定期抽 20 条人工标注,算判官与人的一致率,一致率跌破阈值就修 rubric 或换判官。判官这把尺子,本身也需要校准——不然你就是拿一支没人校过的尺子在量所有改动。

6、evals 进 CI 门禁

回归集建好、评估器选定,最后一步是把 evals 挂进 CI:提示词或模型配置的改动提 PR,流水线自动跑回归,分数跌破阈值就挡合并。质量保障从"上线后救火"前移成"合并前把关"。

LangSmith 提供了 pytest 集成:@pytest.mark.langsmith 把测试执行自动上报成 trace,t.log_outputs 把断言现场挂上去。

import pytest

from agent import agent  # 第 2 篇 create_agent 的产物
from langsmith.testing import t

CASES = [
    ("我的订单 8823 到哪了", ["get_order_status"]),
    ("你好,在吗", []),
]

@pytest.mark.langsmith
@pytest.mark.parametrize("question,expected_tools", CASES)
def test_tool_selection(question, expected_tools):
    result = agent.invoke({"messages": [("user", question)]})
    called = [
        c["name"] for m in result["messages"]
        if getattr(m, "tool_calls", None) for c in m.tool_calls
    ]
    t.log_outputs({"answer": result["messages"][-1].content, "tools": called})
    assert called == expected_tools

断言就是门禁,但阈值要分类设:确定性判断(如工具选择)要求 100% 通过,零容忍;LLM 判官分数有方差,设 0.85 这类下限留余量;轨迹判官建议先只记录不阻断,观察两周稳定后再收紧。测试失败时,t.log_outputs 挂的结果在 LangSmith 里点开就是完整现场,不用去服务器翻日志。

7、成本监控

第三道质检管钱。Agent 的成本结构天然带放大器:每次工具回传都把全量历史重发模型,轮次一多,token 消耗超线性增长——第 2 篇提过的失控循环账单,就是这台放大器失控的样子。

监控闭环至少三个口径。单 trace 成本:模型 run 上记着 usage,输入输出 token 各多少,LangSmith 按模型单价折算成成本,点开 trace 就能看到这次执行花了多少钱,给它设上限告警防失控。日均与环比:Dashboard 按天、按模型聚合 token 与美元,看趋势比看绝对值重要。单位任务成本:每千次请求的美元数,是与业务规模挂钩的核心指标,QPS 翻倍它不该跟着翻倍。

监控的终局是给优化提供证据。最常见的降本动作是模型路由:主干任务用小模型,难题升级到大模型。这个决策别拍脑袋,跑实验拿数据——同一数据集、两版模型各跑一次 evaluate,metadata 里写上模型名(UI 会填进实验对比列),分数与成本并排出现。小模型分数不掉、成本降七成,这才是换的依据;分数掉两个点省三成成本,多半是亏的。evals 不只守质量,也是每一笔降本决策的裁判。

8、总结

三道质检到此闭环:trace 把"Agent 出错了"翻译成"某一层 run 的哪个字段不对";evals 用真实 case 的回归实验证明每次改动的方向;成本监控守住单 trace、日均、单位任务三条线。从这一篇起,改任何提示词、换任何模型,都应该有"跑一遍回归再合并"的肌肉记忆。

留一个练习:给第 17 篇的 Agentic RAG 建一个 10 条 case 的评测集——5 条该检索(含一条需要查询改写的)、3 条不该检索的闲聊与常识题、2 条多跳问题;outputs 同时写期望工具序列与参考答案,分别配 subset 轨迹比对与 LLM 判官,跑完记下单例平均成本。这份评测集会一直陪你到第 30 篇的收官实战。

下一篇讲安全与护栏:Prompt Injection 怎么防、工具权限怎么最小化。对于正在把 Agent 推向生产的读者,建议本周就动手:先把 trace 常开,再攒够十条真实差评 case——评测集是长出来的,不是憋出来的。

相关推荐

Hermes Agent 详解:自进化学习型 AI 代理
Agent

Hermes Agent 详解:自进化学习型 AI 代理

Hermes Agent 详解:自进化学习型 AI 代理Hermes Agent 是由 Nous Research 于 2026 年 2 月开源的自主 AI 代理框架,其核心定位是"与你共同成长的智能体"。与传统的 IDE 编程助手或单一 API 聊天机器人不同,Hermes 运行在你的服务器上,能够记住所学内容,运行时间越长能力越强。它采用 MIT 开源许可,支持 Linux、macOS 和 W

393
Hermes Agent:与你一起成长的开源 AI 代理
Agent

Hermes Agent:与你一起成长的开源 AI 代理

Hermes Agent:与你一起成长的开源 AI 代理大多数 AI 助手是"健忘的租客"——换个窗口就失忆、换个平台就重学、干过的活不留下任何沉淀。Nous Research 出品的 Hermes Agent 反其道而行,口号是"The Agent That Grows With You"(与你一起成长的代理):它是一个开源(MIT)、自托管的 AI 代理,具备持久记忆(学习你的项目、自动生成技

322
speech-to-speech 详解:HuggingFace 的开源语音 Agent 流水线
AI

speech-to-speech 详解:HuggingFace 的开源语音 Agent 流水线

speech-to-speech 详解:HuggingFace 的开源语音 Agent 流水线语音 Agent 的"全开源"路线一直有个尴尬:框架开源了,模型却离不开云端 API。huggingface/speech-to-speech 把这条路走通了:VAD → STT → LLM → TTS 四段低延迟流水线,每个组件都可换成开源模型本地跑——Apple Silicon 一台 Mac 就能撑起

264