当前位置: 首页 > news >正文

Python调用优云智算安装的ComfyUI服务器

1. 申请优云智算服务器

优云智算官网:https://www.compshare.cn/

1.1 申请

选择 部署GPU示例 -->> 平台镜像
在这里插入图片描述
点击确定后:
在这里插入图片描述
等系统初始化完成,显示 运行中

1.2 登录

打开本地shell
输入登录指令和密码

$ ssh -p 23 root@117.50.81.213
root@117.50.81.213's password: 
Welcome to Ubuntu 22.04.3 LTS (GNU/Linux 5.15.0-113-generic x86_64)* Documentation:  https://help.ubuntu.com* Management:     https://landscape.canonical.com* Support:        https://ubuntu.com/advantageThis system has been minimized by removing packages and content that are
not required on a system that users do not log into.To restore this content, you can run the 'unminimize' command.
Last login: Fri Sep 26 08:08:04 2025 from 113.108.106.159

1.3 查看显卡、cuda

# nvcc -V
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2023 NVIDIA Corporation
Built on Tue_Feb__7_19:32:13_PST_2023
Cuda compilation tools, release 12.1, V12.1.66
Build cuda_12.1.r12.1/compiler.32415258_0
# nvidia-smi
Fri Sep 26 08:27:08 2025       
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 570.153.02             Driver Version: 570.153.02     CUDA Version: 12.8     |
|-----------------------------------------+------------------------+----------------------+
| GPU  Name                 Persistence-M | Bus-Id          Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |           Memory-Usage | GPU-Util  Compute M. |
|                                         |                        |               MIG M. |
|=========================================+========================+======================|
|   0  NVIDIA GeForce RTX 3090        Off |   00000000:00:03.0 Off |                  N/A |
| 30%   31C    P8             11W /  350W |    7007MiB /  24576MiB |      0%      Default |
|                                         |                        |                  N/A |
+-----------------------------------------+------------------------+----------------------++-----------------------------------------------------------------------------------------+
| Processes:                                                                              |
|  GPU   GI   CI              PID   Type   Process name                        GPU Memory |
|        ID   ID                                                               Usage      |
|=========================================================================================|
|    0   N/A  N/A           14729      C   ...comfyui_home/.venv/bin/python       6998MiB |
+-----------------------------------------------------------------------------------------+

2. 安装ComfyUI

2.1 安装

首先安装uv

curl -LsSf https://astral.sh/uv/install.sh | sh

为 ComfyUI 创建一个 home 目录,并且使用 uv 初始化一个 Python 虚拟环境

cd ~/work
mkdir comfyui_home
cd comfyui_home
mkdir logs
uv init --python 3.12
vi pyproject.toml

编辑 uv 的配置文件 pyproject.toml,在 pyproject.toml 的开头加入清华大学的 Python 库镜像服务器:

[[tool.uv.index]]
url = "https://pypi.tuna.tsinghua.edu.cn/simple"
default = true

安装 ComfyUI 的命令行工具,并且使用 ComfyUI 命令行工具安装 ComfyUI。ComfyUI 的安装目录是 /root/comfyui_home/ComfyUI

uv add comfy-cli pip
uv run comfy --workspace=/root/comfyui_home/ComfyUI install

安装时 ComfyUI 时要选择 Nvidia 显卡

2.2 启动

如果 ComfyUI 安装成功,可以使用以下命令启动 ComfyUI

uv run comfy launch -- --listen 0.0.0.0 --port 8119

使用 0.0.0.0 就是接受网络中的所有客户端机器连接

2.3 查看

查看服务器运行状态:

# ps aux | grep comfy
root       14706  0.0  0.0 1435008 39568 pts/1   Sl+  08:08   0:00 uv run comfy launch -- --listen 0.0.0.0 --port 8119
root       14725  0.0  0.0  61464 56260 pts/1    S+   08:08   0:00 /root/comfyui_home/.venv/bin/python /root/comfyui_home/.venv/bin/comfy launch -- --listen 0.0.0.0 --port 8119
root       14729  3.2 14.9 72164148 9844528 pts/1 Sl+ 08:08   0:56 /root/comfyui_home/.venv/bin/python main.py --listen 0.0.0.0 --port 8119
root       14865  0.0  0.0   4024  1992 pts/2    S+   08:37   0:00 grep --color=auto comfy

查看端口状态:

 lsof -i :8119
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
python  14729 root   54u  IPv4 265437      0t0  TCP *:8119 (LISTEN)
python  14729 root   55u  IPv4 265438      0t0  TCP 10.60.72.45:8119->113.108.106.159:52834 (ESTABLISHED)

3. Python调用ComfyUI服务器

3.1 先放开端口

点击 控制台 -->> 更多操作 -->> 配置防火墙
选择镜像
在这里插入图片描述
点击 编辑防火墙规则–>> 添加规则
在这里插入图片描述
再点击 下一步 -->> 确定

3.2 本地显示

