AI-Agent 驱动 ComfyUI 出图操作手册
AI-Agent 驱动 ComfyUI 出图操作手册
读者:下一个接手本机的 agent(或人)。 目标:看完就能用 shell 驱动本机 ComfyUI 出图,并能从零把这套能力复现出来。 要下模型:26 个模型的权威下载源 + 实测可达性 + 可复制 curl → 见 §11 模型下载清单(87.3 GiB,18 个 HuggingFace 免登录 / 8 个 Civitai 需 token)。 配套文档:
/home/zero/Desktop/绘画手册.md(511 行)——先读它。那份文档是”出图配方与审美经验”的沉淀(提示词、LoRA 搭配、denoise 调参、踩坑记录);本文件不重复它的内容,只讲**“agent 怎么操作” + “怎么复现” + “怎么验收”,并勘误**其中本次实测不符的几处。 本文件所有数值均来自 2026-10-17 本机实测(原始输出见 §5、§9);凡未实测的一律标注⚠未验证或引自手册。 验证环境:ComfyUI 0.40.0 · Python 3.12.3 · PyTorch 2.11.0+cu130 · RTX 4070 SUPER 12GB · 驱动 595.99.02
0. 一分钟上手(TL;DR)
# 1) 服务活着吗curl -s http://127.0.0.1:8188/system_stats | head -c 200
# 2) 出图(必须用 venv 里的 python,系统 python3 没有 numpy)cd /home/zero/ComfyUI && ./venv/bin/python image_scripts/draw.py --listcd /home/zero/ComfyUI && ./venv/bin/python image_scripts/draw.py --scene aurora --seeds 11
# 3) 产物在哪ls -la /home/zero/ComfyUI/output/ # 新图ls -la /home/zero/ComfyUI/output/4K/ # 4K 成品(11 png + 说明.txt)
# 4) 升 4Kcd /home/zero/ComfyUI && ./venv/bin/python image_scripts/upscale_4k_batch.py四条铁律(每条都有实测支撑,详见 §6):
- 必须用
/home/zero/ComfyUI/venv/bin/python(系统python3连 numpy 都没有)。实测:python3 -c "import numpy"→ModuleNotFoundError: No module named 'numpy'。 - HTTP 400 一定要
e.read()读响应正文,否则只看到一句Bad Request,完全不知道哪个节点哪个参数错了。 SaveImage.filename_prefix必须带时间戳,否则 ComfyUI 节点输出缓存会让你”报成功但文件不存在”。- 真的去
os.path.exists()校验每个产物,/history说成功不等于落盘。
1. 本机环境事实核查表
以下每一项都是本次实测结果(命令与原始输出见括号处)。
| 项 | 实测值 | 出处 |
|---|---|---|
| 服务地址 | http://127.0.0.1:8188 | GET /system_stats |
| ComfyUI 版本 | 0.40.0 | GET /system_stats |
| 前端 / 模板版本 | 1.55.17 / 0.11.82 | GET /system_stats |
| Python | 3.12.3 (main, Aug 31 2026) [GCC 13.3.0],embedded_python: false | GET /system_stats |
| PyTorch | 2.11.0+cu130 | GET /system_stats |
| 进程命令行 | ./venv/bin/python main.py --listen 127.0.0.1 --port 8188 | ps -eo pid,cmd(PID 231536,父进程 231534) |
| 进程 cwd | /home/zero/ComfyUI | readlink /proc/231536/cwd |
| 进程已运行 | 06:29:32(6 小时 29 分) | ps -eo etime |
| 启动日志 | /tmp/comfy_restart.log | 父进程命令行里的 nohup ... > /tmp/comfy_restart.log |
| GPU | NVIDIA GeForce RTX 4070 SUPER,12282 MiB,空闲时占用 1656 MiB | nvidia-smi |
| VRAM(API 视角) | total 12449873920 B / free 11169093108 B | GET /system_stats |
| 内存 | total 33466429440 B / free 21602140160 B | GET /system_stats |
| 节点总数 | 1022 个 | GET /object_info |
| venv 依赖 | numpy 2.5.4 / scipy 1.18.1 / PIL 12.3.0 | venv/bin/python -c ... |
| 系统 python3 | 无 numpy | python3 -c "import numpy" |
| 网络代理 | http://127.0.0.1:7897 可达(HF API 200,0.315s) | curl -x ... https://huggingface.co/api/models/Comfy-Org/BiRefNet |
1.1 ⚠ 与 绘画手册.md 不符的 3 处(本次实测)
| 手册原文 | 实测事实 | 影响 |
|---|---|---|
§1 「手动启动:~/start-comfyui.sh」 | 该文件不存在(ls: 无法访问 '/home/zero/start-comfyui.sh';/home/zero/*.sh 也无匹配) | 别照着敲;用 §4.2 的实际命令 |
§1 / §7.19 「background_removal 目录不在 extra_model_paths.yaml 映射列表里」 | 已在映射里:extra_model_paths.yaml 的 localdisk: 段含 background_removal: background_removal;外置盘 <模型根>/background_removal/ 目录也确实存在(当前只有 put_background_removal_models_here 占位文件) | 该坑描述已过期,但当前有效结论不变:LoadBackgroundRemovalModel 的 options 实测只有 ["birefnet.safetensors"],它来自本地 /home/zero/ComfyUI/models/background_removal/(外置盘那份是空的) |
§3.8 / §4 给出的 RemoveBackground 连线写作 "background_removal_model": ["2",0] | 节点真实输入名是 bg_removal_model;写错会 HTTP 400 required_input_missing: bg_removal_model | 只是手册文档里的示例写法有误。脚本本身是对的:实测 image_scripts/matte_birefnet.py:33 写的就是 bg_removal_model,实跑成功(2.0s,蒙版 213KB)——详见 §6.6 的更正说明 |
2. 架构:agent 只有 shell 时怎么驱动 ComfyUI
2.1 三条通路总览
| 通路 | 入口 | 能做什么 | 限制 |
|---|---|---|---|
| A. HTTP API | http://127.0.0.1:8188 | 万能。任意节点、任意模型(UNET/checkpoint/抠像/放大)、任意工作流 | 要自己写 JSON 图、自己轮询、自己校验落盘 |
| B. MCP 工具 | mcp__comfyui__*(15 个) | 一行调用出图 / 查队列 / 取图;有 asset 台账 | 只能喂 checkpoint 模型;喂不进 Krea-2 / Anima(UNET 系) |
| C. 现成脚本 | /home/zero/ComfyUI/image_scripts/*.py(8 个) | 封装好的 5 条已验证管线,带轮询+落盘校验+时间戳防缓存 | 只能干它写死的那件事;改需求要改代码 |
推荐用法:能用 C 就用 C(已验证、有防坑);C 干不了 → 用 A(照 §3 自己拼图);只想快速看一张 SDXL 图 → 用 B。
2.2 HTTP API 端点速查
| 方法 | 端点 | 作用 | 实测 |
|---|---|---|---|
GET | /system_stats | 服务存活 + 版本 + GPU + VRAM | ✅ |
GET | /object_info | 全部 1022 个节点的定义(参数名/类型/合法枚举/输出槽位) | ✅ |
GET | /object_info/<NodeName> | 单个节点定义 —— 拼图前必查 | ✅ |
POST | /prompt | 提交工作流,返回 prompt_id | ✅ 返回 {"prompt_id": "...", "number": 103, "node_errors": {}} |
GET | /history/<prompt_id> | 查执行结果(状态 + 产物文件名 + 内嵌 metadata) | ✅ 未完成的 id 返回 {} |
GET | /queue | 队列状态 | ✅ 返回 {"queue_running": [], "queue_pending": []} |
GET | /view?filename=<f>&type=output | 取图二进制 | ✅ HTTP 200,image/png,238711 B |
GET | /history | 全部历史 | ⚠未验证 |
POST | /interrupt | 中断当前任务 | ⚠未验证 |
/view为什么重要:MCP 只给 URL;在纯 shell 环境下要拿到像素,就得curl -o落盘再PIL打开。实测取回的 PNG 内嵌prompt文本块('prompt' in img.info == True),既是原图也是证据。
2.3 最小可用客户端(含必须的 400 正文读取)
这段是本次所有验证脚本的骨架,直接抄:
import json, os, time, urllib.request, urllib.error, uuid
API = "http://127.0.0.1:8188"OUT = "/home/zero/ComfyUI/output"
def post(path, data, t=900): req = urllib.request.Request(API + path, data=json.dumps(data).encode(), headers={"Content-Type": "application/json"}) try: return json.load(urllib.request.urlopen(req, timeout=t)) except urllib.error.HTTPError as e: # ★ 关键:不 read() 就永远只看到 "Bad Request" print(f"[ComfyUI {e.code}] {e.read().decode('utf-8', 'replace')[:1500]}") raise
def get(path): return json.load(urllib.request.urlopen(API + path, timeout=900))
def submit_and_wait(wf): """提交 + 轮询 + 返回 (prompt_id, history_record)""" pid = post("/prompt", {"prompt": wf, "client_id": str(uuid.uuid4())})["prompt_id"] while True: h = get(f"/history/{pid}") if pid in h: return pid, h[pid] time.sleep(2) # 实测最小图 4.0s 完成,2s 轮询足够校验落盘(必做):
rec = ... # history 记录for node in rec["outputs"].values(): for im in node.get("images", []): p = os.path.join(OUT, im["filename"]) if not os.path.exists(p): # ★ /history 说成功 ≠ 文件存在 print("[warn] history 报了但文件不存在:", p) continue print("[ok]", p, os.path.getsize(p), "B")2.4 MCP 工具(15 个)能做什么 / 不能做什么
能:
| 工具 | 作用 |
|---|---|
generate_image | 一行出图(checkpoint_model + prompt + width/height/steps/seed/negative_prompt) |
generate_song | 出歌(tags/lyrics/seconds/cfg/steps/lyrics_strength) |
list_checkpoint_models | 列 checkpoint(只 3 个,见下) |
list_unet_models / list_unet_gguf_models | 列出 UNET 文件(共 6 个,但 generate_image 用不了它们) |
list_workflows | 列 MCP 侧工作流(只有 2 个:generate_image、generate_song) |
get_job / wait_for_job / cancel_job / get_queue_status | 作业治理 |
list_assets / get_asset_metadata / view_image / regenerate / run_workflow | 资产台账与重跑 |
不能(实测依据):
- ❌ 喂不进 Krea-2 / Anima。
generate_image唯一模型参数叫checkpoint_model,list_workflows返回的参数表里没有任何 UNET/CLIP/VAE 入口。而本机 checkpoint 实测只有:而RealVisXL_V5.0_fp16.safetensorsanimagine-xl-3.0.safetensorschenkinNoobXLCKXL_v02.safetensorsanima_baseV10/krea2_raw_fp8_scaled只存在于diffusion_models/(走UNETLoader)+ 需要外挂 4B/0.6B 文本编码器。这是”checkpoint 加载器(SDXL 架构)“与”UNET+独立 CLIP”两条路的结构性隔离,不是配置问题。 - ❌ 不能指定 LoRA / IPAdapter / sampler / scheduler / denoise / 抠像 / 放大 / 图生图。
- ❌ 不能拿到本地文件路径去加工(只给 URL 与字节数)—— 而它写出的文件确实落在
/home/zero/ComfyUI/output/(实测ComfyUI_00001_.png就在那儿,可直接PIL处理)。 - ⚠ 命名冲突风险:
generate_image用固定前缀ComfyUI_,连跑会自增编号(_00001_、_00002_…),但仍可能与既有文件重名/覆盖。
结论:MCP 是”给 SDXL checkpoint 快速出图”的便捷通道;本机主力画风(Anima 2B / Krea-2)必须走 HTTP API 或
image_scripts/。
3. 工作流即 JSON 图
3.1 数据结构
ComfyUI 的”工作流”在 API 层就是一个 {节点id: {class_type, inputs}} 的扁平字典——没有 UI 坐标、没有组、没有连线列表。两类 key:
| key | 含义 | 例子 |
|---|---|---|
class_type | 节点类型名,必须是 /object_info 里的 key | "KSampler" |
inputs | 该节点的所有输入参数;参数值直接写,连线写成二元数组 | "steps": 8 / "seed": 1234 |
连线的写法 = ["上游节点id字符串", 输出槽位序号]:
"model": ["1", 0] // 取节点 "1" 的第 0 号输出"positive": ["2", 0] // 取节点 "2" 的第 0 号输出"vae": ["1", 2] // ★ checkpoint 的第 2 号输出才是 VAE输出槽位必须查表(写错槽位不会报 400,会静默接错类型或报类型不匹配)。本次实测的槽位表:
| 节点 | 输出槽位 |
|---|---|
CheckpointLoaderSimple | 0=MODEL, 1=CLIP, 2=VAE |
UNETLoader | 0=MODEL |
CLIPLoader | 0=CLIP |
VAELoader | 0=VAE |
LoraLoader | 0=MODEL, 1=CLIP |
CLIPTextEncode | 0=CONDITIONING |
EmptyLatentImage / EmptySD3LatentImage | 0=LATENT |
KSampler | 0=LATENT |
VAEDecode | 0=IMAGE |
VAEEncode | 0=LATENT |
LatentUpscaleBy | 0=LATENT |
LoadImage | 0=IMAGE, 1=MASK |
SaveImage | 0=images(终端节点) |
UpscaleModelLoader | 0=UPSCALE_MODEL |
ImageUpscaleWithModel / ImageScale | 0=IMAGE |
CLIPVisionLoader | 0=CLIP_VISION |
IPAdapterModelLoader | 0=IPADAPTER |
IPAdapterAdvanced | 0=MODEL |
LoadBackgroundRemovalModel | 0=bg_model |
RemoveBackground | 0=mask |
MaskToImage | 0=IMAGE |
3.2 最小可运行工作流(本次实测跑通的那一份)
这是 §5.1 的真实图,复制即用(只要改 ckpt_name):
{ "1": {"class_type": "CheckpointLoaderSimple", "inputs": {"ckpt_name": "animagine-xl-3.0.safetensors"}}, "2": {"class_type": "CLIPTextEncode", "inputs": {"text": "1girl, blue hair, whale, ocean, masterpiece", "clip": ["1", 1]}}, "3": {"class_type": "CLIPTextEncode", "inputs": {"text": "lowres, bad anatomy, worst quality", "clip": ["1", 1]}}, "4": {"class_type": "EmptyLatentImage", "inputs": {"width": 512, "height": 512, "batch_size": 1}}, "5": {"class_type": "KSampler", "inputs": {"seed": 20261017, "steps": 8, "cfg": 5.0, "sampler_name": "euler", "scheduler": "simple", "denoise": 1.0, "model": ["1", 0], "positive": ["2", 0], "negative": ["3", 0], "latent_image": ["4", 0]}}, "6": {"class_type": "VAEDecode", "inputs": {"samples": ["5", 0], "vae": ["1", 2]}}, "7": {"class_type": "SaveImage", "inputs": {"filename_prefix": "ZZZ_agent_probe", "images": ["6", 0]}}}UNET 系(Anima / Krea-2)把节点 1-3 换成
UNETLoader+CLIPLoader(type=...)+VAELoader,完整模板见绘画手册.md§4.1 / §4.3。
3.3 怎么知道参数名和合法值
永远先查,不要猜——猜错的表现是 HTTP 400:
# 单节点全量定义curl -s http://127.0.0.1:8188/object_info/LatentUpscaleBy | \ /home/zero/ComfyUI/venv/bin/python -m json.tool
# 只看"哪些参数 + 枚举合法值"(省 token 的写法)curl -s http://127.0.0.1:8188/object_info | /home/zero/ComfyUI/venv/bin/python -c "import json,sysd=json.load(sys.stdin)for pn,pv in d['LatentUpscaleBy']['input']['required'].items(): print(' ',pn,'=',pv[0] if isinstance(pv[0],list) else pv[0], pv[1] if len(pv)>1 else '')"本次实测的几个高频枚举(写死这些,别自创):
| 节点.参数 | 合法值(实测) |
|---|---|
LatentUpscaleBy.upscale_method | nearest-exact, bilinear, area, bicubic, bislerp ← 没有 bisect |
LatentUpscaleBy.scale_by | FLOAT,default 1.5,范围 0.01–8.0,step 0.01 |
UNETLoader.weight_dtype | default, fp8_e4m3fn, fp8_e4m3fn_fast, fp8_e5m2 |
CLIPLoader.type | 30 个,含 qwen_image、krea2、stable_diffusion、sd3、flux2… |
IPAdapterAdvanced.weight_type | linear, ease in, ease out, ease in-out, reverse in-out, weak input, weak output, weak middle, strong middle, style transfer, composition, strong style transfer, style and composition, style transfer precise, composition precise ← 没有 style |
IPAdapterAdvanced.combine_embeds | concat, add, subtract, average, norm average |
IPAdapterAdvanced.embeds_scaling | V only, K+V, K+V w/ C penalty, K+mean(V) w/ C penalty |
IPAdapterAdvanced.weight | FLOAT default 1.0,范围 -1–5,step 0.05 |
KSampler.sampler_name | 45 个,常用 euler, euler_ancestral, dpmpp_2m, dpmpp_2m_sde, dpmpp_3m_sde, ddim, uni_pc… |
KSampler.scheduler | simple, sgm_uniform, karras, exponential, ddim_uniform, beta, normal, linear_quadratic, kl_optimal |
LoadBackgroundRemovalModel.bg_removal_name | 实测仅 birefnet.safetensors |
UpscaleModelLoader.model_name | 实测仅 4x-UltraSharp.pth |
CheckpointLoaderSimple.ckpt_name | 实测 3 个(见 §2.4) |
3.4 提交 → 轮询 → 落盘校验(标准三段式)
cd /home/zero/ComfyUI && ./venv/bin/python - <<'EOF'import json, os, time, urllib.request, uuidAPI = "http://127.0.0.1:8188"; OUT = "/home/zero/ComfyUI/output"wf = json.load(open("/tmp/my_workflow.json")) # 你的图pid = json.load(urllib.request.urlopen(urllib.request.Request( API + "/prompt", data=json.dumps({"prompt": wf, "client_id": str(uuid.uuid4())}).encode(), headers={"Content-Type": "application/json"}), timeout=120))["prompt_id"]print("prompt_id:", pid)while True: h = json.load(urllib.request.urlopen(f"{API}/history/{pid}", timeout=120)) if pid in h: rec = h[pid] print("status_str:", rec["status"]["status_str"]) # success / error if rec["status"]["status_str"] == "error": for m in rec["status"]["messages"]: if m[0] == "execution_error": print("exception_message:", m[1].get("exception_message")) for node in rec["outputs"].values(): for im in node.get("images", []): p = os.path.join(OUT, im["filename"]) print(im["filename"], "存在" if os.path.exists(p) else "★缺失", os.path.getsize(p) if os.path.exists(p) else "") break time.sleep(2)EOF三种终态:
status_str | 含义 | 处理 |
|---|---|---|
success | 执行完 | 仍要 os.path.exists() 校验(可能命中缓存不写盘,§6.3) |
error | 节点运行时报错 | 读 messages 里的 execution_error.exception_message |
(压根没有 prompt_id) | POST /prompt 就 400 了 | 读 e.read() 正文,看 node_errors 里是哪个节点哪个参数(§6.1) |
4. 环境准备与自检(从零复现 Step 1–5)
4.1 自检五连(每次开工先跑)
# ① 服务活着吗 —— 期望:一段 JSON,含 "comfyui_version": "0.40.0"curl -s -m 5 http://127.0.0.1:8188/system_stats | head -c 200
# ② GPU 在吗、显存够吗 —— 期望:RTX 4070 SUPER,total 12282 MiBnvidia-smi --query-gpu=name,memory.total,memory.used,driver_version --format=csv
# ③ venv 依赖 —— 期望:numpy 2.5.4 scipy 1.18.1 PIL 12.3.0/home/zero/ComfyUI/venv/bin/python -c "import numpy,scipy,PIL;print('numpy',numpy.__version__,'scipy',scipy.__version__,'PIL',PIL.__version__)"
# ④ 系统 python 的坑 —— 期望:ModuleNotFoundError: No module named 'numpy'(这就是不能用的原因)python3 -c "import numpy" 2>&1 | tail -1
# ⑤ 队列空不空 —— 期望:{"queue_running": [], "queue_pending": []}curl -s -m 5 http://127.0.0.1:8188/queue4.2 服务没在跑 → 这样拉起来
实际有效的命令(~/start-comfyui.sh 不存在,也没有任何 /home/zero/*.sh):
cd /home/zero/ComfyUI && nohup ./venv/bin/python main.py --listen 127.0.0.1 --port 8188 \ > /tmp/comfy_restart.log 2>&1 &
# 等就绪(唯一可信判据是 /system_stats 能返回,不是 sleep 拍脑袋)for i in $(seq 1 60); do sleep 3 curl -s -m 5 http://127.0.0.1:8188/system_stats >/dev/null 2>&1 && { echo "✓ 就绪 (${i}0s内)"; break; }donecurl -s -m 5 http://127.0.0.1:8188/system_stats >/dev/null 2>&1 || { echo "启动失败,日志尾部:"; tail -20 /tmp/comfy_restart.log; }当前实例就是这么起的(
ps里父进程命令行即上述 nohup + 轮询),日志在/tmp/comfy_restart.log,已连续运行 6h29m。 ⚠ 不要重复启动:8188 被占时会失败;先跑curl /system_stats。 ⚠ 若真的需要重启,重启后必须重跑任务(ComfyUI 重启会丢内存中的模型缓存,但不丢/output)。
4.3 模型清单怎么拿(不是 ls,是问 API)
模型可能散在本地 models/ 和外置盘(extra_model_paths.yaml 映射)。唯一权威来源是 /object_info:
curl -s http://127.0.0.1:8188/object_info | /home/zero/ComfyUI/venv/bin/python -c "import json,sysd=json.load(sys.stdin)def opts(n,k): try: return d[n]['input']['required'][k][0] except Exception: return 'N/A'print('节点总数 ->', len(d))for n,k,label in [('CheckpointLoaderSimple','ckpt_name','checkpoint'), ('UNETLoader','unet_name','unet/diffusion_models'), ('CLIPLoader','clip_name','text encoder'), ('VAELoader','vae_name','vae'), ('LoraLoader','lora_name','lora'), ('UpscaleModelLoader','model_name','放大模型'), ('IPAdapterModelLoader','ipadapter_file','ipadapter'), ('CLIPVisionLoader','clip_name','clip_vision'), ('LoadBackgroundRemovalModel','bg_removal_name','抠像')]: o=opts(n,k); o=o if isinstance(o,list) else o.get('options',[]) print(f'{label:24s} {len(o):2d} 个: {o}')"本次实测输出(存档,供比对):
节点总数 -> 1022checkpoint 3 个: RealVisXL_V5.0_fp16 / animagine-xl-3.0 / chenkinNoobXLCKXL_v02unet/diffusion_models 6 个: Anima-2.9B-preview-v1_int8_convrot / anima_baseV10 / krea2Anime_v14_int4 / krea2_raw_fp8_scaled / qwen_image_2.1_int8_convrot / wan2.1_t2v_1.3B_fp16text encoder 4 个: qwen3vl_4b_fp8_scaled / qwen3vl_8b_int8_convrot / qwen_3_06b_base / umt5_xxl_fp16vae 4 个: qwen_image_2.1_vae_bf16 / qwen_image_vae / wan_2.1_vae / pixel_spacelora 6 个: DeepSeek_ZipZipPipe_style_anima2b / deepseek_maid_outfit_illustrious_v10 / deepseek_whale_girl_anima_lora_clean / deepseek_whale_girl_krea2 / deepseek_whalegirl_noobai / ds_whalemaid_anima放大模型 1 个: 4x-UltraSharp.pthipadapter 1 个: ip-adapter_sdxl.safetensorsclip_vision 1 个: CLIP-ViT-bigG-14-laion2B-39B-b160k.safetensors抠像 1 个: birefnet.safetensors4.4 目录与文件布局
/home/zero/ComfyUI/├── venv/bin/python ← ★ 唯一可用的解释器├── main.py ← 启动入口(cwd 必须是 /home/zero/ComfyUI)├── extra_model_paths.yaml ← 外置盘映射(含 background_removal,见 §1.1)├── models/background_removal/birefnet.safetensors ← 424MB,抠像权重(真正的那个)├── image_scripts/ ← 8 个出图脚本(见 §7)├── input/ ← 输入素材(gemini_stand.png 941×1672 白底立绘、│ gemini_matte_birefnet.png 稳定蒙版 218861 B 等)└── output/ ← ★ 所有出图产物 ├── 4K/ ← 4K 成品:11 个 png + 说明.txt ├── 无法用/ ← 废图(当前 0 个文件) └── _output_images_will_be_put_here ← ComfyUI 自带占位文件(0 字节,勿删)
/media/zero/本地磁盘/Model/comfyui/ ← 外置模型根(checkpoints/ loras/ vae/ diffusion_models/ text_encoders/ ipadapter/ clip_vision/ upscale_models/ background_removal/ …)5. 已验证的管线(含本次真实运行记录)
证据说明:以下 [实测] 的结果都来自本次会话真实执行。验证用的临时图(前缀
ZZZ_*与 MCP 的ComfyUI_00001_.png)已在验证后全部删除,output/已 diff 回原状(见 §10)。
5.1 基础 txt2img(checkpoint 系)[实测]
图:§3.2 的 JSON。底模:animagine-xl-3.0.safetensors。参数:512×512 / 8 步 / CFG 5 / euler+simple / seed 20261017。
POST /prompt -> {"prompt_id": "899c338b-0165-478c-ba13-19138d385692", "number": 103, "node_errors": {}}轮询次数 -> 2 耗时 4.0sstatus -> {"status_str": "success", "completed": true, "messages": [ ["execution_start", {...}], ["execution_cached", {"nodes": [], "prompt_id": "..."}], ["execution_success", {...}]]}outputs -> {"7": {"images": [{"filename": "ZZZ_agent_probe_00001_.png", "subfolder": "", "type": "output", "metadata": {"kind": "image", "width": 512, "height": 512}}]}}落盘路径 -> /home/zero/ComfyUI/output/ZZZ_agent_probe_00001_.png存在 -> True 大小 -> 448899 B尺寸/模式 -> (512, 512) RGBPNG 内嵌 prompt 前 200 字 -> {"1": {"class_type": "CheckpointLoaderSimple", "inputs": {"ckpt_name": "animagine-xl-3.0.safetensors"}}, "2": {"class_type": "CLIPTextEncode", ...要点:
outputs里带metadata.width/height,可以不下图就知道尺寸。- 图内嵌完整工作流 JSON(
img.info["prompt"])—— 这是”这张图怎么来的”最硬的证据,比自己记参数可靠。 - 用时 4.0s(512² / 8 步 / 首次已加载模型)。
5.2 两段式高清 hires [实测]
图:EmptyLatentImage 512×512 → KSampler(8步, denoise 1.0) 首出 → LatentUpscaleBy(nearest-exact, 1.5) → KSampler(10步, denoise 0.5) 二段 → VAEDecode → SaveImage。
[hires] status=success 3.0s ZZZ_hires_1792178358_00001_.png 尺寸=(768, 768) 模式=RGB 大小=799998B要点:
- 512×512 × 1.5 = 768×768,实测吻合 →
LatentUpscaleBy是对潜空间缩放,最终像素尺寸 = 原尺寸 ×scale_by(向下取整到 8 的倍数)。 - 二段采样
denoise必须 < 1.0,否则等于重画(本机脚本默认0.45,见 §7)。 - ⚠ 手册 §5 的”手机壁纸竖版 1080×1920 = 首出 832×1472 → LatentUpscaleBy 1.2x → 降采样”是另一条路线(首出非方形,放大后靠 PIL 降采样定尺寸)。Anima 2B / Krea-2 系官方禁止先出图再放大,必须原生尺寸一次出(引自手册 §3.1/§3.6)。
5.3 角色复刻:场景起稿 + 整体 img2img [引自手册 §3.7,本次未重跑]
为什么值得单独讲:这是”给一张白底立绘 → 重画成带背景的图且角色不走形”的唯一可行路线。
四步管线(redraw.py):
| # | 步骤 | 关键参数 |
|---|---|---|
| 1 | BiRefNet 抠出目标立绘 alpha(仅用于搭骨架) | --matte smart(§5.4) |
| 2 | 生成纯场景背景(负向排除人物) | 负向含 1girl, person, people, character, human, figure, silhouette |
| 3 | 搭起稿骨架:背景 + 角色居中摆入 | char_h=1640(1080×1920 画布的 85%),预乘合成 c*a + bg*(1-a) 防白边 |
| 4 | 对骨架整体 img2img | denoise=0.45、IPAdapter(参考原立绘)@0.6、end_at=0.85、34 步 / CFG 6 / dpmpp_2m+karras |
反直觉但已验证的三条(引自手册 §3.7,本次未复测):
| 结论 | 数据 |
|---|---|
| 直接在白底立绘上 img2img 换不掉白底 | 关掉 IPAdapter、denoise 从 0.55 拉到 0.85,白底仍在(只在角色周围长光晕) |
| 骨架自己已经是真场景,所以 denoise 能压到 0.45 | 0.45 角色还原最好;0.70 头发褪成银白;0.85 走形 |
| 成品不是粘贴 | 成品 vs 骨架 MAE 18.58/255,误差 >24 的像素占 38.9%(直接粘贴 MAE≈0) |
用法:
cd /home/zero/ComfyUI/image_scripts/home/zero/ComfyUI/venv/bin/python matte_birefnet.py # 先出蒙版(⚠ 当前有 bug,见 §6.6)/home/zero/ComfyUI/venv/bin/python redraw.py --scene aurora --seeds 11 \ --matte smart --denoise 0.45 --outdir <输出目录>/home/zero/ComfyUI/venv/bin/python redraw.py --scene aurora --nofinal --reuse-bg <背景png> # 只搭骨架调构图5.4 BiRefNet 语义抠像 [实测]
问题的本质:白底立绘里”发丝缝隙 / 腿间 / 双脚之间的背景白”和”白衣服的白”颜色完全相同(都是 [254,254,254]),flood-fill 阈值从 249 放宽到 225 也分不开(被线稿封死)。必须靠语义模型。
标准节点链(⚠ 输入名以 bg_removal_model 为准):
{ "1": {"class_type": "LoadImage", "inputs": {"image": "gemini_stand.png", "upload": "image"}}, "2": {"class_type": "LoadBackgroundRemovalModel", "inputs": {"bg_removal_name": "birefnet.safetensors"}}, "3": {"class_type": "RemoveBackground", "inputs": {"bg_removal_model": ["2", 0], "image": ["1", 0]}}, "4": {"class_type": "MaskToImage", "inputs": {"mask": ["3", 0]}}, "5": {"class_type": "SaveImage", "inputs": {"filename_prefix": "matte_tmp_<时间戳>", "images": ["4", 0]}}}本次实测输出:
status -> success 1.0s落盘 -> ZZZ_matte_1792178385_00001_.png (941, 1672) RGB 218861 B蒙版: 前景(>128)占比 46.91% 均值 119.1 唯一值数 256要点:
- 输入立绘
input/gemini_stand.png是 941×1672,蒙版同尺寸。 - 抠像只需 1 秒,很便宜,可以随便重跑。
- 输出是
MaskToImage后的灰度图(8-bit,256 个灰阶),不是 RGBA。 - stability 交叉验证:本地稳定蒙版
input/gemini_matte_birefnet.png也是 218861 B,与本次重跑完全同尺寸同字节数 → 该管线是确定性的。 - ⚠ “裸用 BiRefNet 不够”:手册 §3.8 实测裸用只能把内部白块误留降到 43.8%,必须再加”逐块算 BiRefNet 均值、
<0.5判背景 />=0.5判白衣服”的第 2 步(redraw.py: load_alpha(matte="smart"))才降到理想水平。这一步在redraw.py里,不在 ComfyUI 节点里。
5.5 4K 放大(单张 / 批量)[实测]
核心链:LoadImage → UpscaleModelLoader(4x-UltraSharp.pth) → ImageUpscaleWithModel → ImageScale(lanczos, 目标尺寸, crop=disabled) → SaveImage。
(a) 4× 模型放大单独跑 [实测]:
[4x-UltraSharp] status=success 11.0s ZZZ_ups4x_1792178358_00001_.png 尺寸=(3764, 6688) 模式=RGB 大小=24199034B输入是 gemini_stand.png 941×1672 → 输出 3764×6688(严格 4 倍)→ 说明 4x-UltraSharp 确实按 4 倍放大,且耗时 11s / 24MB。
(b) 批量 4K 脚本端到端跑 [实测]:
cd /home/zero/ComfyUI && ./venv/bin/python image_scripts/upscale_4k_batch.py --only ZZZ_batch_probe.png待处理 1 个,4K 口径 = 保持比例 + 长边 3840
[1/1] ZZZ_batch_probe.png 320x240 -> 3840x2880 4x -> up4k_1_1792178399_00001_.png (2s) ✅ ZZZ_batch_probe_4K.png 0.1MB
完成:成功 1 / 跳过 0 / 失败 0要点(4K 口径 = 保持比例,长边 3840):
| 源比例 | 目标尺寸 |
|---|---|
| 16<9>9> | 3840×2160 |
| 3<2>2> | 3840×2560 |
| 9<16>16> | 2160×3840 |
| 2<3>3> | 2560×3840 |
| 5<8>8> | 2400×3840(脚本注释给出的口径) |
- 不强行拉成 16<9>9>:3<2>2> 的图会被裁掉约 16% 画面(引自手册 §3.6)。
- 流程 =
4x-UltraSharp放大 4 倍 → Lanczos 降到目标;4x 中间图自动删除(实测output/里没留up4k_*)。 - 命名
原名_4K.png;同名已存在则跳过(除非--overwrite)。 target_size()会把结果对齐到偶数。- 本机脚本对
SaveImage前缀统一加了RUN = f"{int(time.time())}"(防 §6.3 缓存坑)。
cd /home/zero/ComfyUI/image_scripts/home/zero/ComfyUI/venv/bin/python upscale_4k_batch.py # 全部处理,保留原图/home/zero/ComfyUI/venv/bin/python upscale_4k_batch.py --delete-source # 成功后删原图/home/zero/ComfyUI/venv/bin/python upscale_4k_batch.py --only a.png b.png/home/zero/ComfyUI/venv/bin/python upscale_4k_batch.py --long 2160 --overwrite(另有 --srcdir / --outdir,默认 output/ → output/4K/)
6. 关键坑(每条都有实测)
6.1 HTTP 400 必须 e.read() 才看得到原因 ★★★
urllib 抛的 HTTPError 只给你一句 Bad Request;真正的原因在响应正文里,不 read() 就永远看不到。
实测(故意写 upscale_method: "bisect"):
[ComfyUI 400] 正文(必须 e.read() 才看得到): {"error": {"type": "prompt_outputs_failed_validation","message": "Prompt outputs failed validation", "details": "", "extra_info": {}}, "node_errors":{"7": {"errors": [{"type": "value_not_in_list", "message": "Value not in list", "details":"upscale_method: 'bisect' not in ['nearest-exact', 'bilinear', 'area', 'bicubic', 'bislerp']","extra_info": {"input_name": "upscale_method", "input_config": [["nearest-exact", "bilinear","area", "bicubic", "bislerp"], {}], "received_value": "bisect"}}], "dependent_outputs": ["9"],"class_type": "LatentUpscaleBy"}}}正文的三个金矿:node_errors.<节点id> 告诉你哪个节点、class_type 告诉哪个类、details 直接给出合法值列表。
标准写法:
try: return json.load(urllib.request.urlopen(req, timeout=t))except urllib.error.HTTPError as e: print(f"[ComfyUI {e.code}] {e.read().decode('utf-8', 'replace')[:1500]}") raise这条价值最高:本机所有踩坑里,卡最久的就是”只看到
Bad Request而不知道错在哪”。
6.2 LatentUpscaleBy.upscale_method 没有 bisect ★★
实测合法值只有 5 个:nearest-exact / bilinear / area / bicubic / bislerp。
(bislerp 有个 l,没有 bisect。写错 → §6.1 的 400。)
同类风险:IPAdapterAdvanced.weight_type 没有 style,要写全称 style transfer / style and composition / style transfer precise。CLI 传空格参数必须加引号,否则被拆成坏值(引自手册 §7.14)。
预防:动手前先 curl /object_info/<Node> 把枚举抄下来,别凭记忆写。
6.3 节点输出缓存:同图重跑”报成功但不写盘” ★★★(本次严格复现)
机制:提交完全相同的图(同节点 id、同 class_type、同参数、同 seed)时,ComfyUI 复用上次的节点输出 —— /history 里照样列出文件名、照样 status_str: success,但根本不写盘。
实测(严格复现:提交同一份 WF → 删产物 → 再提交同一份 WF):
起始状态: /home/zero/ComfyUI/output/ZZZ_cache_probe_00001_.png 存在? False
--- 第 1 次提交 (prompt_id=5f6cbc49-cddb-4347-be0e-2db4b65c88b4) --- status_str -> success execution_cached -> 被复用的节点: ['1', '4'] history 报的文件名 -> ['ZZZ_cache_probe_00001_.png'] ZZZ_cache_probe_00001_.png 存在=True 大小=354825B 耗时 1.0s
已手动删除产物 -> /home/zero/ComfyUI/output/ZZZ_cache_probe_00001_.png产物删除后,文件存在? False
--- 第 2 次提交 (prompt_id=69d033a6-68f5-40b4-82dd-96289f115ff7) --- status_str -> success execution_cached -> 被复用的节点: ['1', '2', '3', '4', '5', '6', '7'] history 报的文件名 -> ['ZZZ_cache_probe_00001_.png'] ZZZ_cache_probe_00001_.png 存在=False <-- 报成功但没写盘 耗时 1.0s判据:execution_cached.nodes 里包含 SaveImage 那个节点时,这次没有真的写文件。
修法(本机脚本已采用):给 SaveImage.filename_prefix 加时间戳,强制每次都是”新图”:
RUN = f"{int(time.time())}" # 模块级,每次进程启动取一次"filename_prefix": f"{prefix}_{RUN}"实测反例(也很有用):只要改动节点 id 或图结构(哪怕只把 SaveImage 从节点 "7" 挪到 "9"),缓存键就变了,即使参数/seed 完全相同也会真跑真写盘。所以”改了图却还是没写盘”才是缓存问题;“改了图就写盘了”不代表缓存不存在。
注意:这不是服务崩溃(手册 §7.9 那个是崩溃,表现是 connection refused / 文件缺失,需重启)。服务是好的,是缓存命中。
6.4 background_removal 目录的映射(勘误 + 现行正确做法) ★
- 实测事实:
/home/zero/ComfyUI/extra_model_paths.yaml的localdisk:段已经包含background_removal: background_removal;外置盘/media/zero/本地磁盘/Model/comfyui/background_removal/目录也存在,但是空的(只有占位文件put_background_removal_models_here)。 - 因此手册 §7.19 的表述已过期(它说”不在映射里、放外置盘不会被识别”)。
- 但结论一致:当前
LoadBackgroundRemovalModel的 options 实测只有["birefnet.safetensors"],这个文件在本地/home/zero/ComfyUI/models/background_removal/birefnet.safetensors(ls实测 444473596 字节 ≈ 424 MiB)。 - 现行正确做法:把抠像权重放
/home/zero/ComfyUI/models/background_removal/(已验证可用);要放外置盘就放<模型根>/background_removal/(映射已就位,⚠未验证到货后能否被识别)。 - 怎么确认权重被认到:
curl -s http://127.0.0.1:8188/object_info/LoadBackgroundRemovalModel,看options里有没有你的文件名。没出现 = 没被扫到。 - 权重真伪判据(引自手册 §7.18):
comfy/bg_removal_model.py靠 state dict 里是否含bb.layers.1.blocks.0.attn.relative_position_index判定为 birefnet;不含则load()返回None并报background model file is invalid。认准Comfy-Org/BiRefNet仓库。
6.5 HuggingFace 下载必须 curl -L ★
机制:HF 的 /resolve/main/ 会 302 跳到 cdn-lfs。不跟随跳转,curl 拿到的是一个几乎为空的响应体(表现为速度极慢)。
# ✅ 正确:-L 跟随跳转 + 走代理curl -x http://127.0.0.1:7897 -sSL -o "<目标路径>" \ "https://huggingface.co/<repo>/resolve/main/<file>"速度实测(引自手册 §6,本次未复测):
| 路径 | 速度 |
|---|---|
| HF 不跟随跳转 | 2.7 KB/s |
HF + -L + 代理 | 3.3 MB/s(BiRefNet 424MB 峰值 12.8MB/s,35 秒下完) |
| hf-mirror 直连 | 0.45 MB/s |
| hf-mirror 经代理 | 2.2 MB/s |
本次实测的相关项:代理 http://127.0.0.1:7897 可达 —— curl -s -x http://127.0.0.1:7897 -o /dev/null -w "%{http_code}" https://huggingface.co/api/models/Comfy-Org/BiRefNet → 200,0.315s。(下载速度本身本次未复测。)
其余下载要点(引自手册 §6):Civitai 下载要带
?token=或Authorization: Bearer,否则拿到 9.7KB 的 HTML 登录页(用file命令验证);列表 URL 用-x代理;curl -sL与-sSL区别只在是否静默。
6.6 RemoveBackground 的输入名是 bg_removal_model(手册与脚本都写错了)★
实测:curl -s http://127.0.0.1:8188/object_info/RemoveBackground →
{"RemoveBackground": {"input": {"required": { "bg_removal_model": ["BACKGROUND_REMOVAL", {"tooltip": "Background removal model used to generate the mask"}], "image": ["IMAGE", {"tooltip": "Input image to remove the background from"}]}}, "output": ["MASK"], "output_name": ["mask"], "python_module": "comfy_extras.nodes_bg_removal"}}用 background_removal_model 会 400(这是手册散文里的示例写法之误,不是脚本的问题):
[ComfyUI 400] {"error": {"type": "prompt_outputs_failed_validation", ...}, "node_errors":{"3": {"errors": [{"type": "required_input_missing", "message": "Required input is missing","details": "bg_removal_model", "extra_info": {"input_name": "bg_removal_model"}}],"dependent_outputs": ["5"], "class_type": "RemoveBackground"}}}改成 bg_removal_model 后立刻成功(status -> success 1.0s,输出 941×1672 / 218861 B)。
⚠ 更正(Lead 复核):本节初稿曾断言「
image_scripts/matte_birefnet.py第 33 行写的是background_removal_model,所以脚本跑不通」——这是错误的。 实际核查:grep -n "bg_removal_model\|background_removal_model" image_scripts/*.py→ 只有matte_birefnet.py:33的bg_removal_model(正确名);实跑python matte_birefnet.py→[stable] .../gemini_matte_birefnet.png 2.0s (213KB)成功。 结论:脚本无需修改,可直接用。需要改的只是绘画手册.md散文里那处示例键名。
6.7 其他必知(引自手册 §7,本次未复测)
| # | 坑 | 一句话 |
|---|---|---|
| 1 | Anima 2B LoRA + 2.9B 底模 | 画面崩坏,底模必须按 LoRA 说明配 |
| 2 | Krea-2 编码器 | 必须 qwen3vl_4b(CLIPLoader type=krea2),8B 报 got 4096 features |
| 3 | SDXL IPAdapter 的 CLIP-Vision | 必须 ViT-bigG(1280 维),ViT-H(1024 维)size mismatch |
| 4 | LoadImage 输出 | 0=IMAGE、1=MASK;做 inpaint mask 要 ImageToMask(channel=red) |
| 5 | 中文文件名 PNG 用 PIL 另存 | 会剥离 ComfyUI 内嵌 metadata,留证据请看 output/ 原始文件 |
| 6 | ast.parse 抓不到 global 位置错误 | 语法检查用 python -m py_compile |
| 7 | pkill -f 会匹配自身命令行 | 用 pgrep 拿 PID 再 kill |
| 8 | 本机无 ControlNet 权重 | controlnet/ 为空,要控结构得先下(约 2.5GB) |
7. image_scripts/ 八个脚本速查
全部不要修改(本次任务约束);路径自相对,整个文件夹可移动;跑之前
cd进去或用绝对路径都行。 调用解释器一律/home/zero/ComfyUI/venv/bin/python。
| 脚本 | 行数 | 干什么 | 关键参数 |
|---|---|---|---|
draw.py | 244 | 通用 SDXL+IPAdapter 出图(角色复刻”无骨架”版) | --list --scene --seeds --model --w --h --steps --cfg --sampler --hires --hires-steps --hires-cfg --denoise --ref --ipa-weight --ipa-type --ipa-end --no-ipa --prefix --extra --img2img --init-image --outdir --final |
redraw.py | 265 | §3.7 复刻管线(场景起稿 + 整体 img2img) | --scene --seeds --model --denoise(默认0.62) --char-h --ipa-weight(0.60) --w --h --outdir --reuse-bg --matte {smart,birefnet,floodfill} --nofinal |
matte_birefnet.py | 66 | BiRefNet 抠像 → 复制到 input/gemini_matte_birefnet.png | 无参(⚠ 当前 400,见 §6.6) |
upscale4k.py | 124 | 单张 → 4K(2160×3840),附纯 Lanczos 对照 | --src --outdir --name(默认”彩虹猫娘”) |
upscale_4k_batch.py | 150 | 批量 → output/4K/,保持比例长边 3840 | --srcdir --outdir --long --delete-source --only --overwrite |
gen.py | 143 | 两段式出图(首出 + 潜空间 hires) | --seed(必填) --w --h --steps --cfg --sampler --model --hires --hires-steps --hires-cfg --denoise --prefix --prompt --negative --outdir(必填) --tag |
scene.py | 276 | 官方角色抠像 + Krea-2 生成背景 + 合成 | --list --scene --bg-only --plate |
upscale.py | 61 | 用 4x-UltraSharp 出 4x 与 2x 无损 PNG | 无参 |
脚本共有的三条防坑设计(值得新脚本抄):
RUN = f"{int(time.time())}"注入filename_prefix→ 绕过 §6.3 缓存。post()里except HTTPError: print(e.read())→ 符合 §6.1。- 遍历
history["outputs"]时先os.path.exists()再处理,缺失就打[warn] 未落盘。
输出目录约定:默认写 /home/zero/ComfyUI/output;upscale4k.py 默认写 output/4K;output/ 会定期清理,需要长期留存的东西放 input/(手册 §3.8 的经验)。
8. 「从零复现」清单(可直接复制粘贴)
假设你在一台同样配置的新机器上(ComfyUI 源码在 /home/zero/ComfyUI,模型在外置盘)。每步都给了预期输出,对不上就停下来查。
Step 0 · 前置条件
| 要有 | 判据 |
|---|---|
| ComfyUI 源码 + venv | ls /home/zero/ComfyUI/venv/bin/python 存在 |
| venv 依赖 | venv/bin/python -c "import numpy,scipy,PIL" 无报错 |
| 模型 | 外置盘 <模型根> 有 checkpoints/ loras/ vae/ diffusion_models/ text_encoders/ |
extra_model_paths.yaml | 含 localdisk: base_path: <模型根> 与各子目录名 |
| 代理 | curl -x http://127.0.0.1:7897 -sI https://huggingface.co → 200 |
Step 1 · 拉起服务
cd /home/zero/ComfyUI && nohup ./venv/bin/python main.py --listen 127.0.0.1 --port 8188 \ > /tmp/comfy_restart.log 2>&1 &for i in $(seq 1 60); do sleep 3 curl -s -m 5 http://127.0.0.1:8188/system_stats >/dev/null 2>&1 && { echo "✓ 就绪 (${i}0s内)"; break; }done预期:✓ 就绪 (N0s内),N 通常 ≤ 4(本机当前实例已运行 6h29m)。
Step 2 · 自检
curl -s -m 5 http://127.0.0.1:8188/system_stats | head -c 200; echonvidia-smi --query-gpu=name,memory.total --format=csvcurl -s -m 5 http://127.0.0.1:8188/queue; echo预期:"comfyui_version": "0.40.0";NVIDIA GeForce RTX 4070 SUPER, 12282 MiB;{"queue_running": [], "queue_pending": []}。
Step 3 · 确认模型被认到
curl -s http://127.0.0.1:8188/object_info | /home/zero/ComfyUI/venv/bin/python -c "import json,sys; d=json.load(sys.stdin)def o(n,k): v=d[n]['input']['required'][k][0] return v if isinstance(v,list) else v.get('options',[])for n,k in [('CheckpointLoaderSimple','ckpt_name'),('UNETLoader','unet_name'), ('LoraLoader','lora_name'),('LoadBackgroundRemovalModel','bg_removal_name'), ('UpscaleModelLoader','model_name')]: print(n, o(n,k))"预期:checkpoint ≥ 3 个、unet 6 个、lora 6 个、抠像 ['birefnet.safetensors']、放大 ['4x-UltraSharp.pth'](与 §4.3 存档一致)。
Step 4 · 最小出图(这条是整个复现的”心跳”)
cd /home/zero/ComfyUI && ./venv/bin/python - <<'EOF'import json, os, time, urllib.request, uuidAPI="http://127.0.0.1:8188"; OUT="/home/zero/ComfyUI/output"; RUN=str(int(time.time()))wf={"1":{"class_type":"CheckpointLoaderSimple","inputs":{"ckpt_name":"animagine-xl-3.0.safetensors"}}, "2":{"class_type":"CLIPTextEncode","inputs":{"text":"1girl, blue hair, whale, ocean, masterpiece","clip":["1",1]}}, "3":{"class_type":"CLIPTextEncode","inputs":{"text":"lowres, bad anatomy, worst quality","clip":["1",1]}}, "4":{"class_type":"EmptyLatentImage","inputs":{"width":512,"height":512,"batch_size":1}}, "5":{"class_type":"KSampler","inputs":{"seed":20261017,"steps":8,"cfg":5.0,"sampler_name":"euler", "scheduler":"simple","denoise":1.0,"model":["1",0],"positive":["2",0],"negative":["3",0], "latent_image":["4",0]}}, "6":{"class_type":"VAEDecode","inputs":{"samples":["5",0],"vae":["1",2]}}, "7":{"class_type":"SaveImage","inputs":{"filename_prefix":f"smoke_{RUN}","images":["6",0]}}}pid=json.load(urllib.request.urlopen(urllib.request.Request(API+"/prompt", data=json.dumps({"prompt":wf,"client_id":str(uuid.uuid4())}).encode(), headers={"Content-Type":"application/json"}),timeout=120))["prompt_id"]print("prompt_id:",pid)while True: h=json.load(urllib.request.urlopen(f"{API}/history/{pid}",timeout=120)) if pid in h: break time.sleep(2)print("status:",h[pid]["status"]["status_str"])for n in h[pid]["outputs"].values(): for im in n.get("images",[]): p=os.path.join(OUT,im["filename"]) print("产物:",im["filename"],"存在" if os.path.exists(p) else "★缺失", os.path.getsize(p) if os.path.exists(p) else "")EOF预期(与本次 §5.1 同量级):
prompt_id: <uuid>status: success产物: smoke_<时间戳>_00001_.png 存在 448899左右B⏱ 首次约 10–20s(含加载 checkpoint),模型已缓存时约 4s。
Step 5 · 校验 + 清理
# 尺寸/内嵌工作流/home/zero/ComfyUI/venv/bin/python -c "from PIL import Image; import globp=sorted(glob.glob('/home/zero/ComfyUI/output/smoke_*.png'))[-1]im=Image.open(p); print(p, im.size, im.mode, '内嵌prompt:', 'prompt' in im.info)"# ⚠ 自己产生的临时图自己删掉rm -f /home/zero/ComfyUI/output/smoke_*.pngls -la /home/zero/ComfyUI/output/预期:output/ 根目录只剩 4K/、无法用/ 两个文件夹(外加 ComfyUI 自带的 0 字节占位文件 _output_images_will_be_put_here)。
Step 6 · 全套资产就位(可选,按需)
# 抠像权重(必须放本地!外置盘那份当前是空的)curl -x http://127.0.0.1:7897 -sSL -o /home/zero/ComfyUI/models/background_removal/birefnet.safetensors \ "https://huggingface.co/Comfy-Org/BiRefNet/resolve/main/background_removal/birefnet.safetensors"ls -la /home/zero/ComfyUI/models/background_removal/birefnet.safetensors # 预期 ≈ 444473596 Bcurl -s http://127.0.0.1:8188/object_info/LoadBackgroundRemovalModel # options 应含 birefnet.safetensors⚠ 该 URL 的确切路径未在本次验证(
⚠未验证);本机权重是现成的,不要重复下载。下载后无需重启 ComfyUI(手册 §6)。
9. 验收方法(怎么客观地说”成了”)
9.1 五层验收(从弱到强)
| 层 | 检查 | 命令 | 通过判据 |
|---|---|---|---|
| L1 存在 | 文件真的在盘上 | ls -la <path> | 存在且大小 > 0 |
| L2 尺寸/模式 | 像素尺寸对 | PIL: Image.open(p).size | 等于目标(如 (512,512)、(3840,2880)) |
| L3 指纹 | 没被截断/换文件 | md5sum <path> | 记录在案,多次跑可比对 |
| L4 来源 | 这张图是哪个工作流生成的 | Image.open(p).info["prompt"] | 内嵌 JSON 里的 ckpt_name/seed/steps 与预期一致 |
| L5 语义 | 内容对不对 | 像素比对 / 覆盖率统计(下) | 见 9.2–9.4 |
9.2 “服务说成功但没落盘”的判定(必查)
# 1) 从 /history 拿文件名curl -s http://127.0.0.1:8188/history/<prompt_id> | \ /home/zero/ComfyUI/venv/bin/python -c "import json,sys; d=json.load(sys.stdin)for k,rec in d.items(): print('status:', rec['status']['status_str']) for n in rec['outputs'].values(): for im in n.get('images',[]): print('history 报的产物:', im['filename'])"# 2) 逐个人工确认存在ls -la /home/zero/ComfyUI/output/<filename>判据:/history 里有名字 且 ls 能看到 —— 两者缺一即失败。
若 history 有、文件无:命中 §6.3 缓存 → 改 filename_prefix 加时间戳重跑。
9.3 抠像质量验收(可量化,照抄手册 §3.8 的指标)
抠出来的蒙版要看**“内部白块有没有被误判为前景”**,三个客观指标:
| 指标 | 裸 flood-fill | BiRefNet + 逐块判据 | 怎么算 |
|---|---|---|---|
| 头发区纯白占比 | 3.94% | 2.06% | 指定 bbox 内 min(RGB)>=249 且 max-min<=8 的像素比例 |
| 腿间区纯白占比 | 0.23% | 0.05% | 同上,bbox (252,924)-(511,1191)(941×1672 坐标) |
| 全图纯白占比 | 1.169% | 0.554% | 全图口径 |
| 内部近白被误留为前景 | 68.9% | 43.8% | 内部近白连通块中被判为前景的比例 |
本次实测的可用快速指标(§5.4):蒙版 前景(>128) 占比 46.91%、均值 119.1、唯一值 256。前景占比突然从 47% 掉到 20% 或涨到 70% = 抠像出问题了。
/home/zero/ComfyUI/venv/bin/python -c "from PIL import Image; import numpy as npa=np.asarray(Image.open('<蒙版.png>').convert('L'))print('前景(>128)占比 %.2f%% 均值 %.1f 唯一灰阶 %d' % ((a>128).mean()*100, a.mean(), len(np.unique(a))))"9.4 像素比对思路(判断”是重画还是粘贴”)
同一尺寸的两张图转 RGB → numpy 求差:
from PIL import Imageimport numpy as npa = np.asarray(Image.open("成品.png").convert("RGB")).astype(int)b = np.asarray(Image.open("骨架.png").convert("RGB")).astype(int)d = np.abs(a - b).max(axis=2) # 或 .mean(axis=2)print("MAE : %.2f / 255" % np.abs(a - b).mean())print("误差>24 占比: %.1f%%" % ((d > 24).mean() * 100))判据:
- MAE ≈ 0 → 直接粘贴(没重画)。
- MAE 十几个数量级 + 误差>24 占三四成 → 模型真的重画了。
- 参照(引自手册 §3.7):成品 vs 骨架
MAE 18.58/255、误差 >24 占38.9%;网上流传的 webp 与本地原图比对MAE 2.34/255、误差 >64 占0.008%(纯有损压缩噪声,判定”同一张画”)。
9.5 4K 产物的验收
ls /home/zero/ComfyUI/output/4K/*.png | wc -l # 预期 11ls /home/zero/ComfyUI/output/4K/*.txt | wc -l # 预期 1(说明.txt)/home/zero/ComfyUI/venv/bin/python -c "from PIL import Image; import globfor p in sorted(glob.glob('/home/zero/ComfyUI/output/4K/*.png')): w,h = Image.open(p).size print('%-46s %dx%d 长边=%d %s' % (p.split('/')[-1], w, h, max(w,h), 'OK' if max(w,h)==3840 else '★异常'))"判据:每个文件长边 = 3840(彩虹猫娘_4K_2160x3840.png 与 对照_纯Lanczos2x_2160x3840.png 是 2160×3840,短边=2160 长边=3840,也符合)。
9.6 收工前自检(别把临时产物留给下一个人)
find /home/zero/ComfyUI/output -maxdepth 1 -type f # 应无自己产生的图ls /home/zero/ComfyUI/input | grep -E '_tmp_|^smoke_' # 应无临时输入curl -s http://127.0.0.1:8188/queue # queue_pending 应为空10. 本次验证的原始记录与清理
10.1 我做过的验证(全部在本机真跑)
| # | 验证项 | 命令 | 结果 |
|---|---|---|---|
| 1 | 服务/版本/GPU | curl /system_stats、nvidia-smi | ✅ 0.40.0 / RTX 4070 SUPER 12282MiB |
| 2 | 节点与模型清单 | curl /object_info、/object_info/<Node> | ✅ 1022 节点;各 loader options 已存档(§3.1/§4.3) |
| 3 | 最小 txt2img | /tmp/probe1_min.py(checkpoint 512²×8步) | ✅ success,4.0s,448899 B,512×512,内嵌 prompt |
| 4 | 缓存坑复现 | /tmp/probe3_cache.py(同一份图提交两次,中间删产物) | ✅ 第 2 次 execution_cached=[1..7]、history 报名字但文件不存在 |
| 5 | HTTP 400 正文 | /tmp/probe2_pit.py(故意写 bisect) | ✅ 拿到 value_not_in_list + 合法值列表 |
| 6 | 两段式 hires | /tmp/probe4_pipes.py | ✅ success 3.0s,512→768×768(×1.5 吻合) |
| 7 | 4x-UltraSharp | 同上 | ✅ success 11.0s,941×1672 → 3764×6688,24MB |
| 8 | BiRefNet 抠像 | 先踩 400(输入名错),改正后重跑 | ✅ success 1.0s,941×1672,218861 B,前景 46.91% |
| 9 | 批量 4K 端到端 | upscale_4k_batch.py --only ZZZ_batch_probe.png | ✅ 320×240 → 3840×2880,4x 步 2s |
| 10 | MCP 出图 | generate_image(animagine-xl-3.0, 512², 8步) | ✅ 返回 asset_id/prompt_id,落盘 ComfyUI_00001_.png 238711 B |
| 11 | /view 取图 | curl -o /tmp/view_test.png ".../view?filename=..." | ✅ HTTP 200 image/png 238711 B,内嵌 prompt 为 True |
| 12 | MCP 能力边界 | list_checkpoint_models、list_unet_models、list_workflows | ✅ checkpoint 仅 3 个;MCP 工作流仅 2 个;无 UNET 入口 |
10.2 清理(已完成)
产生的临时文件(全部已删):
output/ComfyUI_00001_.png 238711 B (MCP 产出)output/ZZZ_agent_probe_00001_.png 444364 Boutput/ZZZ_agent_probe_ts1792178320_00001_.png 444377 Boutput/ZZZ_batch_probe.png 781 Boutput/ZZZ_hires_1792178358_00001_.png 799998 Boutput/ZZZ_matte_1792178385_00001_.png 218861 Boutput/ZZZ_ups4x_1792178358_00001_.png 24199034 Boutput/ZZZ_cache_probe_00001_.png 354825 B (复现缓存坑时已删)output/4K/ZZZ_batch_probe_4K.png 68814 B/tmp/view_test.png清理结果核对:
$ find /home/zero/ComfyUI/output -type f | sort | diff - /tmp/out_before.txt # 与开工前快照比对(无实质差异;仅路径前缀差异)
$ ls /home/zero/ComfyUI/output/4K/ 无法用/ _output_images_will_be_put_here
$ ls output/4K/*.png | wc -l → 11$ ls output/4K/*.txt | wc -l → 1$ ls output/无法用/ | wc -l → 0$ find output input -name 'ZZZ*' -o -name '_tmp_4k_*' → 无结果唯一保留的非我产物:
output/_output_images_will_be_put_here(0 字节,ComfyUI 自带的占位文件,10月15日就在,属于”原状”的一部分,故保留)。
10.3 本文件中的 ⚠未验证 清单(用之前请自己确认)
| 内容 | 位置 | 原因 |
|---|---|---|
| HF 下载速度 4 档数值(2.7KB/s / 3.3MB/s / 0.45MB/s / 2.2MB/s) | §6.5 | 引自手册 §6,本次只验证了”代理可达 200” |
| §3.7 角色复刻管线的 denoise 表、MAE 18.58、38.9%、骨架参数 1640px | §5.3 | 引自手册 §3.7,本次未重跑该管线 |
| §3.8 抠像四个量化指标(3.94%→2.06% 等) | §9.3 | 引自手册 §3.8 |
| 5<8>8> 比例 → 2400×3840 | §5.5 | 脚本注释口径;手册 §3.6 写 2388×3840,两处不一致,本身未实测该比例 |
GET /history(全量)、POST /interrupt | §2.2 | 未调用 |
外置盘 background_removal/ 放权重能否被识别 | §6.4 | 目录为空,无法测 |
| BiRefNet HF 下载 URL 的确切路径 | Step 6 | 权重已在本机,未重新下载 |
scene.py / upscale.py / gen.py / draw.py 的端到端运行 | §7 | 只读了代码与参数表,未逐个跑(redraw.py/upscale_4k_batch.py 的参数表来自 argparse 定义) |
| ControlNet 相关一切 | §6.7 | 本机无权重 |
10.4 给下一个 agent 的三句话
- 先
curl /system_stats,再用/home/zero/ComfyUI/venv/bin/python,这两步能排掉 90% 的”环境类”问题。 - 拼图先查
/object_info/<Node>,提交后必读 400 正文、必os.path.exists()校验、前缀必带时间戳。 - 改完东西自己擦干净:临时图删掉、
input/别留_tmp_*、output/根目录只该有4K/和无法用/。
11. 模型下载清单(权威源 + 实测可达性)
本机 26 个模型文件 = 87.30 GiB,全部找到公开来源,没有一个是私有的。 访问国际站点必须走代理
-x http://127.0.0.1:7897,并且必须-L跟随 302 到 cdn-lfs(不跟随只有 ~2.7 KB/s)。 实测方法:curl -x http://127.0.0.1:7897 -sSL -o /dev/null -w "%{http_code} %{size_download}" -r 0-2000 "<url>"—— 只取前 2 KB,不真下载;「字节精确」= HF/Civitai API 报的文件字节数 与本机stat完全相等。 Lead 抽验:8 条 HF 链接 + 2 条 Civitai 链接、外加 8 个文件的字节比对,全部与下表一致(krea2_raw_fp8_scaled首次探测遇到一次瞬时 000,重测 206)。
11.1 总览
| 分组 | 文件数 | 大小 | 凭据 |
|---|---|---|---|
| HuggingFace 公开仓库 | 18 | 72.29 GiB | 免登录 |
| Civitai | 8 | 15.01 GiB | 需 API token(?token=<KEY>) |
11.2 逐文件表(URL 均为实测)
| 文件 | 字节 / GiB | 子目录 | 来源 | URL | 实测 |
|---|---|---|---|---|---|
| animagine-xl-3.0.safetensors | 6938218610 / 6.46 | checkpoints | HF cagliostrolab/animagine-xl-3.0 | https://huggingface.co/cagliostrolab/animagine-xl-3.0/resolve/main/animagine-xl-3.0.safetensors | 206 ✅ |
| RealVisXL_V5.0_fp16.safetensors | 6938065488 / 6.46 | checkpoints | HF SG161222/RealVisXL_V5.0 | https://huggingface.co/SG161222/RealVisXL_V5.0/resolve/main/RealVisXL_V5.0_fp16.safetensors | 206 ✅ |
| chenkinNoobXLCKXL_v02.safetensors | 7105349958 / 6.62 | checkpoints | Civitai model 2167995 “Chenkin Noob XL (CKXL)” v0.2 = ver 2532077 | https://civitai.com/api/download/models/2532077?fileId=2419852 | 401 需 token ⚠ |
| anima_baseV10.safetensors | 4182218328 / 3.89 | diffusion_models | HF circlestone-labs/Anima(源名 anima-base-v1.0.safetensors) | https://huggingface.co/circlestone-labs/Anima/resolve/main/split_files/diffusion_models/anima-base-v1.0.safetensors | 206 ✅ |
| krea2_raw_fp8_scaled.safetensors | 13141730784 / 12.24 | diffusion_models | HF Comfy-Org/Krea-2 | https://huggingface.co/Comfy-Org/Krea-2/resolve/main/diffusion_models/krea2_raw_fp8_scaled.safetensors | 206 ✅ |
| Anima-2.9B-preview-v1_int8_convrot.safetensors | 3082486758 / 2.87 | diffusion_models | HF Gazingstars123/Anima-2.9B | https://huggingface.co/Gazingstars123/Anima-2.9B/resolve/main/Anima-2.9B-preview-v1_int8_convrot.safetensors | 206 ✅ |
| qwen_image_2.1_int8_convrot.safetensors | 7256783064 / 6.76 | diffusion_models | HF Comfy-Org/Qwen-Image-2.1 | https://huggingface.co/Comfy-Org/Qwen-Image-2.1/resolve/main/diffusion_models/qwen_image_2.1_int8_convrot.safetensors | 206 ✅ |
| wan2.1_t2v_1.3B_fp16.safetensors | 2838303560 / 2.64 | diffusion_models | HF Comfy-Org/Wan_2.1_ComfyUI_repackaged | https://huggingface.co/Comfy-Org/Wan_2.1_ComfyUI_repackaged/resolve/main/split_files/diffusion_models/wan2.1_t2v_1.3B_fp16.safetensors | 206 ✅ |
| krea2Anime_v14_int4.safetensors | 8057522903 / 7.50 | diffusion_models | Civitai model 2910309 “Krea 2 Anime” v1.4 = ver 3307085, fileId 3192632 (int4) | https://civitai.com/api/download/models/3307085?fileId=3192632 | 401 需 token ⚠ |
| qwen3vl_4b_fp8_scaled.safetensors | 5242467968 / 4.88 | text_encoders | HF Comfy-Org/Krea-2(Krea-2 的文本编码器就是 Qwen3-VL-4B) | https://huggingface.co/Comfy-Org/Krea-2/resolve/main/text_encoders/qwen3vl_4b_fp8_scaled.safetensors | 206 ✅ |
| qwen3vl_8b_int8_convrot.safetensors | 9350798360 / 8.71 | text_encoders | HF Comfy-Org/Qwen-Image-2.1 | https://huggingface.co/Comfy-Org/Qwen-Image-2.1/resolve/main/text_encoders/qwen3vl_8b_int8_convrot.safetensors | 206 ✅ |
| qwen_3_06b_base.safetensors | 1192135096 / 1.11 | text_encoders | HF circlestone-labs/Anima | https://huggingface.co/circlestone-labs/Anima/resolve/main/split_files/text_encoders/qwen_3_06b_base.safetensors | 206 ✅ |
| umt5_xxl_fp16.safetensors | 11366399385 / 10.59 | text_encoders | HF Comfy-Org/Wan_2.1_ComfyUI_repackaged | https://huggingface.co/Comfy-Org/Wan_2.1_ComfyUI_repackaged/resolve/main/split_files/text_encoders/umt5_xxl_fp16.safetensors | 206 ✅ |
| qwen_image_vae.safetensors | 253806246 / 0.24 | vae | HF Comfy-Org/Qwen-Image_ComfyUI | https://huggingface.co/Comfy-Org/Qwen-Image_ComfyUI/resolve/main/split_files/vae/qwen_image_vae.safetensors | 206 ✅ |
| qwen_image_2.1_vae_bf16.safetensors | 675509688 / 0.63 | vae | HF Comfy-Org/Qwen-Image-2.1 | https://huggingface.co/Comfy-Org/Qwen-Image-2.1/resolve/main/vae/qwen_image_2.1_vae_bf16.safetensors | 206 ✅ |
| wan_2.1_vae.safetensors | 253815318 / 0.24 | vae | HF Comfy-Org/Wan_2.1_ComfyUI_repackaged | https://huggingface.co/Comfy-Org/Wan_2.1_ComfyUI_repackaged/resolve/main/split_files/vae/wan_2.1_vae.safetensors | 206 ✅ |
| 4x-UltraSharp.pth | 66961958 / 0.06 | upscale_models | HF Kim2091/UltraSharp(原作者官方仓库,非镜像) | https://huggingface.co/Kim2091/UltraSharp/resolve/main/4x-UltraSharp.pth | 206 ✅ |
| ip-adapter_sdxl.safetensors | 702585376 / 0.65 | ipadapter | HF h94/IP-Adapter(作者官方) | https://huggingface.co/h94/IP-Adapter/resolve/main/sdxl_models/ip-adapter_sdxl.safetensors | 206 ✅ |
| CLIP-ViT-bigG-14-laion2B-39B-b160k.safetensors | 3689912664 / 3.44 | clip_vision | HF h94/IP-Adapter(源名 model.safetensors,需重命名);或 HF pseudotools/…(同名单文件) | ① https://huggingface.co/h94/IP-Adapter/resolve/main/sdxl_models/image_encoder/model.safetensors ② https://huggingface.co/pseudotools/clip-vision-clip-vit-bigg-14-laion2b-39b-b160k/resolve/main/CLIP-ViT-bigG-14-laion2B-39B-b160k.safetensors | 206 / 206 ✅ |
| birefnet.safetensors | 444473596 / 0.41 | background_removal(本地) | HF Comfy-Org/BiRefNet | https://huggingface.co/Comfy-Org/BiRefNet/resolve/main/background_removal/birefnet.safetensors | 206 ✅ |
| DeepSeek_ZipZipPipe_style_anima2b.safetensors | 183628056 / 0.17 | loras | Civitai model 2919135 v1.0 = ver 3302634 | https://civitai.com/api/download/models/3302634?fileId=3187626 | 401 需 token ⚠ |
| deepseek_maid_outfit_illustrious_v10.safetensors | 85441012 / 0.08 | loras | Civitai model 2697171 “DeepSeek Whale Girl” ver 3218534 | https://civitai.com/api/download/models/3218534?fileId=3100362 | 401 需 token ⚠ |
| deepseek_whale_girl_anima_lora_clean.safetensors | 45975456 / 0.04 | loras | Civitai model 2697171 ver 3028705 | https://civitai.com/api/download/models/3028705?fileId=2907525 | 401 需 token ⚠ |
| deepseek_whale_girl_krea2.safetensors | 228587792 / 0.21 | loras | Civitai model 2697171 ver 3370723(源名 …outfits_krea2_character_r32_clean.safetensors) | https://civitai.com/api/download/models/3370723?fileId=3258833 | 401 需 token ⚠ |
| deepseek_whalegirl_noobai.safetensors | 228452020 / 0.21 | loras | Civitai model 2595806 “Deepseek whalegirl” v1.0 = ver 2915962(baseModel=NoobAI) | https://civitai.com/api/download/models/2915962?fileId=2794189 | 401 需 token ⚠ |
| ds_whalemaid_anima.safetensors | 183613496 / 0.17 | loras | Civitai model 2845839 “…whalemaid Chibi anima” v1.0 = ver 3213109 | https://civitai.com/api/download/models/3213109?fileId=3094880 | 401 需 token ⚠ |
结论性纠正:这 6 个
deepseek_*/ds_*LoRA 不是私有模型,全部是 Civitai 公开模型(分属 5 个模型页);只是 Civitai 的下载端点要 API token 鉴权。上表「401」是实测码(无 token 时),不是链接写错——来源正确性用 Civitai API 报的字节数与本地stat逐字节相等确认(8/8 全中)。
11.3 可直接复制的下载命令
PROXY="-x http://127.0.0.1:7897"ROOT="/media/zero/本地磁盘/Model/comfyui"checkpoints/(前两条免 token)
curl $PROXY -sSL -o "$ROOT/checkpoints/animagine-xl-3.0.safetensors" \ "https://huggingface.co/cagliostrolab/animagine-xl-3.0/resolve/main/animagine-xl-3.0.safetensors"curl $PROXY -sSL -o "$ROOT/checkpoints/RealVisXL_V5.0_fp16.safetensors" \ "https://huggingface.co/SG161222/RealVisXL_V5.0/resolve/main/RealVisXL_V5.0_fp16.safetensors"# 需 Civitai tokencurl $PROXY -sSL -o "$ROOT/checkpoints/chenkinNoobXLCKXL_v02.safetensors" \ "https://civitai.com/api/download/models/2532077?fileId=2419852&token=<KEY>"diffusion_models/
curl $PROXY -sSL -o "$ROOT/diffusion_models/anima_baseV10.safetensors" \ "https://huggingface.co/circlestone-labs/Anima/resolve/main/split_files/diffusion_models/anima-base-v1.0.safetensors"curl $PROXY -sSL -o "$ROOT/diffusion_models/krea2_raw_fp8_scaled.safetensors" \ "https://huggingface.co/Comfy-Org/Krea-2/resolve/main/diffusion_models/krea2_raw_fp8_scaled.safetensors"curl $PROXY -sSL -o "$ROOT/diffusion_models/Anima-2.9B-preview-v1_int8_convrot.safetensors" \ "https://huggingface.co/Gazingstars123/Anima-2.9B/resolve/main/Anima-2.9B-preview-v1_int8_convrot.safetensors"curl $PROXY -sSL -o "$ROOT/diffusion_models/qwen_image_2.1_int8_convrot.safetensors" \ "https://huggingface.co/Comfy-Org/Qwen-Image-2.1/resolve/main/diffusion_models/qwen_image_2.1_int8_convrot.safetensors"curl $PROXY -sSL -o "$ROOT/diffusion_models/wan2.1_t2v_1.3B_fp16.safetensors" \ "https://huggingface.co/Comfy-Org/Wan_2.1_ComfyUI_repackaged/resolve/main/split_files/diffusion_models/wan2.1_t2v_1.3B_fp16.safetensors"# ⚠ 必须带 fileId,否则会拿到 bf16/int8 档(该版本有 3 个文件)curl $PROXY -sSL -o "$ROOT/diffusion_models/krea2Anime_v14_int4.safetensors" \ "https://civitai.com/api/download/models/3307085?fileId=3192632&token=<KEY>"text_encoders/ · vae/
curl $PROXY -sSL -o "$ROOT/text_encoders/qwen3vl_4b_fp8_scaled.safetensors" \ "https://huggingface.co/Comfy-Org/Krea-2/resolve/main/text_encoders/qwen3vl_4b_fp8_scaled.safetensors"curl $PROXY -sSL -o "$ROOT/text_encoders/qwen3vl_8b_int8_convrot.safetensors" \ "https://huggingface.co/Comfy-Org/Qwen-Image-2.1/resolve/main/text_encoders/qwen3vl_8b_int8_convrot.safetensors"curl $PROXY -sSL -o "$ROOT/text_encoders/qwen_3_06b_base.safetensors" \ "https://huggingface.co/circlestone-labs/Anima/resolve/main/split_files/text_encoders/qwen_3_06b_base.safetensors"curl $PROXY -sSL -o "$ROOT/text_encoders/umt5_xxl_fp16.safetensors" \ "https://huggingface.co/Comfy-Org/Wan_2.1_ComfyUI_repackaged/resolve/main/split_files/text_encoders/umt5_xxl_fp16.safetensors"curl $PROXY -sSL -o "$ROOT/vae/qwen_image_vae.safetensors" \ "https://huggingface.co/Comfy-Org/Qwen-Image_ComfyUI/resolve/main/split_files/vae/qwen_image_vae.safetensors"curl $PROXY -sSL -o "$ROOT/vae/qwen_image_2.1_vae_bf16.safetensors" \ "https://huggingface.co/Comfy-Org/Qwen-Image-2.1/resolve/main/vae/qwen_image_2.1_vae_bf16.safetensors"curl $PROXY -sSL -o "$ROOT/vae/wan_2.1_vae.safetensors" \ "https://huggingface.co/Comfy-Org/Wan_2.1_ComfyUI_repackaged/resolve/main/split_files/vae/wan_2.1_vae.safetensors"loras/(6 个全部需要 Civitai token)
curl $PROXY -sSL -o "$ROOT/loras/DeepSeek_ZipZipPipe_style_anima2b.safetensors" \ "https://civitai.com/api/download/models/3302634?fileId=3187626&token=<KEY>"curl $PROXY -sSL -o "$ROOT/loras/deepseek_maid_outfit_illustrious_v10.safetensors" \ "https://civitai.com/api/download/models/3218534?fileId=3100362&token=<KEY>"curl $PROXY -sSL -o "$ROOT/loras/deepseek_whale_girl_anima_lora_clean.safetensors" \ "https://civitai.com/api/download/models/3028705?fileId=2907525&token=<KEY>"curl $PROXY -sSL -o "$ROOT/loras/deepseek_whale_girl_krea2.safetensors" \ "https://civitai.com/api/download/models/3370723?fileId=3258833&token=<KEY>"curl $PROXY -sSL -o "$ROOT/loras/deepseek_whalegirl_noobai.safetensors" \ "https://civitai.com/api/download/models/2915962?fileId=2794189&token=<KEY>"curl $PROXY -sSL -o "$ROOT/loras/ds_whalemaid_anima.safetensors" \ "https://civitai.com/api/download/models/3213109?fileId=3094880&token=<KEY>"upscale_models/ · ipadapter/ · clip_vision/
curl $PROXY -sSL -o "$ROOT/upscale_models/4x-UltraSharp.pth" \ "https://huggingface.co/Kim2091/UltraSharp/resolve/main/4x-UltraSharp.pth"curl $PROXY -sSL -o "$ROOT/ipadapter/ip-adapter_sdxl.safetensors" \ "https://huggingface.co/h94/IP-Adapter/resolve/main/sdxl_models/ip-adapter_sdxl.safetensors"# clip_vision 二选一(两文件字节完全相同 = 3689912664)curl $PROXY -sSL -o "$ROOT/clip_vision/CLIP-ViT-bigG-14-laion2B-39B-b160k.safetensors" \ "https://huggingface.co/h94/IP-Adapter/resolve/main/sdxl_models/image_encoder/model.safetensors" # 权威源,需重命名# 或(同名单文件,免重命名)curl $PROXY -sSL -o "$ROOT/clip_vision/CLIP-ViT-bigG-14-laion2B-39B-b160k.safetensors" \ "https://huggingface.co/pseudotools/clip-vision-clip-vit-bigg-14-laion2b-39b-b160k/resolve/main/CLIP-ViT-bigG-14-laion2B-39B-b160k.safetensors"background_removal/ ⚠ 例外:放本地,不放外置盘
curl $PROXY -sSL -o "/home/zero/ComfyUI/models/background_removal/birefnet.safetensors" \ "https://huggingface.co/Comfy-Org/BiRefNet/resolve/main/background_removal/birefnet.safetensors"11.4 下载后的验收
# ① 文件不是 HTML 登录页(Civitai 缺 token 会下到 9.7KB 的 HTML 假文件)file "/media/zero/本地磁盘/Model/comfyui/loras/deepseek_whale_girl_krea2.safetensors" # 期望 data
# ② ComfyUI 真的看得见(唯一权威来源)curl -s http://127.0.0.1:8188/object_info/CheckpointLoaderSimple \ | python3 -c "import json,sys; print(json.load(sys.stdin)['CheckpointLoaderSimple']['input']['required']['ckpt_name'][0])"curl -s http://127.0.0.1:8188/object_info/LoadBackgroundRemovalModel \ | python3 -c "import json,sys; print(json.load(sys.stdin)['LoadBackgroundRemovalModel']['input']['required']['bg_removal_name'][0]['options'])"不需要重启 ComfyUI:新增模型后
/object_info会自动刷新(实测:放入birefnet.safetensors后立刻出现在options里)。
11.5 三条容易踩的纠正
qwen_3_06b_base.safetensors不在 Qwen 系仓库,而在circlestone-labs/Anima(Comfy-Org/Qwen-Image_ComfyUI里只有qwen_2.5_vl_7b*)。qwen3vl_4b_fp8_scaled.safetensors在Comfy-Org/Krea-2/text_encoders/—— 因为 Krea-2 的文本编码器就是 Qwen3-VL-4B;不在 Qwen 仓库。CLIP-ViT-bigG-14不能用laion/CLIP-ViT-bigG-14-laion2B-39B-b160k:那个仓库只有 10.16 GB 的open_clip_model.safetensors和分片版,没有 ComfyUI 可用的 3.69 GB 单文件。可用的是h94/IP-Adapter的sdxl_models/image_encoder/model.safetensors(字节精确 3689912664,需重命名)。
12. ComfyUI 本体与 MCP 的获取、安装、注册
§11 只讲了模型。本节补 ComfyUI 本体(§12.1)和 MCP 桥接(§12.2)——没有这两样,前面所有内容都跑不起来。 全部基于 2026-10-17 本机实测(链接可达性、进程归属、systemd 状态、补丁是否生效均为真跑)。
12.1 ComfyUI 本体
本机实况
| 项 | 实测值 |
|---|---|
| 安装位置 | /home/zero/ComfyUI/ |
| 上游仓库 | https://github.com/comfyanonymous/ComfyUI —— 实测 200 |
| 本机 git remote | https://ghfast.top/https://github.com/comfyanonymous/ComfyUI.git(套了国内加速前缀) |
| commit / 版本 | ba99487 · 0.40.0(comfyui_version.py) |
| Python | venv 3.12.3(/home/zero/ComfyUI/venv/,8.4 GB) |
| PyTorch | 2.11.0+cu130(CUDA 编译版 13.0,cuDNN 91900) |
| GPU | RTX 4070 SUPER,torch.cuda.is_available() = True |
| 整个目录 | 9.1 GB(venv 8.4G + models 425M + custom_nodes 1.5M) |
| 自定义节点 | 仅 ComfyUI_IPAdapter_plus(ComfyUI-Manager 未装) |
| 监听 | 127.0.0.1:8188(默认就是本机,未对外) |
从零安装(对齐本机版本的完整步骤)
# ① 依赖:Python 3.12 + venv + gitsudo apt install -y python3.12 python3.12-venv git
# ② 克隆本体(国内建议加 ghfast.top 前缀;实测 git ls-remote 可用)cd /home/zerogit clone https://ghfast.top/https://github.com/comfyanonymous/ComfyUI.git# 官方地址(代理可用时):git clone https://github.com/comfyanonymous/ComfyUI.git
# ③ 建 venv 并装依赖cd /home/zero/ComfyUIpython3 -m venv venv./venv/bin/pip install --upgrade pip./venv/bin/pip install -r requirements.txt
# ④ 装 PyTorch(CUDA 13.0 版,对齐本机的 2.11.0+cu130)./venv/bin/pip install torch torchvision torchaudio \ --index-url https://download.pytorch.org/whl/cu130# ⚠ 若换 index-url 建议走代理:-x http://127.0.0.1:7897# ⚠ 12 GB 显存以下建议先跑 --lowvram 验证
# ⑤ 验收:三个必须全过./venv/bin/python -c "import torch; print(torch.__version__, torch.cuda.is_available())"# 期望:2.11.0+cu130 True放模型:新建 /home/zero/ComfyUI/extra_model_paths.yaml 指向外置盘(本机映射了 localdisk: → /media/zero/本地磁盘/Model/comfyui),这样模型不必塞进系统盘。映射生效后 output/、input/ 仍在本地。
⚠ 启动方式有两个脚本 + 一个真实的端口冲突陷阱
本机 /home/zero/ComfyUI/ 下有两个启动脚本(实测都可执行):
| 脚本 | 机制 | 适用 |
|---|---|---|
/home/zero/ComfyUI/start.sh | 直接 exec ./venv/bin/python main.py --listen 127.0.0.1 --port 8188,并设 HF_ENDPOINT=https://hf-mirror.com | 手动前台跑、调试、加 --lowvram |
/home/zero/ComfyUI/start-comfyui.sh | 走 systemctl --user start comfyui,轮询等到 200 才返回;--dsh 还能顺带拉起 DSH Web UI | 日常启动(systemd 托管) |
对应的 systemd unit 在 /home/zero/.config/systemd/user/comfyui.service(Restart=on-failure、WantedBy=default.target;实测 is-enabled = disabled,即未设开机自启)。
🔴 陷阱(本机当前就处于这个状态) systemd 服务是
inactive的同时,ComfyUI 却正在跑——它的 cgroup 是user@1000.service/app.slice/dsh-subprocess-230663-….scope,即由 DSH 用 nohup 拉起的。 此时若直接执行start-comfyui.sh:脚本看到systemctl --user is-active不是 active → 执行systemctl start comfyui→ 再起一个实例去抢 8188 → 端口冲突/启动失败。先判端口再决定用哪个脚本:
Terminal window ss -tlnp | grep 8188 # 有人听 = 已经在跑,别再启动systemctl --user is-active comfyui # inactive 不代表没在跑!想切成 systemd 托管:先停掉 nohup 那个进程,再
systemctl --user start comfyui。
日常命令:
systemctl --user status comfyui # 状态systemctl --user restart comfyui # 重启systemctl --user stop comfyui # 停止journalctl --user -u comfyui -f # 实时日志不改 systemd、临时前台跑(等价于本机当前 nohup 那种方式):
cd /home/zero/ComfyUInohup ./venv/bin/python main.py --listen 127.0.0.1 --port 8188 > /tmp/comfy.log 2>&1 &# 就绪判据(本机实测有效):轮询到 /system_stats 返回 200for i in $(seq 1 60); do sleep 3; curl -s -m 5 http://127.0.0.1:8188/system_stats >/dev/null && { echo "就绪"; break; }; done官方文档与生态
| 项 | 链接 | 实测 |
|---|---|---|
| 官方文档首页 | https://docs.comfy.org/ | 200 |
| 手动安装文档 | https://docs.comfy.org/get_started/manual_install | 200(注意:…/installation/manual_install 也是 200;我之前猜的 /zh-CN/get_started/manual_install 404) |
| 中文文档 | https://docs.comfy.org/zh-CN | 200 |
| ComfyUI-Manager(本机未装) | https://github.com/Comfy-Org/ComfyUI-Manager | 200 |
| 本机已装的节点 | ComfyUI_IPAdapter_plus | — |
12.2 MCP 桥接(让 agent 用 mcp__comfyui__* 工具)
它是什么
本机装的是 npm 包 comfyui-mcp-server-node@2.1.1:
| 项 | 值 |
|---|---|
| 包名 / 版本 | comfyui-mcp-server-node 2.1.1(npm 上 latest 也是 2.1.1,共 13 个版本) |
| 上游仓库 | https://github.com/yar3333/comfyui-mcp-server-node —— 实测 200 |
| 作者 / 许可 | yar3333 / MIT |
| 安装位置 | /home/zero/.local/share/comfyui-mcp/(含 node_modules/、workflows/) |
| npm 页面 | https://www.npmjs.com/package/comfyui-mcp-server-node —— 403(npm 反爬,浏览器可开,非链接错误) |
装着三步
# ① 独立目录装包(不污染 ComfyUI)mkdir -p /home/zero/.local/share/comfyui-mcp && cd /home/zero/.local/share/comfyui-mcp# 本机 package.json 里就是这一条依赖:# {"dependencies": {"comfyui-mcp-server-node": "^2.1.1"}}npm install comfyui-mcp-server-node@^2.1.1# 国内可加 --registry=https://registry.npmmirror.com
# ② 在 DSH 的 profile 里注册(本机已注册在 /home/zero/.dsh/profiles/web/cordis.patch.yml)# 关键点:新插件必须用 `insert:` 列表引入(顶层 - id: 只能覆盖已有行)# - insert:# - id: mcp-comfyui# name: "@deepseek-ai/dsh-mcp-client"# config:# serverName: comfyui # ← 决定工具前缀 mcp__comfyui__<name># transport: stdio# command: <node 绝对路径># args:# - /home/zero/.local/share/comfyui-mcp/node_modules/comfyui-mcp-server-node/dist/server.js# env:# COMFYUI_URL: http://127.0.0.1:8188# COMFY_MCP_WORKFLOW_DIR: /home/zero/.local/share/comfyui-mcp/workflows# COMFY_MCP_ASSET_TTL_HOURS: "24"# cwd: /home/zero/.local/share/comfyui-mcp# toolCallTimeoutMs: 300000# failOnStartupError: false
# ③ 重启 DSH 让配置生效🔴 必须打 3 个兼容补丁(本机为什么装了还得修)
comfyui-mcp-server-node@2.1.1 对 ComfyUI 0.40.0 有三处不兼容,不打补丁会 generate_image 报 HTTP 400、模型列表恒为空。本机用 reapply-fixes.sh 修复,重装该包后会被覆盖,需重跑:
bash /home/zero/.local/share/comfyui-mcp/reapply-fixes.sh| # | 文件 | 问题 | 修法 |
|---|---|---|---|
| 1 | dist/comfyui_client.js | 残留 Promise.allSettled 重构痕迹:判 response.status === "fulfilled",而 axios 的 status 是数字 200 → 模型列表永远为空 | 改判 === 200,并把 response.value.data → response.data |
| 2 | dist/managers/workflow_manager.js | 省略的可选参数被写成 undefined,JSON.stringify 直接丢掉该键 → ComfyUI 报 required_input_missing | 注入 DEFAULT_PARAM_VALUES(negative_prompt/width/height/steps/cfg/…)+ 禁止写入 undefined/null + seed 的 undefined/null/负数 一律视为随机 |
| 3 | workflows/generate_image.json | 模板硬编码 "seed": -1,而 ComfyUI 0.40 要求 seed >= 0 | 改成 "seed": "PARAM_INT_SEED" 占位符 |
补丁是否已生效的自检(实测本机已生效):
Terminal window grep -n 'response.status === 200' \/home/zero/.local/share/comfyui-mcp/node_modules/comfyui-mcp-server-node/dist/comfyui_client.js# 期望:至少 3 行命中(本机实测 27/48/81 行)。若只看到 "fulfilled",说明补丁被覆盖,需重跑脚本。
验活(跑通才算装好)
mcp__comfyui__list_checkpoint_models() # 本机实测返回 3 个:RealVisXL_V5.0_fp16 / # animagine-xl-3.0 / chenkinNoobXLCKXL_v02mcp__comfyui__get_queue_status() # 本机实测 {"queue_running":[],"queue_pending":[]}mcp__comfyui__generate_image(...) # 真正出图,见 §5补丁①不生效的典型症状:
list_checkpoint_models返回空数组(而不是报错)——因为 status 判断永远为假。看到空的先查这一条。
MCP 与 HTTP API 的分工(别用错)
MCP 工具 mcp__comfyui__* | HTTP API(POST /prompt) | |
|---|---|---|
| 能喂的模型 | 只有 checkpoint 系(走 CheckpointLoaderSimple) | 任意(UNET+CLIP、Krea-2、Anima 都行) |
| 工作流 | 固定模板(workflows/*.json) | 任意 JSON 图 |
| 适用 | 快速出图、列模型、看队列 | 自定义管线(hires、IPAdapter、img2img) |
MCP 有 15 个工具,但喂不进 Krea-2/Anima(架构不通,见 §6 相关条目)。要跑那些管线必须走 HTTP API +
image_scripts/。
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!



