通过 AI API 网关统一批处理作业:持久队列、提供商适配器和租户级计费
一种通过一个多模型 API 运行耐延迟 AI 工作负载的实用架构:持久作业记录、提供商批量适配器、幂等结果摄取、预算预留和租户级分析。
批处理不应被视为 AI API 网关周围的侧门。如果评估、文档丰富、提取、审核扫描或嵌入作业离开同步请求路径,它们仍然需要租户控制、成本归因、重试、可审核性和使用情况分析。
实现模式是使批量执行成为一流的网关子系统。网关应公开一份与提供商无关的作业合同,同时在幕后适应 OpenAI、Anthropic、Gemini 和未来的提供商批处理 API。
读者问题:批处理 API 意图相似,操作不同
耐延迟工作负载非常适合批处理执行。困难的部分不是决定一份工作是否可以等待。困难的部分是跨提供商一致地操作批处理工作。
已验证的事实: OpenAI 的 Batch API 是异步的,从上传的文件读取请求,将响应写入输出文件,目前使用 24 小时处理窗口。 OpenAI 列出了 validating、failed、in_progress、finalizing、completed、expired、cancelling 和 cancelled 等状态。 Anthropic的消息批次API异步处理许多消息请求,独立处理每个请求,需要轮询,处理结束后返回结果。 Anthropic 还建议有意义的 custom_id 值,因为不保证结果顺序。 Gemini 的 Batch API 公开了长时间运行的操作式方法,例如列表、取消、删除和更新方法,并且其取消操作被描述为尽力而为。
一旦添加实际业务需求,这些差异就很重要:
- 哪个租户、客户、项目或 API 键拥有每个项目?
- 是预算在作业离开网关之前保留?
- 如果批次过期或取消,哪些已完成的项目需要计费?
- 如何在不重复成功工作的情况下重试部分失败?
- 可以检索结果文件多长时间,以及网关应存储什么?
- 合作伙伴能否在不暴露上游提供商的情况下构建客户范围的批处理凭据?
答案不是隐藏每个提供商的差异。答案是标准化操作合约,同时保留提供者本机元数据以进行调试、协调和支持。
建议公开API:将批处理作业与同步完成分开
建议:将批处理作业公开为其自己的API表面,而不是作为聊天完成上的特殊标志。同步请求和异步批处理作业具有不同的生命周期、计费、重试和结果检索语义。
实用的网关合约包括以下操作:
create_job:创建租户、项目、密钥或合作伙伴客户拥有的草稿作业。append_items或upload_manifest:添加包含稳定项目的单独请求标识符。submit:验证、预留预算、选择提供商、调度和锁定提交的清单。get_status:返回标准化作业和项目计数。list_results:分页浏览标准化项目结果、错误和使用情况。cancel:取消请求,但不承诺立即执行终止。export_usage:为分析或计费系统导出作业级和项目级成本记录。
公共作业对象示例:
{
"job_id": "job_01j7...",
"tenant_id": "tenant_acme",
"customer_id": "cust_123",
"endpoint": "chat.completions",
"model": "analysis-large",
"status": "running",
"counts": {
"submitted": 50000,
"completed": 31240,
"failed": 180,
"expired": 0
},
"cost": {
"estimated": "184.20",
"reserved": "205.00",
"settled": "117.43",
"currency": "USD"
},
"created_at": "2026-08-19T10:00:00Z",
"submitted_at": "2026-08-19T10:05:00Z",
"retrieval_deadline": "2026-09-17T10:00:00Z"
}默认情况下,公共对象不应公开提供程序文件 ID、操作名称或原始上游错误。这些属于面向操作员的元数据。
使用持久作业记录作为事实来源
网关拥有的批处理层在向上游提交任何内容之前需要持久状态。不要依赖提供商批次记录作为您唯一的状态存储。提供商记录是必要的,但它们不知道您的租户层次结构、预算预留、内部模型别名、合作伙伴客户或分析要求。
最小数据库模型
有用的架构具有三个级别:
1.批处理作业
batch_jobs
- job_id
- tenant_id
- project_id
- customer_id nullable
- api_key_id
- endpoint
- requested_model
- resolved_provider
- resolved_provider_model
- status
- item_count
- estimated_input_tokens
- estimated_output_tokens
- reserved_amount
- settled_amount
- created_at
- submitted_at
- completed_at
- expires_at
- retrieval_deadline
- cancellation_requested_at2.批次项目
batch_items
- job_id
- item_id
- custom_id
- idempotency_key
- request_hash
- status
- provider_request_index nullable
- estimated_tokens
- actual_input_tokens nullable
- actual_output_tokens nullable
- settled_amount nullable
- result_pointer nullable
- error_code nullable
- retry_of_item_id nullable
- created_at
- settled_at3.提供程序元数据
batch_provider_metadata
- job_id
- provider
- provider_batch_id nullable
- input_file_id nullable
- output_file_id nullable
- error_file_id nullable
- operation_name nullable
- endpoint
- region nullable
- native_status
- native_request_counts jsonb
- last_polled_at
- raw_error_pointer nullable将提供程序元数据与公共作业合同分开,让网关能够在不破坏面向租户的 API 的情况下发展提供程序适配器。
在分派之前需要稳定的项目标识符
建议: 生成网关 job_id,并在之前需要每个项目 custom_id 或幂等密钥派遣。切勿按顺序协调结果。
Anthropic 明确警告结果顺序无法保证,并建议有意义的 custom_id 值。即使提供商似乎维护秩序,网关也不应该依赖它。作业会被分块、重试、取消、部分完成和重新摄取。排序假设最终会失败。
安全的项目标识符格式具有描述性,但不敏感:
tenantA.invoice_extraction.2026-08-19.row_000381避免将原始电子邮件、姓名、文档标题或客户机密放入标识符中。将敏感相关数据存储在您自己的租户数据库中,而不是存储在提供商可见的 ID 中。
在不删除提供商详细信息的情况下规范状态
提供商批量 API 公开不同的生命周期。网关应将它们规范化为仪表板、结算和自动化可以理解的小型内部状态机。
建议的规范化生命周期:
draft:作业存在,但仍可编辑。validating:网关或提供商验证正在运行。queued:接受但尚未处理。running:提供程序正在处理项目。finalizing:提供程序已完成计算并正在准备结果工件。completed:所有接受的项目均已达到最终成功。completed_with_errors:某些项目成功,某些项目失败。expired:提供程序窗口在所有工作之前结束已完成。cancel_requested:租户要求取消,但最终计费工作尚未解决。cancelled:取消已解决。failed:作业级故障阻止了有用的执行。
不要过早将本机提供程序错误折叠到通用标签中。调试时,操作员仍需要访问本机状态、验证错误、请求计数、文件 ID 和操作名称。
在提交之前根据功能矩阵进行验证
建议:在预算预留和提供商分派之前运行预检验证。批处理模式不仅仅是带有延迟的同步模式。提供商的批处理可能不支持某些模型、端点、请求功能、区域和工具配置API。
您的内部能力矩阵应检查:
- 支持的端点:聊天、消息、嵌入、审核或生成。
- 批处理模式的模型资格。
- 最大作业数大小、项目数、请求大小和上传的文件大小。
- 是否禁止流式传输。
- 支持工具使用和函数调用。
- 结构化输出或JSON架构支持。
- 图像、音频或多模式输入支持。
- 区域和居住地约束。
- 提供程序保留和结果检索窗口。
- 批次特定的速率限制和队列限制。
- 取消语义。
良好的预检响应是特定的:
{
"error": "batch_capability_not_supported",
"message": "The selected provider batch adapter does not support streaming responses. Remove stream=true or choose a synchronous endpoint.",
"field": "items[*].request.stream"
}这比接受作业并在上游验证后失败更有用pass.
预留租户预算,然后结算实际使用情况
批量执行会使计费变得复杂,因为在结果文件可用之前,网关可能会失去对准确使用情况的同步访问。安全模式是报价、保留、提交、提取、结算和协调。
已验证的事实: OpenAI 表明与同步 API 相比,批次 API 的定价有折扣,过期或取消的批次可能仍会返回已完成的可计费工作。Anthropic 指出,高吞吐量批处理可能会稍微超出工作区支出限制,因此网关端预留和结算后非常重要。
建议: 在提交之前使用估计代币、选定的提供商价格规则和安全边际预留租户预算。获取结果后,在项目级别确定实际使用情况。如果估计值太高,则释放未使用的预留。如果太低,请应用租户配置的超额政策。
实用分类账事件:
batch.estimated
batch.reserved
batch.submitted
batch.item.settled
batch.item.refunded
batch.cancel_requested
batch.expired
batch.reconciled项目级分类账至关重要。如果 45,000 个项目已完成,其中 5,000 个项目已过期,则租户应为已完成的提供程序工作付费,而不是为作为单个无差别 blob 的原始清单付费。
将提供程序适配器构建为转换器,而不是业务逻辑所有者
每个提供程序适配器应了解如何将网关作业转换为提供程序的批处理格式、提交、轮询或检索状态、下载结果以及将本机结果映射回规范化记录。
将租户策略保留在适配器之外。适配器不应决定客户是否有足够的预算、合作伙伴客户是否被暂停或是否可以存储提示。这些是网关决策。
适配器职责
- 呈现提供程序特定的请求清单。
- 上传输入文件或创建提供程序操作。
- 将提供程序标识符存储在元数据中。
- 将本机状态映射到规范化状态。
- 检索输出和错误工件。
- 解析项目级结果。
- 返回本机使用记录(如果可用)。
- 表面可重试与终端错误。
网关职责
- 对租户和 API 密钥进行身份验证。
- 应用团队、项目和客户控制。
- 解析模型别名和提供商路由策略。
- 验证批量功能。
- 预留和结算预算。
- 保留作业和项目状态。
- 执行保留策略。
- 公开分析和导出。
这种分离使得添加新提供商变得更加容易,而无需重写结算、分析或租户管理。
幂等地提取结果
结果提取是许多批处理系统意外重复收费或丢失部分工作的地方。将摄入视为一个可重复的过程。下载相同的输出文件两次、处理相同的提供程序操作两次或重播相同的 Webhook 事件两次应该是安全的。
建议: 使用项目级幂等性密钥和账本唯一性约束。即使重试提取,job_id + custom_id 的结果也应该准确解决一次。
强大的提取流程:
- 获取作业或结果工件的短期锁定。
- 获取提供程序输出和错误工件。
- 将记录解析为标准化项目结果事件。
- 通过以下方式匹配每个记录
custom_id或网关项目 ID。 - 在事务中写入结果元数据和使用情况。
- 仅在分类帐结算事件尚不存在时创建分类帐结算事件。
- 根据项目状态而不是假设更新作业计数。
- 在已知所有终端状态时释放未使用的预算预留。
如果网络挂钩可用,验证签名并防止重放。如果需要轮询,请使用自适应轮询:在接近预期完成时频繁轮询,在长时间运行期间后退,并在最终结算后停止。
重试项目,而不是整个作业
建议:尽可能在项目级别重试。整个作业重试很简单,但会增加重复工作的风险并使计费变得更加困难。
在重试之前对失败进行分类:
- 验证错误: 通常会终止,直到请求得到修复。
- 提供商 5xx 错误: 通常可通过以下方式重试退避。
- 配额或速率限制失败:仅在容量可用后重试。
- 安全块:不要盲目重试;路由到政策处理。
- 过期项目: 如果租户仍希望工作且预算允许,则可以在新作业中重试。
重试应创建链接到原始项目的新项目:
{
"item_id": "item_retry_002",
"retry_of_item_id": "item_001",
"custom_id": "tenantA.eval.row_901.retry_1"
}不要仅仅因为已完成的项目属于以 completed_with_errors 或结尾的作业的一部分而重新提交它们expired.
决定存储什么:原始结果、指针或哈希值
批处理系统是累积提示和输出的诱人场所。这对于导出和调试可能很有用,但会增加数据保留责任。
建议:使存储策略租户可配置。对于敏感工作负载,存储元数据、哈希值、使用情况和结果指针,而不是原始提示和输出。对于不太敏感的工作负载,如果保留窗口、访问控制和删除工作流程清晰,标准化结果存储可能是可以接受的。
至少跟踪:
- 是否存储了原始输入。
- 是否存储了原始输出。
- 提供程序结果工件所在的位置。
- 提供程序检索截止时间。
- 网关删除截止日期。
- 用于审核的请求和响应的哈希值,无需暴露内容。
已验证的事实: Anthropic 表示批次结果在创建后 29 天内可用,并在工作区中隔离。这种特定于提供商的检索窗口应反映在网关的元数据和面向租户的导出中。
公开与团队运作方式相匹配的分析
批量分析应同时存在于作业和项目级别。产品负责人想知道夜间强化是否完成。财务管理员需要按租户、模型和客户划分的成本。工程师想知道要重试哪个失败类别。
有用的指标包括:
- 已提交、已完成、失败、过期和取消的项目计数。
- 预计成本与结算成本。
- 仍保留预留预算。
- 提供商的输入和输出令牌以及模型。
- 提供程序公开的缓存命中指示器。
- 重试计数和重试成功率。
- 排队、运行和完成状态的平均时间。
- 按端点和模型划分的主要验证错误。
- 合作伙伴客户归因。
对于合作伙伴API 个用户,将批处理作业公开为客户范围的资源。这使得代理机构和 SaaS 构建者能够提供离线 AI 处理,同时在网关内保留上游提供商凭据、计费对账和速率限制处理。
进行明确权衡
网关抽象与提供商特定功能:统一合同可简化集成,但无法使每个提供商的功能都相同。保持能力错误的明确性。
预算预留与估算准确性:预留可以保护租户免受工作失控的影响,但估算可能是错误的。账本必须支持调整、退款和超额处理。
轮询与 Webhook: 轮询简单可靠,但可能会浪费 API 调用并延迟完成。 Webhook 速度更快,但需要签名验证、重放保护和监控。
原始结果存储与保留最小化:存储标准化结果可改进导出和分析,但会增加合规负担。敏感的租户可能更喜欢指针和哈希。
大批量与分块批量:大批量可能会提高提供商端效率,但较小的分块会减少爆炸半径并使重试更容易。
实施清单
- 创建单独的批处理作业 API 表面。
- 保留作业和项目在提供程序提交之前记录。
- 需要网关作业 ID 和每个项目的自定义 ID。
- 在存储本机提供程序元数据时标准化状态。
- 为每个提供程序批量适配器构建功能矩阵。
- 在预留预算之前验证清单。
- 在之前预留租户预算调度。
- 提取后在项目级别确定实际使用情况。
- 使结果提取幂等。
- 有选择地重试失败的项目,而不是盲目地重试整个作业。
- 跟踪提供程序检索截止时间和网关保留政策。
- 向租户和合作伙伴公开作业和项目分析客户。
预测:此模式的发展方向
预测:批量执行将成为 AI 自动化基础设施的正常组成部分,而不仅仅是折扣机制。随着团队运行更多的评估、数据清理任务、安全审查和丰富管道,他们将期望异步工作负载具有与同步 API 调用相同的治理。
预测: 提供程序批处理 API 将继续以有用的方式出现差异。有些将针对文件进行优化,另一些将针对长时间运行的操作进行优化,还有一些将针对托管数据集或事件回调进行优化。网关适配器层将变得更有价值,而不是更有价值,因为适配器之上的操作合同可以保持稳定。
可行的结论
不要将批处理固定到 AI API 网关上,作为特定于提供商的逃生舱口。将其构建为一个持久的子系统,具有自己的作业记录、项目标识符、状态模型、提供商适配器、预算预留、幂等摄取和分析。
最重要的设计选择是项目级会计。一旦批次中的每个请求都有稳定的身份,网关就可以协调无序的结果,仅重试失败的工作,仅对已完成的提供商工作进行计费,并向租户显示发生的情况。这就是向提供商发送文件和为异步工作负载运行可靠的多模型 API 之间的区别。