Kimi 批量推理适合什么场景:Batch API 的门槛与取舍
数据截至 2026-08,价格与限额以各官网为准。本文只讲计费与接入机制,不列具体价格数字。
判断一个任务能不能丢进 Kimi 批量推理,不要先看便宜多少,先看三件事:任务能不能接受”只承诺在窗口内完成、不承诺什么时候完成”;请求里用不用得上 temperature、top_p、n 这类采样参数(Batch 明确不让改);整批请求是不是都用同一个模型(官方硬性要求一批一模型)。 这三条任意一条不满足,Batch API 就不是”更便宜的调用方式”,而是根本跑不通或跑出来不是你要的东西。满足了,官方对它的定位就非常清楚——“大规模、低实时性要求的任务”,按低于标准价计费,具体比例见官方定价页。下面按真实接入顺序把每一步的判据拆开。
第一道门槛:那几个被锁死的参数
官方在《使用 Batch API 批量处理任务》里写得很直接:Batch 支持的模型”这些模型的 temperature、top_p、n、presence_penalty、frequency_penalty 参数均不可修改,请勿在 body 中设置这些参数”。
这句话看着不起眼,但它一次性砍掉了好几类常见任务:
- 想靠调高温度做多样性采样的(比如批量生成多个候选文案再人工挑),不行;
- 想用
n一次请求拿多条候选的,不行——n在被锁列表里; - 想用 presence/frequency penalty 压制重复的,不行。
反过来说,Batch 天生适合那种每条请求只要一个确定性输出的活:分类、打标、抽字段、翻译、摘要、结构化改写。官方指南自己举的例子就是文本分类,输入是一批句子,输出是”文学类/新闻类/学术类/科技类/生活类”里的一个。这个例子选得很有代表性——它恰好是那种不需要调采样参数、每条互相独立、跑一天再看结果也无所谓的任务。
受支持的模型范围:两页官方文档说得不一样
这一点值得单独拎出来,因为它会直接决定你的 JSONL 写哪个 model。
- 《Batch API 指南》页写的是:Batch API 支持 kimi-k2.6 和 kimi-k2.5 模型,暂不支持 kimi-k3;
- 《批量推理定价》页写的是:Batch API 支持 kimi-k2.7-code、kimi-k2.6 和 kimi-k2.5 模型。
两页对同一件事给出的清单不一致,定价页多列了一个 code 型号。我没有跑过接口,也不打算替官方裁决哪一页是对的——真正要做的是:写死 model 之前,回官方文档当前版本确认一遍,别照抄任何二手清单(包括本文这一段)。这类差异说明模型支持范围是会随版本滚动的,官方文档本身也未必同步得那么齐。
另外,输入文件校验会检查”指定的模型必须存在且用户有访问权限”。也就是说,模型名写错、或者账号没有该模型权限,任务不会在提交时就报错给你,而是走到校验阶段变成 failed。
输入文件的四个字段,决定了一个批次只能干一件事
JSONL 每行是一个独立请求,官方规定必须包含四个字段:
| 字段 | 说明 |
|---|---|
custom_id | 自定义请求标识,用于追踪结果,文件内必须唯一 |
method | 固定为 POST |
url | 固定为 /v1/chat/completions |
body | 请求体,与 Chat Completions API 参数一致 |
url 固定这一条,意味着 Batch 目前只服务于对话补全这一个端点(创建任务接口的 endpoint 也是个枚举,官方标注”目前仅支持 /v1/chat/completions”)。想批量跑别的接口,走不通。
更影响场景设计的是这两条约束:所有行的 model 必须相同,一个批次只允许一个模型;custom_id 在文件内必须唯一。前者意味着”同一批数据用两个模型跑一遍做对比”这种需求,必须拆成两个批次、两个文件、两个任务分别提交,没有偷懒的写法。后者意味着 custom_id 应该直接编成能反查业务主键的形式——因为输出文件里除了它,没有别的东西能把结果和你的原始记录对上号。
文件本身还有几道硬限制:必须是 .jsonl 扩展名、不能为空且有明确的大小上限,组织层面还有一个 batch 类型文件的数量配额(具体数值见官方接口文档,这类数字会变,别写进代码注释当常量)。上传时 purpose 必须设为 "batch",用别的 purpose 传上去的文件,创建任务时用不了。
completion_window:这个参数才是”适不适合”的真正分水岭
创建任务时 completion_window 是必填的,官方说明它是”任务处理的时间窗口,支持语义化格式如 12h、1d、3d”,并给出了最小值与最大值(以官方接口文档为准)。
关键在于它的反面:未在 completion_window 内完成的任务,状态会变成 expired。官方在扩展建议里也给了一句很实在的话——“根据实际数据量调整 completion_window,较大的数据集建议设置 3d 或 7d”,以及”较长的时间窗口可以提高任务完成率”。
把这两句连起来读,结论有点反直觉但很重要:窗口不是”我希望多久跑完”,而是”我最多能等多久”。 窗口设短了不会让任务跑得更快,只会提高它变成 expired 的概率。所以判断一个业务能不能用 Batch,问法应该是”这批结果最晚什么时候要”,而不是”这批数据大概要跑多久”。
由此可以划一条清楚的线:
- 适合:夜间跑存量数据清洗、历史工单批量打标、语料批量结构化、周期性报表生成——这些都有一个宽松的”明天上班前要”式的截止时间;
- 不适合:任何面向用户在线等待的链路、任何有硬性交付时刻且不能重试的流程。后者请回到实时接口,配合并发与限流规划来做,可以参考限流与 RPM/TPM 的通用机制。
状态机与轮询:调度代码要处理八种状态
官方给出的状态枚举是完整的八个,含义也逐条说明了:
validating——已创建,正在校验输入数据;failed——数据校验失败,任务终止;in_progress——校验通过,正在执行;finalizing——执行完毕,正在准备结果;completed——结果准备完毕,任务完成;expired——未在 completion_window 内完成;cancelling——已发起取消,等待实际取消;cancelled——取消完成,任务终止。
写调度代码时有两处容易踩空。一是 failed 是校验阶段的失败,和”部分请求执行失败”不是一回事——后者体现在 request_counts.failed 和 error_file_id 上,任务整体仍可能是 completed。二是取消不是同步的:官方明确”仅 validating、in_progress、finalizing 状态的任务可以取消”,取消后状态先变 cancelling,最终才变 cancelled。所以”点了取消就当它停了”的写法会漏掉中间态。
任务对象上还挂了一整排 Unix 时间戳字段:created_at、in_progress_at、expires_at、finalizing_at、completed_at、failed_at、cancelling_at、cancelled_at。这些字段的价值在于事后复盘——排队等了多久、执行段耗了多久、是卡在准备结果还是卡在执行,光看最终状态是分不出来的,看时间戳差值就一目了然。想把这些数据接进成本与用量看板的,可以顺着API 成本监控的做法搭。
轮询频率上,官方给了建议区间(见指南”扩展建议”一节),意思是别把轮询打得太密。列表接口本身是游标分页的:查询参数有 after 和 limit,响应里的 has_more 为 true 时,把本页最后一个 batch.id 传给 after 取下一页;省略 after 则每次都返回第一页——批任务攒多了之后,这个细节会让”我怎么翻不到旧任务”变成一个真实问题。
结果文件:成功和失败是两个文件
任务完成后,output_file_id 指向成功结果文件,error_file_id 指向失败请求的错误文件,两者都通过获取文件内容接口下载。
输出文件每行的结构是:custom_id、response(内含 status_code、request_id 和与实时接口一致的 body,包括 choices 和 usage)、以及 error 字段。这个结构决定了两件事:
- 回连全靠 custom_id。所以前面说的”把业务主键编进 custom_id”不是洁癖,是唯一的可行路径;
- usage 是逐条给的。想知道这批活到底花了多少 token、哪几条请求特别贵,不用等账单,把输出文件里的 usage 累加一遍就能自己算。批量场景下这一步几乎是必做的,因为一个批次里混进几条超长输入,成本分布会完全走样。
官方定价页的说明里同时覆盖了输入、输出和缓存命中三类 token 的价格,也就是说批量推理的账单里缓存命中是单独一档,不是和普通输入混在一起算的。缓存和批量这两条降本路径怎么搭配、各自适合什么形态的负载,站内有一篇缓存与 Batch 的取舍对比;Kimi 自家的计费口径则可以对照Kimi API 计费机制看。
多模态批量:base64 内嵌还是 ms:// 引用
Batch 输入文件里可以带图片和视频,官方说明”与文本任务的区别主要在于构造输入文件这一步,其余流程完全一致”。两种传入方式的取舍是官方直接给出的:
- base64 内嵌:把媒体编码进 JSONL,适合小文件,无需额外上传步骤;但官方提示 base64 会让体积明显膨胀,而 JSONL 是有大小上限的,所以这条路很容易在文件层面撞墙;
- 文件引用:先用文件接口上传(图片用
purpose="image",视频用purpose="video"),再在 JSONL 里用ms://<file_id>引用,官方标注”适合大图片或图片复用场景”。
“复用”这个词是关键。如果你的任务形态是同一张图配十几个不同的提问,base64 内嵌等于把同一份二进制在文件里抄十几遍,引用方式则只上传一次。这类任务反而是引用方式最划算的地方。
不写代码也能跑:控制台批量推理有额外门槛
如果只是偶尔跑一批,不想写脚本,官方另有一条控制台路径:用户中心 → 项目管理 → 查看项目 → 批量推理 → 创建批任务,弹窗里填批量任务名称、选最长等待时间、上传或选择数据文件,提交后在列表里看状态,完成后点详情下载结果;历史的输入文件和输出结果文件都能在项目的文件页面找到。
但这条路有一个 API 路径上没写的限制:官方在《使用控制台进行批量推理》页里明确,批量推理是针对某一项目进行的,且只有 Tier1 及以上的用户可以使用批量推理。这句话写在控制台那一页,Batch API 指南页没有重复它——所以如果你是新账号在控制台里找不到批量推理入口,先去核对账户等级,而不是怀疑自己路径点错了。账户等级本身和累计充值挂钩,规则见官方”充值与限速”页,那一页还挂着一条平台预告:相关规则会更新,以页面当前版本为准。
最后:三个最容易栽的坑
第一,把 Batch 当成”绕开限速的通道”。官方原文说的是”Batch API 不受实时并发限制,适合大批量任务”,这句话的范围就是实时并发这一层,不是”批量推理没有任何约束”。想省钱是对的,想靠它规避账号层面的规则就是误读。
第二,用短窗口试水。很多人第一次试会把 completion_window 设到最小值想”快点看到结果”,结果撞上 expired。真要试水,应该缩小的是数据量——先发几十条验证 JSONL 格式和 custom_id 设计,窗口该给多长给多长。
第三,忘了检查 error_file_id。任务显示 completed 不等于每条都成功,request_counts 里的 failed 才是真相。把错误文件下载下来按 custom_id 归并进重试队列,这一步不做,批量跑完看着数字挺漂亮,实际数据是缺的。
下一步建议:先拿一小批真实数据,把 custom_id 的编码规则和结果回连脚本跑通,再放大数据量。格式和回连这两件事在小批量上返工的成本几乎为零,等到十万行的文件跑完才发现 custom_id 对不上业务主键,那就只能整批重来。