ComfyUI学习笔记(一):环境搭建

1.创建基础环境

1
2
3
4
5
# 默认安装conda
# 1.创建comfyui环境
>> conda create -n comfyui python=3.12
# 2.激活comfyui环境
>> conda activate comfyui

2.安装pytorch环境

 不同版本的Pytorch安装命令可以从Pytorch安装命令查询得到,我这里安装2.6.0

1
>> pip install torch==2.6.0 torchvision==0.21.0 torchaudio==2.6.0 --index-url https://download.pytorch.org/whl/cu124

 最近感觉国内源好像没有官方源快,就直接用官方源吧。

3.安装ComfyUI

1
2
3
4
5
6
7
# 1.下载源码:默认已装git,由于cuda版本较旧,
# 最新版本需要12.8及以上才能玩,所以这里用v0.7.0
>> git clone -b v0.7.0 https://github.com/Comfy-Org/ComfyUI.git
# 2.安装ComfyUI环境依赖
>> cd ComfyUI && pip install -r requirements.txt
# 3.安装ComfyUI-Manager环境依赖
>> pip install -r manager_requirements.txt

4.启动ComfyUI服务

  • (1)启动服务:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 1.直接启动
>> python ./main.py --enable-manager --port 10086 --listen 0.0.0.0
Total VRAM 22906 MB, total RAM 257566 MB
pytorch version: 2.6.0+cu124
Set vram state to: NORMAL_VRAM
Device: cuda:0 Tesla P40 : cudaMallocAsync
Using async weight offloading with 2 streams
Enabled pinned memory 244687.0

Import times for custom nodes:
0.0 seconds: /home/mirror/workspace/ComfyUI/custom_nodes/websocket_image_save.py

Context impl SQLiteImpl.
Will assume non-transactional DDL.
No target revision found.
Starting server

To see the GUI go to: http://0.0.0.0:10086

# 2.后台启动,并指定显卡
>> CUDA_VISIBLE_DEVICES=3 nohup python main.py --listen 0.0.0.0 --port 10086 > comfyui.log 2>&1 &
  • (2)访问服务:网页端打开<服务器ip>:10086即可:
    ComfyUI

5.文生图工作流

5.1 打开Z-Image-Turbo文生图工作流:

Z-Image-Turbo

5.2 下载所需模型

5.3 直接执行工作流

 调整一下提示词后运行,提示词调整为:生成一个红色的苹果,局部出现腐烂

Z-Image-Turbo-Result

5.4 服务请求执行工作流

 先看一下文档关于核心API路由介绍:ComfyUI-Server

路径 get/post/ws 用途
/ get 加载 Comfy 网页
/ws websocket 用于与服务器进行实时通信的 WebSocket 端点
/embeddings get 获取可用的嵌入模型名称列表
/extensions get 获取注册了 WEB_DIRECTORY 的扩展列表
/features get 获取服务器功能和能力
/models get 获取可用模型类型列表
/models/{folder} get 获取特定文件夹中的模型
/workflow_templates get 获取自定义节点模块及其关联模板工作流的映射
/upload/image post 上传图片
/upload/mask post 上传蒙版
/view get 查看图片。更多选项请参见 server.py 中的 @routes.get("/view")
/view_metadata/ get 获取模型的元数据
/system_stats get 获取系统信息(Python 版本、设备、显存等)
/prompt get 获取当前队列状态和执行信息
/prompt post 提交提示到队列
/object_info get 获取所有节点类型的详细信息
/object_info/{node_class} get 获取特定节点类型的详细信息
/history get 获取队列历史记录
/history/{prompt_id} get 获取特定提示的队列历史记录
/history post 清除历史记录或删除历史记录项
/queue get 获取执行队列的当前状态
/queue post 管理队列操作(清除待处理/运行中的任务)
/interrupt post 停止当前工作流执行
/free post 通过卸载指定模型释放内存
/userdata get 列出指定目录中的用户数据文件
/v2/userdata get 增强版本,以结构化格式列出文件和目录
/userdata/{file} get 获取特定的用户数据文件
/userdata/{file} post 上传或更新用户数据文件
/userdata/{file} delete 删除特定的用户数据文件
/userdata/{file}/move/{dest} post 移动或重命名用户数据文件
/users get 获取用户信息
/users post 创建新用户(仅限多用户模式)

 对于文生图任务而言,需要三步来实现工作流调用:(1) 调用/prompt将工作流提交到队列;(2) 调用/history{prompt_id}获取当前任务的队列记录;(3) 调用/view获取对应结果。

 具体操作步骤:

  • (1)导出对应API配置:

Z-Image-Turbo-API

  • (2)请求服务:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
'''
Author: chenjingyu
Date: 2025-11-26 15:33:14
Contact: 2458006466@qq.com
Description: z_image
'''
import sys
import json
import time
import uuid
import requests
from urllib.parse import urlencode
from pathlib import Path

curr_path = Path(__file__).parent.resolve()
if str(curr_path) not in sys.path:
sys.path.append(str(curr_path))

req_url = 'http://修改为你的服务器IP'
req_port = 10086

# 1.载入工作流
def load_config(path: str):
with open(path, 'r', encoding='utf-8') as fp:
return json.load(fp)

# 2.修改对应提示词内容,并调用/prompt接口提交任务
def submit_prompt(url: str, port: int, wf: dict):
payload = {"prompt": wf, "client_id": str(uuid.uuid4())}
resp = requests.post(f"{url}:{port}/prompt", json=payload).json()
print(resp)
if "error" in resp:
raise RuntimeError(resp["error"])
return resp["prompt_id"]

# 3.调用/history接口查看当前任务执行情况,执行完毕后,调用/view接口获取生成内容
def wait_and_download(url: str, port: int, prompt_id: str, save_dir: str):
while True:
time.sleep(1)
hist = requests.get(f"{url}:{port}/history/{prompt_id}").json()
if prompt_id not in hist:
continue
for _, outs in hist[prompt_id]["outputs"].items():
if "images" in outs:
for idx, element in enumerate(outs["images"]):
url = f"{url}:{port}/view?{urlencode(element)}"
save_name = f"{save_dir}/{idx}.png"
Path(save_name).write_bytes(requests.get(url).content)
print(f"保存 {save_name}")
return # 全部下完就结束
break
raise FileNotFoundError("❌ 未找到输出图")

# 主调用流程
def text_to_image_z_image(url: str, port: int, wf_path: str, node_name: str, prompt: str, save_path: str):
wf = load_config(wf_path)
wf[node_name]["inputs"]["text"] = prompt
if not Path(save_path).exists():
Path(save_path).mkdir(exist_ok=True, parents=True)
try:
start = time.time()
pid = submit_prompt(url, port, wf)
print(f"已提交,prompt_id={pid}")
wait_and_download(url, port, pid, save_path)
end = time.time()
print(f"总用时:{end-start:.2f}s")
return True
except Exception as e:
print(f"Error: {e}")
return False

if __name__ == '__main__':
in_node_name = "45"
wf_path = f"{curr_path}/image_z_image_turbo.json"
text_to_image_z_image(req_url, req_port, wf_path, in_node_name, '生成一张桌子,上面摆放一个白色的花瓶', './output')
  • (3)执行任务:
1
2
3
4
5
>> python z_image.py
{'prompt_id': '2e2ce1d0-e57d-498a-acb0-2abe1a9813ca', 'number': 5, 'node_errors': {}}
已提交,prompt_id=2e2ce1d0-e57d-498a-acb0-2abe1a9813ca
保存 ./output/0.png
总用时:8.93s
  • (4)生成结果:

Z-Image-Turbo-API-Result

参考资料