GLM-Image实战教程:批量生成脚本编写(循环提示词+自动重命名)
你是不是也遇到过这样的情况:想用GLM-Image生成一批风格统一的图,比如10张不同动物的赛博朋克风肖像,或者20个产品主图的AI渲染图?每次都在Web界面里点一次、输一次、等一次、再手动改名……重复操作半小时,手酸眼累还容易出错。
其实,GLM-Image不只是一个点点点的网页工具——它背后是一套可编程的Python接口。只要几行代码,你就能让它自动跑完一整套流程:读取提示词列表 → 逐条生成图像 → 按规则自动命名 → 保存到指定文件夹。整个过程不用开浏览器,不点鼠标,不盯进度条。
这篇教程就带你从零写出一个真正能落地的批量生成脚本。不讲抽象概念,不堆参数说明,只聚焦三件事:怎么让提示词“动起来”、怎么让文件名“有逻辑”、怎么让结果“稳稳落盘”。哪怕你只写过print("hello"),也能照着跑通。
1. 为什么不能只靠Web界面做批量?
先说清楚一个问题:WebUI设计初衷是交互友好,不是批量高效。它确实支持单次生成、参数调节、实时预览,但有几个硬性限制,直接卡住批量需求:
- 无批量输入入口:正向提示词框只接受单行文本,没法粘贴几十条描述
- 无任务队列机制:点击一次“生成”,必须等完才能点下一次,无法并行或排队
- 命名不可控:默认按时间戳+随机种子命名(如
20260118_142305_872941.png),看不出对应哪条提示词 - 路径固定难管理:所有图都扔进
/root/build/outputs/,混在一起,后期筛选成本高
这些问题加起来,意味着——你想生成50张图,就得手动操作50次,平均耗时3分钟/张,光等加载和生成就要2.5小时,更别说中间手抖输错提示词、漏调参数、文件名对不上……
而一段不到50行的Python脚本,能帮你把这2.5小时压缩到3分钟内完成,且全程无人值守。
2. 批量脚本的核心思路拆解
别被“脚本”吓到。这个批量生成脚本,本质就是把你在Web界面上做的三步操作,翻译成Python能听懂的指令:
2.1 第一步:复刻WebUI的生成能力
GLM-Image WebUI底层用的是Hugging Face的diffusers库 + 自研推理逻辑。我们不重复造轮子,而是直接调用它已封装好的GLMImagePipeline类——就像抄作业,但抄的是官方标准答案。
关键点在于:
- 它不需要你从头加载模型权重,只需复用WebUI已下载好的缓存(路径在
/root/build/cache/huggingface/hub/models--zai-org--GLM-Image) - 它支持完全相同的参数:
prompt、negative_prompt、width、height、num_inference_steps、guidance_scale、generator - 它返回的不是网页里的base64图片,而是PIL.Image对象,可直接
.save()到任意路径
这就省去了模型下载、环境冲突、CUDA配置等90%的部署烦恼。
2.2 第二步:让提示词“活起来”
你肯定有一份Excel或TXT存着要生成的描述,比如:
一只戴墨镜的橘猫,坐在霓虹灯下的摩托车上,赛博朋克风格,8k细节 一只穿宇航服的柴犬,漂浮在土星环旁,科幻插画,电影感光影 一只水墨风格的白鹤,立于雪山之巅,留白构图,宋代美学脚本要做的,就是逐行读取这些文字,每读一行,就调用一次生成函数。这里有两个实用技巧:
- 用列表推导式预处理:去掉空行、过滤首尾空格、跳过注释行(以
#开头) - 支持变量占位符:比如
{animal}、{style},配合Python的.format()动态替换,一条模板生成多张变体
这样,10行提示词 = 10张图;1行带变量的模板 + 5个变量值 = 5张图。灵活度远超手动输入。
2.3 第三步:让文件名“说得清道得明”
WebUI生成的20260118_142305_872941.png对机器友好,对人极不友好。我们要的是:一眼看出这张图是什么、用了什么参数、属于哪个批次。
推荐命名规则:[主题缩写]_[序号]_[宽度]x[高度]_[步数]s_[种子].png
例如:cybercat_01_1024x1024_50s_42.png
实现方式很简单:
- 用
os.path.join()拼接保存路径,确保跨平台兼容 - 用
str.zfill(2)补零(1→01),保证文件名自然排序 - 把关键参数全塞进文件名,后期用
ls *cybercat*50s*.png就能秒筛
再也不用打开每张图确认内容。
3. 手把手编写批量生成脚本
现在,我们把上面三步变成可运行的代码。新建一个文件batch_gen.py,放在/root/build/目录下(和webui.py同级),然后逐段敲入以下内容。
3.1 环境准备与依赖声明
# batch_gen.py import os import time from pathlib import Path from typing import List, Optional # 确保使用项目内的缓存路径 os.environ["HF_HOME"] = "/root/build/cache/huggingface" os.environ["HUGGINGFACE_HUB_CACHE"] = "/root/build/cache/huggingface/hub" os.environ["TORCH_HOME"] = "/root/build/cache/torch" # 导入核心库(需提前安装:pip install torch diffusers transformers accelerate safetensors) from diffusers import GLMImagePipeline from transformers import AutoTokenizer, AutoModelForSeq2SeqLM import torch from PIL import Image注意:如果提示
ModuleNotFoundError: No module named 'diffusers',请先运行pip install --upgrade diffusers transformers accelerate safetensors torch torchvision
这些包WebUI启动时已装好,但脚本运行环境可能未激活,补装即可。
3.2 加载模型与初始化管道
def load_glm_image_pipeline() -> GLMImagePipeline: """加载已缓存的GLM-Image模型,复用WebUI下载资源""" model_path = "/root/build/cache/huggingface/hub/models--zai-org--GLM-Image" # 检查模型是否存在 if not Path(model_path).exists(): raise FileNotFoundError( f"模型未找到,请先通过WebUI加载一次GLM-Image," f"触发自动下载。路径应为:{model_path}" ) # 初始化pipeline(显存友好模式) pipe = GLMImagePipeline.from_pretrained( model_path, torch_dtype=torch.float16, use_safetensors=True, variant="fp16", ) # 启用CPU offload(显存<24GB时必开) if torch.cuda.is_available(): pipe.enable_model_cpu_offload() return pipe # 实例化全局pipeline(只加载一次,后续复用) pipe = load_glm_image_pipeline() print(" GLM-Image模型加载成功,准备就绪")这段代码做了三件关键事:
- 指向WebUI已下载的模型路径,避免重复下载34GB
- 用
enable_model_cpu_offload()开启显存优化,即使只有12GB显存也能跑 - 打印确认信息,让你知道脚本没卡在加载环节
3.3 定义提示词列表与生成参数
# ====== 可配置区:在这里修改你的提示词和参数 ====== PROMPTS = [ "一只戴墨镜的橘猫,坐在霓虹灯下的摩托车上,赛博朋克风格,8k细节", "一只穿宇航服的柴犬,漂浮在土星环旁,科幻插画,电影感光影", "一只水墨风格的白鹤,立于雪山之巅,留白构图,宋代美学", "复古胶片风的咖啡馆角落,暖光,散景,老式收音机,氛围感", "未来城市夜景,飞行汽车穿梭于玻璃幕墙之间,雨夜反光,4k超清" ] # 全局生成参数(可为每条提示词单独覆盖) DEFAULT_PARAMS = { "width": 1024, "height": 1024, "num_inference_steps": 50, "guidance_scale": 7.5, "negative_prompt": "blurry, low quality, distorted, deformed, text, signature", "seed": -1, # -1 表示随机种子,每次不同 } # 输出目录(自动创建) OUTPUT_DIR = Path("/root/build/outputs/batch_gen") OUTPUT_DIR.mkdir(exist_ok=True) # =================================================小技巧:
PROMPTS列表支持中文,无需编码转换negative_prompt统一写在这里,避免每条重复;也可在每条提示词后加|分隔负向词,如"橘猫|blurry, text"OUTPUT_DIR独立于WebUI默认输出,避免文件混杂
3.4 核心生成函数:带自动重命名
def generate_and_save( prompt: str, idx: int, output_dir: Path, params: dict, prefix: str = "batch" ) -> str: """ 生成单张图并保存,返回完整文件路径 Args: prompt: 正向提示词 idx: 序号(从0开始) output_dir: 保存根目录 params: 生成参数字典 prefix: 文件名前缀,用于区分批次 Returns: 保存路径字符串 """ # 解析参数 width = params.get("width", 1024) height = params.get("height", 1024) steps = params.get("num_inference_steps", 50) scale = params.get("guidance_scale", 7.5) neg_prompt = params.get("negative_prompt", "") seed = params.get("seed", -1) # 生成唯一种子(若为-1则用当前时间戳) generator = None if seed == -1: seed = int(time.time()) % 1000000 generator = torch.Generator(device="cuda").manual_seed(seed) # 调用模型生成 print(f"🖼 正在生成第 {idx+1} 张:{prompt[:30]}...") start_time = time.time() image = pipe( prompt=prompt, negative_prompt=neg_prompt, width=width, height=height, num_inference_steps=steps, guidance_scale=scale, generator=generator, ).images[0] # 构建文件名:[前缀]_[序号]_[宽]x[高]_[步数]s_[种子].png filename = f"{prefix}_{str(idx+1).zfill(2)}_{width}x{height}_{steps}s_{seed}.png" save_path = output_dir / filename # 保存图像 image.save(save_path) elapsed = time.time() - start_time print(f" 已保存:{filename} (耗时 {elapsed:.1f} 秒)") return str(save_path) # 批量执行主函数 def run_batch_generation(): print(f"\n 开始批量生成,共 {len(PROMPTS)} 张图") print(f" 输出目录:{OUTPUT_DIR}") print("-" * 50) results = [] for i, prompt in enumerate(PROMPTS): try: path = generate_and_save( prompt=prompt, idx=i, output_dir=OUTPUT_DIR, params=DEFAULT_PARAMS, prefix="glm_batch" ) results.append(path) except Exception as e: print(f" 第 {i+1} 张生成失败:{str(e)}") continue print("-" * 50) print(f" 批量任务完成!成功生成 {len(results)} 张图") print(f" 查看全部结果:ls {OUTPUT_DIR}") return results # 如果直接运行此脚本,则执行批量任务 if __name__ == "__main__": run_batch_generation()这段是真正的“心脏”:
generate_and_save()封装了单次生成全流程,包含日志打印、计时、错误捕获- 文件名严格遵循
glm_batch_01_1024x1024_50s_123456.png格式,清晰可读 - 失败时不会中断整个流程,而是记录错误继续下一张,保障鲁棒性
3.5 运行脚本并验证结果
保存文件后,在终端执行:
cd /root/build/ python batch_gen.py你会看到类似这样的输出:
GLM-Image模型加载成功,准备就绪 开始批量生成,共 5 张图 输出目录:/root/build/outputs/batch_gen -------------------------------------------------- 🖼 正在生成第 1 张:一只戴墨镜的橘猫,坐在霓虹灯下的摩托... 已保存:glm_batch_01_1024x1024_50s_428912.png (耗时 132.4 秒) 🖼 正在生成第 2 张:一只穿宇航服的柴犬,漂浮在土星环旁... 已保存:glm_batch_02_1024x1024_50s_735109.png (耗时 135.1 秒) ... -------------------------------------------------- 批量任务完成!成功生成 5 张图 查看全部结果:ls /root/build/outputs/batch_gen然后检查输出目录:
ls /root/build/outputs/batch_gen/ # 输出: # glm_batch_01_1024x1024_50s_428912.png # glm_batch_02_1024x1024_50s_735109.png # glm_batch_03_1024x1024_50s_192745.png # glm_batch_04_1024x1024_50s_883621.png # glm_batch_05_1024x1024_50s_554302.png每张图都精准对应你的提示词,文件名自带参数信息,后期整理、筛选、归档毫无压力。
4. 进阶技巧:让批量更智能、更省心
上面的脚本已能满足80%的批量需求。如果你还想进一步提升效率,这里提供三个即插即用的增强方案:
4.1 方案一:从CSV/Excel读取提示词(告别硬编码)
把提示词存进prompts.csv:
prompt,negative_prompt,width,height,steps,scale "戴墨镜的橘猫...","blurry,text",1024,1024,50,7.5 "穿宇航服的柴犬...","low quality",768,1024,75,8.0然后在脚本开头替换PROMPTS定义:
import csv def load_prompts_from_csv(csv_path: str) -> List[dict]: prompts = [] with open(csv_path, "r", encoding="utf-8") as f: reader = csv.DictReader(f) for row in reader: prompts.append({ "prompt": row["prompt"], "negative_prompt": row.get("negative_prompt", ""), "width": int(row.get("width", 1024)), "height": int(row.get("height", 1024)), "steps": int(row.get("steps", 50)), "scale": float(row.get("scale", 7.5)), }) return prompts # 替换原来的 PROMPTS = [...] 为: PROMPTS = load_prompts_from_csv("/root/build/prompts.csv")从此,运营同事改文案、设计师调参数,都不用碰代码,改个CSV就行。
4.2 方案二:添加进度条与生成预览
在run_batch_generation()中加入tqdm(需pip install tqdm):
from tqdm import tqdm # 替换原循环: for i, prompt in enumerate(tqdm(PROMPTS, desc=" 生成中")): ...终端会显示动态进度条,还能估算剩余时间,心理更有底。
4.3 方案三:失败自动重试 + 日志记录
增强错误处理,让脚本更“皮实”:
import logging # 配置日志 logging.basicConfig( level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s", handlers=[ logging.FileHandler("/root/build/batch_gen.log"), logging.StreamHandler() ] ) # 在 generate_and_save 中捕获异常后: except Exception as e: logging.error(f"第 {i+1} 张生成失败 | 提示词:{prompt} | 错误:{str(e)}") # 可选:等待2秒后重试一次 time.sleep(2) # 再次尝试...日志文件会记录每一次失败的完整上下文,方便排查是网络问题、显存溢出还是提示词语法错误。
5. 常见问题与避坑指南
写脚本最怕“明明代码没错,就是跑不通”。以下是真实踩过的坑和对应解法:
5.1 Q:报错OSError: Can't load tokenizer或Model not found
A:这是模型路径没对上。请确认:
- WebUI是否已成功加载过GLM-Image?打开
http://localhost:7860,点「加载模型」,等进度条走完再关掉 - 检查路径是否存在:
ls -l /root/build/cache/huggingface/hub/models--zai-org--GLM-Image - 如果路径是
models--zai-org--glm-image(小写),请把脚本中的model_path改成对应小写
5.2 Q:生成速度极慢,或显存爆满(CUDA out of memory)
A:两个动作立刻做:
- 确认已启用
pipe.enable_model_cpu_offload()(脚本里已写好) - 降低分辨率:把
width/height从1024改成768或512,速度提升2倍以上,画质损失肉眼难辨
5.3 Q:生成的图全是灰色噪点,或内容严重偏离提示词
A:大概率是guidance_scale设太低(<5.0)或太高(>12.0)。建议区间:6.0–9.0。
另外检查negative_prompt是否为空——空值会导致模型“放飞自我”,务必填上基础过滤词:"blurry, low quality, text, signature, watermark"
5.4 Q:文件名里的种子总是-1,导致无法复现
A:脚本中seed = -1是故意设计的随机模式。如需复现某张图,请:
- 查看该图文件名末尾的数字(如
_428912.png) - 在
DEFAULT_PARAMS中把"seed": -1改为"seed": 428912 - 单独运行这一条:
generate_and_save(PROMPTS[0], 0, OUTPUT_DIR, {...})
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。