尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

成功与满意拆开看,TaoToken Key 下跑 GAUGE 对照

成功与满意拆开看,TaoToken Key 下跑 GAUGE 对照 1. 一次 57.5% 的满意度把评测同事坑了评测平台里最容易骗人的一栏是“用户满意度”。我们按 Amazon GAUGE 的思路把 LLM 模拟用户 LLM judge 这条链路重跑了一遍结论和论文对得上被评为满意的对话里有 57.5% 实际没完成客户任务。先把调用出口固定成 TaoToken官网入口Key 与 Base URL 一处配好后面所有对照实验都走同一条通道否则你根本分不清指标漂移是 judge 的锅还是供应商的锅。这篇不是论文导读是一份评测平台工程师视角的落地记录。任务型智能体评测里有两个问题被长期混在一起任务是否完成可验证的事实和用户是否满意模拟用户的主观表态。GAUGE 的价值在于把这两件事拆开测量并且指出在能力相近的 agent 之间这套 LLM 关卡有相当比例的配对会把更高的奖励发给实际更差的一方而能力差距拉开后误判比例会掉到 1% 以下。换句话说这道关卡擅长区分强弱悬殊不擅长区分旗鼓相当。而真实选型场景里你面对的恰恰是几个能力相近的候选。本文产出两样东西一张双轴指标对照表成功轴 / 满意轴一份能对得上的 Token 账单。所有模型调用统一指向https://taotoken.net/apiClaude Code、Codex、评测脚本共用同一个 Key减少变量。2. 为什么“成功”和“满意”必须拆成两根轴先明确评测对象。我们平台当时评测的是一个客服工单处理 agent输入是一段客户诉求输出是一串工具调用加最终答复。旧流程只有一根轴LLM 模拟用户扮演客户跟被测 agent 多轮对话对话结束后模拟用户给出一个 1–5 分的满意度超过阈值就算通过。这个流程有三个结构性缺陷跟 GAUGE 的观察一致。第一模拟用户会“被说服”。被测 agent 只要话术足够礼貌、解释足够冗长模拟用户很可能给出高分即使工单里要求的退款、改地址、查物流一次都没真正执行。满意是对话层面的感受成功是任务层面的状态变更两者不同源。第二judge 在相近候选之间接近抛硬币。当两个 agent 的成功率差 20 个点以上judge 排序基本靠谱当两者只差两三个点judge 的排序噪声就会淹没真实差异。论文给出的数字是相近配对中约 31% 选错、差距大的配对中不足 1%这个梯度本身就说明judge 的可靠性是候选间距离的函数不是常数。第三单轴指标无法定位失败类型。只看满意度你无法区分“agent 没做对但说得好听”和“agent 做对了但语气生硬”。前者要改工具调用逻辑后者要改提示词与话术动作完全不同。所以本文将评测拆成两个独立采集的指标轴采集方式判定依据可自动化任务成功规则校验 状态断言工具调用是否命中必需动作、终态是否符合预期是优先用户满意LLM 模拟用户打分对话结束后的主观评分与理由是但需抽样人工校准关键原则成功轴尽量不依赖 LLM。能写成断言的就写成断言LLM 只负责生成用户话语和打分不负责判定事实。这样即使 judge 有噪声成功轴依然是干净的。3. 跑对照前先把出口统一到 TaoTokenKey 与 Base URL做 A/B 对照最怕的就是两个候选走了不同供应商、不同限流策略、不同版本的模型。所以第一步不是写评测代码是把调用出口收敛到一个地址。到 TaoToken 官网 注册后在控制台创建 API Key。本文所有示例里的 Key 都写成YOUR_API_KEY你替换成自己的即可。统一 Base URL 为https://taotoken.net/api注意这个地址在工具配置里不要附加任何查询参数保持干净。3.1 环境变量的正确分层很多人踩的坑是把ANTHROPIC_*一路套到所有工具上。必须分清Claude Code 读的是ANTHROPIC_BASE_URL/ANTHROPIC_AUTH_TOKEN/ANTHROPIC_MODELCodex 读的是config.toml里的model_providers配置配的是base_url和env_key跟ANTHROPIC_*没有任何关系自己写的 Python 评测脚本走 OpenAI 兼容接口读OPENAI_API_KEY/OPENAI_BASE_URL。三条链路各配各的互不覆盖。可以在 shell 里这样组织# 评测脚本用的 OpenAI 兼容变量 export OPENAI_API_KEYYOUR_API_KEY export OPENAI_BASE_URLhttps://taotoken.net/api # Claude Code 用的变量 export ANTHROPIC_BASE_URLhttps://taotoken.net/api export ANTHROPIC_AUTH_TOKENYOUR_API_KEY # Codex 用的变量config.toml 里通过 env_key 引用 export TAOTOKEN_API_KEYYOUR_API_KEY命名分开的好处是出问题时你能一眼看出是哪条链路没读到 Key而不是对着一堆同名变量互相覆盖排查半天。3.2 自检先确认通道是通的在跑任何评测之前先用最小请求确认 Key 和 Base URL 可用curl -s https://taotoken.net/api/models \ -H Authorization: Bearer YOUR_API_KEY \ | head -c 500能返回模型列表就说明通道没问题。这一步不通后面所有指标都不可信——而且往往是 401 或 404 被评测脚本吞掉最后表现为“成功率为 0”非常具有误导性。4. Claude Code 侧settings.json 与 ANTHROPIC_* 的写法Claude Code 的配置分两层全局的~/.claude/settings.json和项目级的.claude/settings.json。做评测对照时建议把供应商配置写在项目级避免污染你日常开发的环境。{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_AUTH_TOKEN: YOUR_API_KEY, ANTHROPIC_MODEL: claude-sonnet-4-5, ANTHROPIC_SMALL_FAST_MODEL: claude-haiku-4-5 }, permissions: { allow: [ Read, Grep, Glob ], deny: [ Bash(rm:*), Bash(git push:*) ] } }几个实操要点模型名以控制台可用列表为准。上面写的是示例值跑之前用第 3.2 节的/models接口核对一遍。写错模型名通常会返回 404Claude Code 的报错信息不一定会直接点出是模型名问题。ANTHROPIC_AUTH_TOKEN和ANTHROPIC_API_KEY别同时设。两个都存在时行为依赖工具版本容易造成“我明明配了但没生效”的错觉。选一个即可。项目级 settings.json 要进版本库。但 Key 不要进版本库。推荐做法是 JSON 里写占位符用 shell 的 env 覆盖或者用.claude/settings.local.json存真实 Key 并加进.gitignore。对照实验期间固定模型版本。如果两个候选 agent 一个用 Sonnet 一个用 Haiku你测出来的是模型差异而不是 agent 差异。所有候选统一模型或者把模型作为变量单独做一轮消融。跑起来之后用/status或/config确认当前生效的 Base URL 是https://taotoken.net/api。这一步花十秒能省掉后面两小时的困惑。5. Codex 侧config.toml 的写法Codex 的配置在~/.codex/config.toml。再次强调这里不写ANTHROPIC_*Codex 只认model_providers段。model gpt-5-codex model_provider taotoken [model_providers.taotoken] name TaoToken base_url https://taotoken.net/api env_key TAOTOKEN_API_KEY wire_api chat [profiles.gauge-judge] model gpt-5 model_provider taotokenenv_key指向的是环境变量名不是 Key 本身。所以配置里不出现明文 Key这就是前面为什么要单独准备一个TAOTOKEN_API_KEY变量。profiles段在本文场景里很有用给 judge 单独开一个 profile指定推理能力更强的模型而模拟用户用便宜快速的小模型。评测成本大头通常就在这两处分开配能省下可观的开销。验证方式codex --profile gauge-judge 输出你当前使用的模型名和供应商名如果它回显的供应商不是taotoken说明 profile 没被正确读取检查 TOML 缩进和段名拼写。6. CC Switch 三件套模拟用户 / 被判 agent / judge 三个槽位评测链路里有三个模型角色它们的诉求完全不同槽位角色模型诉求配置来源ALLM 模拟用户便宜、快、话术多样小模型 profileB被测 agent与生产环境一致生产同款模型CLLM judge强推理、低温度大模型 profile用 CC Switch 管理时建议维护三份独立 profile分别绑定同一个 Base URL 和同一个 Key只在模型名和温度上做区分。这样做的好处是切换成本低。换候选 agent 时只动 B 槽位A 和 C 保持不变实验变量被压到最小。账单可归因。三个槽位用同一个 Key但模型名不同账单里按模型拆分就能看出钱花在哪一环。judge 通常是隐藏的成本黑洞——它要看完整对话输入 token 是模拟用户的好几倍。失败可隔离。如果整批结果异常先单独跑 A 槽位的一句话生成再跑 C 槽位的一次打分能快速定位是哪个角色挂了。具体操作就是把三份配置分别导出成文件切换时直接替换settings.json/config.toml中的对应字段或者用 CC Switch 的 profile 切换功能。注意切换后要清掉上一轮的会话缓存否则可能读到旧配置。配置完成后建议先跑一轮连通性冒烟测试A 生成一句话、B 回一句话、C 打一个分三步全过再开始批量。7. 复现脚本LLM 模拟用户 LLM judge 的双轴打分下面是一个最小可运行的对照脚本。它做三件事跑若干条任务、用断言判成功、用 judge 判满意最后输出双轴统计。import json from collections import defaultdict from openai import OpenAI client OpenAI( api_keyYOUR_API_KEY, base_urlhttps://taotoken.net/api, ) SIM_USER_MODEL claude-haiku-4-5 AGENT_MODEL claude-sonnet-4-5 JUDGE_MODEL claude-sonnet-4-5 def chat(model, messages, temperature0.0): resp client.chat.completions.create( modelmodel, messagesmessages, temperaturetemperature, ) return resp.choices[0].message.content, resp.usage def simulate_user(task, history, turns_left): prompt [ {role: system, content: 你在扮演客户按给定诉求与客服沟通。不要主动帮对方完成任务 只提出问题、确认结果。还剩 %d 轮时必须结束并给出满意度。 % turns_left}, {role: user, content: 你的诉求 task[request]}, ] prompt.extend(history) return chat(SIM_USER_MODEL, prompt, temperature0.8) def run_agent(task, history): prompt [{role: system, content: 你是客服工单处理助手请调用可用工具完成客户诉求。}] prompt.extend(history) return chat(AGENT_MODEL, prompt, temperature0.0) def judge_satisfaction(task, transcript): prompt [ {role: system, content: 阅读对话站在客户立场给出 1-5 分满意度 并输出 JSON{\score\: int, \reason\: str}}, {role: user, content: transcript}, ] text, usage chat(JUDGE_MODEL, prompt, temperature0.0) try: data json.loads(text) except json.JSONDecodeError: data {score: 0, reason: parse_error} return data, usage def check_success(task, transcript): 规则断言成功轴尽量不依赖 LLM。 required task.get(required_actions, []) return all(action in transcript for action in required) def run_case(task, max_turns6): history [] usage_total defaultdict(int) for turn in range(max_turns): agent_reply, u1 run_agent(task, history) usage_total[AGENT_MODEL] u1.total_tokens history.append({role: assistant, content: agent_reply}) user_reply, u2 simulate_user(task, history, max_turns - turn - 1) usage_total[SIM_USER_MODEL] u2.total_tokens history.append({role: user, content: user_reply}) transcript \n.join(m[content] for m in history) satisfaction, u3 judge_satisfaction(task, transcript) usage_total[JUDGE_MODEL] u3.total_tokens return { task_id: task[id], success: check_success(task, transcript), satisfaction: satisfaction[score], reason: satisfaction[reason], tokens: dict(usage_total), } if __name__ __main__: tasks json.load(open(tasks.json, encodingutf-8)) rows [run_case(t) for t in tasks] n len(rows) success_rate sum(r[success] for r in rows) / n avg_sat sum(r[satisfaction] for r in rows) / n mismatch [r for r in rows if r[success] is False and r[satisfaction] 4] print(case%d success%.3f avg_sat%.2f 满意但失败%d(%.1f%%) % (n, success_rate, avg_sat, len(mismatch), 100 * len(mismatch) / n))脚本里有三个刻意的设计值得说明成功轴用字符串匹配做占位生产里要换成结构化断言。上面用required_actions出现在文本里作为简化判定真实场景应该解析工具调用记录检查是否真的执行了退款、改址这类有副作用的操作。原则不变能验证事实就不问 LLM。judge 输出强制 JSON。一旦解析失败按 0 分处理避免脏数据悄悄混进均值。你也可以在 judge 提示里给出 few-shot 示例显著降低解析失败率。token 用量按模型分别累计。usage字段来自每次响应直接累加即可得到单条任务的成本为后面的账单核对打基础。8. 双轴指标对照表怎么填跑完多个候选后把结果整理成下面这张表。这张表才是本文标题所说的“把成功和满意拆开看”的最终形态。候选样本数任务成功率平均满意度满意但失败占比judge 触顶率平均轮数agent-A2000.814.3221.5%44%3.8agent-B2000.794.5126.0%52%4.1agent-C2000.624.0518.0%31%3.4读表方式成功率高、满意度低→ agent 做得多但沟通差优化提示词与话术不要动工具逻辑。成功率低、满意度高→ 典型的“说得好听没干活”这正是 GAUGE 指出的失效模式。此时满意度轴不可信任何基于它的排序都要打问号。表格里 agent-B 成功率低于 agent-A但满意度更高如果只按单轴决策就会选错。judge 触顶率高→ 打分区分度不足大量样本挤在 5 分。这时应该拉长评分粒度比如 1–10 分或要求 judge 给出理由后再打分也可以加入成对比较而非绝对打分。相近候选的排序要谨慎。当两个候选成功率差距在 3 个百分点以内先算置信区间再做配对显著性检验。GAUGE 的核心提醒就是这个区间的 judge 排序噪声很大单次实验的排名不具备决策价值。建议对相近候选增加样本量或者引入人工抽检做黄金标准校准。9. Token 账单怎么对成本是评测方案能否长期运行的决定因素尤其是 judge 这一环。把每个模型的 token 消耗单独记账环节模型单条平均 token200 条合计占比模拟用户小模型1.8k360k18%被测 agent生产同款3.2k640k32%judge强推理模型5.0k1000k50%三个可以立刻执行的优化judge 只喂关键轮次。完整对话里大量寒暄对判定没有贡献。截取首轮、工具调用轮、末轮通常能把 judge 输入压掉一半且不损失判定质量。模拟用户用小模型 高温度。模拟用户需要的是话术多样性而不是推理深度用便宜模型反而更贴近真实用户的随意表达。成功轴先行judge 抽样。断言能判的样本不必再过 judge。对成功轴已经通过的样本只需抽样 20%–30% 做满意度评估即可维持统计效力。账单能对上还有个隐性收益如果某天指标突然漂移token 用量会先露出异常。judge 输入 token 突然翻倍通常意味着对话轮数失控或者 agent 开始输出超长回复。10. 排障清单按出现频率排序遇到问题逐条对照。401 / invalid api key。检查 Key 是否被 shell 配置覆盖或者用了ANTHROPIC_AUTH_TOKEN却在 OpenAI 兼容脚本里读OPENAI_API_KEY。重新执行第 3.2 节的 curl 自检。404 model not found。模型名拼错或者该模型不在当前账号可用范围内。用/models接口列出真实可用列表再改配置。请求超时。长对话加上 judge 全文输入容易触发超时。给客户端加显式超时和重试重试时降低max_tokens不要无条件指数退避到几分钟。judge 返回非 JSON。在提示里加一句“只输出 JSON不要任何解释”并加 few-shot 示例。仍失败时按解析错误单独计数不要把 0 分混入均值。成功率全为 0。九成是评测脚本把 HTTP 异常吞掉了或者required_actions的匹配串写错。先单跑一条任务打印完整 transcript肉眼确认。两个候选结果完全一致。检查是不是 profile 没切成功两个槽位指向了同一个模型。打印每次请求实际使用的模型名。Claude Code 里配置没生效。项目级配置优先于全局检查.claude/settings.json是否覆盖了~/.claude/settings.json以及是否设置了ANTHROPIC_API_KEY与ANTHROPIC_AUTH_TOKEN冲突。11. 把结论落到流程里回到最初那个问题LLM 模拟用户加 LLM judge 这道关卡什么时候不可信答案是——当你用它来区分两个能力相近的候选时。它擅长筛掉明显不合格的方案不擅长在优秀方案之间排座次。而选型决策恰恰发生在后者。所以落地时记住三条第一成功轴独立于 LLM。能用断言验证的事实绝不交给 judge这是整个评测体系的压舱石。第二相近候选必须加人工校准。当成功率差异小于 3 个百分点抽 30–50 条样本人工标注用人工结果校准 judge 的排序可信度。第三统一出口减少变量。所有槽位走同一个 Base URL、同一个 Key、按模型分开记账这样指标变化才可归因。如果你也想复现这套双轴对照建议按下面的顺序走一遍先在 模型对话 里确认目标模型可以正常交互把系统提示词和参数调到满意接着看 Coding Plan批量评测的调用量不小选一个匹配用量的方案能明显压低单次实验成本然后到 创建 API Key 生成 Key把YOUR_API_KEY替换掉Base URL 统一填https://taotoken.net/api最后对照 Claude Code 文档 把settings.json配好把软件工程类的修复任务也纳入同一套评测口径。评测方法的价值不在于跑出多漂亮的数字而在于当数字和直觉冲突时你能说清楚是哪个环节出了问题。把成功和满意拆开是让这件事变得可解释的第一步。
返回列表