电商上百个 SKU 要配图,自媒体每天要十几张封面。一张张手动生成太慢了。这篇教你搭一套能批量跑、风格统一的 AI 出图平台。
写在前面
做电商、做自媒体的都懂那种痛:图永远不够用。新品上架要主图、要细节图、要场景图;公众号、小红书每天要配图要封面。一张张去 AI 工具里敲提示词、等生成、下载、改尺寸——一天下来人都麻了。
AI 文生图早就够用了,真正的瓶颈是规模化 :怎么一次性提交几十上百个出图任务,自动排队、自动保持风格统一、出问题自动重试。换句话说,你需要的不是一个"出图工具",而是一条出图流水线 。
这篇就带你把这套批量出图平台搭起来,并在中途接入 4sapi.com 这个中转 API 统一调用图像模型。
一、先理清楚:批量出图的链路长啥样
一批出图需求(CSV/表格)
↓
① 提示词构造 每行需求 → 规范化的出图提示词(含统一风格)
↓
② 任务入队 几十上百个任务 → 排进队列,控制并发
↓
③ 批量生成 每个任务 → 调文生图/图生图模型出图
↓
④ 质检过滤 太糊/不合规的自动剔除或重抽
↓
⑤ 归档交付 按命名规则存好,打包给用户下载 Copy
③ 靠文生图/图生图模型 ,① 里如果要让模型帮忙润色提示词,还会用到大语言模型 。模型分散在不同厂商——还是那句话,这正是要引入中转 API 的原因。
二、架构设计:任务队列 + 出图 Agent + 中转网关
批量场景和前面几篇不太一样,核心是队列 + 并发控制 :
批量需求 ──→ ┌─────────────────────┐
│ Producer 任务生产者 │ 拆成一个个出图任务
└──────────┬──────────┘
↓ 推入队列
┌─────────────────────┐
│ Task Queue │ 控制并发、失败重试
└──────────┬──────────┘
┌────────────┼────────────┐
↓ ↓ ↓
[出图Worker] [出图Worker] [出图Worker] ← 多个并发消费
└────────────┼────────────┘
↓
┌─────────────────────┐
│ 统一 API 网关 (4sapi) │ ← 文生图/图生图都走这
└─────────────────────┘ Copy
关键设计点:用任务队列解耦"提交"和"生成" 。用户一次提交一百个需求,不是同步等一百张图跑完,而是全推进队列,由若干个 Worker 并发消费,每个 Worker 都通过统一网关出图。好处:
一个 Key 调文生图 + 图生图 :要原创出图用文生图,要保持风格一致用图生图,同一套凭证;
换模型零成本 :4sapi 背后接了多家图像模型,哪个效果好/便宜就切哪个;
并发和算账集中 :批量出图最怕失控烧钱,所有调用走一个网关,限流和对账都在一处。
网关我选 4sapi.com ,兼容 OpenAI 格式,文生图、图生图、文本模型都能统一调。
三、中途接入 4sapi:三步把网关接通
第一步:拿 Key、记住 BaseURL
注册 4sapi.com,后台创建令牌(sk-xxxxxxxx),记下接口地址:
放进环境变量,别硬编码:
bash
# .env
FOURSAPI_BASE_URL = https://4sapi.com/v1
FOURSAPI_KEY = sk-你的令牌 Copy
第二步:封装统一客户端
python
# gateway.py
import os
from openai import OpenAI
client = OpenAI(
api_key = os.environ[ "FOURSAPI_KEY" ],
base_url = os.environ[ "FOURSAPI_BASE_URL" ], # 指向中转网关
)
def gen_image (prompt, size = "1024x1024" , seed = None ):
"""文生图,走网关"""
extra = { "seed" : seed} if seed is not None else {}
resp = client.images.generate(
model = "flux-dev" , prompt = prompt, size = size, extra_body = extra,
)
return resp.data[ 0 ].url Copy
第三步:发请求验证连通
python
if __name__ == "__main__" :
url = gen_image( "a red apple on a white table, product photo" )
print (url) # 能返回图片 URL 即网关接通 Copy
拿到一个可访问的图片 URL,说明出图链路通了。还是「改 base_url + 配 Key」。
四、关键环节实现
4.1 提示词构造 —— 让一批图风格统一
批量出图最大的坑是风格飘 :一百张图一百个样,没法用。解法是抽一段"全局风格后缀",拼到每个任务的提示词后面:
python
# 全局风格:所有图共用,保证视觉统一
STYLE_SUFFIX = "clean studio lighting, white background, product photography, high detail"
def build_prompt (item):
# item 来自 CSV 的一行,比如 {"name": "陶瓷马克杯", "color": "米白色"}
core = f "a { item[ 'color' ] } { item[ 'name' ] } "
return f " { core } , {STYLE_SUFFIX} " Copy
4.2 任务队列 —— 控制并发,别一把梭烧爆
用一个带并发上限的队列消费任务,这是批量场景不翻车的关键:
python
import asyncio
async def worker (name, queue, results):
while True :
item = await queue.get()
if item is None :
break
try :
prompt = build_prompt(item)
url = gen_image(prompt, seed = item.get( "seed" ))
results.append({ "item" : item, "url" : url, "ok" : True })
except Exception as e:
results.append({ "item" : item, "error" : str (e), "ok" : False })
finally :
queue.task_done()
async def run_batch (items, concurrency = 4 ):
queue = asyncio.Queue()
for it in items:
queue.put_nowait(it)
results = []
# 并发上限 = concurrency,别让请求一把涌出去
workers = [asyncio.create_task(worker( f "w { i } " , queue, results))
for i in range (concurrency)]
await queue.join()
for _ in workers: queue.put_nowait( None )
await asyncio.gather( * workers)
return results Copy
4.3 质检过滤 —— 自动剔掉废图
出图难免有废片。简单的质检可以查分辨率、查是否纯色(生成失败常返回灰图),进阶可以用多模态模型打分:
python
def quality_check (img_bytes):
from PIL import Image
import io
img = Image.open(io.BytesIO(img_bytes))
# 太小直接淘汰
if img.width < 512 or img.height < 512 :
return False
# 颜色过于单一(疑似生成失败)淘汰
colors = img.getcolors( maxcolors = 10000 )
if colors and len (colors) < 20 :
return False
return True Copy
4.4 图生图 —— 保持系列一致性
电商一个系列要风格统一时,用一张基准图做"图生图",比纯文生图稳得多:
python
def img2img (base_image_url, prompt, strength = 0.6 ):
resp = client.images.edit( # 图生图,走网关
model = "flux-dev" ,
image = base_image_url,
prompt = prompt,
extra_body = { "strength" : strength}, # 越低越贴近原图
)
return resp.data[ 0 ].url Copy
五、串起来:从一张表到一批图
python
import csv
async def batch_generate (csv_path):
with open (csv_path, encoding = "utf-8" ) as f:
items = list (csv.DictReader(f)) # 读入批量需求
results = await run_batch(items, concurrency = 4 ) # 并发出图
ok = [r for r in results if r[ "ok" ]]
failed = [r for r in results if not r[ "ok" ]]
# 失败的自动重试一轮
if failed:
retry = await run_batch([r[ "item" ] for r in failed], concurrency = 2 )
ok += [r for r in retry if r[ "ok" ]]
return ok # 交付:按命名规则归档打包 Copy
所有出图调用——文生图、图生图——全走同一个 4sapi 网关 。
六、前端:上传表格、看进度、批量下载
jsx
function BatchImageStudio () {
const [ progress , setProgress ] = useState ({ done: 0 , total: 0 });
async function upload ( file ) {
const form = new FormData ();
form. append ( "csv" , file);
const res = await fetch ( "/api/batch" , { method: "POST" , body: form });
// SSE 实时回报 done/total,渲染进度
}
return (
< div >
< FileUpload accept = ".csv" onUpload = {upload} />
< StyleConfigPanel /> { /* 配全局风格 */ }
< Progress done = {progress.done} total = {progress.total} />
< DownloadAll /> { /* 全部完成后打包下载 */ }
</ div >
);
} Copy
安全提醒:批量出图是烧钱重灾区,一次手滑提交几千个任务,账单瞬间起飞。务必设单次任务上限 + 用户配额 + 全局并发限制 。另外,生成的图要过一遍内容合规,别让平台产出违规图像。
七、几条实战经验
全局风格后缀是批量出图的命根子 。抽成统一配置拼到每个 prompt,一百张图才像一个系列出来的。
并发别贪多 。并发越高越快,但也越容易撞网关限流、越容易失控烧钱。从 4 起步,看着调。
失败任务单独收集、自动重试一轮 。批量里总有几个抽风失败的,攒一批重跑,比整体重来省太多。
质检前置,废图别进交付 。哪怕只做"分辨率 + 纯色"两条规则,也能挡掉大半明显废片。
要系列一致就上图生图 。纯靠文生图 + 风格后缀只能"大致像",真要严格统一,固定一张基准图做图生图。
写在最后
批量出图平台的难点,从来不是"会不会生成一张图",而是怎么把一次性几百张的生成,做得稳、统一、还不失控烧钱 。
提示词标准化、任务进队列、并发受控制、废图被拦截——这四件事做扎实,出图就从手工活变成了流水线。
中途接入 4sapi,让"文生图 + 图生图"用同一个 Key、同一套代码调用,换模型不动业务。把模型差异挡在网关后面,让流水线专注于调度本身 ——规模越大,这套结构省的事越多。
本文代码为说明思路的简化示意,具体模型名称、接口字段请以 4sapi.com 官方文档为准。涉及付费接口,请做好用量控制与内容合规。