评估推理强度
本应用通过 Grok API 建立评估工具,用你自己的测试用例比较各档推理强度,从而找出哪些任务无需为额外推理付费。
提供提示词及一组带预期答案的测试用例。应用会将每个用例交给 grok-4.7,分别以 low、medium、high 和 xhigh 推理强度生成答案,逐个评分,再绘制准确率与成本的对比图。最后选出与最高准确率相差不超过 5 个百分点且费用最低的档位。示例既可在网页中运行,也可在终端运行。自带的任务包含虚构开票应用的 30 张支持工单,要求 Grok 为每张工单选择类别和优先级,并撰写回复。
增加推理并不总能带来收益。对于示例中的简短工单,medium、high 和 xhigh 每次回答使用的推理 token 都在 600 左右,因此成本接近。low 约用 140 个,费用约为一半。我们多次运行时,各档准确率都在 87% 到 93% 之间,表现最好的档位每次都有可能不同。
你将学到什么
用代码先检查有标准答案的字段,只把通过的答案交给大语言模型评审;它会按照评分标准评估自由文本,并以结构化输出返回判定
保持评审公平:不向评审模型透露答案来自哪个强度档位;两两比较答案时,将两种排列顺序都评一遍
为每个任务定义一份 Zod schema,在请求中将其用作 JSON Schema,并用同一份 schema 验证答复,调用
toJson(schema)限制并发数来运行大量请求,让 SDK 对限流请求退避重试
从以下字段获取每次请求的费用:
usage;测量延迟,按每 1,000 个答案的费用比较不同档位通过 Batch API 发送整次运行的请求,不占用速率配额
运行示例
需要 Node.js 22.13 或更高版本。将 API 密钥放入 .env(位于仓库根目录),或导出环境变量 XAI_API_KEY。
cd examples/reasoning-effort-evals/typescript
npm install
npm run web打开 http://localhost:3000,点击 Run the sample。网页是一个评估仪表板。每行代表一个推理强度,每个单元格代表一个用例:Grok 回答时单元格闪动,评分后变为绿色或红色。最新的答案流式出现在右侧。随着答案陆续返回,各档位的数据点会在准确率与成本图上移动;最后一个答案评分完成后,点变为实心。所有档位完成后,顶部文字会推荐应使用的档位,图上会以阴影标出与最高准确率相差不超过 5 个百分点的区域。点击数据点、评分表的行或单元格,可查看相应档位的错误答案,包括原始工单、代码检查结果、评审扣分的原因以及 Grok 的推理过程。点击 Stop 或关闭网页即可取消运行。
要评估自己的提示词,请点击 Edit prompt and cases,粘贴提示词,并将字段、评分标准和用例替换为你自己的内容。页面会在运行前检查这些内容。使用终端时,传入任务文件即可;不传则会运行示例:
npm start -- your-task.json两个版本都会将每个答案、检查、费用和延迟保存至 output/<task>-<time>.json。运行一次示例将生成 120 个答案,最多发起约 180 次评分请求。我们的每次运行耗时 4 至 6 分钟,花费约 $1.05,答题与评分各占一半。网页和终端都会在结束时显示总费用。延迟包括遇到限流后的等待时间。
使用自己的任务
任务用 JSON 文件定义,例如 sample-task.json:
{
"name": "Support ticket triage",
"prompt": "You triage support tickets for Fernbill...",
"fields": {
"category": { "options": ["billing", "payments", "bug"] },
"priority": { "options": ["urgent", "high", "normal", "low"] },
"reply": { "max_words": 80 }
},
"rubric": {
"accurate": "Everything it says about Fernbill matches the facts in the instructions."
},
"cases": [
{
"id": "t01",
"input": "Plan: Pro\n\nI was charged twice this month.",
"expected": { "category": "billing", "priority": "high" },
"notes": "Says the duplicate charge will be refunded within 5 to 10 business days."
}
]
}prompt是系统提示词,可以是一个字符串,也可以是由多行字符串组成的数组。fields定义 Grok 返回的答案结构。带options的字段为选择题,其余字段为自由文本。max_words限制字段长度。expected保存有标准答案的各字段的正确值,由代码进行检查。rubric列出评审需要在自由文本中检查的项目,而notes说明对该用例的理想回答应涵盖哪些内容。省略评分标准即可只用代码评分。
批处理模式
在网页上切换到 grok-4.3 Batch API,或传入 --batch 命令行选项,即可在一个批次中发送所有答题请求:
npm start -- --batch批处理请求不占用速率配额,在一次运行包含数千个请求时尤为重要。本示例所用的 Batch API 尚不接受 grok-4.7,因此批处理模式评估的是 grok-4.3。它支持相同的四档推理强度,且价格更低;批处理模式下更便宜,因为批处理请求享有折扣。我们的测试批次约两分钟完成,但 API 只承诺大多数批次在 24 小时内完成。每个答案一返回便会评分,评审仍然实时运行。由于批处理请求会在队列中等待,批处理模式不测量延迟。停止运行会取消批次,尚未执行的请求不会计费。
工作原理
任务格式位于 src/task.ts,执行逻辑位于 src/scorecard.ts。runScorecard() 执行以下步骤。每完成一个答案的评分就报告该答案,在某个档位的所有答案评完后就报告该档位,因此网页和终端可用各自的方式显示相同的进度:
parseTask()使用 Zod 验证任务,并检查每个预期答案是否属于相应字段的可选值。除 SDK 外,唯一依赖是 Zod。Node 没有内置 schema 验证器,下一步还会用同一库构建答案 schema。answerSchema()将任务字段转为 Zod 对象,使用z.enum()定义带可选值的字段。z.toJSONSchema()将其转为 JSON Schema,供text.format使用,而response.toJson(schema)会根据它验证每个答案并为结果赋予类型,从而将格式错误的答案判为错误,不会导致运行中断。每个用例都按全部强度档位排队,优先执行最低档。
limit()保持 24 个请求并发。速率限制按团队计算,同时运行 24 个请求可能触发限流。SDK 遇到429会自动退避重试。创建客户端时将重试配置设为maxRetries: 5,取代默认的 2 次。它的onResponse钩子统计重试数,网页会显示这一数字。答题请求共享同一个prompt_cache_key,因此会发往同一服务器,复用缓存的提示词。create()发送请求,并设置一分钟的idleTimeout。Grok 推理时会流式输出内容,因此如果一分钟都没有输出,可判断请求已停滞,再重试一次。SDK 不会自行重试这种情况,它只重试未产生任何输出就发生的故障。grade()首先运行代码检查。checkAnswer()核对每个有预期答案的字段,并统计设置了max_words的字段中的词数。只有全部通过的答案才会进入judge():如果工单类别选错,无论评审如何评价回复,这条答案都是错的,而调用评审模型还会产生费用。judge()将评分标准、Grok 执行的指令、用例、用例备注和自由文本发送给grok-4.7,使用 low 推理强度,以结构化输出取得各项标准的判定。Schema 要求先给出理由,再给出判定,促使评审先解释再决定。评审看不到答案来自哪个档位。评分标准和指令排在最前面,所有评分请求都能共享缓存前缀。只有通过全部检查的答案才算正确。每个请求的费用取自
usage.cost_usd,延迟则由包围该请求的计时器测得。pickSetting()以最高准确率为基准,在误差阈值TOLERANCE(5 个百分点)以内选取最便宜的档位。30 个用例中,每个用例占 3 个百分点以上,一两个用例的差别可能只是噪声。成本也会波动,因此低于最高分的档位只有在节省的费用至少达到MIN_SAVING(10%)时才会被选中。如果选中的档位并非得分最高的档位,
compareSettings()会将两者的自由文本答案逐对比较。评审模型常偏向某个位置,因此每对答案会交换顺序评两次,只有两次结果一致才计为获胜。
批处理模式下,sendBatch() 位于 src/batch.ts 中,先调用 client.batches.create() 创建批次,再通过 client.batches.requests.add() 添加每个答题请求,并轮询 client.batches.results()(每 10 秒一次)。每个返回的答案都会立即移交评分,其余请求此时仍可继续等待。批结果采用 Chat Completions 格式,SDK 将其作为普通 JSON 而非响应对象返回,因此 fromBatchResult() 会直接用 Zod schema 验证。每条结果通过 cost_in_usd_ticks 报告费用,100 亿个计量单位等于 1 美元。
src/server.ts 是一个小型 node:http 服务器。EventSource 只能发送 GET 请求,因此页面先将任务 POST 到 /api/tasks,再打开 /api/scorecard,传入返回的 ID。服务器运行 runScorecard(),通过 SSE 将每一步发送到网页,并且只提供本次运行保存的结果文件。它会将 AbortSignal 传给每个请求,在页面关闭时中止请求。public/index.html 使用原生 HTML 和 JavaScript,将这些事件显示在仪表板上。src/index.ts 在终端中完成相同的工作,并打印评分表和所选档位答错的用例。