从写代码,到创作下一幕

探索 字节跳动 - 火山方舟 的 AI 编程与视频创作活动。

火山方舟 Agent Plan 与 Coding Plan 活动,价格 ¥9.9 起

Agent Plan & Coding Plan

一站体验多款热门模型,为 AI 编程与智能体开发提供更多选择。新用户可联系(微信: goo_lvyouyou)免费体验 9.9 agent plan。

查看套餐优惠
Seedance 2.5 视频创作活动:30 秒视频、多模态参考、局部编辑

Seedance 2.5

让创意,跃然成片。探索 30 秒视频、多模态参考与局部编辑,把脑海中的画面变成下一支作品。

探索视频创作

评估推理强度

查看 Markdown

本应用通过 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。

Bash

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,粘贴提示词,并将字段、评分标准和用例替换为你自己的内容。页面会在运行前检查这些内容。使用终端时,传入任务文件即可;不传则会运行示例:

Bash

npm start -- your-task.json

两个版本都会将每个答案、检查、费用和延迟保存至 output/<task>-<time>.json。运行一次示例将生成 120 个答案,最多发起约 180 次评分请求。我们的每次运行耗时 4 至 6 分钟,花费约 $1.05,答题与评分各占一半。网页和终端都会在结束时显示总费用。延迟包括遇到限流后的等待时间。

使用自己的任务

任务用 JSON 文件定义,例如 sample-task.json:

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 命令行选项,即可在一个批次中发送所有答题请求:

Bash

npm start -- --batch

批处理请求不占用速率配额,在一次运行包含数千个请求时尤为重要。本示例所用的 Batch API 尚不接受 grok-4.7,因此批处理模式评估的是 grok-4.3。它支持相同的四档推理强度,且价格更低;批处理模式下更便宜,因为批处理请求享有折扣。我们的测试批次约两分钟完成,但 API 只承诺大多数批次在 24 小时内完成。每个答案一返回便会评分,评审仍然实时运行。由于批处理请求会在队列中等待,批处理模式不测量延迟。停止运行会取消批次,尚未执行的请求不会计费。

工作原理

任务格式位于 src/task.ts,执行逻辑位于 src/scorecard.ts。runScorecard() 执行以下步骤。每完成一个答案的评分就报告该答案,在某个档位的所有答案评完后就报告该档位,因此网页和终端可用各自的方式显示相同的进度:

  1. parseTask() 使用 Zod 验证任务,并检查每个预期答案是否属于相应字段的可选值。除 SDK 外,唯一依赖是 Zod。Node 没有内置 schema 验证器,下一步还会用同一库构建答案 schema。

  2. answerSchema() 将任务字段转为 Zod 对象,使用 z.enum() 定义带可选值的字段。z.toJSONSchema() 将其转为 JSON Schema,供 text.format 使用,而 response.toJson(schema) 会根据它验证每个答案并为结果赋予类型,从而将格式错误的答案判为错误,不会导致运行中断。

  3. 每个用例都按全部强度档位排队,优先执行最低档。limit() 保持 24 个请求并发。速率限制按团队计算,同时运行 24 个请求可能触发限流。SDK 遇到 429 会自动退避重试。创建客户端时将重试配置设为 maxRetries: 5,取代默认的 2 次。它的 onResponse 钩子统计重试数,网页会显示这一数字。答题请求共享同一个 prompt_cache_key,因此会发往同一服务器,复用缓存的提示词。

  4. create() 发送请求,并设置一分钟的 idleTimeout。Grok 推理时会流式输出内容,因此如果一分钟都没有输出,可判断请求已停滞,再重试一次。SDK 不会自行重试这种情况,它只重试未产生任何输出就发生的故障。

  5. grade() 首先运行代码检查。checkAnswer() 核对每个有预期答案的字段,并统计设置了 max_words 的字段中的词数。只有全部通过的答案才会进入 judge():如果工单类别选错,无论评审如何评价回复,这条答案都是错的,而调用评审模型还会产生费用。

  6. judge() 将评分标准、Grok 执行的指令、用例、用例备注和自由文本发送给 grok-4.7,使用 low 推理强度,以结构化输出取得各项标准的判定。Schema 要求先给出理由,再给出判定,促使评审先解释再决定。评审看不到答案来自哪个档位。评分标准和指令排在最前面,所有评分请求都能共享缓存前缀。只有通过全部检查的答案才算正确。

  7. 每个请求的费用取自 usage.cost_usd,延迟则由包围该请求的计时器测得。pickSetting() 以最高准确率为基准,在误差阈值 TOLERANCE(5 个百分点)以内选取最便宜的档位。30 个用例中,每个用例占 3 个百分点以上,一两个用例的差别可能只是噪声。成本也会波动,因此低于最高分的档位只有在节省的费用至少达到 MIN_SAVING(10%)时才会被选中。

  8. 如果选中的档位并非得分最高的档位,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 在终端中完成相同的工作,并打印评分表和所选档位答错的用例。