v2.0 · 6 路并发生图

按face.json
批量生图.

基于 ModelScope · bozoyan/k-feifei 模型的命令行批量生图工具。 读取结构化的 face.json,按分类批量生成人物肖像, 6 路并发 + 5 秒节流,自动轮询 API Key,失败重试, 生成结果自动回填 JSON 并下载到本地。

~/temp — k-feifei-face — 120×40
# 全量并发生图(6 路并发,5s 节流)
$ python k-feifei-face.py
========================================================
k-feifei-face 启动(模式:生图)
图片尺寸 : 1152x2048
API Keys : 9 条
并发线程 : 6 | 提交节流 : 6 次 / 5s
### 分类【发型】(hairstyle) 共 24 项
启动并发生图:6 线程 | 待处理 24 项
✅ 生成+下载完成: temp/发型/短发.jpg
✅ 生成+下载完成: temp/发型/长发.jpg
✅ 生成+下载完成: temp/发型/卷发.jpg
>>> 进度 3/24 完成 ...

为什么用它

单线程串行生图,每张要等 30 秒以上。这个工具把串行变成了流水线 —— 6 路并发跑, 单张平均时间被压到原来的 1/4。

⚡

6 路并发流水线

ThreadPoolExecutor 同时处理 6 个 item,单个任务完成立刻补下一个,整体吞吐提升约 4-6 倍。

⏱

5 秒节流防限流

SubmitRateLimiter 滑动窗口控制:每 5 秒最多 6 次 API 提交,避免击穿 ModelScope 限流。

🔑

Key 顺序轮询

KeyRotator 线程安全分配,按 ModelScope_Token.txt 顺序依次提交,失败自动换下一个。

💾

增量回写 JSON

每张图生成后立即把 url 回填到 face.json,进程中断也不丢进度,重跑自动跳过。

🔁

断点续跑

已有 url 或本地已有图片的 item 自动跳过 API 调用;缺图自动补下载。

📥

纯下载模式

加 --down 不调生图 API,只把已有 url 的图片批量下载到本地。

命令示例

所有命令在 temp/ 目录下执行。 命令行参数支持组合使用。

$ python k-feifei-face.py
全量并发生图,默认 6 线程,2K 尺寸(1152×2048)
$ python k-feifei-face.py --category hairstyle
只生图「发型」分类下的所有 item
$ python k-feifei-face.py --category hairstyle pose --limit 2
每类最多生 2 张,用于测试 / 分批跑
$ python k-feifei-face.py --ratio 1k
使用 1K 尺寸预设(936×1664),速度快、配额省
$ python k-feifei-face.py --workers 4
调整为 4 并发(默认 6)。Key 数量不足或限流严重时降低
$ python k-feifei-face.py --down
仅下载模式:不调生图,把所有已生 url 的图片批量下载
$ python k-feifei-face.py --down --category hairstyle
只下载「发型」分类下已有 url 的图片
$ python k-feifei-face.py --size 1024x1024
自定义任意尺寸(与 --ratio 互斥)

命令行参数

所有参数都是可选的。无参数运行 = 全量生图。

参数 类型 默认 说明
--category list None 只处理指定分类 key(可多个),如 hairstyle hairColor
--limit int 0 本次最多生成的图片数;0 = 不限,常用于测试
--down flag False 仅下载模式:不调生图 API,只下载已有 url 的图片
--workers int 6 生图并发线程数(仅生图模式生效,下载仍串行)
--ratio enum 2k 尺寸预设:1k=936×1664 / 2k=1152×2048(与 --size 互斥)
--size str — 自定义尺寸 WIDTHxHEIGHT(与 --ratio 互斥)

// 顶部常量(需改源码)

常量 默认 说明
CONCURRENCY 6 默认并发线程数(可被 --workers 覆盖)
SUBMIT_PER_PERIOD 6 每个节流窗口允许的 API 提交次数
SUBMIT_PERIOD 5 节流窗口长度(秒)—— "每 5s 最多 6 次提交"
POLL_INTERVAL 10 提交后轮询任务状态的间隔(秒)
MAX_POLL 120 单任务最大轮询次数(约 20 分钟超时)
MAX_KEY_RETRY 5 单项最多换 Key 重试次数
MODEL_ID bozoyan/k-feifei ModelScope 模型 ID

执行流程

从读取 face.json 到本地落盘,5 步走完。每个 worker 独立完成「提交→轮询→下载→回填」全链路。

读取数据

从上级目录加载 face.json(保留 UTF-8 BOM 状态),扁平化所有分类下的 item 成任务队列。

排队并发

ThreadPoolExecutor 启动 6 个 worker 线程,从队列拉取 item;KeyRotator 按 Token 文件顺序分配 API Key。

节流提交

提交 API 前 limiter.acquire() —— 每 5 秒最多放行 6 次提交,超出则阻塞等待下个窗口。

轮询生图

异步任务 task_id 每 10 秒查一次状态;SUCCEED 取回 url,FAILED 视情况换 Key 或抛错。

下载 + 回填

url 写回 face.json(加全局锁防并发写),图片下载到 temp/<label>/<name>.jpg。

文件结构

脚本会读取 / 写入以下路径。所有相对路径基于 temp/ 目录。

extension_prompt/
├── face.json → 输入:分类 + items + 已生成 url
└── temp/ → 脚本工作目录
    ├── k-feifei-face.py → 本脚本
    ├── ModelScope_Token.txt → API Key 列表(一行一个)
    ├── face_gen_<ts>.log → 详细日志(运行时生成)
    ├── face_gen_<ts>.txt → 任务记录汇总(运行结束生成)
    └── <label>/ → 按分类名分文件夹
        ├── 短发.jpg
        ├── 长发.jpg
        └── ...

// face.json item 结构

{
  "hairstyle": {
    "label": "发型",
    "items": [
      {
        "name": "短发",
        "prompt": "short black hair, bob cut",
        "url": "https://..." // ← 生成后自动回填
      }
    ]
  }
}

注意事项

实战使用中容易踩的坑。建议跑大批量前先 --limit 6 测一轮。

✓ 断点续跑

进程可以随时 Ctrl+C 中断。face.json 每张图完成就回写,下次启动会自动跳过已完成的 item。

! Key 配额

每个 Key 有日 / 小时配额。9 个 Key 跑大批量前先确认配额;Key 失败会自动换下一个,ModelScope_Token.txt 一行一个,支持 # 注释。

! 节流参数

如果 ModelScope 提示限流,调大 SUBMIT_PERIOD(如 8)或调小 SUBMIT_PER_PERIOD(如 4)。反之可适度激进。

✗ 瞬态错误

"Dequeued / unknown FC status / Retrying" 等瞬态错误自动重试 12 次。若 12 次仍失败,整项标为失败并记录到 .txt 报告。

! 下载失败

url 已回填但下载失败时,item 标记为 gen_url_only,可用 --down 模式重新批量下载。

✓ 日志可追溯

每次运行按启动时间戳生成 .log(详细日志)+ .txt(任务记录),方便复盘或排查失败项。