# curl ipinfo.io
{"ip": "117.50.81.213","city": "Beijing","region": "Beijing","country": "CN","loc": "39.9075,116.3972","org": "AS23724 IDC, China Telecommunications Corporation","postal": "100000","timezone": "Asia/Shanghai","readme": "https://ipinfo.io/missingauth"
}

本地浏览器输入 http://117.50.81.213:8119/ 显示:
在这里插入图片描述

3.3 python代码

import urllib.request
import urllib.parse
import json
import time
import os
import base64
from PIL import Image
import io
import requestsclass ComfyUIClient:def __init__(self, server_address="127.0.0.1", port=8188):self.server_address = server_addressself.port = portself.base_url = f"http://{server_address}:{port}"def _make_request(self, endpoint, data=None, method="GET"):"""发送HTTP请求到ComfyUI服务器"""url = f"{self.base_url}{endpoint}"if data and method == "POST":data = json.dumps(data).encode('utf-8')req = urllib.request.Request(url, data=data, headers={'Content-Type': 'application/json'})req.method = "POST"else:req = urllib.request.Request(url)try:with urllib.request.urlopen(req) as response:return json.loads(response.read().decode('utf-8'))except urllib.error.HTTPError as e:print(f"HTTP错误: {e.code} - {e.reason}")if e.code == 400:# 读取错误详情error_detail = e.read().decode('utf-8')print(f"错误详情: {error_detail}")return Noneexcept Exception as e:print(f"请求错误: {e}")return Nonedef get_available_nodes(self):"""获取服务器上可用的节点列表"""return self._make_request("/object_info")def validate_workflow(self, workflow):"""验证工作流中的节点是否都存在"""available_nodes = self.get_available_nodes()if available_nodes:available_node_types = set(available_nodes.keys())# 检查工作流中的所有节点类型for node_id, node_data in workflow.items():node_type = node_data.get("class_type")if node_type and node_type not in available_node_types:print(f"警告: 节点类型 '{node_type}' 在服务器上不存在")return Falsereturn Truereturn Falsedef submit_prompt(self, workflow):"""提交工作流到ComfyUI服务器执行"""return self._make_request("/prompt", data={"prompt": workflow}, method="POST")def wait_for_completion(self, prompt_id, check_interval=1, timeout=300):"""等待工作流执行完成"""start_time = time.time()while time.time() - start_time < timeout:history = self.get_history(prompt_id)if history and prompt_id in history:status = history[prompt_id]if status.get('status', {}).get('completed', False):return Trueelif status.get('status', {}).get('failed', False):print("工作流执行失败")return Falsetime.sleep(check_interval)print("等待超时")return Falsedef get_history(self, prompt_id):"""获取指定提示ID的历史记录"""return self._make_request(f"/history/{prompt_id}")def view_image(self, filename, subfolder="", type="output"):"""查看生成的图像"""params = {"filename": filename}if subfolder:params["subfolder"] = subfolderif type:params["type"] = typeurl = f"{self.base_url}/view?{urllib.parse.urlencode(params)}"try:response = requests.get(url)if response.status_code == 200:return response.contentelse:print(f"获取图像失败: HTTP {response.status_code}")return Noneexcept Exception as e:print(f"获取图像错误: {e}")return Nonedef download_image(self, image_data, filename, output_dir="output_images"):"""下载图像到本地"""if not os.path.exists(output_dir):os.makedirs(output_dir)filepath = os.path.join(output_dir, filename)with open(filepath, "wb") as f:f.write(image_data)print(f"图像已保存到: {filepath}")return filepathdef display_image(self, image_data):"""显示图像(需要PIL库)"""try:image = Image.open(io.BytesIO(image_data))image.show()return imageexcept Exception as e:print(f"显示图像错误: {e}")return Nonedef get_image_info_from_history(self, history, prompt_id):"""从历史记录中提取图像信息"""if not history or prompt_id not in history:return []outputs = history[prompt_id].get('outputs', {})image_infos = []for node_id, output in outputs.items():if 'images' in output:for image_info in output['images']:image_infos.append(image_info)return image_infosdef generate_simple_workflow(self, prompt_text, model_name="sdxl-动漫二次元_2.0.safetensors"):"""生成一个简单的工作流,只使用核心节点"""# 修复节点连接问题workflow = {"checkpoint_loader": {"class_type": "CheckpointLoaderSimple","inputs": {"ckpt_name": model_name}},"positive_prompt": {"class_type": "CLIPTextEncode","inputs": {"text": prompt_text,"clip": ["checkpoint_loader", 1]  # 使用索引1获取CLIP模型}},"negative_prompt": {"class_type": "CLIPTextEncode","inputs": {"text": "blurry, low quality","clip": ["checkpoint_loader", 1]  # 使用索引1获取CLIP模型}},"latent_image": {"class_type": "EmptyLatentImage","inputs": {"width": 1024,"height": 1024,"batch_size": 1}},"ksampler": {"class_type": "KSampler","inputs": {"seed": 42,"steps": 20,"cfg": 7,"sampler_name": "euler","scheduler": "normal","denoise": 1,"model": ["checkpoint_loader", 0],  # 使用索引0获取模型"positive": ["positive_prompt", 0],"negative": ["negative_prompt", 0],"latent_image": ["latent_image", 0]}},"vae_decode": {"class_type": "VAEDecode","inputs": {"samples": ["ksampler", 0],"vae": ["checkpoint_loader", 2]  # 使用索引2获取VAE}},"save_image": {"class_type": "SaveImage","inputs": {"images": ["vae_decode", 0],"filename_prefix": "comfyui_output"}}}return workflow# 使用示例
if __name__ == "__main__":# 创建客户端实例 http://117.50.81.213:8119/client = ComfyUIClient("117.50.81.213", 8119)# 获取服务器上的可用节点available_nodes = client.get_available_nodes()if available_nodes:print("服务器上的节点数量:", len(available_nodes))# 打印前10个节点类型for i, node_type in enumerate(list(available_nodes.keys())[:10]):print(f"{i+1}. {node_type}")else:print("无法获取节点列表")# 生成一个简单的工作流# workflow = client.generate_simple_workflow("A princess standing in front of a church, holding a long magic wand in her left hand and a Bible in her right, was about to use magic, masterpiece, best quality")workflow = client.generate_simple_workflow("A princess standing in front of a church, holding a crystal ball in her left hand and a Bible in her right, was about to use magic, masterpiece, best quality")# 验证工作流if client.validate_workflow(workflow):print("工作流验证通过")# 提交工作流result = client.submit_prompt(workflow)if result and 'prompt_id' in result:prompt_id = result['prompt_id']print(f"工作流已提交,ID: {prompt_id}")# 等待执行完成if client.wait_for_completion(prompt_id):# 获取执行结果history = client.get_history(prompt_id)if history and prompt_id in history:# 获取所有生成的图像信息image_infos = client.get_image_info_from_history(history, prompt_id)if image_infos:print(f"找到 {len(image_infos)} 张生成的图像")# 下载和显示所有图像for i, image_info in enumerate(image_infos):filename = image_info['filename']subfolder = image_info.get('subfolder', '')type = image_info.get('type', 'output')print(f"正在获取图像 {i+1}: {filename} (子文件夹: {subfolder})")# 获取图像数据image_data = client.view_image(filename, subfolder, type)if image_data:# 保存图像到本地local_path = client.download_image(image_data, f"output_{prompt_id}_{i+1}.png")# 显示图像(需要PIL库)try:client.display_image(image_data)except Exception as e:print(f"无法显示图像: {e}")print("请确保已安装PIL库: pip install pillow")else:print(f"无法获取图像 {filename}")else:print("未找到生成的图像")else:print("无法获取历史记录")else:print("提交工作流失败")else:print("工作流验证失败,包含不存在的节点")

