AI 批量商品图:先管好任务,再扩大数量

最后更新:

从几个 SKU 扩到上百个,难点不只是生成速度。每张图必须找到原商品、调用记录和验收结果,失败后只恢复需要处理的任务。

两项实际任务,一项超时、一项返回

2026-09-11 的小样使用两张无品牌合成水瓶参考图,串行执行同一场景要求。A 项在 180.514 秒后超时,B 项约 53.5 秒返回 1024×1024 图片。我们保留 A 的异常记录,并没有因为 B 成功就登记整批完成,也没有对 A 无条件重试。

这批只有两个任务,不是规模测试。它说明批量流程需要逐项状态:B 进入收到图片后的审核,A 进入待核对;超时与最终扣费尚需独立关联。本页不据此计算商品通过率或声称超时免费。下面的任务 ID、预算和目录方法就是为避免把这样的不同状态混在一起。

两项批量任务中成功返回的蓝色水瓶场景图
2026-09-11 两项任务中的 B 图真实返回,A 图超时;不是整批成功截图。
任务客户端结果已有文件下一步
A180 秒超时请求与异常记录核对任务和费用终态
B返回成功1024×1024 图片逐项审核主体与构图

不要从 100 个 SKU 同时生成开始

第一次批量任务的目标应是证明流程能被管理:原图和 SKU 对得上、结果能下载、费用能查到、失败可以定位。先挑几个不同难度的商品,例如普通实物、带小字标签和反光材质,各做少量样例;只有通过这一轮,才讨论并发和整店处理。

同一个提示词在水瓶上可用,不代表在衣服、首饰或透明包装上也适用。把品类、背景和尺寸分开分批,避免某个错误参数影响所有商品。样例失败要留在记录里,不能删除后只统计好看的结果。

一份 SKU 清单是整个流程的起点

至少登记 SKU、原图路径、场景、目标尺寸、提示词版本和审核人。文件名不能只叫“图片1”,也不要把密钥放在表格里。原图内容变化后应更新输入版本,否则下次恢复任务时可能把新旧商品素材混在一起。

同一 SKU 下两个场景就是两个独立任务。重复尝试使用相同业务任务 ID 加尝试编号,不能把第二次调用伪装成另一个新品。业务任务 ID 只是你自己的对应关系,不代表图片接口具有服务端幂等保证。

字段示例用途
skubottle-001关联真实商品
input / input_versionbottle-001.png / v1固定输入资料
scene / sizedesk / 1024x1024区分产物与请求尺寸
prompt_versionbackground-v1知道本轮具体改了什么
task_id / attemptbottle-001-desk-v1 / 1恢复和费用对账
status / reviewreceived / pending收到结果与人工通过分开

先固定场景规范,再让商品逐个进入

把背景、光照、留白和允许修改项写成模板,而商品属性来自各自的原图和资料。不同 SKU 不能共用一套虚构的规格描述。制作营销版时,也要让价格与文案从已经确认的字段进入排版。

教学图展示了三种场景方向。真正的小样要使用自己的授权素材,记录哪一种场景更容易保持商品准确,再把通过的流程扩展到同类商品。

绿色水瓶在白底、浅色桌面和深色台面中的三联教学示意,供比较主体轮廓与场景变化
AI 生成教学示意,不是 KK API 实测对比。三幅图用于说明布景变化;真实交付仍须逐项比对原商品,不代表主体能被无损保留。

先在本地算任务数量,不触发付费请求

下面是可运行的本地计划示例。保存为 plan.mjs,用当前价格页上相同模型、相同计费档位的单张价格设置 IMAGE_PRICE,再运行 node plan.mjs。它只打印数量与预算,不读取密钥、不提交图片,也不代表正式任务队列。

首次尝试包含在 maxAttempts 中。不同尺寸或不同收费规则应拆开计划,不能把一个单价套到所有模型。整数金额转换只用于本地预算展示,最终账务仍以实际调用记录为准。

