在 Hugging Face Spaces 上使用 Gradio 免費執行 ComfyUI 工作流
目錄
- 引言
- 匯出你的 ComfyUI 工作流以在純 Python 環境中執行
- 為你的 ComfyUI 應用建立一個 Gradio 應用
- 準備在 Hugging Face Spaces 上執行
- 匯出到 Spaces 並在 ZeroGPU 上執行
- 結論
簡介
在本教程中,我將逐步介紹如何將一個複雜的 ComfyUI 工作流轉換為一個簡單的 Gradio 應用程式,以及如何將此應用程式部署在 Hugging Face Spaces 的 ZeroGPU 無伺服器架構上,從而實現免費的無伺服器部署和執行。在本教程中,我們將使用 Nathan Shipley 的 Flux[dev] Redux + Flux[dev] Depth ComfyUI 工作流,但你也可以使用任何你喜歡的工作流來學習本教程。
本教程將涵蓋的內容摘要如下:
- 使用
ComfyUI-to-Python-Extension
匯出你的 ComfyUI 工作流; - 為匯出的 Python 建立一個 Gradio 應用;
- 在 Hugging Face Spaces 上使用 ZeroGPU 進行部署;
- 即將推出:整個過程將實現自動化;
先決條件
- 瞭解如何執行 ComfyUI:本教程要求你能夠獲取一個 ComfyUI 工作流並在你的機器上執行它,包括安裝缺失的節點和找到缺失的模型(不過我們計劃很快將這一步自動化);
- 將你想要匯出的工作流準備好並執行(如果你想在沒有特定工作流的情況下學習,可以隨時獲取 Nathan Shipley 的 Flux[dev] Redux + Flux[dev] Depth ComfyUI 工作流 並讓它執行起來);
- 一點點程式設計知識:但我鼓勵初學者嘗試學習,因為這可以作為一個很好的 Python、Gradio 和 Spaces 入門教程,不需要太多先前的程式設計知識。
(如果你正在尋找一個端到端的“工作流到應用”的結構,而不需要設定和執行 ComfyUI 或瞭解程式設計,請在 Hugging Face 或 Twitter/X 上關注我的個人資料,我們計劃在 2025 年初實現這一目標!)。
1. 匯出你的 ComfyUI 工作流以在純 Python 環境中執行
ComfyUI 非常棒,顧名思義,它包含一個使用者介面 (UI)。但 Comfy 遠不止一個 UI,它還包含自己基於 Python 的後端。由於本教程的目的不是使用 Comfy 的基於節點的 UI,我們需要將程式碼匯出為純 Python 指令碼來執行。
幸運的是,Peyton DeNiro 建立了這款令人難以置信的 ComfyUI-to-Python-Extension 擴充套件,它可以將任何 Comfy 工作流匯出為 Python 指令碼,讓你無需啟動 UI 即可執行工作流。
安裝此擴充套件最簡單的方法是 (1) 在 ComfyUI Manager 擴充套件的自定義節點管理器選單中搜索 ComfyUI to Python Extension
並 (2) 安裝它。然後,要讓該選項出現,你需要 (3) 進入 UI 右下角的設定,(4) 停用新選單,然後 (5) 點選 Save as Script
。這樣,你就會得到一個 Python 指令碼。
2. 為匯出的 Python 建立一個 Gradio 應用
現在我們有了 Python 指令碼,是時候為它建立一個 Gradio 應用了。Gradio 是一個 Python 原生的 Web-UI 構建器,可以讓我們建立流暢的應用程式。如果你還沒有安裝,可以在你的 Python 環境中使用 pip install gradio
進行安裝。
接下來,我們需要稍微重新安排一下我們的 Python 指令碼來為它建立一個 UI。
提示:像 ChatGPT、Claude、Qwen、Gemini、Llama 3 等大型語言模型都知道如何建立 Gradio 應用。將你匯出的 Python 指令碼貼上給它,並要求它建立一個 Gradio 應用,基本上是可行的,但你可能需要利用本教程中學到的知識進行一些修正。為了本教程的目的,我們將自己建立應用程式。
開啟匯出的 Python 指令碼並新增 Gradio 的匯入語句。
import os
import random
import sys
from typing import Sequence, Mapping, Any, Union
import torch
+ import gradio as gr
現在,我們需要考慮 UI——我們希望在 UI 中暴露覆雜的 ComfyUI 工作流中的哪些引數?對於 Flux[dev] Redux + Flux[dev] Depth ComfyUI 工作流
,我希望暴露:提示詞、結構影像、風格影像、深度強度(用於結構)和風格強度。
影片演示了哪些節點將暴露給終端使用者
為此,一個最小的 Gradio 應用將是
if __name__ == "__main__":
# Comment out the main() call in the exported Python code
# Start your Gradio app
with gr.Blocks() as app:
# Add a title
gr.Markdown("# FLUX Style Shaping")
with gr.Row():
with gr.Column():
# Add an input
prompt_input = gr.Textbox(label="Prompt", placeholder="Enter your prompt here...")
# Add a `Row` to include the groups side by side
with gr.Row():
# First group includes structure image and depth strength
with gr.Group():
structure_image = gr.Image(label="Structure Image", type="filepath")
depth_strength = gr.Slider(minimum=0, maximum=50, value=15, label="Depth Strength")
# Second group includes style image and style strength
with gr.Group():
style_image = gr.Image(label="Style Image", type="filepath")
style_strength = gr.Slider(minimum=0, maximum=1, value=0.5, label="Style Strength")
# The generate button
generate_btn = gr.Button("Generate")
with gr.Column():
# The output image
output_image = gr.Image(label="Generated Image")
# When clicking the button, it will trigger the `generate_image` function, with the respective inputs
# and the output an image
generate_btn.click(
fn=generate_image,
inputs=[prompt_input, structure_image, style_image, depth_strength, style_strength],
outputs=[output_image]
)
app.launch(share=True)
這是應用渲染後的樣子
但如果你嘗試執行它,它還不能工作,因為我們現在需要透過修改我們匯出的 Python 的 def main()
函式來設定這個 generate_image
函式
指令碼
- def main():
+ def generate_image(prompt, structure_image, style_image, depth_strength, style_strength)
在函式內部,我們需要找到我們想要的節點的硬編碼值,並用我們想要控制的變數替換它,例如
loadimage_429 = loadimage.load_image(
- image="7038548d-d204-4810-bb74-d1dea277200a.png"
+ image=structure_image
)
# ...
loadimage_440 = loadimage.load_image(
- image="2013_CKS_01180_0005_000(the_court_of_pir_budaq_shiraz_iran_circa_1455-60074106).jpg"
+ image=style_image
)
# ...
fluxguidance_430 = fluxguidance.append(
- guidance=15,
+ guidance=depth_strength,
conditioning=get_value_at_index(cliptextencode_174, 0)
)
# ...
stylemodelapplyadvanced_442 = stylemodelapplyadvanced.apply_stylemodel(
- strength=0.5,
+ strength=style_strength,
conditioning=get_value_at_index(instructpixtopixconditioning_431, 0),
style_model=get_value_at_index(stylemodelloader_441, 0),
clip_vision_output=get_value_at_index(clipvisionencode_439, 0),
)
# ...
cliptextencode_174 = cliptextencode.encode(
- text="a girl looking at a house on fire",
+ text=prompt,
clip=get_value_at_index(cr_clip_input_switch_319, 0),
)
對於我們的輸出,我們需要找到儲存影像的輸出節點,並匯出其路徑,例如
saveimage_327 = saveimage.save_images(
filename_prefix=get_value_at_index(cr_text_456, 0),
images=get_value_at_index(vaedecode_321, 0),
)
+ saved_path = f"output/{saveimage_327['ui']['images'][0]['filename']}"
+ return saved_path
觀看這些修改的影片演示
現在,我們應該準備好執行程式碼了!將你的 Python 檔案另存為 app.py
,將其新增到你的 ComfyUI 資料夾的根目錄,然後執行它:
python app.py
就這樣,你應該能夠在 http://0.0.0.0:7860 上執行你的 Gradio 應用了。
* Running on local URL: http://127.0.0.1:7860
* Running on public URL: https://366fdd17b8a9072899.gradio.live
要除錯此過程,請檢視此處 ComfyUI-to-Python-Extension
匯出的原始 Python 檔案與 Gradio 應用之間的差異。你也可以在該 URL 下載這兩個檔案,以便與你自己的工作流進行檢查和比較。
就是這樣,恭喜!你成功地將你的 ComfyUI 工作流轉換為了一個 Gradio 應用。你可以在本地執行它,甚至可以將 URL 傳送給客戶或朋友。然而,如果你關閉計算機或 72 小時後,臨時的 Gradio 連結將會失效。要獲得一個持久的託管應用結構——包括允許人們以無伺服器方式免費執行它,你可以使用 Hugging Face Spaces。
3. 準備在 Hugging Face Spaces 上執行
現在我們的 Gradio 演示可以工作了,我們可能會想直接把所有東西上傳到 Hugging Face Spaces。然而,這將需要上傳數十 GB 的模型到 Hugging Face,這不僅速度慢,而且沒有必要,因為所有這些模型都已經存在於 Hugging Face 上了!
相反,我們首先需要安裝 pip install huggingface_hub
(如果還沒有的話),然後在我們的 app.py
檔案頂部執行以下操作:
from huggingface_hub import hf_hub_download
hf_hub_download(repo_id="black-forest-labs/FLUX.1-Redux-dev", filename="flux1-redux-dev.safetensors", local_dir="models/style_models")
hf_hub_download(repo_id="black-forest-labs/FLUX.1-Depth-dev", filename="flux1-depth-dev.safetensors", local_dir="models/diffusion_models")
hf_hub_download(repo_id="Comfy-Org/sigclip_vision_384", filename="sigclip_vision_patch14_384.safetensors", local_dir="models/clip_vision")
hf_hub_download(repo_id="Kijai/DepthAnythingV2-safetensors", filename="depth_anything_v2_vitl_fp32.safetensors", local_dir="models/depthanything")
hf_hub_download(repo_id="black-forest-labs/FLUX.1-dev", filename="ae.safetensors", local_dir="models/vae/FLUX1")
hf_hub_download(repo_id="comfyanonymous/flux_text_encoders", filename="clip_l.safetensors", local_dir="models/text_encoders")
hf_hub_download(repo_id="comfyanonymous/flux_text_encoders", filename="t5xxl_fp16.safetensors", local_dir="models/text_encoders/t5")
這會將 ComfyUI 上的所有本地模型對映到它們的 Hugging Face 版本。不幸的是,目前沒有辦法自動化這個過程,你需要找到你工作流中模型在 Hugging Face 上的位置,並將它對映到相同的 ComfyUI 資料夾。
如果你正在執行的模型不在 Hugging Face 上,你需要找到一種方法透過 Python 程式碼以程式設計方式將它們下載到正確的資料夾。這將在 Hugging Face Space 啟動時只執行一次。
現在,我們將對 app.py
檔案進行最後一次修改,即包含 ZeroGPU 的函式裝飾器,這將讓我們免費進行推理!
import gradio as gr
from huggingface_hub import hf_hub_download
+ import spaces
# ...
+ @spaces.GPU(duration=60) #modify the duration for the average it takes for your worflow to run, in seconds
def generate_image(prompt, structure_image, style_image, depth_strength, style_strength):
在此處檢視差異,瞭解之前 Gradio 演示版本與為 Spaces 準備的更改之間的區別。
4. 匯出到 Spaces 並在 ZeroGPU 上執行
程式碼已準備就緒——你可以在本地或任何你喜歡的雲服務上執行它——包括專用的 Hugging Face Spaces GPU。但要在一個無伺服器的 ZeroGPU 上執行,請繼續閱讀下文。
修正依賴項
首先,你需要修改你的 requirements.txt
檔案,以包含 custom_nodes
資料夾中的依賴項。由於 Hugging Face Spaces 需要一個單一的 requirements.txt
檔案,請確保將該工作流所需的節點依賴項新增到根資料夾的 requirements.txt
檔案中。
請看下面的圖示,對所有 custom_nodes
都需要重複相同的過程
現在我們準備好了!
- 前往 https://huggingface.co 並建立一個新的 Space。
- 將其硬體設定為 ZeroGPU(如果你是 Hugging Face PRO 訂閱使用者)或設定為 CPU basic(如果你不是 PRO 使用者,最後需要額外一個步驟)。2.1 (如果你更喜歡付費的專用 GPU,可以選擇 L4、L40S、A100 而不是 ZeroGPU,這是一個付費選項)
- 點選“檔案”選項卡,選擇“新增檔案” > “上傳檔案”。拖動你所有 ComfyUI 資料夾中的檔案,除了
models
資料夾(如果你試圖上傳models
資料夾,你的上傳將會失敗),這就是為什麼我們需要第三部分的原因。 - 點選頁面底部的
Commit changes to main
按鈕,等待所有檔案上傳完成。 - 如果你正在使用受限模型(gated models),比如 FLUX,你需要在設定中新增一個 Hugging Face 令牌。首先,在這裡建立一個對所有你需要的受限模型具有
讀取
許可權的令牌,然後進入你 Space 的設定
頁面,建立一個名為HF_TOKEN
的新 secret,其值為你剛剛建立的令牌。
將模型移出裝飾器函式(僅限 ZeroGPU)
你的演示應該已經可以運行了,然而,在當前的設定下,每次執行時模型都會從磁碟完全載入到 GPU。為了利用無伺服器 ZeroGPU 的效率,我們需要將所有模型宣告移出被裝飾的函式,放到 Python 的全域性上下文中。讓我們編輯 app.py
檔案來實現這一點。
@@ -4,6 +4,7 @@
from typing import Sequence, Mapping, Any, Union
import torch
import gradio as gr
from huggingface_hub import hf_hub_download
+from comfy import model_management
import spaces
hf_hub_download(repo_id="black-forest-labs/FLUX.1-Redux-dev", filename="flux1-redux-dev.safetensors", local_dir="models/style_models")
@@ -109,6 +110,62 @@
from nodes import NODE_CLASS_MAPPINGS
+intconstant = NODE_CLASS_MAPPINGS["INTConstant"]()
+dualcliploader = NODE_CLASS_MAPPINGS["DualCLIPLoader"]()
+dualcliploader_357 = dualcliploader.load_clip(
+ clip_name1="t5/t5xxl_fp16.safetensors",
+ clip_name2="clip_l.safetensors",
+ type="flux",
+)
+cr_clip_input_switch = NODE_CLASS_MAPPINGS["CR Clip Input Switch"]()
+cliptextencode = NODE_CLASS_MAPPINGS["CLIPTextEncode"]()
+loadimage = NODE_CLASS_MAPPINGS["LoadImage"]()
+imageresize = NODE_CLASS_MAPPINGS["ImageResize+"]()
+getimagesizeandcount = NODE_CLASS_MAPPINGS["GetImageSizeAndCount"]()
+vaeloader = NODE_CLASS_MAPPINGS["VAELoader"]()
+vaeloader_359 = vaeloader.load_vae(vae_name="FLUX1/ae.safetensors")
+vaeencode = NODE_CLASS_MAPPINGS["VAEEncode"]()
+unetloader = NODE_CLASS_MAPPINGS["UNETLoader"]()
+unetloader_358 = unetloader.load_unet(
+ unet_name="flux1-depth-dev.safetensors", weight_dtype="default"
+)
+ksamplerselect = NODE_CLASS_MAPPINGS["KSamplerSelect"]()
+randomnoise = NODE_CLASS_MAPPINGS["RandomNoise"]()
+fluxguidance = NODE_CLASS_MAPPINGS["FluxGuidance"]()
+depthanything_v2 = NODE_CLASS_MAPPINGS["DepthAnything_V2"]()
+downloadandloaddepthanythingv2model = NODE_CLASS_MAPPINGS[
+ "DownloadAndLoadDepthAnythingV2Model"
+]()
+downloadandloaddepthanythingv2model_437 = (
+ downloadandloaddepthanythingv2model.loadmodel(
+ model="depth_anything_v2_vitl_fp32.safetensors"
+ )
+)
+instructpixtopixconditioning = NODE_CLASS_MAPPINGS[
+ "InstructPixToPixConditioning"
+]()
+text_multiline_454 = text_multiline.text_multiline(text="FLUX_Redux")
+clipvisionloader = NODE_CLASS_MAPPINGS["CLIPVisionLoader"]()
+clipvisionloader_438 = clipvisionloader.load_clip(
+ clip_name="sigclip_vision_patch14_384.safetensors"
+)
+clipvisionencode = NODE_CLASS_MAPPINGS["CLIPVisionEncode"]()
+stylemodelloader = NODE_CLASS_MAPPINGS["StyleModelLoader"]()
+stylemodelloader_441 = stylemodelloader.load_style_model(
+ style_model_name="flux1-redux-dev.safetensors"
+)
+text_multiline = NODE_CLASS_MAPPINGS["Text Multiline"]()
+emptylatentimage = NODE_CLASS_MAPPINGS["EmptyLatentImage"]()
+cr_conditioning_input_switch = NODE_CLASS_MAPPINGS[
+ "CR Conditioning Input Switch"
+]()
+cr_model_input_switch = NODE_CLASS_MAPPINGS["CR Model Input Switch"]()
+stylemodelapplyadvanced = NODE_CLASS_MAPPINGS["StyleModelApplyAdvanced"]()
+basicguider = NODE_CLASS_MAPPINGS["BasicGuider"]()
+basicscheduler = NODE_CLASS_MAPPINGS["BasicScheduler"]()
+samplercustomadvanced = NODE_CLASS_MAPPINGS["SamplerCustomAdvanced"]()
+vaedecode = NODE_CLASS_MAPPINGS["VAEDecode"]()
+saveimage = NODE_CLASS_MAPPINGS["SaveImage"]()
+imagecrop = NODE_CLASS_MAPPINGS["ImageCrop+"]()
@@ -117,75 +174,6 @@
def generate_image(prompt, structure_image, style_image, depth_strength, style_strength):
import_custom_nodes()
with torch.inference_mode():
- intconstant = NODE_CLASS_MAPPINGS["INTConstant"]()
intconstant_83 = intconstant.get_value(value=1024)
intconstant_84 = intconstant.get_value(value=1024)
- dualcliploader = NODE_CLASS_MAPPINGS["DualCLIPLoader"]()
- dualcliploader_357 = dualcliploader.load_clip(
- clip_name1="t5/t5xxl_fp16.safetensors",
- clip_name2="clip_l.safetensors",
- type="flux",
- )
-
- cr_clip_input_switch = NODE_CLASS_MAPPINGS["CR Clip Input Switch"]()
cr_clip_input_switch_319 = cr_clip_input_switch.switch(
Input=1,
clip1=get_value_at_index(dualcliploader_357, 0),
clip2=get_value_at_index(dualcliploader_357, 0),
)
- cliptextencode = NODE_CLASS_MAPPINGS["CLIPTextEncode"]()
cliptextencode_174 = cliptextencode.encode(
text=prompt,
clip=get_value_at_index(cr_clip_input_switch_319, 0),
)
cliptextencode_175 = cliptextencode.encode(
text="purple", clip=get_value_at_index(cr_clip_input_switch_319, 0)
)
- loadimage = NODE_CLASS_MAPPINGS["LoadImage"]()
loadimage_429 = loadimage.load_image(image=structure_image)
- imageresize = NODE_CLASS_MAPPINGS["ImageResize+"]()
imageresize_72 = imageresize.execute(
width=get_value_at_index(intconstant_83, 0),
height=get_value_at_index(intconstant_84, 0),
interpolation="bicubic",
method="keep proportion",
condition="always",
multiple_of=16,
image=get_value_at_index(loadimage_429, 0),
)
- getimagesizeandcount = NODE_CLASS_MAPPINGS["GetImageSizeAndCount"]()
getimagesizeandcount_360 = getimagesizeandcount.getsize(
image=get_value_at_index(imageresize_72, 0)
)
- vaeloader = NODE_CLASS_MAPPINGS["VAELoader"]()
- vaeloader_359 = vaeloader.load_vae(vae_name="FLUX1/ae.safetensors")
- vaeencode = NODE_CLASS_MAPPINGS["VAEEncode"]()
vaeencode_197 = vaeencode.encode(
pixels=get_value_at_index(getimagesizeandcount_360, 0),
vae=get_value_at_index(vaeloader_359, 0),
)
- unetloader = NODE_CLASS_MAPPINGS["UNETLoader"]()
- unetloader_358 = unetloader.load_unet(
- unet_name="flux1-depth-dev.safetensors", weight_dtype="default"
- )
- ksamplerselect = NODE_CLASS_MAPPINGS["KSamplerSelect"]()
ksamplerselect_363 = ksamplerselect.get_sampler(sampler_name="euler")
- randomnoise = NODE_CLASS_MAPPINGS["RandomNoise"]()
randomnoise_365 = randomnoise.get_noise(noise_seed=random.randint(1, 2**64))
- fluxguidance = NODE_CLASS_MAPPINGS["FluxGuidance"]()
fluxguidance_430 = fluxguidance.append(
guidance=15, conditioning=get_value_at_index(cliptextencode_174, 0)
)
- downloadandloaddepthanythingv2model = NODE_CLASS_MAPPINGS[
- "DownloadAndLoadDepthAnythingV2Model"
- ]()
- downloadandloaddepthanythingv2model_437 = (
- downloadandloaddepthanythingv2model.loadmodel(
- model="depth_anything_v2_vitl_fp32.safetensors"
- )
- )
- depthanything_v2 = NODE_CLASS_MAPPINGS["DepthAnything_V2"]()
depthanything_v2_436 = depthanything_v2.process(
da_model=get_value_at_index(downloadandloaddepthanythingv2model_437, 0),
images=get_value_at_index(getimagesizeandcount_360, 0),
)
- instructpixtopixconditioning = NODE_CLASS_MAPPINGS[
- "InstructPixToPixConditioning"
- ]()
instructpixtopixconditioning_431 = instructpixtopixconditioning.encode(
positive=get_value_at_index(fluxguidance_430, 0),
negative=get_value_at_index(cliptextencode_175, 0),
vae=get_value_at_index(vaeloader_359, 0),
pixels=get_value_at_index(depthanything_v2_436, 0),
)
- clipvisionloader = NODE_CLASS_MAPPINGS["CLIPVisionLoader"]()
- clipvisionloader_438 = clipvisionloader.load_clip(
- clip_name="sigclip_vision_patch14_384.safetensors"
- )
loadimage_440 = loadimage.load_image(image=style_image)
- clipvisionencode = NODE_CLASS_MAPPINGS["CLIPVisionEncode"]()
clipvisionencode_439 = clipvisionencode.encode(
crop="center",
clip_vision=get_value_at_index(clipvisionloader_438, 0),
image=get_value_at_index(loadimage_440, 0),
)
- stylemodelloader = NODE_CLASS_MAPPINGS["StyleModelLoader"]()
- stylemodelloader_441 = stylemodelloader.load_style_model(
- style_model_name="flux1-redux-dev.safetensors"
- )
-
- text_multiline = NODE_CLASS_MAPPINGS["Text Multiline"]()
text_multiline_454 = text_multiline.text_multiline(text="FLUX_Redux")
- emptylatentimage = NODE_CLASS_MAPPINGS["EmptyLatentImage"]()
- cr_conditioning_input_switch = NODE_CLASS_MAPPINGS[
- "CR Conditioning Input Switch"
- ]()
- cr_model_input_switch = NODE_CLASS_MAPPINGS["CR Model Input Switch"]()
- stylemodelapplyadvanced = NODE_CLASS_MAPPINGS["StyleModelApplyAdvanced"]()
- basicguider = NODE_CLASS_MAPPINGS["BasicGuider"]()
- basicscheduler = NODE_CLASS_MAPPINGS["BasicScheduler"]()
- samplercustomadvanced = NODE_CLASS_MAPPINGS["SamplerCustomAdvanced"]()
- vaedecode = NODE_CLASS_MAPPINGS["VAEDecode"]()
- saveimage = NODE_CLASS_MAPPINGS["SaveImage"]()
- imagecrop = NODE_CLASS_MAPPINGS["ImageCrop+"]()
emptylatentimage_10 = emptylatentimage.generate(
width=get_value_at_index(imageresize_72, 1),
height=get_value_at_index(imageresize_72, 2),
batch_size=1,
)
此外,為了預載入模型,我們需要使用 ComfyUI 的 load_models_gpu
函式,該函式將從上述預載入的模型中載入所有已載入的模型(一個好的經驗法則是,檢查上面哪些載入了 *.safetensors
檔案)
from comfy import model_management
#Add all the models that load a safetensors file
model_loaders = [dualcliploader_357, vaeloader_359, unetloader_358, clipvisionloader_438, stylemodelloader_441, downloadandloaddepthanythingv2model_437]
# Check which models are valid and how to best load them
valid_models = [
getattr(loader[0], 'patcher', loader[0])
for loader in model_loaders
if not isinstance(loader[0], dict) and not isinstance(getattr(loader[0], 'patcher', None), dict)
]
#Finally loads the models
model_management.load_models_gpu(valid_models)
檢視差異以準確瞭解哪些地方發生了變化。
如果你不是 PRO 訂閱使用者(如果你是,請跳過此步驟)
如果你不是 Hugging Face PRO 訂閱使用者,你需要申請 ZeroGPU 贊助。你可以很容易地在你的 Space 的設定頁面提交 ZeroGPU 贊助申請。所有使用 ComfyUI 後端的 Spaces 的 ZeroGPU 贊助申請都將被批准 🎉。
演示正在執行
我們用本教程構建的演示已在 Hugging Face Spaces 上線。來這裡體驗一下吧:https://huggingface.co/spaces/multimodalart/flux-style-shaping
5. 總結
😮💨,就這些了!我知道這有點工作量,但回報是你可以用一個簡單的 UI 和免費的推理能力輕鬆地與每個人分享你的工作流!如前所述,我們的目標是在 2025 年初儘可能地自動化和簡化這個過程!節日快樂 🎅✨