#AI#DevOps

LLM 批量推理与离线任务

不是所有 LLM 任务都要实时——批量分类、摘要、标注、内容生成这类离线任务,用 Batch API 能省一半。本文讲清 LLM 批量推理的价值与场景、各家 Batch API(OpenAI/Anthropic,通常 50% 折扣)、自部署批量(vLLM continuous batching)、任务管线(提交/轮询/重试/成本),以及实时 vs 批量的取舍。

本文要点

  • 主题聚焦:AI、DevOps
  • 适合人群:独立开发者、全栈工程师、AI 应用开发者
  • 核心价值:快速理解背景、实践路径、常见误区和工程建议
作者 @admin·发布于 2026年7月10日·更新于 2026年7月23日

大多数团队把 LLM 当成同步的"请求-响应"服务:用户点一下,前端调一次,等模型吐完,返回。这对聊天、搜索、Copilot 这类交互场景没问题。可一旦业务里冒出"给十万条工单分类""为一万篇文档生成摘要""每晚把当天新增内容打标签"这类活,同步实时调用就成了最贵、最笨的解法——你明明有几小时的时间窗,却按"立即返回"的优先级付了钱。

LLM 推理的成本其实有两档:实时档贵(你为低延迟和弹性算力付溢价),离线档便宜(供应商把你的请求塞进闲时算力慢慢跑)。批量的本质就是用延迟换价格——把"不需要立刻拿到结果"的请求攒成一堆,异步提交,几小时后取结果,直接对折。不是所有任务都该走批量,但有相当一部分该走却走了实时。

一、实时 vs 批量:你为"立刻"这三个字付了多少溢价

实时推理贵,不是供应商黑心,是成本结构决定的。实时流量要求低延迟和弹性峰值算力——你的请求一来,GPU 必须立刻接得住,峰值还要能扩。这意味着供应商得常备一批利用率不可能满载的算力,这笔闲置成本最终摊进实时单价。

而批量请求的特点恰好相反:不在乎几小时延迟,可以排队。供应商就能把它塞进算力的"低谷时段"、和实时请求抢不到的零碎 GPU 时间里跑,GPU 利用率拉满。省下来的钱,供应商以折扣还给你——OpenAI 和 Anthropic 的 Batch API 都是标价 50% off,这不是促销,是经济学。

一条粗略的成本曲线:

text
延迟容忍度          推荐路径              相对成本
─────────────────────────────────────────────────
< 2 秒(交互)       实时 + 流式           1.0x
几秒~几分钟        实时(可缓存)         0.3~0.5x(命中缓存)
几十分钟~几小时    Batch API             0.5x
几个小时~隔夜      Batch + prompt cache  0.1~0.2x

关键判断不是"这活儿难不难",而是"这活儿用户在不在等"。 用户在前端等的,再贵也得实时;没人等的后台批处理,走实时就是白烧钱。

二、适合批量的五类场景

批量不是万能,但它能稳定吃下这几类"量大、非交互、可重跑"的任务:

  1. 数据分类 / 打标签。给客服工单分派类目、给内容打风险等级、给用户评论判情感。这类任务动辄几十万条,每条只产出几个 token,实时跑 API 费用几乎全在输入上,批量直接砍一半。
  2. 文档摘要 / 信息抽取。给一堆合同抽关键字段、给长报告生成摘要、给商品页提取结构化属性。输入长、输出短,延迟不敏感,天然适合攒批。
  3. 内容批量生成。SEO 落地页文案、商品描述、邮件营销文案的批量起草。隔夜跑完第二天人工 review,延迟换价格非常划算。
  4. 评测集跑分。研发阶段在几千条 eval set 上跑模型对比,本来就不是给用户看的。用 Batch API 跑评测,成本减半,且可以一次性跑多组模型/多版 prompt 对比。
  5. ETL 管线里的 LLM 步骤。数据Pipeline 里"用 LLM 清洗 / 富化 / 转换"那一环——比如把非结构化简历转成结构化 JSON 入库。它本就在离线链路里,没有任何理由走实时。

共同特征很清晰:延迟可容忍、量大、失败可重跑、单条产出相对独立。反例也明显:多轮对话、带工具调用的 Agent、用户实时盯着的结果——这些走实时,别硬塞批量。

三、各家 Batch API:提交 JSONL → 异步处理 → 拿结果,通常 50% off

