给 LLM judge 加一道任务核对,TaoToken 只做 Key 通道

📅 发布时间:2026/9/18 0:24:23
给 LLM judge 加一道任务核对,TaoToken 只做 Key 通道
1. 从 401 与 base_url 配置切入先让 judge 有稳定的 Key 通道调试 LLM judge 时401 invalid api key、base_url 末尾多一层/v1、Codex 里误用ANTHROPIC_*都会先把你拦住。这里把 TaoToken 只当 Key 通道先到 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_contentjudge_key_channel 获取 KeyBase URL 填https://taotoken.net/api。把 Key 通道跑通之后再去改 judge 提示词顺序会清楚很多。Amazon GAUGE 这类论文提醒我们LLM 模拟用户加 LLM judge 的评估关卡并不是永远可信满意度信号和任务完成度可能错位。尤其在能力相近的智能体之间单看满意度很容易把“聊得舒服”误判成“任务完成”。本文不展开新闻复述而是从 Prompt 工程师视角给出一套可跟做的改法把 judge 拆成“满意度初判”和“任务核对”两段并把 TaoToken 作为模型调用的 Key 通道。最终会落到三类可复制配置Claude Code 的settings.json、Codex 的config.toml以及 CC Switch 的三件套管理方式。为什么要在 judge 前面加一道任务核对因为任务型智能体的成功标准不是“用户说谢谢”而是状态真的变了。比如改签机票、提交退款、更新工单、创建订单、查询库存、发送通知这些都需要工具结果或系统返回值作为证据。LLM judge 如果只看最终回复很容易被“已处理”“已提交”“请放心”这类文本骗过去。任务核对层要做的是把用户目标拆成可验证清单再逐项找证据。没有证据就判unknown而不是猜pass。下面的路径适合本地评估流水线你已经有对话日志和工具轨迹想给现有 judge 增加第二道核对或者你正在用 Claude Code / Codex 调试评估提示词需要先把模型调用通道切到 TaoToken。所有命令和脚本都只在本地读取脱敏后的导出文件不连接生产库也不让智能体直连数据库。SQL 或业务查询由读者在本地或测试环境执行。2. 环境准备TaoToken Key、Base URL 与最小调用第一步不是写 prompt而是确认 Key 和 Base URL 可用。进入 TaoToken 官网后在控制台或 API Keys 页面创建 Key建议单独建一个评估用途的 Key不要和线上业务混用。官网入口在这里https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_contentjudge_env_setup。创建后将 Key 写入环境变量占位符统一用YOUR_API_KEY。Base URL 按工具配置要求填https://taotoken.net/api这个地址不要加 UTM 参数。本地环境变量可以这样设置export TAOTOKEN_API_KEYYOUR_API_KEY export TAOTOKEN_BASE_URLhttps://taotoken.net/api export JUDGE_MODELgpt-4.1-mini如果你用 OpenAI 兼容 SDK最小调用可以写成下面这样。注意模型名要换成 TaoToken 控制台中实际可用的模型如果某个模型不支持response_format先去掉该参数再在代码里做 JSON 修复。import json import os from openai import OpenAI client OpenAI( api_keyos.environ[TAOTOKEN_API_KEY], base_urlos.environ.get(TAOTOKEN_BASE_URL, https://taotoken.net/api), ) def call_json(prompt: str) - dict: completion client.chat.completions.create( modelos.environ.get(JUDGE_MODEL, gpt-4.1-mini), temperature0, response_format{type: json_object}, messages[ {role: system, content: 你只输出 JSON不要输出 Markdown不要额外解释。}, {role: user, content: prompt}, ], ) content completion.choices[0].message.content return json.loads(content) result call_json(返回一个 JSON{\ok\: true}) print(result)这一步的目标不是评估质量而是确认三件事Key 没有写错、Base URL 没有多路径、模型名可用。很多“judge 不稳定”其实不是 prompt 问题而是调用层间歇性 401 或 404导致空结果被当成低分。先把调用层稳定住再谈任务核对。这里再次强调配置边界Claude Code 使用ANTHROPIC_*系列变量Codex 使用config.toml里的 provider 配置不要把ANTHROPIC_BASE_URL或ANTHROPIC_AUTH_TOKEN塞进 Codex。两者协议和读取方式不同混用最容易出现“明明 Key 没错但 CLI 就是不工作”。TaoToken 的角色只是 Key 通道不改变你本地评估逻辑。3. 两阶段 judge 设计满意度初判 任务核对GAUGE 这类研究最有价值的提醒是满意度 judge 和任务成功 judge 不是同一个东西。满意度 judge 擅长判断用户情绪、语气和主观反馈任务核对 judge 擅长检查目标是否被真实完成。把两者塞进一个 prompt模型往往会偏向更容易观察的信号也就是“用户最后有没有说谢谢”。所以更稳的做法是拆成两个阶段。阶段 A满意度初判。只读对话文本不读工具细节输出主观满意度倾向和置信度。它的作用是保留用户体验信号但不直接决定任务是否成功。你是 LLM judge只评估用户对本次对话的主观满意度倾向。 不要判断任务是否真正完成不要评价工具调用是否正确。 只根据用户可见对话内容判断用户是否表现出满意、不满或中性。 输入 对话记录 {dialogue} 输出 JSON { satisfaction: positive|neutral|negative|unknown, confidence: 0.0, evidence: 引用用户原话或关键对话片段, notes: 不确定时说明原因 }阶段 B任务核对。读用户目标、任务清单、工具轨迹、最终回复和业务规则逐项找证据。这个阶段才是决定“任务是否完成”的关卡。你是任务型智能体的“任务核对员”不是满意度评委。 你的职责是判断用户目标是否在对话和工具轨迹中被真正完成。 输入 1. 用户目标{user_goal} 2. 任务清单{task_checklist} 3. 工具调用轨迹{tool_trace} 4. 最终回复{final_answer} 5. 业务规则{business_rules} 核对原则 - 只有工具结果、系统返回值、可验证状态变化能作为完成证据。 - 最终回复中的“已完成”“已提交”“已处理”不是证据。 - 每个核对项必须给出 pass / fail / unknown。 - 如果证据不足判 unknown不要猜。 - 如果满意度高但任务未完成在 contradiction 中标记。 输出 JSON { task_completed: yes|no|partial|unknown, checklist: [ { item: 核对项, required: true, status: pass|fail|unknown, evidence: 引用具体工具结果或对话片段, risk: 低|中|高 } ], satisfaction_signal: positive|neutral|negative|unknown, contradiction: 有/无说明满意度与任务完成是否冲突, final_reason: 一句话结论 }这两个 prompt 的关键差异是证据来源。阶段 A 可以引用“用户说谢谢”阶段 B 不能把“用户说谢谢”当成任务完成证据。阶段 B 必须看到类似refund_statussubmitted、ticket_id123、order_statechanged、inventory_count8这类可验证结果。如果工具轨迹里只有模型说“我已经帮你提交了”但没有任何返回任务核对就应该给fail或unknown。Prompt 工程师常犯的一个错误是试图用一个超长 prompt 同时做满意度、任务完成、工具正确性、安全合规。模型在长规则下会忽略一部分约束尤其是“没有证据不能判 pass”这种反直觉规则。拆成两阶段后每个阶段的目标更窄输出 JSON 也更容易被程序消费。你还可以在阶段 B 之后加一个校准器当satisfactionpositive且task_completedno时打上contradiction标签进入人工复核队列。4. 可复现对照judge 提示词与任务核对结果表为了验证第二道核对是否有效可以准备一组小样本每条样本包含用户目标、对话、工具轨迹和最终回复。不要直接接生产库先把脱敏日志导出为本地 JSONL。每条样本跑阶段 A 和阶段 B然后把两个结果并排看。下面是一个对照表示例。注意这里的“满意度 judge”只代表用户主观倾向不代表任务成功。任务核对列才是最终采信依据。样本用户目标最终回复满意度 judge任务核对是否应采信处理建议S01退款订单 A“已为您提交退款”positivefail工具轨迹无退款单号无状态变化否标记 contradiction人工复核S02改签航班“改签成功请查收”positivepass工具返回新航班号和确认码是可进入自动通过S03查询库存“目前有货可以下单”neutralunknown查询结果字段缺失否补工具日志后重跑S04关闭工单“工单已关闭”negativepass工单状态从 open 变 closed是用户不满但任务完成单独归因S05发送通知“通知已发送”positivefail消息队列无 message_id否判任务未完成这张表的结论很直接满意度高不等于任务完成。阶段 A 可以保留用户体验信号但最终评估指标应该以任务核对为主。你可以计算三个指标task_pass_rate任务核对为pass的比例。satisfaction_rate满意度为positive的比例。contradiction_rate满意度为positive但任务核对为no/fail/unknown的比例。在能力相近的智能体之间满意度 judge 更容易受到表达风格影响。一个回复更礼貌、更笃定的智能体可能得到更高满意度但任务核对会把它拉回真实完成度。对于差距明显的智能体满意度 judge 可能也能区分但在接近的候选之间必须用任务核对做二次裁决。下面是一个本地批量对照脚本骨架。它读取samples.jsonl分别调用两阶段 prompt然后写出judge_compare.jsonl。所有数据都来自本地文件不连接生产库。import json from pathlib import Path from call_judge import call_json # 上一节的封装 def build_satisfaction_prompt(row: dict) - str: return f 你是 LLM judge只评估用户对本次对话的主观满意度倾向。 输入对话 {row[dialogue]} 输出 JSON {{satisfaction:positive|neutral|negative|unknown,confidence:0.0,evidence:...,notes:...}} def build_task_check_prompt(row: dict) - str: return f 你是任务型智能体的“任务核对员”不是满意度评委。 用户目标{row[user_goal]} 任务清单{json.dumps(row[task_checklist], ensure_asciiFalse)} 工具调用轨迹{json.dumps(row[tool_trace], ensure_asciiFalse)} 最终回复{row[final_answer]} 业务规则{row.get(business_rules, 无)} 输出 JSON {{task_completed:yes|no|partial|unknown,checklist:[],satisfaction_signal:positive|neutral|negative|unknown,contradiction:有/无说明,final_reason:...}} def main(): src Path(samples.jsonl) dst Path(judge_compare.jsonl) with src.open(r, encodingutf-8) as fin, dst.open(w, encodingutf-8) as fout: for line in fin: row json.loads(line) sat call_json(build_satisfaction_prompt(row)) task call_json(build_task_check_prompt(row)) out { id: row.get(id), satisfaction_judge: sat, task_check: task, need_review: sat.get(satisfaction) positive and task.get(task_completed) ! yes, } fout.write(json.dumps(out, ensure_asciiFalse) \n) if __name__ __main__: main()如果你要把这套方法用于 Coding Agent 或工具型 Agent建议把任务清单写得像验收标准而不是像聊天话题。例如[ {item: 确认用户身份, required: true, evidence_hint: 认证工具返回 user_id}, {item: 查询原订单状态, required: true, evidence_hint: order_statuspaid}, {item: 执行退款动作, required: true, evidence_hint: refund_id 非空}, {item: 告知用户下一步, required: false, evidence_hint: 最终回复包含退款单号} ]这样阶段 B 就不容易被自然语言说服。它必须逐项找证据找不到就unknown。这比在单个 judge prompt 里写“请严格判断”有效得多。5. Claude Code / Codex / CC Switch 三件套配置Prompt 调试阶段你可能会在 Claude Code 或 Codex 里反复改 judge 提示词。此时先把 CLI 的模型通道配置好避免因为 Key 和 Base URL 问题打断调试。TaoToken 官网入口可以作为统一配置起点https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_contentjudge_cli_config。Claude Code 使用settings.json和ANTHROPIC_*变量。可以把配置放到~/.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 } }如果你更喜欢 shell 临时覆盖也可以这样export ANTHROPIC_BASE_URLhttps://taotoken.net/api export ANTHROPIC_AUTH_TOKENYOUR_API_KEY export ANTHROPIC_MODELclaude-sonnet-4-5Codex 不要复用ANTHROPIC_*。它走config.toml里的 provider 配置。可以放到~/.codex/config.toml。示例model gpt-5 model_provider taotoken [model_providers.taotoken] name TaoToken base_url https://taotoken.net/api env_key TAOTOKEN_API_KEY wire_api chat对应环境变量export TAOTOKEN_API_KEYYOUR_API_KEY这里再次区分Claude Code 读ANTHROPIC_AUTH_TOKENCodex 通过env_key TAOTOKEN_API_KEY读取 Key。把这两套混在一起常见结果就是 Claude Code 能用、Codex 报 401或者反过来。排查时先看 CLI 实际读取了哪个配置文件再看环境变量是否被 shell profile 覆盖。CC Switch 这类切换工具通常管理三件套Provider profile保存 Base URL、API Key 环境变量名、协议类型。Model 映射指定默认模型、judge 模型、备用模型。启动命令或激活状态决定当前终端会话使用 Claude Code 配置还是 Codex 配置。你可以把“评估专用 profile”单独拆出来。比如profiles: - name: taotoken-judge provider: base_url: https://taotoken.net/api api_key_env: TAOTOKEN_API_KEY models: default: gpt-5 judge: gpt-4.1-mini fallback: claude-sonnet-4-5 clients: claude_code: auth_token_env: ANTHROPIC_AUTH_TOKEN base_url_env: ANTHROPIC_BASE_URL codex: provider_name: taotoken wire_api: chat实际字段以你使用的 CC Switch 版本为准。关键是不要把 Claude Code 的ANTHROPIC_*填进 Codex provider也不要把 Codex 的wire_api概念硬塞给 Claude Code。配置正确后再用阶段 A 和阶段 B prompt 做小样本对照。这样你调试的是 judge 逻辑不是 Key 通道。6. 批量评估流水线从对话日志到任务通过率当两阶段 prompt 稳定后就可以接入批量评估。推荐目录结构如下所有文件都在本地eval/ samples.jsonl prompts/ satisfaction.txt task_check.txt outputs/ satisfaction.jsonl task_check.jsonl judge_compare.jsonl scripts/ run_compare.py reports/ metrics.jsonrun_compare.py的顺序是读取样本调用满意度 judge调用任务核对合并结果计算指标。下面只列出指标计算部分import json from pathlib import Path rows [json.loads(line) for line in Path(outputs/judge_compare.jsonl).read_text(encodingutf-8).splitlines() if line.strip()] total len(rows) task_pass sum(1 for r in rows if r[task_check].get(task_completed) yes) sat_positive sum(1 for r in rows if r[satisfaction_judge].get(satisfaction) positive) contradiction sum(1 for r in rows if r.get(need_review)) metrics { total: total, task_pass_rate: round(task_pass / total, 4) if total else 0, satisfaction_positive_rate: round(sat_positive / total, 4) if total else 0, contradiction_rate: round(contradiction / total, 4) if total else 0, } print(json.dumps(metrics, ensure_asciiFalse, indent2))如果要做 A/B 智能体配对评估不要让满意度 judge 单独决定胜者。流程可以改成先跑任务核对得到每个候选的任务完成状态。如果两边任务完成状态不同优先选完成度更高的一方。如果两边都完成再比较满意度、延迟、工具调用次数和风险项。如果两边都未完成标记为无效配对不进入奖励比较。这正好回应了 GAUGE 类研究里的风险能力相近时LLM judge 可能选出奖励更低的一方。把任务核对放在前面可以让“谁会说话”不再压过“谁真的完成任务”。对于 Prompt 工程师来说这比继续调高 judge 的 temperature 或增加字数更有效。批量跑的时候常见瓶颈是速率限制。建议加上本地限速和重试import time import random def call_with_retry(fn, *args, max_retries5, **kwargs): for attempt in range(max_retries): try: return fn(*args, **kwargs) except Exception as exc: if attempt max_retries - 1: raise sleep min(2 ** attempt random.random(), 20) time.sleep(sleep)注意不要并发过高。评估任务通常可以分批跑先跑 50 条校准 prompt再扩大到几百条。每批都保存原始 JSON方便事后复查为什么某个样本被判fail。7. 常见报错与排查清单下面这些问题在给 judge 加任务核对前后都很常见。401 invalid api keyYOUR_API_KEY没有替换或者 Claude Code 读的是旧环境变量。检查ANTHROPIC_AUTH_TOKEN和TAOTOKEN_API_KEY是否写到了正确的配置文件。404 not foundBase URL 可能多写了/v1或少了路径。按产品要求填https://taotoken.net/api不要在 Base URL 后追加 UTM 参数。400 model not found模型名和 TaoToken 控制台不一致。把JUDGE_MODEL换成控制台实际可用的模型再重试。429 rate limit批量评估并发过高。降低并发加入指数退避或把满意度初判和任务核对分批执行。Claude Code 不生效检查settings.json是否在正确位置env字段是否被外层配置覆盖。先在一个新终端里env | grep ANTHROPIC看实际值。Codex 不生效检查config.toml的model_provider是否指向taotokenenv_key是否和 shell 变量一致。不要把ANTHROPIC_*写进 Codex。CC Switch 三件套混乱确认当前激活的 profile 是评估专用 profile并且 provider、model、client 三处没有互相覆盖。judge 仍然误判检查任务核对 prompt 是否允许unknown以及核对项是否可验证。如果核对项写成“用户是否满意”那就又回到了满意度 judge。输出不是 JSON先降低模型温度再在系统 prompt 里强调“只输出 JSON”。如果模型仍不稳定可以加 JSON 修复函数但不要把修复结果当成原始判断。工具轨迹缺失没有工具结果时任务核对只能给unknown。不要把unknown强行改成fail否则会污染指标。排查顺序建议固定先确认 Key 通道再确认 CLI 配置再确认单条 prompt最后才跑批量。很多“judge 不可信”的案例实际是调用层失败后把空结果当成了负面判断。8. 文末 CTA按路径跑通任务核对如果你想把本文的 judge 对照实验跑起来建议按下面路径操作。先用模型对话调阶段 A 和阶段 B 的提示词确认输出 JSON 稳定模型对话https://taotoken.net/models/detail/chat?utm_sourcetaotoken_aicg_blog_endutm_contentjudge_chat如果评估样本变多再考虑用 Coding Plan 做批量回归和提示词迭代Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentjudge_plan然后在控制台创建独立评估 Key把占位符YOUR_API_KEY替换掉创建 API Keyhttps://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentjudge_apikey最后按 Claude Code 文档接入确认settings.json与ANTHROPIC_*配置无误Claude Code 文档https://taotoken.net/doc/ClaudeCodeAnthropic?utm_sourcetaotoken_aicg_blog_endutm_contentjudge_claude_doc整套改法的核心只有一句话TaoToken 只做 Key 通道真正决定评估可信度的是 judge 后面的任务核对。先让满意度 judge 保留用户体验信号再让任务核对逐项找证据当两者冲突时优先相信可验证的任务完成度。这样再去比较智能体才不会把“说得好”误当成“做完了”。