فِهرِس:

مقدمة

سأقدم في هذا البرنامج التعليمي دليلًا خطوة بخطوة حول كيفية تحويل سير عمل ComfyUI المعقد إلى تطبيق Gradio بسيط، وكيفية نشر هذا التطبيق على البنية بدون خادم Hugging Face Spaces ZeroGPU، والتي تسمح بنشره وتشغيله مجانًا بطريقة بدون خادم. في هذا البرنامج التعليمي، سنعمل مع Flux الخاص بـ Nathan Shipley[dev] الإعادة + الجريان[dev] سير عمل Depth ComfyUI، ولكن يمكنك متابعة البرنامج التعليمي مع أي سير عمل تريده.

مريح إلى غراديو

ملخص tl;dr لما سنغطيه في هذا البرنامج التعليمي هو:

  1. قم بتصدير سير عمل ComfyUI الخاص بك باستخدام ComfyUI-to-Python-Extension;
  2. إنشاء تطبيق Gradio لـ Python المصدرة؛
  3. انشره على مساحات الوجه المعانقة باستخدام ZeroGPU؛
  4. قريبًا: سيتم أتمتة هذه العملية برمتها؛

المتطلبات الأساسية

  • معرفة كيفية تشغيل ComfyUI: يتطلب هذا البرنامج التعليمي أن تكون قادرًا على الحصول على سير عمل ComfyUI وتشغيله على جهازك، وتثبيت العقد المفقودة والعثور على النماذج المفقودة (نحن نخطط لأتمتة هذه الخطوة قريبًا)؛
  • الحصول على سير العمل الذي ترغب في تصديره وتشغيله (إذا كنت تريد التعلم دون وضع سير العمل في الاعتبار، فلا تتردد في الحصول على Nathan Shipley’s Flux[dev] الإعادة + الجريان[dev] عمق سير العمل ComfyUI وتشغيله)؛
  • القليل من المعرفة بالبرمجة: لكنني أشجع المبتدئين على محاولة متابعتها، لأنها يمكن أن تكون مقدمة رائعة حقًا لـ Python وGradio وSpaces دون الحاجة إلى الكثير من المعرفة البرمجية المسبقة.

(إذا كنت تبحث عن بنية “سير العمل إلى التطبيق” شاملة، دون الحاجة إلى إعداد Comfy وتشغيله أو معرفة البرمجة، فابق على اطلاع على ملفي الشخصي على Hugging Face أو تويتر/X ونحن نخطط للقيام بذلك في أوائل عام 2025!).

1. تصدير سير عمل ComfyUI الخاص بك ليعمل على لغة Python النقية

ComfyUI رائع، وكما يشير الاسم، فهو يحتوي على واجهة مستخدم. لكن Comfy هو أكثر من مجرد واجهة مستخدم، فهو يحتوي على الواجهة الخلفية الخاصة به والتي تعمل على لغة Python. نظرًا لأننا لا نريد استخدام واجهة المستخدم المستندة إلى العقدة الخاصة بـ Comfy لأغراض هذا البرنامج التعليمي، فنحن بحاجة إلى تصدير الكود ليتم تشغيله على لغة python النقية.

لحسن الحظ، قام Peyton DeNiro بإنشاء ComfyUI-to-Python-Extension المذهل الذي يصدر أي سير عمل Comfy إلى نص برمجي بلغة python، مما يتيح لك تشغيل سير العمل دون تشغيل واجهة المستخدم.

مريح إلى غراديو

أسهل طريقة لتثبيت الامتداد هي (1) البحث عن ComfyUI to Python Extension في قائمة Custom Nodes Manager الخاصة بملحق ComfyUI Manager و(2) تثبيته. بعد ذلك، لكي يظهر الخيار، عليك (3) الانتقال إلى الإعدادات في أسفل يمين واجهة المستخدم، (4) تعطيل القائمة الجديدة و(5) الضغط على Save as Script. وبذلك، سينتهي بك الأمر مع برنامج Python النصي.

2. قم بإنشاء تطبيق Gradio لـ Python المصدرة

