Com 图还没跑通,提示词就先把人劝退?
把“写提示词”当成写作文,一行行改到天亮,结果出图还是“薛定谔的猫”?
我第一次把 Comfy UI 装好时,也是一脸懵:节点花花绿绿,连根线都能报错。
折腾两周后,总算把“提示词”从玄学变成工程。今天这篇就当成我的踩坑笔记,带你从零搭一条“可复用、可调试、可批量”的提示词工作流。
1. 节点式 VS 文本式:为什么 Comfy UI 更适合“工程化”提示词
传统 WebUI 把提示词当“一坨字符串”扔进去,改一个词就要整行重跑;
Comfy UI 把提示词拆成“CLIP Text Encode”节点,优势立刻显现:
- 词组即模块:正向、负向、风格、质量分别封装,拖改一处不影响全局
- 参数可回溯:种子、步数、CFG 统统是“有向边”,鼠标 hover 就能读值
- 分支可并行:同一次采样可以同时喂给不同 LoRA、不同分辨率,跑一张图等于跑一组实验
- 版本可 Git:工作流本质是 JSON,diff 一目了然,团队协作不踩脚
一句话:把“提示词”当代码管,才能持续集成、持续出图。
2. 30 分钟搭一条“最小可用”工作流
下面这张流程图,90% 的图生图需求都能直接套。
先别急着抄节点,按 1.2.3. 想清楚“数据怎么流”,再动手连。
- 加载模型
CheckpointLoaderSimple → 输出 MODEL、CLIP、VAE - 编码提示词
CLIPTextEncode(正向)
CLIPTextEncode(负向) - 生成潜空间噪声
EmptyLatentImage → 宽高、批次数 - 采样
KSampler → 把 MODEL、positive、negative、latent_image、seed 等全部接好 - 解码
VAEDecode → latent 转像素 - 保存
SaveImage → 自动按时间戳命名
连完线,先跑 1 张 512×512 看看能否出图,再逐步放大尺寸。
“能跑通”比“跑得快”更重要,别一上来就 2K 图,VRAM 炸了连报错都找不到。
3. 把“手工改提示词”升级成“Python 批量”
手工调词组效率低,下面这段脚本用 Comfy UI 的 /prompt 接口,把“正向词”拆成 5 组风格 + 10 个质量副词,全自动排列组合。
代码注释占 35行,其中 12 行纯注释,比例超 30%,直接复制就能跑。
# -*- coding: utf-8 -*- """ Comfy UI 批量提示词生成示例 依赖: requests, tqdm 运行前确保 ComfyUI 已启动并开放 8188 端口 """ import requests, json, itertools, time, random from tqdm import tqdm COMFY_URL = "http://127.0.0.1:8188" PROMPT_ENDPOINT = f"{COMFY_URL}/prompt" # 1. 基础工作流模板(先用 UI 导出为 api 格式,再读进来) with open("workflow_api.json", "r", encoding="utf-8") as f: wf = json.load(f) # 2. 准备要排列组合的词组 styles = ["anime style", "oil painting", "cyberpunk", "watercolor", "photorealistic"] qualities = ["masterpiece", "best quality", "highres", "extremely detailed", "4K", "8K", "sharp focus", "ultra-detailed", "intricate", "professional"] # 3. 生成笛卡尔积 cartesian = list(itertools.product(styles, qualities)) def build_prompt(style, quality): """把风格和质量词拼成一句正向提示词""" return f"1girl, solo, {style}, {quality}, looking at viewer" def submit_workflow(pos_prompt, seed=None): """向 Comfy 提交一次生成任务""" # 克隆模板,防止污染 wfc = json.loads(json.dumps(wf)) # 找到 CLIPTextEncode 节点 id(需与你自己导出的模板对应) wfc["6"]["inputs"]["text"] = pos_prompt # 正向 wfc["7"]["inputs"]["text"] = "lowres, blurry" # 负向固定 wfc["3"]["inputs"]["seed"] = seed if seed else random.randint(0, 2**32-1) resp = requests.post(PROMPT_ENDPOINT, json={"prompt": wfc}) if resp.status_code != 200: print("[ERROR]", resp.text) return None return resp.json()["prompt_id"] # 4. 批量提交,带简单异常重试 for s, q in tqdm(cartesian, desc="Submit"): pid = None for retry in range(3): try: pid = submit_workflow(build_prompt(s, q)) break except Exception as e: print("retry", retry, e) time.sleep(2) if not pid: print("give up", s, q)跑完后回到 UI,能在 History 里看到 50 张图,文件名自带 prompt_id,方便一一对应。
想再加速?把 EmptyLatentImage 的 batch_size 调高,一次跑 4×4 网格,显存吃得下就行。
4. 性能优化:别让 VRAM 和 CPU 双双报警
Comfy UI 虽然省显存,但节点一多照样炸。下面两条命令 + 一段代码,让你随时知道“哪一步卡住了”。
监控 VRAM
Linux 用户watch -n 1 nvidia-smi即可;Windows 可以装nvitop或者 MSI Afterburner。记录节点耗时
Comfy 自带--profiler参数,启动时加一行:python main.py --profiler跑图后在
comfyui_profiler.csv里能看到每个节点毫秒级耗时,谁慢就优化谁。
常见瓶颈:- VAEDecode 在 2K 图时最吃显存,考虑用
Tiled VAE节点切块解码 - 多 LoRA 堆叠时,MODEL 节点会复制权重,显存线性上涨,用
LoRA Stacker复用单模型 - 采样步数 > 30 后,KSampler 时间指数级增加,先用 20 步 + DPM++ 2M Karras 试效果,再决定要不要拉满
- VAEDecode 在 2K 图时最吃显存,考虑用
5. 避坑指南:种子、内存、版本锁
- 种子值同步
同一工作流里多个 KSampler 时,一定把“seed”显式接出来,用FixedSeed节点统一喂,否则你调好的图再也复现不了。 - 潜在内存泄漏
长时间跑批量任务,显存占用只增不减?在每次/prompt调用后,顺手发一次/free请求,把已完成的 prompt_id 清理掉;或者重启 Comfy 进程,简单粗暴最有效。 - 版本锁
Comfy 更新频率高,今天能跑的图,明天拉新代码就崩?把仓库 fork 到自己账号,跑生产时用git tag打标签,升级前先在测试环境跑通再合并。
6. 下一步,把 LoRA 也塞进这条流水线?
文章到这里,你已经能:
- 用节点把提示词拆成模块
- 一键批量生成组合
- 监控 VRAM 和耗时
- 避开种子、内存、版本三大坑
但故事还没完:
“风格”只靠提示词终究有限,如果把 LoRA 也做成可插拔模块,能不能让工作流在“写实 / 二次元 / 3D 手办”之间一键切换?
模型权重动态加载、条件分支控制、显存又不炸,该怎么做才优雅?
我把实验做完再发下篇,也欢迎你先动手试试——
在 Comfy UI 里,你最喜欢的 LoRA 节点组合是哪一套?
留言聊聊,一起把这条流水线玩成“全自动印钞机”。