OpenAI 和 Anthropic 的 Batch API 设计高度一致:你把一批 Messages 请求写成 JSONL(每行一个独立请求,带个你自定义的 custom_id),提交后拿一个 batch id,几小时内轮询状态,完成后逐行取结果。折扣都是对折。

以 Anthropic Message Batches 为例(TypeScript,几个硬约束先记下:单批最多 10 万请求或 256MB,多数批次 1 小时内完成、最长 24 小时,结果保留 29 天,50% off):

typescript
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();

// 1. 提交:requests 里每个请求带 custom_id + 完整的 messages 参数
const batch = await client.messages.batches.create({
  requests: tickets.map((t, i) => ({
    custom_id: `ticket-${t.id}`,            // 结果按它对回原数据,别按顺序
    params: {
      model: "claude-haiku-4-5",
      max_tokens: 64,
      messages: [{ role: "user", content: `分类以下工单的类目:\n${t.text}` }],
    },
  })),
});

// 2. 轮询:processing_status 从 in_progress → ended
while (true) {
  const b = await client.messages.batches.retrieve(batch.id);
  if (b.processing_status === "ended") break;
  await new Promise(r => setTimeout(r, 60_000));
}

// 3. 取结果:顺序不保证!必须用 custom_id 做 key
const results = new Map<string, string>();
for await (const r of client.messages.batches.results(batch.id)) {
  if (r.result.type === "succeeded") {
    results.set(r.custom_id, r.result.message.content[0].text ?? "");
  } else if (r.result.type === "errored") {
    // 部分失败是常态,见下一节的管线设计
  }
}

OpenAI 的 /v1/batches 几乎同构,差别只在入参是先上传一个 JSONL 文件再拿 file_id 去创建 batch。两边都支持叠加 prompt caching:稳定前缀(system prompt、few-shot)命中的那部分在批量折扣之外还能再省,理论上综合能压到原价的 10%~20%。还有个常被忽略的点:batch 的限流比实时 API 宽松得多——实时被 TPM 卡住跑不动的大批量,走 batch 往往一次就过。

四、自部署批量:vLLM 的 continuous batching 扛高吞吐

调用闭源 Batch API 是最省事的降本路径,但有两个场景你得自部署:数据合规(数据不能出你的 VPC)和成本极限(海量调用下,自跑开源模型单价比任何 API 都低)。这时你要的不是某个 Batch 接口,而是一个高吞吐推理引擎,首推 vLLM。

vLLM 之所以吞吐高,核心是 continuous batching(也叫 in-flight batching / iteration-level scheduling)。传统批处理要"凑齐一批再跑",凑批等延迟、批内长短不一又浪费 GPU;continuous batching 把调度粒度降到每次 forward 级别——新请求随时插进正在跑的 batch,生成完的请求立刻让位、腾出位置给排队里的下一条。GPU 始终保持饱和,显存碎片被 PagedAttention 压住,显存利用率拉满。

text
传统 static batching:    [等凑满 8 条] → [8 条一起跑完] → [等凑满下一批]
                         空等 + 短请求被长请求拖累

vLLM continuous batching: [3 条在跑] → 第 4 条进 → 第 1 条完,立刻塞第 5 条 → ...
                          GPU 不空转,吞吐数倍于静态批

起一个面向批量的 vLLM 服务,关键就几个参数:

bash
vllm serve Qwen/Qwen2.5-7B-Instruct \
  --max-num-seqs 256          # 并发请求数,显存允许就调大,吞吐基本线性涨
  --gpu-memory-utilization 0.9
  --enable-prefix-caching     # 复用稳定前缀,自部署版的 prompt caching

然后你直接用 OpenAI 兼容的 /v1/chat/completions 批量打过去就行——vLLM 的 continuous batching 在服务端自动生效,客户端只是并发地发请求。自部署的代价是你要管 GPU、显存、模型权重升级;收益是数据不出域、且边际成本趋近于电费+折旧。数据敏感、量又大、能接受开源模型质量的场景,自部署批量是闭源 Batch API 的正选替代。

五、把批量当"任务管线"来建,而不是"调一次 API"

新手把 Batch 当一次性函数调,老手把它当一条离线任务管线来运维。一个生产级批量管线至少要有这五段:

text
组装 JSONL → 提交 batch → 轮询状态 → 下载结果 → 失败重试 + 成本统计
   │            │           │          │              │
   持久化       记录        指数退避    按 custom_id   单条降级实时
   原始请求     batch_id    不阻塞      对回原数据     重算 + 核账