الآن بعد أن أصبح لدينا نص Python الخاص بنا، فقد حان الوقت لإنشاء تطبيق Gradio الخاص بنا والذي سيقوم بتنسيقه. Gradio هو منشئ واجهة مستخدم الويب الأصلي بلغة python والذي يسمح لنا بإنشاء تطبيقات مبسطة. إذا لم يكن لديك بالفعل، فيمكنك تثبيته على بيئة Python الخاصة بك باستخدام pip install gradio

بعد ذلك، سيتعين علينا إعادة ترتيب نص بايثون الخاص بنا قليلاً لإنشاء واجهة مستخدم له.

نصيحة: يعرف حاملو شهادات الماجستير مثل 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

الآن، نحن بحاجة إلى التفكير في واجهة المستخدم – ما هي المعلمات من سير عمل ComfyUI المعقد الذي نريد عرضه في واجهة المستخدم الخاصة بنا؟ ل Flux[dev] Redux + Flux[dev] Depth ComfyUI workflow، أود أن أكشف: الموجه، وصورة الهيكل، وصورة النمط، وقوة العمق (للهيكل) وقوة النمط.

لذلك، سيكون الحد الأدنى من تطبيق Gradio هو:

if __name__ == "__main__":
    
    
    
    with gr.Blocks() as app:
        
        gr.Markdown("# FLUX Style Shaping")

        with gr.Row():
            with gr.Column():
                
                prompt_input = gr.Textbox(label="Prompt", placeholder="Enter your prompt here...")
                
                with gr.Row():
                    
                    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")
                    
                    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")
                
                
                generate_btn = gr.Button("Generate")
            
            with gr.Column():
                
                output_image = gr.Image(label="Generated 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)

هذه هي الطريقة التي يبدو بها التطبيق بمجرد عرضه

مريح لواجهة المستخدم إلى Gradio

ولكن إذا حاولت تشغيله، فلن يعمل بعد، حيث نحتاج الآن إلى إعداده generate_image وظيفة عن طريق تغيير def main() وظيفة بيثون المصدرة لدينا

البرنامج النصي:

- 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

تحقق من ملخص الفيديو لهذه التعديلات:

الآن، يجب أن نكون جاهزين لتشغيل الكود! احفظ ملف بايثون الخاص بك باسم app.py، قم بإضافته إلى جذر مجلد ComfyUI الخاص بك وتشغيله باسم

python app.py

وبهذه الطريقة، يجب أن تكون قادرًا على تشغيل تطبيق Gradio على http://0.0.0.0:7860

* Running on local URL:  http://127.0.0.1:7860
* Running on public URL: https://366fdd17b8a9072899.gradio.live

لتصحيح هذه العملية، تحقق هنا من الفرق بين ملف بايثون الأصلي الذي تم تصديره بواسطة ComfyUI-to-Python-Extension وتطبيق غراديو. يمكنك تنزيل كليهما على عنوان URL هذا أيضًا للتحقق من سير العمل الخاص بك ومقارنته.

هذا كل شيء، تهانينا! لقد تمكنت من تحويل سير عمل ComfyUI إلى تطبيق Gradio. يمكنك تشغيله محليًا أو حتى إرسال عنوان URL إلى عميل أو صديق، ومع ذلك، إذا قمت بإيقاف تشغيل جهاز الكمبيوتر الخاص بك أو إذا مرت 72 ساعة، فسوف يتوقف رابط Gradio المؤقت. للحصول على بنية ثابتة لاستضافة التطبيق – بما في ذلك السماح للأشخاص بتشغيله مجانًا بطريقة بدون خادم، يمكنك استخدام Hugging Face Spaces.

3. تهيئته لتشغيل مساحات الوجه المعانقة

الآن مع عمل العرض التوضيحي لـ Gradio، قد نشعر بالإغراء لتحميل كل شيء إلى Hugging Face Spaces. ومع ذلك، قد يتطلب هذا تحميل عشرات الجيجابايت من النماذج إلى 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 المخصصة. ولكن لتشغيله على ZeroGPU بدون خادم، اتبع أدناه.

إصلاح المتطلبات

أولا، تحتاج إلى تعديل الخاص بك requirements.txt لتضمين المتطلبات في custom_nodes المجلد. حيث أن مساحات الوجه المعانقة تتطلب واحدة requirements.txt الملف، تأكد من إضافة متطلبات العقد لسير العمل هذا إلى ملف requirements.txt على المجلد الجذر.

انظر الرسم التوضيحي أدناه، يجب تكرار نفس العملية للجميع custom_nodes:

الآن نحن جاهزون!

إنشاء مساحة

  1. انتقل إلى https://huggingface.co وقم بإنشاء مساحة جديدة.
  2. اضبط أجهزته على ZeroGPU (إذا كنت مشتركًا في Hugging Face PRO) أو اضبطه على وحدة المعالجة المركزية الأساسية إذا لم تكن مستخدمًا محترفًا (ستحتاج إلى خطوة إضافية في النهاية إذا لم تكن محترفًا). 2.1 (إذا كنت تفضل وحدة معالجة الرسومات المخصصة التي تدفع ثمنها، فاختر L4، وL40S، وA100 بدلاً من ZeroGPU، فهذا خيار مدفوع)
  3. انقر فوق علامة التبويب “الملفات”، ثم “إضافة”. File > Upload Files. اسحب جميع ملفات مجلد ComfyUI الخاصة بك يستثني ال models المجلد (إذا حاولت تحميل ملف models المجلد، سيفشل التحميل)، ولهذا السبب نحتاج إلى الجزء 3.
  4. انقر فوق Commit changes to main الزر الموجود أسفل الصفحة وانتظر حتى يتم تحميل كل شيء
  5. إذا كنت تستخدم نماذج مسورة، مثل FLUX، فستحتاج إلى تضمين رمز Hugging Face المميز في الإعدادات. أولاً، قم بإنشاء رمز مميز باستخدام read الوصول إلى جميع النماذج المسورة التي تحتاجها هنا، ثم انتقل إلى Settings صفحة مساحتك الخاصة وأنشئ سرًا جديدًا باسم HF_TOKEN بقيمة الرمز المميز الذي قمت بإنشائه للتو.

المتغيرات والأسرار

نقل النماذج خارج الوظيفة المزخرفة (ZeroGPU فقط)

من المفترض أن يكون العرض التوضيحي الخاص بك يعمل بالفعل، ومع ذلك، في الإعداد الحالي، سيتم تحميل النماذج بالكامل من القرص إلى وحدة معالجة الرسومات في كل مرة تقوم فيها بتشغيله. للاستفادة من كفاءة 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


model_loaders = [dualcliploader_357, vaeloader_359, unetloader_358, clipvisionloader_438, stylemodelloader_441, downloadandloaddepthanythingv2model_437]


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)
]


