90分钟实测免费模型端点:从怀疑到决策的探针工作坊

用九十行串行探针测量免费模型端点的延迟、错误和记账,再决定自动化能否依赖它。
文章提出一套九十分钟的工作坊流程,用约九十行 Node.js 代码串行调用免费模型端点十二次,记录延迟、状态、错误分类和 usage 字段,把"免费访问能否试用"与"自动化循环能否依赖"分开验证。核心测量原则是串行而非并发,因为限流器会把并发下的延迟分布折叠成阶梯函数,破坏信号。读数字时最该关注的不是中位数,而是 usage 字段是否缺失(意味着成本模型不可靠)、p95 是否逼近超时(意味着尾部会在夜里叫醒人)、以及并发为一是否已出现 429。文章给出决策表把信号映射为行动,并强调十二次样本只够发现存在性问题,不足以估计 p99,整个流程是第一道筛子而非采购替代。
把摘要步骤挪到免费模型端点上,一周后凌晨两点的重构任务开始失败——没人改代码,变的只是响应结构和延迟尾部。这个场景在不同团队反复上演。免费访问回答的是"开发者能否试用模型",而不是"自动化循环能否依赖它"。

为什么要先测量再接入
围绕 AI 工具的疲劳,大多不是对模型本身的疲劳,而是对未经验证的宣称的疲劳。团队因为演示看起来快就采用某个端点,然后在故障中发现:超时没有状态码、用量计数器有时缺失、速率限制藏在没人解析的响应头里。
下面这套探针不评测供应商,只测量一个账号、一个模型、一条网络路径、一个下午的表现。这是一个刻意收窄的结论,也是工作坊唯一愿意捍卫的结论。
九十分钟的时间表
前十分钟定框架:主持人在白板上画出那个失败任务的故事,问全场——你希望提前知道哪个属性?延迟、错误分类法、token 记账通常胜出。
第 10 到 30 分钟做清点:参与者列出自己代码里所有调用模型的地方,标出哪些处在自动化循环里而非人机交互之后。只有自动化调用对本次工作坊有意义。
第 30 到 55 分钟动手构建,两个文件、约九十行代码,从终端运行。第 55 到 70 分钟分析:百分位数、错误计数,以及用量对象缺失时该怎么办这个尴尬问题。第 70 到 85 分钟用后面的决策表把数字变成决定。最后五分钟把停止规则写进代码仓库——没人写下来的决定只是偏好。
练习一:探针本身
探针串行发送同一个固定提示十二次,每次记录一行 JSON。串行很关键:并发看起来漂亮,却会毁掉信号,因为限流器会把延迟分布折叠成阶梯函数。
// probe.mjs — node probe.mjs > runs.jsonl
import { performance } from 'node:perf_hooks';
const BASE = process.env.PROBE_BASE_URL;
const PATH = process.env.PROBE_PATH ?? '/chat/completions';
const KEY = process.env.PROBE_API_KEY;
const MODEL = process.env.PROBE_MODEL;
const N = Number(process.env.PROBE_N ?? 12);
上面的路径是常见的 OpenAI 兼容形态,不是保证。参与者要先对照供应商当前文档确认 base URL 和路径,并把链接写进文件头。
每次调用带 60 秒 AbortController 超时;遇到 429 或 5xx 时读取 retry-after 头,没有就用指数退避加随机抖动重试,最多四次。成功时记录 usage 对象、响应文本长度和前 120 个字符样本。凭证通过环境变量导出,而不是粘贴进文件——主持人在首次执行前会检查这个习惯。
PROBE_BASE_URL="$MC_BASE_URL" PROBE_PATH="/chat/completions" \
PROBE_API_KEY="$MC_API_KEY" PROBE_MODEL="$MC_MODEL" PROBE_N=12 \
node probe.mjs > runs.jsonl
AbortController 是浏览器和 Node.js(v15+)都内置的取消原语,本身并不发起请求。用法是创建一个控制器,把它绑到 fetch 的 signal 选项上,然后在别处(通常是 setTimeout)调用 controller.abort(),挂起的请求会立刻以 AbortError 拒绝。对探针来说这比在调用方包一层 Promise.race 更可靠,因为 Promise.race 只是让外层提前返回,底层连接仍然挂着,会在后续请求里继续占用配额或连接池。注意 AbortError 不是 HTTP 错误——响应根本没回来,状态码是缺失的,所以探针需要把它与 4xx/5xx 分开计数,否则错误分类法会被污染。
retry-after 是 HTTP 响应头,告诉客户端多久之后重试,值可以是秒数或 HTTP 日期。429(Too Many Requests)和部分 503 会带它,但大量免费层的实现干脆省略,这正是文章要求"没有就用指数退避加随机抖动"的原因。指数退避是把等待时间按 2 的幂增长(如 1s、2s、4s、8s),随机抖动是在每段等待上加一个随机量,避免多个客户端在同一时刻齐步重试形成二次冲击。上限四次是为了让一次探针运行不至于因为一个持续限流而拖到不可接受的长度。
练习二:读数字
汇总脚本按状态分组,输出 p50、p95、最大值,以及 usage_reported 的比例。十二个样本的百分位数是描述性的,不是推断性的,脚本打印时应该把这句话说出来。
最值得看的列很少是中位数。如果 usage_reported 不等于成功次数,记账层就不可信,团队建立的任何按请求成本模型都成了猜测。发现这一点的人应该停止调提示词,转去读供应商条款。
p50 是中位数:十二个样本排序后第 6、7 个之间的值,一半请求比它快、一半比它慢。p95 表示 95% 的请求快于该值,只有约 5% 更慢——用十二个样本算 p95,实际上落在第 11 与第 12 个样本之间,几乎是"第二慢的那次",所以它极不稳定。最大值就是字面意义的最慢一次,对发现长尾最敏感,但也最容易被一次网络抖动带偏。三者合看的意义在于:p50 描述常态,p95 描述你会在自动化里多久撞一次异常,最大值告诉你最坏情况有多坏。文章强调"描述性而非推断性",是因为从十二个观测推不出总体分布的形状——没有理由假设延迟服从正态或任何特定分布,尾部通常也不是。
N 与百分位的关系有个粗略的经验门槛:要谈 p95 至少需要几十个样本,p99 需要上百个。十二次能给的是存在性证据——有没有缺失的 usage 字段、有没有 429、尾部是两秒还是二十秒——而不是分位数的精确估计。这也是汇总脚本在被要求输出 p99 时应当报警的原因:那个数字是从两三个样本插值出来的,看起来精确,实则毫无意义。
练习三:一个不动的采集器
办公 Wi-Fi 上的笔记本是糟糕的测量仪器,酒店 Wi-Fi 上的更糟。想让十二次运行跨周可比,就得把采集器放在稳定环境里。
MonkeyCode 提供免费模型访问和免费服务器选项,适合作为第一轮跑这个测试台的位置:探针从固定机器运行,写出 runs.jsonl,团队读文件。端点、当前限制和条款要在会前对照文档确认,而不是会中才查——这里不假设任何配额、硬件规格或时长,因为这些细节会变,工作坊不该教过时的数字。
(披露:本文为 MonkeyCode 产品推广内容的一部分。)
同样的提醒适用于任何免费层:免费服务器是跑测量的地方,不是可用性保证的替代品。需要保证的团队应该去找供应商谈,而不是读一份工作坊大纲。
练习四:现场常见的三个误区
总有人想加并发。让他加,放在另一个文件里,然后对比——出现的阶梯函数就是那堂课。也有人想调提示词直到输出质量好看,那是另一个工作坊,混进来会污染延迟数据。
第三个人会问十二次够不够。够发现缺失的 usage 字段、429 风暴或两秒的尾部;不够估计 p99,有人要求时汇总脚本应该打印警告。
决策表
全场一起填完这张表,然后和探针脚本一起提交。
| 运行信号 | 解读 | 行动 |
|---|---|---|
| p95 远低于循环超时、无错误、usage 存在 | 可预测性足以支撑受控试用 | 在超时和终止开关之后接入,记录每个响应 |
| p50 正常,p95 接近或超过超时 | 尾部会在夜里叫醒人 | 先加低于观测 p95 的超时和回退路径 |
多数成功响应缺少 usage | 成本和 token 预算不可测 | 暂不要在此端点上做预算强制 |
| 并发为一仍出现 429 | 限制比循环假设的更紧 | 批处理、缓存,或把调用移出循环 |
表中的"终止开关"(kill switch)指一段在运行时能立即停止所有模型调用的代码路径,通常是一个环境变量或配置标志,触发后循环退出而不是继续重试。它和超时是两个不同层次的防线:超时限制单次调用能拖多久,终止开关限制整条自动化链能烧多久。没有终止开关的循环在供应商侧出问题时会把错误放大——每次失败都触发重试,重试又触发限流,限流又触发更多重试。
"回退路径"则指主端点不可用或超过阈值时的替代行为,可以是降级到更慢但更稳的端点、排队稍后重试、或直接跳过该步骤并以可识别的方式标记未完成。决策表第二行要求"先加低于观测 p95 的超时",逻辑是:如果超时设得比 p95 还高,那么至少 5% 的调用会在超时前就花掉远超预期的时间,尾部延迟会原封不动地传进你的循环。把超时压在观测 p95 之下,意味着主动放弃那 5%,换取的是循环时长有上界。这个取舍是否可接受取决于任务能否容忍跳过,不能一概而论。
局限与谁该跳过
十二次串行调用只测量一台机器、一条路径、一个时刻。供应商行为会变,免费层条件会变,一个好下午证明不了下个月。探针也不涉及输出质量、数据处理和许可,这些是另有负责人的独立评审。
承担服务水平义务的团队、处理受监管数据却无审查协议的团队、规划生产流量的团队,都不应把这个流程当作采购的替代。它是第一道筛子,不是合同。
对于想每周重跑又不想维护机器的团队,把采集器放到 MonkeyCode 免费服务器上、指向免费模型访问,是组织者所知的最短路径——记得把当前条款带到现场,大声读出来。
相关推荐

FlyEnv 插件实测:可视化运行 llama.cpp 与 GGUF 模型管理
FlyEnv 推出 llama.cpp 官方插件,提供多个 Metal 运行时并存管理、公共 GGUF 仓库索引与模型文件类型标注,以及上下文、线程、GPU 层数等推理参数可视化配置,支持模板与投机解码随模型保存,一键启动本地 LLM 推理服务。

前端如何进阶AI智能体开发?从OpenClaw拆解系统级Agent架构
从B站公开课演示的OpenClaw出发,拆解系统级AI智能体的三层架构与通用公式,分析前端开发者基于TypeScript切入Agent开发的路径、插件化设计与安全记忆层难点,附面试回答框架。

WorkBuddy实战:AI Agent如何自动批量转换与归档文件
通过B站UP主珊瑶老师的实测,对比豆包与WorkBuddy在文件批量转换任务中的表现,解析AI Agent如何从“给方案”到“直接执行”,附完整操作流程与积分消耗参考。