plan.mjs
const skus = ['bottle-001', 'bottle-002', 'bottle-003'];
const scenes = ['desk', 'white'];
const maxAttempts = 2;
const price = Number(process.env.IMAGE_PRICE);
if (!Number.isFinite(price) || price <= 0) {
  throw new Error('Set IMAGE_PRICE to the current per-image price');
}
if (new Set(skus).size !== skus.length || new Set(scenes).size !== scenes.length) {
  throw new Error('Duplicate SKU or scene');
}
const jobs = skus.flatMap(sku => scenes.map(scene => ({
  taskId: sku + '-' + scene + '-v1', sku, scene, size: '1024x1024',
})));
const maxCalls = jobs.length * maxAttempts;
const budget = Number((maxCalls * price).toFixed(4));
console.log(JSON.stringify({ mode: 'plan-only', planned: jobs.length, maxCalls, budget, jobs }, null, 2));

串行跑通后,再考虑有限并发

先串行完成上传、生成、下载、尺寸检查与人工审核。真实通过后逐步增加并发,并同时观察延迟、429、失败数量和费用。不要在教程里找到一个固定并发数就直接套用,它与模型、任务大小和账户限制有关。

可以用脚本或工作流工具组织请求,但需要自己实现明确的任务状态。建议把 planned、submitted、received、approved、rejected、unknown 分开;下载成功进入 received,人工核对通过才进入 approved。

SKU 与场景任务清单 → 受限并发 + 独立 Key + 任务记录 → 图片生成 / 参考图编辑
这是应用侧工作流设计,不代表 API 内置了任务队列、预算熔断或请求幂等。

超时先进入待核对,不自动当成失败重发

任务被客户端取消或网络超时时,服务端可能已经执行。先标记 unknown,保留时间、模型和可用的请求标识,再查询调用记录或联系支持。确认状态之后决定补发,不让后台无条件重试把同一商品生成多次。

参数错误应先修正请求;额度或权限问题应暂停相关批次;429 要按接口提示等待;5xx 也要结合响应和任务状态判断。恢复时只选择明确需要重跑的任务,已经收到但尚未审核的图片不属于未执行任务。

审核和交付是两个独立步骤

审核先检查商品真实性,再检查构图和文件要求。不通过的图片记录原因,例如标签变形、产品颜色不符、返回尺寸不符或主体遮挡。分别统计原因才能决定是修改模板、补原图,还是换制作路线。

交付目录只收已通过的结果,但原始响应、失败记录和未通过图要留在内部项目目录。给客户的文件按 SKU 和场景命名,附尺寸与版本清单;不要把含签名下载链接、密钥或客户隐私的运行日志一起交出去。

任务目录示例.txt
project/
  inputs/                 原始授权素材
  tasks.json              SKU、场景和版本
  attempts/               每次请求的内部记录
  received/               已下载但未全部通过
  review.csv              人工结论与原因
  delivery/               只放审核通过的图片
  delivery-manifest.csv    文件、SKU、尺寸和版本

每一批结束后,算通过率与实际单件成本

记录提交次数、收到图片数、通过数、未知状态数、总费用和人工时间。验收通过率的分母要写清是候选图片还是业务任务,避免同一张商品反复生成后把统计算得越来越漂亮。

假设 100 个任务各需要一张交付图,实际产生 150 次计费请求,而只有 80 个任务通过,那么模型费用除以 80 才是当前交付成本。这个数字是示例,不是预期成功率。预算脚本只是预估;实际耗费、已付费但未通过的结果和未知状态都应在项目复盘中体现。

常见问题

多少个 SKU 才值得做批量工作流?

没有固定数量。重复执行、频繁改稿和需要对账时,就值得整理清单;首先证明单任务可验收。

计划脚本会扣费吗?

不会。示例只在本地计算任务与预算,没有网络请求,也不读取 API Key。

设置任务 ID 就不会重复计费了吗?

不是。业务任务 ID 只帮助对应记录,不能代替接口层明确提供的幂等能力。

应该开多大并发?

从串行开始,依据账户限制、任务耗时和错误情况逐步调整,没有适用于所有模型的固定值。

失败请求一定不收费吗?

不能只按客户端报错判断。应查询实际调用与费用记录;超时等未知状态先核对,再决定是否补发。