model_management.load_models_gpu(valid_models)

تحقق من الفرق لفهم بالضبط ما الذي يتغير

إذا لم تكن مشتركًا في PRO (تخطى هذه الخطوة إذا كنت كذلك)

في حال لم تكن مشتركًا في Hugging Face PRO، فأنت بحاجة إلى التقدم بطلب للحصول على منحة ZeroGPU. يمكنك القيام بذلك بسهولة من خلال الانتقال إلى صفحة الإعدادات في مساحتك الخاصة وإرسال طلب منحة لـ ZeroGPU. سيتم تلبية جميع طلبات منح ZeroGPU للمساحات ذات الواجهات الخلفية ComfyUI 🎉.

العرض قيد التشغيل

العرض التوضيحي الذي أنشأناه باستخدام هذا البرنامج التعليمي موجود مباشرة على Hugging Face Spaces. تعال والعب بها هنا: https://huggingface.co/spaces/multimodalart/flux-style-shaping

5. الاستنتاج

😮‍💨، هذا كل شيء! أعلم أن الأمر يحتاج إلى القليل من العمل، ولكن المكافأة هي طريقة سهلة لمشاركة سير عملك من خلال واجهة مستخدم بسيطة واستدلال مجاني للجميع! وكما ذكرنا من قبل، فإن الهدف هو أتمتة هذه العملية وتبسيطها قدر الإمكان في أوائل عام 2025! إجازة سعيدة 🎅✨



شاركها.
اترك تعليقاً