1. 为什么 Agent 评估总在“凭感觉”阶段翻车
做 Agent 的团队几乎都会经历同一个阶段:Demo 演示时效果惊艳,上线后用户反馈“有时候行有时候不行”,但具体哪里不行、为什么不行,谁也说不清。这就是典型的“盲人摸象”状态——没有评估体系,所有优化都是拍脑袋。
Agent 评估方法的核心,是让每一次改动都有可量化的反馈信号。它要回答三个问题:哪里好、哪里不好、改完有没有变好。这三个问题对应三个层次:端到端评估看整体质量,步骤级评估定位具体环节,运营级评估做 Badcase 闭环。缺了任何一层,评估都会失真。
我见过太多团队只做端到端打分,结果发现准确率从 72% 掉到 68%,却完全不知道是检索环节退化了,还是工具调用顺序错了,还是生成阶段开始编造内容。这时候就需要 LLM-as-Judge 做细粒度打分,配合 Trace 回放把每一步的输入输出摊开看。
这篇会带你从零搭一套可跑的评估流程:用 TaoToken 统一 Key 接入评估脚本,写 Judge 提示词模板,映射 Trace 字段,最后用 SWE-bench 风格的任务集跑一次端到端验证。适合正在做 Agent 落地、需要建立评估体系的工程师,也适合想搞清楚 LLM-as-Judge 和 Trace 到底怎么配合的读者。
2. TaoToken 统一 Key 接入评估脚本的前置准备
评估脚本最烦的事情之一,是不同模型要走不同通道:Judge 用 GPT-4 系,被测 Agent 用 Claude 系,Embedding 又换一家。每换一个模型就要改一次 base_url、换一次 key、调一次鉴权逻辑。TaoToken 的价值在这里就体现出来了——它提供统一的 API 通道,一个 Key 可以路由到多个模型,评估脚本里只需要维护一份配置。
先说清楚它是什么:TaoToken 是一个大模型 API 聚合网关,对外暴露 OpenAI 兼容的接口格式。你可以把它理解成一个“统一插座”,不管后面接的是哪个厂商的模型,前端调用方式都一样。对评估场景特别友好,因为评估脚本经常需要同时调用 Judge 模型和被测模型,统一通道能省掉大量适配代码。
适合谁用:需要频繁切换模型做对比评估的团队、要跑多模型 Judge 打分的场景、以及希望把评估脚本和业务代码解耦的工程团队。
前置准备分三步。第一步,拿到 API Key。访问 https://taotoken.net/api-keys 创建,注意这个 Key 只在创建时显示一次,复制保存好。第二步,确认你要用的模型 ID。评估场景常用的有 Judge 模型(建议用推理能力强的)和被测 Agent 模型。第三步,记下 Base URL:https://taotoken.net/api,所有请求都走这个地址,不需要加 UTM 参数。
这里有个容易踩的坑:很多人把 Base URL 写成 https://taotoken.net/api/v1 或者带斜杠的版本,结果 404。正确写法就是 https://taotoken.net/api,具体路径由 SDK 自己拼接。如果你用 OpenAI SDK,base_url 参数填这个值即可。
另外提醒一点,评估脚本里不要把 Key 硬编码。用环境变量或者配置文件管理,跑 CI 的时候从 secrets 注入。下面第三节会给出完整的配置片段。
3. 可复制的评估配置与 Judge 提示词模板
这一节是核心,直接给可复制的内容。先看配置文件。我用 JSON 格式,因为大多数评估框架都支持。
{ "gateway": { "base_url": "https://taotoken.net/api", "api_key_env": "TAOTOKEN_API_KEY", "timeout_seconds": 60, "max_retries": 3 }, "models": { "judge": { "model_id": "gpt-4o", "temperature": 0.0, "max_tokens": 1024 }, "agent_under_test": { "model_id": "claude-3-5-sonnet", "temperature": 0.2, "max_tokens": 4096 }, "embedding": { "model_id": "text-embedding-3-large" } }, "evaluation": { "dimensions": ["input_understanding", "tool_usage", "answer_accuracy"], "scale": "1-5", "comparison_mode": "pairwise" } }注意 judge 的 temperature 设成 0.0,评估要的是稳定复现,不是创意。agent_under_test 可以保留一点温度,模拟真实场景。
如果你用 TOML 管理配置(比如配合 Rust 或 Python 的 tomllib),等价写法:
[gateway] base_url = "https://taotoken.net/api" api_key_env = "TAOTOKEN_API_KEY" timeout_seconds = 60 [models.judge] model_id = "gpt-4o" temperature = 0.0 [models.agent_under_test] model_id = "claude-3-5-sonnet" temperature = 0.2接下来是 Judge 提示词模板。这是 LLM-as-Judge 的灵魂,写不好打分就不可信。核心原则:给明确评分标准、用对比评估而非绝对分数、三维度独立打分。
你是一个 Agent 输出质量评估员。你的任务是对比两个 Agent 对同一任务的输出,判断哪个更好。 【任务输入】 {task_input} 【Agent A 输出】 {output_a} 【Agent B 输出】 {output_b} 【评分维度】 1. 输入理解(input_understanding):Agent 是否正确理解了用户意图?1-5 分。 2. 工具使用(tool_usage):Agent 选择的工具和调用顺序是否合理?1-5 分。 3. 回答准确性(answer_accuracy):最终回答是否正确、完整、无幻觉?1-5 分。 【评分规则】 - 每个维度独立打分,不要因为一个维度差就压低其他维度。 - 如果两个输出在某维度上难以区分,都打相同分数。 - 优先看事实正确性,其次看表达清晰度。 - 如果输出包含编造信息(幻觉),answer_accuracy 直接打 1 分。 【输出格式】 严格返回 JSON,不要有其他内容: { "input_understanding": {"A": 分数, "B": 分数, "reason": "简短理由"}, "tool_usage": {"A": 分数, "B": 分数, "reason": "简短理由"}, "answer_accuracy": {"A": 分数, "B": 分数, "reason": "简短理由"}, "overall_winner": "A 或 B 或 tie" }这个模板的关键点:强制 JSON 输出方便程序解析,三维度独立避免“一荣俱荣”,对比模式比绝对打分更稳定。实测下来,对比评估的一致性比绝对打分高不少,尤其是当两个输出差距不大时。
调用 Judge 的 Python 代码片段:
import os import json from openai import OpenAI client = OpenAI( base_url="https://taotoken.net/api", api_key=os.environ["TAOTOKEN_API_KEY"] ) def judge_pairwise(task_input, output_a, output_b, prompt_template): prompt = prompt_template.format( task_input=task_input, output_a=output_a, output_b=output_b ) resp = client.chat.completions.create( model="gpt-4o", temperature=0.0, messages=[{"role": "user", "content": prompt}] ) return json.loads(resp.choices[0].message.content)注意resp.choices[0]这个路径,后面排障会讲到常见的reading 'choices'报错就是这里出的问题。
4. Trace 字段映射与端到端跑分验证
Trace 是步骤级评估的命脉。没有 Trace,你只知道结果错了,不知道哪一步错的。Trace 的核心是记录每次调用的完整路径:LLM 调用的输入输出、工具调用的参数和结果、节点间的流转。
先定义 Trace 的字段映射。不管你用 LangFuse 还是 Arize Phoenix,字段语义要对齐。下面是一份通用映射表:
| 业务字段 | Trace 字段 | 说明 |
|---|---|---|
| 会话 ID | trace_id | 一次完整任务的唯一标识 |
| 步骤序号 | span_id | 每个环节的独立 ID |
| 环节类型 | span_type | llm / tool / retrieval / decision |
| 输入 | input | 该环节的原始输入 |
| 输出 | output | 该环节的原始输出 |
| 耗时 | latency_ms | 毫秒级耗时 |
| Token 消耗 | token_usage | prompt + completion |
| 工具名 | tool_name | 仅 tool 类型有 |
| 工具参数 | tool_args | JSON 格式 |
| 工具结果 | tool_result | 原始返回 |
| 错误信息 | error | 失败时记录 |
有了这份映射,Trace 回放才能回答“用户说答案错了,是哪个环节造成的”。比如检索环节 Recall@K 正常,但工具调用选错了工具,那问题就在决策环节,不用去改检索。
端到端跑分验证的流程:准备一个 SWE-bench 风格的任务集,每条任务包含 issue 描述和期望修复。让 Agent 跑一遍,记录 Trace,然后用 Judge 打分,最后对比分数和 Trace 定位问题。
def run_evaluation(task_set, agent, judge_template): results = [] for task in task_set: trace = [] output = agent.run(task["input"], trace_callback=trace.append) score = judge_pairwise( task["input"], output, task["expected_output"], judge_template ) results.append({ "task_id": task["id"], "score": score, "trace": trace, "latency": sum(s["latency_ms"] for s in trace) }) return results跑完之后看三个数:整体准确率、各维度平均分、Trace 里失败步骤的分布。如果 answer_accuracy 低但 tool_usage 高,说明工具选对了但生成有问题,去查生成环节的 prompt。如果 tool_usage 低,去查决策逻辑。
验证成功的标志:同一任务集跑两次,分数波动在 2% 以内。如果波动超过 5%,说明 Judge 不稳定或者任务集区分度不够,需要调整 Judge 提示词或增加任务数量。
5. 常见报错排查:401、local proxy failed、reading choices、OAuth
评估脚本跑不起来,八成是这几类错误。逐个说。
401 Unauthorized。最常见的原因是 Key 没读到或者读错了。检查环境变量名是否和配置里一致,比如配置写TAOTOKEN_API_KEY,但实际导出的是TAOTOKEN_KEY。另一个原因是 Key 前后有空格或换行,从网页复制时容易带上。用echo $TAOTOKEN_API_KEY | wc -c看长度对不对。还有一种情况是 Key 被禁用或额度耗尽,去 https://taotoken.net/api-keys 确认状态。
local proxy failed。这个报错通常出现在请求根本没发出去的时候。检查 base_url 是否写对,必须是https://taotoken.net/api,不要加/v1或尾部斜杠。如果你本地有网络代理配置,确认它没有拦截这个域名。另外检查防火墙是否放行了 443 端口。这个错误和网络环境有关,但不需要任何特殊网络工具,正常网络即可访问。
reading 'choices'。这是解析响应时的报错,典型写法resp.choices[0]但resp结构不对。原因通常是请求失败返回了错误对象,但代码没检查就直接取 choices。修复方式:先判断响应状态,再取字段。
resp = client.chat.completions.create(...) if not resp.choices: raise RuntimeError(f"Empty response: {resp}") content = resp.choices[0].message.content还有一种可能是模型 ID 写错了,网关返回了错误信息而不是正常响应。确认 model_id 和 TaoToken 支持的模型列表一致。
OAuth 相关报错。如果你用 Claude Code 或者某些 CLI 工具接入,可能会遇到 OAuth token 过期或未授权。这类工具通常需要单独配置。以 Claude Code 为例,需要设置三个东西:Base URL 指向https://taotoken.net/api,API Key 用 TaoToken 的 Key,Model ID 填你要用的模型。三件套缺一不可。如果只配了 Key 没配 Base URL,它会走默认通道然后 OAuth 失败。
如果你用 Cline 或 CC Switch 这类工具,配置逻辑一样:Base URL + Key + Model ID。Cline 的 MCP 配置里,把 provider 设成 openai-compatible,base_url 填 TaoToken 地址。Codex 的 auth.json 里同样需要这三个字段对齐。
排障的通用思路:先确认 Key 有效,再确认 Base URL 正确,再确认 Model ID 存在,最后看响应结构。四步走完,90% 的问题都能定位。
6. 把评估跑成习惯:从一次性脚本到持续闭环
评估体系搭起来只是开始,真正产生价值的是让它持续跑。我的做法是把评估脚本接进 CI,每次改 Prompt、换模型、调参数后自动触发。关键指标下降超过 2% 就告警,阻止合并。
测试集要先行。不要等系统做完了才想评估,而是先准备 50-100 个核心场景用例,每次改完跑一遍。这些用例来自真实 Badcase,每条 Badcase 修复后加入测试集,防止回归。跑起来的团队,质量从 70% 到 90% 通常需要 3-6 个月,靠的就是这个闭环。
人工抽检不能省。自动化评估有盲区,Judge 也会犯错。每周抽 20 条 Trace 人工看一遍,校准 Judge 的打分标准。如果发现 Judge 和人工判断偏差大,回去改提示词模板。
最后说个实用技巧:把 Trace 的 trace_id 打到日志里,用户反馈问题时能直接定位到完整链路。这比事后复现高效得多。评估的价值不在于打分本身,而在于让每次优化都有确定的反馈信号。系统确定性永远大于模块灵活性。
需要跑通完整流程的话,先去 https://taotoken.net/api-keys 拿 Key,配置参考 https://taotoken.net/doc 的接入文档。Judge 模型可以先在 https://taotoken.net/models 对话验证效果,确认打分稳定后再写进脚本。长期做 Agent 评估和编码任务的,可以看看 Coding Plan 的额度方案,评估脚本频繁调用 Judge 模型时更划算。