目前 AI 繪畫領域的產品非常多,比如 Midjourney、Dalle3、Stability AI 等等,這些產品大體上可以分為兩類:
- 模型與產品深度融合:比如 Midjourney、Dalle3 等等。
- 模型與產品分離:比如 SD Web UI、ComfyUI 等等。
對於絕大多數普通使用者而言,學習成本低、功能一體化的融合產品,能以最快的速度上手 AI 繪畫,享受 AI 帶來的樂趣。
但如果你想靠 AI 生圖技術來賺錢,或者你是個設計師,想獲取更高的靈活度和自由度,建議還是學習使用模型與產品分離的產品。
AI 不會淘汰人類,AI 只會淘汰 “不會使用 AI” 的人類。
如果你想獲得更多的自由,那麼請關注本系列文章,我們將會帶你走進那個自由的世界。
SD WebUI = SD?
先來說一個誤區,很多人誤以為 SD 就是 SD WebUI,其實是不對的。SD 只是一個文生圖模型,而 SD WebUI 是基於 SD 這項模型技術來進行影像生成的工具。
然而,基於 SD 來進行影像生成的工具遠不止 SD WebUI 這一個,還有很多其他同類工具,比如 Fooocus、WebUI Forge、ComfyUI 等等。
ComfyUI 介紹
在這所有的基於 SD 的同類工具裡,ComfyUI 的自由度最高,直接看圖就明白了:
ComfyUI 並不追求簡單易用,而是將重點放在了自由度和可擴充性上。它透過模組化的節點設計,讓使用者能夠根據自己的需求,自由組合和調整工作流,實現高度個性化的創作。同時,ComfyUI 還支援使用者自行開發和擴充節點功能,使其成為一個開放的創作平臺。
在 AI 知識庫領域,FastGPT 也採用了工作流的設計,有異曲同工之妙。
採用工作流模式,使用者可以清晰地看到整個創作流程,並且可以方便地對每個節點進行配置和調整。除此之外,還有很多肉眼可見的優勢,比如:
- 相比於 SD WebUI,ComfyUI 對視訊記憶體的要求更低,資源利用率非常高。
- 相比於 SD WebUI,ComfyUI 啟動速度快,出圖速度快。
- 可以搭建自己的工作流程,可以匯出流程並分享給別人,報錯的時候也能清晰的發現錯誤出在哪一步。
怎麼樣,想實現 AI 繪畫自由麼?跟我一起來學 ComfyUI 吧。
在哪安裝?
這一節內容玩過 SD WebUI 的同學應該很熟悉,一般來說有兩種選擇:要麼裝在本地,要麼裝在雲上。
如果你自己的電腦 GPU 給力,完全可以直接裝在本地,0 成本,一分錢不用花。
如果你本地的電腦 GPU 不太給力,可以選擇雲端服務,雲端的配置上限很高,生圖速度更快,唯一需要考慮的就是費用問題。
我的電腦是 M1 Max,用 ComfyUI 生圖的速度也很慢,如果你的配置還不如我的 M1 Max,就別想在本地跑了。
如果你決定了要將 ComfyUI 部署在雲端,可以試試 Sealos 最近上線的雲主機,Sealos 的付費模式是按量付費,用的時候開機,不用的時候關機,關機狀態下只收少量的儲存費用。如果你不是一天 24 小時使用 ComfyUI,可以試試 Sealos 的這種模式。
當然,如果你只是短期玩玩,大可以選擇某些雲廠商所謂的新人優惠,價格確實非常低,但是 “老使用者與狗不得入內啊”
實際測試下來,我在 Sealos 上新建了個 12C/44G 的雲主機,GPU 選的是 NVIDIA A10,儲存 50G,關機狀態下每小時的費用是 0.04 元。開機狀態下每小時的費用是 9.24 元。
如果你一天只玩倆小時,那麼一天的花費不到 20 元。然而現實情況是,有時候你可能一個星期只玩了一兩天,其他時間都是關機,那就更便宜了,因為關機狀態下一天只有 9 毛錢。
總結一下:
- 如果你只是一時興起圖個新鮮,只想短期玩玩,大可以使用某些雲廠商的新人優惠,那是最便宜的方案。
- 如果你想長期玩耍 ComfyUI,可以試試 Sealos。
ComfyUI 的安裝
下面介紹如何在 Linux 主機上安裝 ComfyUI,Windows 使用者請自行參考 ComfyUI 官方文件或者網上的文章進行安裝。
以 Sealos 為例,首先進入 Sealos 廣州可用區:https://gzg.sealos.run
點選桌面的 “雲主機”:
點選 “新建主機”,選擇 “異構計算”,然後在機型中選擇 GPU 型號,目前最便宜的是 T4,但是好像已經售空了,可以選擇 A10。
下面繼續選擇作業系統映象,儲存推薦 50G 以上,因為各種模型要佔用儲存空間,有條件建議直接 100G。公網 IP 也需要開啟,不然無法聯網。頻寬直接預設 1M 就夠了。最後設定好密碼就可以點選右上角的 “提交” 了。
建立完成後,點選雲主機右邊的三個點,然後點選 “終端”:
開啟終端後,輸入雲主機的密碼即可登入雲主機。然後執行命令 sudo su
切換到 root 使用者。
接下來正式進入安裝流程。
首先需要安裝 NVIDIA 驅動:
apt update
ubuntu-drivers install nvidia:535
安裝完驅動後,執行以下命令重啟雲主機:
systemctl reboot
重啟之後執行命令 nvidia-smi
測試驅動是否安裝成功:
接著安裝 NVIDIA Container Toolkit:
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \
&& curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
apt update
apt install -y nvidia-container-toolkit
安裝 Docker:
apt install -y docker.io
配置 Docker 使用 GPU:
nvidia-ctk runtime configure --runtime=docker
systemctl restart docker
執行以下命令拉取 ComfyUI 的映象:
docker pull registry.cn-guangzhou.aliyuncs.com/yangchuansheng/comfyui-boot:latest
這個映象比較大,需要多等待一會兒。
映象拉取完成後,再在當前目錄下建立一個 download.txt 檔案,內容如下:
# Stable Cascade
#https://huggingface.co/stabilityai/stable-cascade/resolve/main/comfyui_checkpoints/stable_cascade_stage_c.safetensors
# dir=models/checkpoints
# out=stable_cascade_stage_c.safetensors
#https://huggingface.co/stabilityai/stable-cascade/resolve/main/comfyui_checkpoints/stable_cascade_stage_b.safetensors
# dir=models/checkpoints
# out=stable_cascade_stage_b.safetensors
#https://huggingface.co/stabilityai/stable-cascade/resolve/main/controlnet/canny.safetensors
# dir=models/controlnet
# out=stable_cascade_canny.safetensors
#https://huggingface.co/stabilityai/stable-cascade/resolve/main/controlnet/inpainting.safetensors
# dir=models/controlnet
# out=stable_cascade_inpainting.safetensors
#https://huggingface.co/stabilityai/stable-cascade/resolve/main/controlnet/super_resolution.safetensors
# dir=models/controlnet
# out=stable_cascade_super_resolution.safetensors
# VAE
https://hf-mirror.com/stabilityai/sd-vae-ft-mse-original/resolve/main/vae-ft-mse-840000-ema-pruned.safetensors
dir=models/vae
out=vae-ft-mse-840000-ema-pruned.safetensors
https://hf-mirror.com/madebyollin/taesd/resolve/main/taesd_decoder.safetensors
dir=models/vae_approx
out=taesd_decoder.safetensors
https://hf-mirror.com/madebyollin/taesdxl/resolve/main/taesdxl_decoder.safetensors
dir=models/vae_approx
out=taesdxl_decoder.safetensors
# Upscale
https://mirror.ghproxy.com/https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.0/RealESRGAN_x4plus.pth
dir=models/upscale_models
out=RealESRGAN_x4plus.pth
https://mirror.ghproxy.com/https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.2.4/RealESRGAN_x4plus_anime_6B.pth
dir=models/upscale_models
out=RealESRGAN_x4plus_anime_6B.pth
https://hf-mirror.com/Kim2091/AnimeSharp/resolve/main/4x-AnimeSharp.pth
dir=models/upscale_models
out=4x-AnimeSharp.pth
https://hf-mirror.com/Kim2091/UltraSharp/resolve/main/4x-UltraSharp.pth
dir=models/upscale_models
out=4x-UltraSharp.pth
https://hf-mirror.com/gemasai/4x_NMKD-Siax_200k/resolve/main/4x_NMKD-Siax_200k.pth
dir=models/upscale_models
out=4x_NMKD-Siax_200k.pth
https://hf-mirror.com/uwg/upscaler/resolve/main/ESRGAN/4x_foolhardy_Remacri.pth
dir=models/upscale_models
out=4x_foolhardy_Remacri.pth
https://hf-mirror.com/uwg/upscaler/resolve/main/ESRGAN/8x_NMKD-Superscale_150000_G.pth
dir=models/upscale_models
out=8x_NMKD-Superscale_150000_G.pth
# Embeddings
https://hf-mirror.com/datasets/gsdf/EasyNegative/resolve/main/EasyNegative.safetensors
dir=models/embeddings
out=easynegative.safetensors
https://hf-mirror.com/lenML/DeepNegative/resolve/main/NG_DeepNegative_V1_75T.pt
dir=models/embeddings
out=ng_deepnegative_v1_75t.pt
# CLIP Vision
https://hf-mirror.com/openai/clip-vit-large-patch14/resolve/main/model.safetensors
dir=models/clip_vision
out=clip_vit14.safetensors
#https://huggingface.co/stabilityai/control-lora/resolve/main/revision/clip_vision_g.safetensors
# dir=models/clip_vision
# out=control-lora-clip_vision_g.safetensors
# unCLIP
#https://huggingface.co/stabilityai/stable-diffusion-2-1-unclip-small/resolve/main/image_encoder/model.safetensors
# dir=models/checkpoints
# out=stable-diffusion-2-1-unclip-small.safetensors
# ControlNet v1.1
# More models: https://huggingface.co/lllyasviel/sd_control_collection
https://hf-mirror.com/lllyasviel/ControlNet-v1-1/resolve/main/control_v11f1p_sd15_depth.pth
dir=models/controlnet
out=control_v11f1p_sd15_depth.pth
https://hf-mirror.com/lllyasviel/ControlNet-v1-1/resolve/main/control_v11p_sd15_canny.pth
dir=models/controlnet
out=control_v11p_sd15_canny.pth
https://hf-mirror.com/lllyasviel/ControlNet-v1-1/resolve/main/control_v11p_sd15_openpose.pth
dir=models/controlnet
out=control_v11p_sd15_openpose.pth
#https://huggingface.co/lllyasviel/ControlNet-v1-1/resolve/main/control_v11e_sd15_ip2p.pth
# dir=models/controlnet
# out=control_v11e_sd15_ip2p.pth
#https://huggingface.co/lllyasviel/ControlNet-v1-1/resolve/main/control_v11e_sd15_shuffle.pth
# dir=models/controlnet
# out=control_v11e_sd15_shuffle.pth
#https://huggingface.co/lllyasviel/ControlNet-v1-1/resolve/main/control_v11f1e_sd15_tile.pth
# dir=models/controlnet
# out=control_v11f1e_sd15_tile.pth
#https://huggingface.co/lllyasviel/ControlNet-v1-1/resolve/main/control_v11p_sd15_inpaint.pth
# dir=models/controlnet
# out=control_v11p_sd15_inpaint.pth
#https://huggingface.co/lllyasviel/ControlNet-v1-1/resolve/main/control_v11p_sd15_lineart.pth
# dir=models/controlnet
# out=control_v11p_sd15_lineart.pth
#https://huggingface.co/lllyasviel/ControlNet-v1-1/resolve/main/control_v11p_sd15_mlsd.pth
# dir=models/controlnet
# out=control_v11p_sd15_mlsd.pth
#https://huggingface.co/lllyasviel/ControlNet-v1-1/resolve/main/control_v11p_sd15_normalbae.pth
# dir=models/controlnet
# out=control_v11p_sd15_normalbae.pth
#https://huggingface.co/lllyasviel/ControlNet-v1-1/resolve/main/control_v11p_sd15_scribble.pth
# dir=models/controlnet
# out=control_v11p_sd15_scribble.pth
#https://huggingface.co/lllyasviel/ControlNet-v1-1/resolve/main/control_v11p_sd15_seg.pth
# dir=models/controlnet
# out=control_v11p_sd15_seg.pth
#https://huggingface.co/lllyasviel/ControlNet-v1-1/resolve/main/control_v11p_sd15_softedge.pth
# dir=models/controlnet
# out=control_v11p_sd15_softedge.pth
#https://huggingface.co/lllyasviel/ControlNet-v1-1/resolve/main/control_v11p_sd15s2_lineart_anime.pth
# dir=models/controlnet
# out=control_v11p_sd15s2_lineart_anime.pth
# Control-LoRA
#https://huggingface.co/stabilityai/control-lora/resolve/main/control-LoRAs-rank256/control-lora-canny-rank256.safetensors
# dir=models/controlnet
# out=control-lora-canny-rank256.safetensors
#https://huggingface.co/stabilityai/control-lora/resolve/main/control-LoRAs-rank256/control-lora-depth-rank256.safetensors
# dir=models/controlnet
# out=control-lora-depth-rank256.safetensors
#https://huggingface.co/stabilityai/control-lora/resolve/main/control-LoRAs-rank256/control-lora-recolor-rank256.safetensors
# dir=models/controlnet
# out=control-lora-recolor-rank256.safetensors
#https://huggingface.co/stabilityai/control-lora/resolve/main/control-LoRAs-rank256/control-lora-sketch-rank256.safetensors
# dir=models/controlnet
# out=control-lora-sketch-rank256.safetensors
建立本地儲存目錄並賦予許可權:
mkdir storage
chmod -R a+w storage
最後執行以下命令啟動容器:
docker run --restart always -d --net host --name comfyui --gpus all -p 8188:8188 -v "$(pwd)"/storage:/home/runner -v "$(pwd)"/download.txt:/home/scripts/download.txt -e CLI_ARGS="" registry.cn-guangzhou.aliyuncs.com/yangchuansheng/comfyui-boot:latest
容器啟動過程中,會下載各種必要的模型和節點,如果某個模型下載失敗,最終容器會重啟繼續進行下載,直到最後模型全部下載完成,耐心等待即可。
可以透過命令 docker logs -f comfyui
檢視啟動日誌,最終啟動成功日誌如下:
在瀏覽器位址列中輸入 <雲主機的公網地址>:8188
就可以訪問 ComfyUI 的 Web 介面了。
ComfyUI 的基礎配置
我們先來裝一個必備的節點。點選右下角的 “Manager”:
接著點選 “Install Custom Nodes”:
在搜尋框輸入 workspace 進行搜尋,然後點選 ComfyUI Workspace Manager - Comfyspace
右邊的 “Install” 按鈕進行安裝:
安裝完成後回到雲主機執行命令 systemctl restart docker
重啟容器,然後直接重新整理瀏覽器頁面,你會發現左上角多了幾個按鈕:
這個玩意就是用來管理各種工作流和模型的,非常好用。我們先來安裝 SD 最先進的模型 SDXL,直接點選左上角的 “Models”,然後點選 “Install Models”。
這裡面的模型都來自 C 站 (https://civitai.com),需要縱雲梯才能下載,我們的雲主機是沒法下載的。為了曲線救國,我們可以點選右上角的 “Cumstom URL Install”:
在彈出來的彈窗中輸入國內模型下載站的模型下載連結和模型儲存目錄:
- 模型連結:https://hf-mirror.com/stabilityai/stable-diffusion-xl-base-1.0/resolve/main/sd_xl_base_1.0.safetensors
- 模型儲存目錄:/home/runner/ComfyUI/models/checkpoints
然後點選 Confirm,左下角就會出現一個進度條開始下載模型,靜靜等待模型下載完成即可。如果下載速度過慢,可以換一個魔搭的下載連結繼續嘗試下載:https://modelscope.cn/api/v1/models/AI-ModelScope/stable-diffusion-xl-base-1.0/repo?Revision=master&FilePath=sd_xl_base_1.0.safetensors
模型下載完成後,關掉彈窗,點選右下角的 “Manager”:
然後點選 “Restart” 重啟服務:
關掉彈窗,多點選兩次右邊的 “Refresh” 按鈕:
現在你再點選下圖中我用紅框選出來的區域,就會出現你之前下載好的模型了:
接下來就是見證奇蹟的時刻,直接點選 “Queue prompt”:
頃刻之間,圖就畫好了,你可以在圖片上方點選滑鼠右鍵,然後點選 “Open Image” 來檢視大圖。
我們將圖片的高度和寬度改成 1024 再試試:
最終畫出來的圖更加高畫質:
ComfyUI 原理解析
秀完了肌肉,我們再來看看 ComfyUI 的工作原理。
ComfyUI 採用了視覺化程式設計的思路,將 Stable Diffusion 的各個功能模組以 “節點” 的形式呈現,使用者只需將節點用 “邊” 連線起來,就能自定義出一個完整的影像生成流程。
“節點” 代表特定的操作或函式,“邊” 將 “節點” 的輸出連線到另一節點的輸入。整個流程有點像一條生產線,原材料 (如文字提示) 在不同工位 (節點) 加工處理,最終生成成品 (如影像)。
每個節點上的術語看起來可能會很晦澀難懂,不用擔心,下面我以系統預設的工作流為例,按照生圖的順序依次來講解。
載入模型
首先要在 “Load Checkpoint” 節點中選擇預訓練的 SD Checkpoint 模型進行載入,單機其中的模型名稱即可顯示 ComfyUI 伺服器所有可用的模型列表。
如果節點太小,可以使用滑鼠滾輪或在觸控板上用兩根手指捏合來放大和縮小。
一個完整的 Stable Diffusion 模型由以下三個主要部分構成:
- 文字編碼器 (CLIP):一個將自然語言文字對映為潛在空間的神經網路。它使用 Contrastive Language-Image Pre-training (CLIP) 模型。
- 先驗/去噪模型 (UNet):一個 UNet 結構的神經網路,用於從潛在空間中的隨機噪聲影像出發,去噪生成與提示匹配的影像。這是整個生成過程的核心。
- 解碼器 (VAE):一個 Variational Autoencoder,用於在影像空間和潛在空間之間進行轉換。具體來說,編碼器將影像編碼為潛碼,解碼器將潛碼解碼回影像。
Load Checkpoint 節點會返回這三個元件,分別輸出到 CLIP、MODEL 和 VAE 埠,供下游節點使用。這有點像把一臺機器拆解成不同的功能模組。
輸入提示詞
接下來 CLIP 會連線到兩個 CLIP Text Encode 節點,這個節點會利用 CLIP 模型的文字編碼器部分,將輸入的文字提示轉換為一個潛在向量表示,也就是 “embedding”。
它會先將提示拆分為一系列 token,然後將這些 token 輸入 CLIP 的文字編碼器 (該編碼器是一個預訓練的 Transformer 語言模型)。編碼器會將這些 token 編譯成一個個的詞特徵向量。此步驟下會輸出 77 個等長的向量,每個向量包含 768 個維度。這個向量就可以指引後續的影像生成過程了。
我們可以將文字編碼過程理解為對食材進行切割、醃製等預處理,讓它們可以更好地融入最終的佳餚中。
在本工作流中,上面的 CLIP Text Encode 節點 CONDICTIONG 輸出連線到 KSampler 節點的 “正輸入”,所以它的提示詞是正向提示詞 (所謂正向提示詞,就是我想要什麼)。下面的 CLIP Text Encode 節點 CONDICTIONG 輸出連線到 KSampler 節點的 “負輸入”,所以它的提示詞是反向提示詞 (所謂反向提示詞,就是我不想要什麼)。
潛空間影像
接下來,這些特徵向量會和一張隨機圖 (可以簡單理解這是一張佈滿電子雪花的圖,或充滿資訊噪聲的圖) 一起被轉化到一個潛空間 (Latent Space) 裡。
潛空間影像 (latent image) 的尺寸通常小於最終生成影像的大小,但與之成正比。所以調整潛空間影像的寬高就可以控制最終影像的解析度。潛空間影像的畫素值是隨機取樣自標準正態分佈的。
我們可以將潛像類比為一塊 “畫布”,畫布的大小決定了最終作品的尺幅。開始時畫布上只有隨機的色塊,但它蘊含了千變萬化的可能,等待被創意的火花點燃。
在這裡你可以設定最終影像的高度和寬度,也可以設定生成的圖片數量 (預設是 1)。
生成影像
接下來,我們來到 KSampler 節點,這是整個工作流程中最關鍵核心的一個節點。KSampler 實現了擴散模型的迭代取樣過程,可以將上面的隨機潛空間影像根據文字提示詞生成最終的影像。
KSampler 使用的取樣演算法和排程器 (scheduler) 決定了每一步去噪的幅度和方式。不同的取樣器在速度和效果上都各有權衡。
在每個取樣步驟中,先將潛像輸入 VAE 解碼為普通影像,再和 CLIP 嵌入一起送入 UNet。UNet 會預測噪聲殘差,將其從潛像中減去一部分,從而讓影像更接近目標的提示語義。這個過程重複多個步驟,每一步去除一些噪聲,讓影像變得越來越清晰。
打個比方,取樣過程就像一位雕塑家在雕刻。最初她面對的是一塊毫無章法的石料,經過一點一點的鑿削打磨,漸漸顯露出美輪美奐的藝術品。每一錘一鑿都要拿捏分寸,避免破壞已有的成果。
所以與其說 SD 是在 “生成” 影像,不如說它是在 “雕刻” 影像。
世間所有的圖片都在一張充滿噪點的圖片裡,SD 只是將這張圖片裡不需要的部分都去掉了,剩下的部分就是你想要的圖片。
解碼影像
最終來到了 VAE Decode 節點,這個節點使用 VAE 的解碼器部分將最終的潛像解碼為常規的 RGB 影像。你可以將 VAE 類比為一個 “翻譯官”,它在抽象表徵空間和具象影像空間之間往復穿梭、翻譯。
具體來說,VAE 解碼器由一系列的轉置卷積 (transposed convolution) 層組成。它將潛像視作一個低解析度的特徵圖,透過上取樣 (upsampling) 和卷積操作,逐步將其解碼為高解析度的影像。在這個過程中,解碼器會學習填補細節,將抽象的表徵還原為豐富的視覺細節。
打個比方,如果將潛像看作建築的結構圖紙,那麼 VAE 解碼就像根據圖紙將大樓建造出來,為骨架添筋加肉,直至每個房間的裝潢都妥帖合宜,每扇窗戶都熠熠生輝。
怎麼樣,現在你應該能理解 ComfyUI 生圖的整個過程了吧?
生成更高質量的圖片
再來看一個稍微有億點點複雜的工作流,它充分利用了 SDXL 模型的優勢,做了很多調優工作,同時還用上了精煉模型使最終生成的圖片細節更加豐富。
感興趣的朋友可以自己先研究下,後續文章我將為大家講解其中的原理。
掃碼關注 Sealos 公眾號,後臺回覆 refiner 即可獲取該工作流。
如何匯入工作流呢?還記得一開始我讓你安裝的 ComfyUI Workspace Manager 節點嗎,這時候就派上用場了。點選左上角的資料夾圖示:
然後點選 "Import" 就可以匯入工作流了。
再來點刺激的:
喜歡麼?喜歡就關注公眾號,等我後續教程😁