批量跑免费模型前,先测成功率与尾延迟
文章提出在提交大批任务前,以真实并发进行小规模探测,测量可用完成比例和 p95 延迟。结合截止时间余量估算批次耗时,再决定是否使用免费资源。
AI 深度解读
把 2,000 个任务扔进免费 AI 接口,省下的可能是账单,付出的却是整晚的等待。原文用一个场景提醒读者:18:00 提交任务,到 02:00 只拿到 300 份结果,剩余请求消耗在拒绝和配额限制上。这个场景是引子,作者没有提供对应的实测记录。
作者的建议很具体:先用少量请求探测免费通道,再决定整批执行、拆分,还是升级容量或延期。思路值得借鉴,但示例脚本距离可靠的批处理准入检查,还有几处需要补齐。
免费接口能不能用,要看截止时间前能否交付
免费容量通常由多人共享,同一个接口在不同时间的接收能力和延迟可能不同。价格页能告诉你怎么计费,却无法回答今晚这批任务能不能跑完。
作者选了两个指标:接收率(accept rate)和 p95 延迟。前者应该表示拿到可用结果的请求比例;后者观察较慢请求的耗时,并且要在实际使用的并发数下测量。
再加一个业务约束:距离必须交付结果,还剩多少时间。作者称它为 deadline slack,默认设为 240 分钟。
免费通道是否划算,先看任务能否按时完成。
脚本用「任务数 ÷ 并发数」估算执行波次,再乘以成功请求的 p95 延迟。示例中,2,000 个任务、并发 3、p95 为 2.4 秒,算出约 26.7 分钟。
原文给出的健康输出还包括:接收率 1.0、预计消耗 14,800 tokens,以及 RUN_FREE 决策。这些是预期输出,不是作者公布的生产测试成绩。
作者把时间估算标为 optimistic,理由成立:小样本结束后,服务端排队可能继续增长。更准确地说,它只是偏乐观的参考值,不能当作严格的耗时下界,也没有覆盖重试、校验、存储和上传。
先发 12 个请求,再给整批任务设门槛
探测器是一个只用 Python 标准库的脚本,调用兼容 OpenAI 风格的 /chat/completions。每次要求模型只回答 OK,设置 max_tokens: 8、temperature: 0,记录 HTTP 状态、耗时、token 用量和 Retry-After。
运行方式如下,用来测量指定接口在并发 3 下的表现:
export FREE_LANE_KEY=...
python3 probe_free_lane.py \
--endpoint https://your-endpoint/v1 \
--model your-free-model \
--size 12 --concurrency 3 --jobs 2000 --slack-min 240
这里最需要关注的是 --concurrency 3:探测并发应贴近后续任务,否则测出的延迟很难用于估算。其余参数中,--key-env 默认读取 FREE_LANE_KEY,--timeout 默认为 30.0 秒,--canary-id 默认使用 canary-%Y%m%dT%H%M 格式生成标识。
作者建议把探测器部署在队列旁边,让它经过实际任务使用的网络路径。12 个请求占 2,000 个任务的 0.6%,请求数量确实低于 1%;但原文所说的「不到一分钟」依赖接口及时响应,并不是超时配置能保证的结果。
脚本用下面这段逻辑决定是否放行:
if accept < 0.80 or projected_min > a.slack_min:
action = "ESCALATE_OR_DEFER"
elif accept < 0.95 or projected_min > 0.70 * a.slack_min:
action = "SPLIT"
else:
action = "RUN_FREE"
要看清第二个分支:接收率不足 0.95,或者预计耗时超过可用时间的 70%,都会进入 SPLIT。接收率低于 0.80,或者预计耗时已经超时,则升级容量或延期。
这些阈值容易理解,但没有对照数据证明它们适合所有团队。原文开头说有四种动作,代码实际输出三种标签,只是把升级和延期合并了。
探测结果还要设置有效期。作者建议 15 分钟后重新探测,因为共享容量不会替你保留当时的服务水平。
示例最该补的是结果校验和真正的停止机制
脚本把 HTTP 200 全部计为成功,却没有检查 choices 中有没有有效内容,更没有验证回答是否符合任务要求。
对于 AI 批处理,接口返回成功与产物可用之间,还隔着一次业务验收。生成 JSON、代码片段或分类结果,都可能出现状态码正常、内容无法消费的情况。
时间估算也没有把接收率带进计算。即使一部分请求失败,公式仍按所有任务一次完成来算;失败请求的耗时也没有进入成功请求的 p95。这个数字适合初筛,距离交付预测还差一步。
token 估算同样有边界:它把成功探测请求的平均用量乘以 2,000。一个只输出 8 tokens 上限的短请求,无法代表长提示词和长输出的真实消耗。max_tokens 是输出上限,实际消耗仍取决于输入和生成内容。
原文还建议连续出现四次 429 就停止,不重试。但脚本中的 short_circuit 只在所有请求结束后,检查前四条记录是否全是 429。它既不会提前终止,也不会识别后续位置出现的连续四次 429。
STOP_PROBE 文件也只是建议,代码没有实现检查。X-Canary-Id 则负责标识请求,便于关联日志;要按 canary_id 前缀清理产物,下游还得主动保存这个字段,单有请求头不会自动获得撤销能力。
作者提供了本地故障注入器,在 127.0.0.1:8099 启动服务,让探测器访问 http://127.0.0.1:8099/v1。默认 FAIL_RATE = 0.45、LATENCY = 0.08,失败返回 429 和 Retry-After: 30,成功返回 OK,用量为 26 tokens。
理论接收率约为 0.55,但只有 12 次随机请求,单次结果可能偏离不少。把失败率调到 0.9,也不能保证前四次全部失败。这个服务使用单线程 HTTPServer,适合演练错误处理,不适合验证真实并发吞吐。
我的判断
我赞成把探测放在提交整批任务之前。它把一个模糊判断变成可记录的决策:当时接收率多少、预计耗时多少、为什么放行。作者强调最终应沉淀的是阈值及其理由,而不是探测脚本,这一点尤其有用。
但阈值目前属于经验之谈。原文举例说,0.95 的接收率门槛可以用「每二十次拒绝一次,会让尾部完成时间翻倍」来解释,却没有给出任务分布、重试策略或测量数据。不能直接把这句话当作普遍规律。
12 个样本本来也很粗:全部成功时接收率是 1.0,失败一次就约为 0.917,已经触发拆分。它更适合发现通道明显拥堵,难以精确判断服务是否稳定达到 95%。
和失败后自动重试相比,前置探测能减少整批任务入队后的被动处理;不过两者仍需配合。探测通过后,长批次运行期间照样可能限流,需要继续观察和调整。
如果业务承诺硬性 p99 延迟、有严格数据驻留要求,或任务时长超过免费服务器容忍范围,作者建议直接购买容量。这是合理的适用边界。原文也披露文章属于 MonkeyCode 产品推广,但没有提供其当前配额或对照测试,不能据此判断具体产品的容量表现。
能拿来做什么
- 给夜间 AI 批处理增加一次准入检查,先记录接收率、延迟和剩余交付时间,再决定放行、拆分或延期。阈值应根据真实批次复盘,按月检查,探测结果超过 15 分钟则重新获取。
- 按实际任务定义成功标准。若队列消费的是 JSON 或代码产物,就校验对应结构和内容,并用有代表性的输入、输出长度测量耗时与 token 消耗。
- 接入免费通道前,先用本地 429 注入器演练停止逻辑。补上真正的连续失败停止、波次间
STOP_PROBE检查,并确保探测器自身异常时默认延期。 - 用
X-Canary-Id串起请求与产物,保留canary.jsonl用于每周成本复盘,清理载荷和测试产物。小批次应缩小探测规模;原文对 200 个任务的成本提醒存在口径歧义,不宜直接照搬比例。