前言
生成式 AI 正在深刻改变各行各业的工作方式,在游戏行业尤其如此。众所周知,美术质量对游戏的成功至关重要,而美术资源的制作往往占据了游戏研发成本的很大比重。传统上,要制作一张高质量的游戏美术图像,美术人员需要投入大量时间。 随着 Stable Diffusion 和 Flux 等高质量 AI 大模型的出现,通过文生图、图生图等生成式 AI 技术,结合模型微调,我们可以显著提升游戏美术的工作效率。本文将介绍如何利用开源免费的绘图软件 Krita,结合 ComfyUI 的功能来提高美术创作效率。
如上图所示,通过 Krita 的 AI 插件,我们可以将传统绘图功能与 AIGC 能力无缝结合。美术人员可以在数位板上实时绘画,同时观察 AI 生成的图像效果,快速调整创意方向。创作者可以通过提示词(Prompt)和参考图来精确控制图像生成效果,从而高效完成绘画和设计工作。
关于 Krita
Krita 是一款功能强大且完全免费的开源数字绘画软件,旨在为艺术家提供一个无障碍的创作平台。目前 Krita 支持在 Windows、MacOS 和 Linux 操作系统使用。
软件特点
- 自由开源:Krita 遵循 GNU GPL 许可证,确保用户可以自由使用、修改和分发软件,而不受商业限制。
- 多功能绘画工具:Krita 提供了丰富的绘画功能,包括:
- 强大的笔刷引擎,支持多种绘画风格。
- 图层管理、绘画辅助工具和笔刷防抖功能,帮助用户实现精细的绘画效果。
- 动画制作工具,支持多图层动画和音频导入。
- 用户友好的界面:Krita 的界面可高度定制,用户可以根据自己的需求调整面板布局和快捷键,以提高创作效率。
- 社区支持:Krita 拥有一个活跃的国际社区,用户可以在论坛中分享作品、讨论创作经验,并与开发者直接交流。
关于 ComfyUI
ComfyUI 是基于 Stable Diffusion 的图像生成工具,采用节点式工作流设计,具有以下特点:
高效的图像生成
- ComfyUI 在图像生成速度上优于传统的 WebUI,适合需要快速生成图像的用户。
- 显存占用较低,即使在显存有限的情况下也能有效运行。
高度可定制的工作流
- 用户可以创建和复用自定义工作流,通过节点连接实现复杂的图像生成过程。
- 支持导入和导出工作流,便于分享和学习。
扩展性和社区支持
- ComfyUI 允许用户开发自定义节点,社区贡献了大量自定义节点,极大丰富了功能选择。
- 尽管学习曲线较陡,但其灵活性和可玩性吸引了许多高级用户。
实时反馈和调试
- 通过节点式设计,用户可以实时查看生成过程中的每个步骤,便于调试和优化工作流。
通过上面的介绍可以看到,Krita 适合需要手绘和复杂图层管理的艺术创作,提供了丰富的工具和灵活的工作环境;而 ComfyUI 则更适合快速生成图像和需要高度定制化的用户,尤其在 AI 绘画和图像处理方面表现突出。本文会介绍如何通过 Krita 结合 ComfyUI 实现非常高效的实时绘画,并带大家一起来构建在亚马逊云科技 EC2 上的 ComfyUI 环境。整体架构信息如下所示:
架构说明
本方案中暴露了一系列 API 给到外部进行调用完成 EC2 创建维护等,其中使用的重要组件列举如下:
- EC2:用来部署 ComfyUI 服务
- EFS:存储全局、不同部门、不同用户的 Custom Nodes 以及 Model
- DynamoDB:管理 Custom Nodes 以及服务器-用户的 mapping 信息
- API Gateway,Lambda:通过 API gateway 和 Lambda 来暴露外部调用 API
- Eventbridge:监听 EC2 的状态并调用 Lambda 来修改 DynamoDB 中 EC2 的状态信息
整个方案中使用的服务基本都是 Serverless 的服务,其中 EC2 启动之后会监控针对 GPU 的使用率。一旦一段时间没有使用后就会被停止,待下一次用户使用时再启动。
安装 Krita
在 Krita 官网下载后直接安装完后,下载 AI 插件 krita-ai-diffusion,进行安装
安装完毕后,在 Krita 的右下角可以看到插件信息
方案部署
下面我们开始部署整体方案。
EC2 AMI 制作
1. 使用 Ubuntu 系统来制作 EC2 Image,或者直接使用已经安装好环境的官方 Ubuntu 镜像,本文采用第一种
首先我们需要在亚马逊云科技控制台来启动一台 Ubuntu 系统的 EC2,EC2 的安全组需要开放 22 以及 8848 端口,EBS 选择 gp3, 200G。
2. 安装 AWS CLI
sudo apt install unzip
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
3. 安装 Nvidia 驱动
按照 AWS 官网来安装驱动,打开下面的网页,选择 Option4:Nvidia Gaming Driver。一定要安装下面的包,不然会导致 EC2 重启后 GPU Driver 不能 work:
sudo apt-get install -y nvidia-cuda-toolkit
sudo apt-get install -y ubuntu-drivers-common
sudo ubuntu-drivers autoinstall
sudo reboot
4. 安装 Cloudwatch Agent
下载 Cloudwatch Agent 后,使用以下命令启动。
Agent.json 文件参考下面内容,文件目录为:/home/ubuntu/cloudwatch-agent/agent.json
{
"metrics": {
"append_dimensions": {
"InstanceId": "${aws:InstanceId}"
},
"metrics_collected": {
"nvidia_gpu": {
"measurement": [
"utilization_gpu",
"utilization_memory",
"memory_total",
"memory_used",
"memory_free"
],
"metrics_collection_interval": 30
}
}
}
}
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c file:/home/ubuntu/cloudwatch-agent/agent.json -s
5. 安装 EFS Driver
sudo apt-get update
sudo apt-get -y install git binutils rustc cargo pkg-config libssl-dev
git clone https://github.com/aws/efs-utils
cd efs-utils
./build-deb.sh
sudo apt-get -y install ./build/amazon-efs-utils*deb
6. 安装 ComfyUI 服务
此处不需要创建为系统服务,在后面的方案中会自动创建,下面的命令会自动安装 Comfy Manager 的 custom node。
# ubuntu根目录下执行以下命令, 根据本地python3版本调整
sudo apt install python3.12-venv
python3 -m venv venv
. venv/bin/activate
pip install comfy-cli
comfy install # 一路“Y”下去
#启动服务
/home/ubuntu/venv/bin/python3 /home/ubuntu/comfy/ComfyUI/main.py --listen 0.0.0.0 --port 8848
7. 安装 Krita 需要的 Custom Nodes
按照 Krita AI 插件的介绍 ComfyUI Setup,需要安装以下 Custom Nodes:
- ComfyUI Nodes for External Tooling
- ComfyUI’s ControlNet Auxiliary Preprocessors
- ComfyUI_IPAdapter_plus
- Inpaint Nodes
我们可以通过 Comfy Manager 中的 Custom Nodes Management 来下载安装
8. 下载测试模型
wget https://github.com/Acly/krita-ai-diffusion/releases/download/v1.22.0/krita_ai_diffusion-1.22.0.zip
unzip krita_ai_diffusion-1.22.0.zip
cd ai_diffusion/
pip3 install aiohttp tqdm
python3 download_models.py /home/ubuntu/comfy/ComfyUI --recommended # 注意ComfyUI Home
9. 安装完毕后,测试当前环境是否正常,显示 Connected 则为正常
10. 至此 EC2 环境已经完备,停止 EC2,制作 Image,制作完毕后,请记录一下 AMI 的 ID,以备后续使用
CDK 部署环境
创建部署用 EC2(推荐 t3.large,仅作为部署短期使用),默认使用 Amazon Linux 2023,赋予必要 IAM Role 角色权限,涉及权限如下:VPC、EC2、EFS、API Gateway、Lambda、DynamoDB、EventBridge 创建权限。
安装 CDK
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
source ~/.bashrc
nvm --version
nvm install 20
nvm use 20
node -v
npm -v
npm install -g aws-cdk
cdk --version
下载部署代码
yum install git -y
git clone https://github.com/aws-samples/using-EC2-build-Krita-with-ComfyUI-practice.git
修改配置,进行部署
cd using-EC2-build-Krita-with-ComfyUI-practice/
vim gen_env.sh
# 打包好的comfyui ubuntu的 AMI ID, 请务必替换成我们自己的AMI ID, 此处需要注意不同机型的AMI有可能不适配,请一定一定要使用指定机型的AMI
EC2_AMI_ID='ami-0633a0cxxxx'
# EC2 key pair name, 请务必替换成我们自己的EC2 Key Name
EC2_KEY_NAME='west'
# EC2 实例类型, 默认为: g6.2xlarge
EC2_INSTANCE_TYPE='g6.2xlarge'
# DynamoDB Table 名称, 用户分配的ComfyUI服务器信息, 默认为: user-comfyui-servers
USER_COMFYUI_SERVERS_TABLE='user-comfyui-servers'
# DynamoDB Table 名称, Custom Nodes信息, 默认为: comfyui_custom_nodes
COMFYUI_CUSTOM_NODES_TABLE='comfyui_custom_nodes'
# 指定自己的VPC CIDR
VPC_CIDR='10.0.0.0/16'
# 指定机器闲置时间,单位为分钟
SERVER_IDLE_TIME='30'
修改完毕后,执行
sh gen_env.sh
npm install
cdk bootstrap
cdk deploy
等待大约十多分钟后,部署完毕
检查 CloudFormation
根据 APIKeyARN 获取 APIKeyID,格式如下:
arn:aws:apigateway:region::/apikeys/{api-key-id}
根据 apikeyid 获取 apikey
aws apigateway get-api-key --api-key {api-key-id} --include-value --query "value" --output text
记录下 InvokeUrl、APIKey、FileBroswerInstanceIP。
使用 Postman 测试接口
下载测试 json 文件
导入到 Postman,定义环境变量 api-key 用上面的 APIKey 赋值,url 用 InvokeUrl 赋值
/ComfyUI-Servers 一共有三个接口
- Post 接口,根据 userid 创建/启动 ComfyServer
- Get 接口,根据 username 查询 ComfyServer 状态以及对外暴露的 IP 和 Port,直接配置在 Krita 中进行使用
- Stop 管理接口,根据 username,group_name 停止 ComfyServer
/ComfyUI-Servers/custom_nodes 一共有四个接口,分别对应查询,创建,更新,删除
- Post 接口,创建 custom_nodes
{
"node_name": "ComfyUI Inspire Pack",
"node_type": "global",
"group_name": "group1",
"repo_url": "https://github.com/example/repo.git",
"status": "available",
"creator": "user1"
}
- 通过 id 获取 custom_node
- 通过 id 更新 custom_node
{
"node_name": "ComfyUI Inspire Pack",
"node_type": "global",
"group_name": "group1",
"repo_url": "https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git",
"status": "available"
}
- 通过 id 删除 custom_node
模型管理
模型是通过 EFS 进行共享,分为 global 和 group 模型
File browser 管理模型
通过使用 FileBroswerInstanceIP 地址打开管理界面,使用默认账号密码登录 admin/admin,默认工作目录是 /home/ec2-user/EFS/
models 目录结构为 global,{groups}/{group_name},{users}/{username};
output 目录结构为 {output_dir}/{group_name}/{username}
可以通过设置界面修改 admin 登录密码,和默认工作目录
模型上传
- 通过 comfyui manager 下载模型到指定文件夹
- 使用 file browser 上传,路径在 /home/ec2-user/EFS/models/checkpoints/global/
- 通过密钥登录 file browser 服务器进行更新
cd /home/ec2-user/EFS/models/checkpoints/global/
wget -O sd_xl_base_1.0.safetensors https://huggingface.co/stabilityai/stable-diffusion-xl-base-1.0/resolve/main/sd_xl_base_1.0.safetensors?download=true
从 FileBrowser 使用命令下载模型
首先将 wget、curl 等常用文件下载和管理命令设置为允许在 FileBrowser 中使用。
点击左侧配置按钮
再点击用户管理,选择需要赋予命令权限的用户,点击铅笔图标
滑动到画面下端的用户命令(Shell 命令),添加 ls、wget、curl、rm、cp、mv 等文件操作命令,注意命令之间使用半角空格分割。编辑完成后点击保存按钮
返回文件操作界面,点击右上角的“<>”图标,开启 terminal
在页面下半部分的 terminal 执行各种文件管理命令,来下载和管理模型文件
关键代码解析
comfyui_servers_post.py
- 创建 EC2 的逻辑
result = query_comfyui_servers_by_username(username) # 获取用户之前是否创建过EC2
if result: # 如果已有EC2,则将其启动
print(f"Username:{username} already has a comfyui server")
for item in result:
instance_id = item['instance_id']
response = ec2_client.describe_instances(InstanceIds=[instance_id])
instance_status = response['Reservations'][0]['Instances'][0]['State']['Name']
if instance_status == 'stopped':
start_instance(instance_id=instance_id, idle_time=idle_time)
update_status(username=username, instance_id=instance_id, status='starting')
else:
return {
"statusCode": 400,
"body": json.dumps({"message": f"Can not start instance_id: {instance_id}, current status:{instance_status}", "code": 400})
}
else: # 若之前没有EC2,则为其创建信息的EC2
print(f"Username:{username} doesn't have a comfyui server, now create a new one.")
instances = create_instance(username=username, group_name=group_name, idle_time=idle_time)
instance_id = instances[0].id
- 获取用户配置的 custom nodes 并组装安装命令
repo_list = get_custom_nodes_by_type('global')
# Convert repo_list to a string for the user data script
repo_clone_commands = "\n".join([
f"""
if [ ! -d {comfyui_home_dir}/custom_nodes/{repo['repo_url'].split('/')[-1].replace('.git', '')} ]; then
git clone {repo['repo_url']} {repo.get('extra_parameter', '')} {comfyui_home_dir}/custom_nodes/{repo['repo_url'].split('/')[-1].replace('.git', '')} &&
if [ -f {comfyui_home_dir}/custom_nodes/{repo['repo_url'].split('/')[-1].replace('.git', '')}/requirements.txt ]; then
source /home/ubuntu/venv/bin/activate && pip install -r {comfyui_home_dir}/custom_nodes/{repo['repo_url'].split('/')[-1].replace('.git', '')}/requirements.txt;
fi
else
echo "Repository {repo['repo_url']} already cloned."
fi
"""
for repo in repo_list
])
print(repo_clone_commands)
- 使用 user data 精准挂载当前用户的 group 以及自身下载的模型
user_data_script = f"""#!/bin/bash
echo "---------user data start-----------"
# Mount EFS
if [ ! -d "{ec2_start_script_dir}" ]; then
mkdir -p {ec2_start_script_dir}
fi
mount -t efs -o tls,iam,accesspoint={access_point_start_script_id} {file_system_id}:/{username} {ec2_start_script_dir}
echo "{file_system_id}:/{username} {ec2_start_script_dir} efs _netdev,tls,iam,accesspoint={access_point_start_script_id} 0 0" >> /etc/fstab
chmod +x {ec2_start_script_dir}/mount.sh
bash {ec2_start_script_dir}/mount.sh
# Create User Output Dir
if [ ! -d "{user_output_dir}" ]; then
mkdir -p {user_output_dir}
fi
# Custom Nodes Clone
{repo_clone_commands}
chown -R ubuntu:ubuntu {comfyui_home_dir}/custom_nodes/*
# Set Comfyui as system service
cat << EOF > /etc/systemd/system/comfyui.service
[Unit]
Description=ComfyUI Service
After=network.target
[Service]
User=root
WorkingDirectory=/home/ubuntu/comfy/ComfyUI
ExecStart=/home/ubuntu/venv/bin/python3 main.py --listen 0.0.0.0 --port {comfyui_server_port} --output-directory {user_output_dir}
Restart=always
[Install]
WantedBy=multi-user.target
EOF
# start comfyui as system service
systemctl daemon-reload
systemctl enable comfyui.service
systemctl start comfyui.service
echo "---------user data end-----------"
"""
- 设置 CloudWatch metrics 以及 alarm 一旦超过一段时间没有用 EC2,则直接关机
def put_alarm_metric_alarm(instance_id, idle_time):
gpu_info = next((item for item in INSTANCE_GPU if item['instance'] == instance_type[:2]), None)
put_response = cw.put_metric_alarm(
AlarmName=f'{alarm_name_prefix}{instance_id}',
ComparisonOperator='LessThanThreshold',
EvaluationPeriods=int(idle_time),
MetricName='nvidia_smi_utilization_gpu',
Namespace='CWAgent',
Period=60,
Statistic='Maximum',
Threshold=1.0,
ActionsEnabled=True,
AlarmActions=[f'arn:aws:swf:{region}:{account_id}:action/actions/AWS_EC2.InstanceId.Stop/1.0'],
AlarmDescription=f'Alarm when GPU utilization is low for {idle_time} minutes',
Dimensions=[
{
'Name': 'InstanceId',
'Value': instance_id
},
{
'Name': 'name',
'Value': gpu_info['gpu']
},
{
'Name': 'index',
'Value': '0'
},
{
'Name': 'arch',
'Value': gpu_info['arch']
}
],
TreatMissingData='notBreaching' #没有数据的点不不触发告警.
)
print(f'Alarm reset response: {put_response}')
总结
在这篇博客中,我们探讨了如何在 Amazon EC2 上构建 Krita 与 ComfyUI 的集成环境,以实现高效的实时绘画。通过使用 Serverless 架构,结合 API Gateway 和 Lambda,我们实现了对 ComfyUI 服务的管理和监控,确保用户可以方便地创建和管理自己的绘画环境。
常见问题
执行命令 nvidia-smi
报错如下
Failed to initialize NVML: Driver/library version mismatch;
通过以下方案
sudo apt-get --purge remove "*nvidia*"
之后重新安装 Driver
查看日志
systemctl status comfyui # 查看服务状态
journalctl -f -u comfyui # 查看服务日志
本篇作者