几个实战要点:

  • 原始请求落库。提交前把每条请求(custom_id + payload)写进表/对象存储。Batch 结果只能拿 custom_id 对回数据,原始请求丢了就再也串不起来。
  • 轮询别阻塞主流程。批量是异步的,你的提交进程不该死等。用 cron 或任务队列定时 retrieve,状态变了再推进。
  • 部分失败要单独重试,不要整批重跑。Batch 里总有几条因为 prompt 超长、内容触发安全策略等失败。把这些 errored 条目抽出来,要么改 prompt 重投批量,要么降级走实时 API——个别失败不该让整批结果卡着不出。
  • 结果下载后立刻核账。结果文件里的 usage 带 token 消耗,按"实时半价"的系数算成本,落到成本归因系统里。批量的折扣要能在看板上看出来,否则没人知道你省了多少钱。
  • 幂等。同一批数据可能因为上游重试被提交两次,custom_id 必须业务可追溯,结果入库走 upsert。

这条管线的本质是:把"延迟换价格"这件好事,用工程手段把它的不确定性(部分失败、延迟波动、结果乱序)兜住。没有这层管线,批量就只能停留在 demo。

六、实时 vs 批量:按业务选,别按习惯选

取舍的标准其实很简单,看三件事:

维度实时 APIBatch API
延迟秒级分钟~小时级(最长 24h)
单价1.0x~0.5x
限流紧松
适合用户在等后台、可攒批
失败成本单次整批重跑要拆

判断公式:用户在不在屏幕前等,决定走实时还是批量。前端聊天、搜索建议、Copilot 补全——实时;夜间 ETL、离线标注、评测跑分、邮件批量生成——批量。模棱两可时问一句:"这个结果晚 2 小时拿到,业务会不会塌?"不会塌,就批量。

七、进阶:把实时流量里"可等"的部分削峰挪到批量

真正高阶的成本优化,不是"新任务用批量",而是从现有实时流量里,把"可等"的部分挪到批量——也就是削峰(peak shaving)。

很多实时功能其实有隐藏的可延迟面。比如"用户上传文档后生成摘要":前端可以立刻返回"正在处理",后台把摘要任务丢进批量队列,几小时后通过推送/通知把结果交回去。用户体验只损失"立刻看到"的即时感,换来的是这条链路成本减半。再比如内容审核:实时只跑一个轻量分类器做硬阻断,深度审核挪到批量隔夜跑。

削峰的工程模式:

text
实时路径(贵):    请求 → 实时 LLM → 返回      [高峰期扛不住,TPM 爆表]
削峰路径(省):    请求 → 轻量判断
                        ├ 紧急/关键 → 实时 LLM(只放行尾部少数)
                        └ 可延迟   → 入批量队列 → 完成后回调

高峰时段实时算力最贵、最容易触限,这时把"可等"流量切到批量,既避开实时溢价、又绕开实时限流。削峰让批量的折扣作用在"本来要付实时全价"的流量上,ROI 比新增批量任务高得多。 这是把批量从"离线工具"升级成"在线成本杠杆"的关键一跳。

小结

  1. LLM 推理有两档定价:实时贵、离线便宜。 批量的本质是"用延迟换价格",OpenAI / Anthropic 的 Batch API 都给 50% off,这不是促销是经济学。
  2. 五类任务默认该走批量:分类标注、文档摘要、内容批量生成、评测跑分、ETL 里的 LLM 步骤。判断标准是"用户在不在等",不是"任务难不难"。
  3. Batch API 模式统一:JSONL 提交 → 轮询 → 按 custom_id 取结果。结果乱序、部分失败是常态,要把它当任务管线来建(落库、重试、降级、核账),而不是一次性函数调用。
  4. 数据合规或成本极限场景,自部署 vLLM 的 continuous batching。iteration 级调度让 GPU 饱和、吞吐数倍于静态批,是闭源 Batch API 的正选替代。
  5. 高阶玩法是削峰:把实时流量里"可等"的部分挪到批量,避开实时溢价和限流,让批量折扣作用在本来要付全价的流量上。

金句:实时是为"立刻"付溢价,批量是为"能等"拿折扣。 一个成本健康的 AI 应用,不是把所有请求都塞进实时,而是诚实地问每一条请求——"你到底急不急?"急的走实时,不急的攒批,这一问就能把账单砍掉一半。

Related

相关推荐