输出图片
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

http://www.dtcms.com/a/409944.html

相关文章:

  • ACA云原生工程师认证知识点脑图
  • 用 Flink 打造事件驱动流式应用从 DataStream 到 ProcessFunction
  • MySQL学习笔记05:MySQL 索引原理与优化实战指南
  • 【提示工程】Ch2(续)-提示技术(Prompt Technique)
  • 嵌入式软件知识点汇总(day2)
  • QT中QStackedWidget控件功能及应用
  • 网络爬虫(上)
  • 论文精读(六):微服务系统服务依赖发现技术综述
  • 农业推广网站建设企业商城网站建设价格
  • 教师做班级网站手机网站打开微信号
  • 司法审计师:在数字与法律之间行走的“侦探”
  • google drive 怎么断点续传下载?
  • 基于STM32单片机的温湿度臭氧二氧化碳检测OneNET物联网云平台设计
  • LeetCode 面试经典 150_哈希表_快乐数(45_202_C++_简单)(哈希表;快慢指针)
  • K8S部署的ELK分片问题解决,报错:unexpected error while indexing monitoring document
  • Atlas Mapper 教程系列 (7/10):单元测试与集成测试
  • 众智FlagOS 1.5发布:统一开源大模型系统软件栈,更全面、AI赋能更高效
  • 理解 mvcc
  • 【网络编程】TCP 粘包处理:手动序列化反序列化与报头封装的完整方案
  • 数据库MVCC
  • 如何用AI工具开发一个轻量化CRM系统(七):AI生成pytest测试脚本
  • qData:一站式开源数据中台
  • 国外中文网站排行在线图片编辑网站源码
  • [数据结构]优先级队列
  • ARM内部寄存器
  • Laravel + UniApp AES加密/解密
  • 5G开户时切片配置参数详解
  • 面向新质生产力,职业院校“人工智能”课程教学解决方案
  • wap网站如何做福建外贸网站
  • ElasticSearch-提高篇