@ agentproto/ 夹子
一份供应商批量推断API合同——提交 N Anthropic
信息形状的请求、民意测验和收集结果 custom_id, (中文(简体) ),
而不关心哪个供货商经营它们。 没有 SDK 道具: 原始 fetch + .
为什么
Anthropic和OpenRouter都以50%的令牌暴露出Aync Batch API
价格: 最多提交100克请求,获取批次id回执,进行投票,收集
在24小时窗口内得出结果。 批次为 不是一个模型 - 这是送货模式
包裹在同一信件正文上(model, (中文(简体) ), system, (中文(简体) ), messages, (中文(简体) ),
max_tokens, (中文(简体) ), tools(......) (中文(简体) ). 此软件包会给呼叫者( 静态、 eval)
判断, 数据集生成, 代理扇出) 1 BatchDriver 合同性质
他们不需要每个供应商的信封 特写.
合同
interface BatchDriver {
readonly id: string
submit(requests: readonly BatchRequest[], opts?: BatchSubmitOptions): Promise<BatchHandle>
status(handle: BatchHandle): Promise<BatchStatus>
results(handle: BatchHandle): AsyncIterable<BatchResult>
cancel(handle: BatchHandle): Promise<void>
}
BatchRequest = { customId, body: MessagesBody }—— 说body一样 Anthropic Messages 形状 您会同步发送.BatchHandle.id是我们的b_<ulid>在整个进程重新启动时保持稳定;provider.batchIds所分配的API(驱动程序) 扇出数个——见下文OpenRouter).- 结果按键
customId, (中文(简体) ), 从不按位置 ——批次API返回 他们随意行事. expired这不是失败。 意思是那东西从没跑过24小时 窗口,应当重新提交expiredCustomIds(results)寻找 哪个.
import {
anthropicBatchDriver,
pollUntilEnded,
collectResults,
expiredCustomIds,
} from "@agentproto/batch"
const driver = anthropicBatchDriver({ apiKey: process.env.ANTHROPIC_API_KEY! })
const handle = await driver.submit([
{ customId: "doc-1", body: { model: "claude-sonnet-5", max_tokens: 1024, messages: [...] } },
])
await pollUntilEnded(driver, handle, { onTick: s => console.error(s.counts) })
const results = await collectResults(driver, handle)
const toResubmit = expiredCustomIds(results.values())
提交前验证
validateForBatch(request) 拒绝批量信封不能携带的字段——
stream, (中文(简体) ), speed, (中文(简体) ), fallbacks, (中文(简体) ), max_tokens < 1和强迫 tool_choice
联 合 国 any编号 :tool - 点出违法者的名字 customId。 。 。 . validateBatchRequests
也拒绝重复 customId横跨提交文件(结果将是
(见A/CN.9/WG.III/WP.III/WP.1号文件)。 每个司机 submit() 说话前运行此选项
一个供应商.
持久存储
BatchStore 持续批次为 <stateDir>/batches/<id>/{manifest.json, requests.jsonl, results.jsonl} 因此,它活过这个过程,任何人与
id可以通过 store.load(id)。 。 。 . stateDir 是一个明确的构造器
选项;此软件包从不默认为真正的主目录.
import { BatchStore } from "@agentproto/batch"
const store = new BatchStore({ stateDir: "/path/to/workspace/.batch" })
司机
anthropicBatchDriver({ apiKey, baseUrl?, fetch? })
每一份呈报一份供应商批次. results() 溪流 results_url这是JSONL
逐行排列. cancel() 张贴文档取消的结束点.
openrouterBatchDriver({ apiKey, baseUrl?, fetch? })
OpenRouter的批次API(β)范围将一个供应商批次改为一个型号,因此是
向N供应商批次提交混合型号风扇——按
body.model,每组1 POST endpoint: "/v1/messages" (安东尼)
身体形状,通过现在。 请求对象的密钥顺序
(单位:千美元)endpoint, (中文(简体) ), model, (中文(简体) ), requests)是故意的——OpenRouter流派
这个. cancel() 掷出 BatchUnsupportedError 而不是假装
工作——OpenRouter的β道克不记录一.
提交方的供应商批次的状态/汇总是准确的
所提交的驱动实例仍为常住(每个组)
customId 列表在内存中缓存; 整个进程重新启动, 无
缓存, status() 仍然数到手柄的全部要求,但不能
将部分进展归为正在运行的特定组.
localQueueDriver({ complete, concurrency?, store, retry? })
模拟没有批量API的供应商(请求、月光照片、,
Groq, xAI, 一个本地的wllm-endpoint...). 通过注入的每个请求运行
complete(body) 重试一发
RetryableCompletionError (信号 a complete 实施工作的用途
a 429/5xx,来自其基本供应商),备份最多 retry.max
在记录永久记录之前 errored 结果。 每个结果都是
附 录 store 当它降落时. 全价——没有供货方
批次可获得50%的折扣.
submit() 将每个未决项目运行到解决前完成(有
没有外部服务来投票)。 如果进程在中跑中坠入, 将会有新鲜的
localQueueDriver 指向同一个商店可以调用额外
resume(handle) 方法——不属于共享 BatchDriver 合同——至
重新装入原请求, 只重新运行仍然缺少的
结果.
帮助者
pollUntilEnded(driver, handle, { intervalMs?, timeoutMs?, onTick? })—— 说 民意调查status()直至ended编号 :failed(默认24小时超时, 匹配) 每个供应商的批量窗口).collectResults(driver, handle)- 排水沟results()改为 aMap<customId, BatchResult>。 。 。 .
这个包裹故意不做的
没有OpenAI/Gemini/Mistral本地批量驱动程序,没有守护进程MCP/CLI工具,没有
cron投票,没有模型目录批次定价场. MessagesBody 覆盖
anthropic 信件只请求形状——批量信封,而不是 a
提供者-不可知请求格式.
许可证
阿帕奇 - 2.0