commit 24b3b021ee6fa988cd156ccce21d8a0d01c14028 Author: 康宇佳 Date: Fri Feb 28 15:11:04 2025 +0800 ADD 添加Modal ComfyUI 部署相关文件 diff --git a/deploy.py b/deploy.py new file mode 100644 index 0000000..d080353 --- /dev/null +++ b/deploy.py @@ -0,0 +1,80 @@ +import json +import subprocess +import uuid +from pathlib import Path +from typing import Dict + +import modal + +image = ( # build up a Modal Image to run ComfyUI, step by step + modal.Image.debian_slim( # start from basic Linux with Python + python_version="3.10" + ) + .apt_install("git") # install git to clone ComfyUI + .pip_install("fastapi[standard]==0.115.4") # install web dependencies + .pip_install("comfy-cli==1.3.5") # install comfy-cli + .pip_install("cos-python-sdk-v5") + .pip_install("sqlalchemy") + .pip_install("ultralytics") + .pip_install("tencentcloud-sdk-python") + .pip_install("pymysql") + .pip_install("Pillow") + .pip_install("ffmpy") + .pip_install("opencv-python") + .run_commands( # use comfy-cli to install ComfyUI and its dependencies + "comfy --skip-prompt install --nvidia --version 0.3.10" + ).add_local_file("snapshot.json","/root/snapshot.json", copy=True) +) + +image = ( + image.run_commands("comfy node install https://github.com/M1kep/ComfyLiterals") + .run_commands("comfy node install https://github.com/evanspearman/ComfyMath") + .run_commands("comfy node install https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved") + .run_commands("comfy node install https://e.coding.net/g-ldyi2063/dev/ComfyUI-Bowong.git") + .run_commands("comfy node install https://github.com/crystian/ComfyUI-Crystools") + .run_commands("comfy node install https://github.com/pythongosssss/ComfyUI-Custom-Scripts") + .run_commands("comfy node install https://e.coding.net/g-ldyi2063/dev/ComfyUI-CustomNode.git") + .run_commands("comfy node install https://github.com/BennyKok/comfyui-deploy") + .run_commands("comfy node install https://github.com/yolain/ComfyUI-Easy-Use") + .run_commands("comfy node install https://e.coding.net/g-ldyi2063/dev/ComfyUI-LatentSync-Node.git") + .run_commands("comfy node install https://e.coding.net/g-ldyi2063/dev/ComfyUI-VideoHelperSuite.git") + .run_commands("comfy node install https://e.coding.net/g-ldyi2063/dev/CosyVoice-ComfyUI.git") + .run_commands("comfy node install https://github.com/jags111/efficiency-nodes-comfyui") + .run_commands("comfy node install https://github.com/WASasquatch/was-node-suite-comfyui") + .run_commands("comfy node install https://github.com/rgthree/rgthree-comfy") + .run_commands("comfy node install https://github.com/cubiq/ComfyUI_essentials") + .run_commands("comfy node install https://github.com/melMass/comfy_mtb") + .run_commands( + "mkdir -p /root/comfy/ComfyUI/models/ComfyUI-CustomNode/model && rm -rf /root/comfy/ComfyUI/custom_nodes/ComfyUI-CustomNode/model && ln -s /root/comfy/ComfyUI/models/ComfyUI-CustomNode/model /root/comfy/ComfyUI/custom_nodes/ComfyUI-CustomNode/model" + ).run_commands( + "mkdir -p /root/comfy/ComfyUI/models/ComfyUI-LatentSync-Node/checkpoints && rm -rf /root/comfy/ComfyUI/custom_nodes/ComfyUI-LatentSync-Node/checkpoints && ln -s /root/comfy/ComfyUI/models/ComfyUI-LatentSync-Node/checkpoints /root/comfy/ComfyUI/custom_nodes/ComfyUI-LatentSync-Node/checkpoints" + ).run_commands( + "mkdir -p /root/comfy/ComfyUI/models/CosyVoice-ComfyUI/pretrained_models/CosyVoice-300M-SFT && mkdir -p /root/comfy/ComfyUI/custom_nodes/CosyVoice-ComfyUI/pretrained_models/CosyVoice-300M-SFT && rm -rf /root/comfy/ComfyUI/custom_nodes/CosyVoice-ComfyUI/pretrained_models/CosyVoice-300M-SFT && ln -s /root/comfy/ComfyUI/models/CosyVoice-ComfyUI/pretrained_models/CosyVoice-300M-SFT /root/comfy/ComfyUI/custom_nodes/CosyVoice-ComfyUI/pretrained_models/CosyVoice-300M-SFT" + ).run_commands( + "mkdir -p /root/comfy/ComfyUI/models/.cache/torch/hub/checkpoints && mkdir -p /root/.cache/torch/hub/checkpoints && rm -rf /root/.cache/torch/hub/checkpoints && ln -s /root/comfy/ComfyUI/models/.cache/torch/hub/checkpoints /root/.cache/torch/hub/checkpoints" + ).run_commands( + "mkdir -p /root/comfy/ComfyUI/models/stabilityai && ln -s /root/comfy/ComfyUI/models/stabilityai /root/comfy/ComfyUI/stabilityai" + ).run_commands( + "rm -rf /root/comfy/ComfyUI/models" + ).run_commands( + "apt update && apt install -y ffmpeg && ffmpeg -version" + ).pip_install("av") + # Add .run_commands(...) calls for any other custom nodes you want to download +) + +image = image.add_local_file( + "highlight_v0.113_api.json", "/root/workflow_api.json" +) + +app = modal.App(name="highlight-comfyui", image=image) +vol = modal.Volume.from_name("comfyui-model", create_if_missing=True) + +@app.function( + allow_concurrent_inputs=10, # required for UI startup process which runs several API calls concurrently + concurrency_limit=1, # limit interactive session to 1 container + gpu="T4", # good starter GPU for inference + volumes={"/root/comfy/ComfyUI/models": vol}, # mounts our cached models +) +@modal.web_server(8000, startup_timeout=60) +def ui(): + subprocess.Popen("comfy launch -- --listen 0.0.0.0 --port 8000", shell=True) diff --git a/server.py b/server.py new file mode 100644 index 0000000..5aebc1e --- /dev/null +++ b/server.py @@ -0,0 +1,149 @@ +import json +import os +import subprocess +import uuid +from pathlib import Path +from typing import Dict + +import modal + + +image = ( # build up a Modal Image to run ComfyUI, step by step + modal.Image.debian_slim( # start from basic Linux with Python + python_version="3.10" + ) + .apt_install("git") # install git to clone ComfyUI + .pip_install("fastapi[standard]==0.115.4") # install web dependencies + .pip_install("comfy-cli==1.3.5") # install comfy-cli + .pip_install("cos-python-sdk-v5") + .pip_install("sqlalchemy") + .pip_install("ultralytics") + .pip_install("tencentcloud-sdk-python") + .pip_install("pymysql") + .pip_install("Pillow") + .pip_install("ffmpy") + .pip_install("opencv-python") + .run_commands( # use comfy-cli to install ComfyUI and its dependencies + "comfy --skip-prompt install --nvidia --version 0.3.10" + ).add_local_file("snapshot.json","/root/snapshot.json", copy=True) +) + +image = ( + image.run_commands("comfy node install https://github.com/M1kep/ComfyLiterals") + .run_commands("comfy node install https://github.com/evanspearman/ComfyMath") + .run_commands("comfy node install https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved") + .run_commands("comfy node install https://e.coding.net/g-ldyi2063/dev/ComfyUI-Bowong.git") + .run_commands("comfy node install https://github.com/crystian/ComfyUI-Crystools") + .run_commands("comfy node install https://github.com/pythongosssss/ComfyUI-Custom-Scripts") + .run_commands("comfy node install https://e.coding.net/g-ldyi2063/dev/ComfyUI-CustomNode.git") + .run_commands("comfy node install https://github.com/BennyKok/comfyui-deploy") + .run_commands("comfy node install https://github.com/yolain/ComfyUI-Easy-Use") + .run_commands("comfy node install https://e.coding.net/g-ldyi2063/dev/ComfyUI-LatentSync-Node.git") + .run_commands("comfy node install https://e.coding.net/g-ldyi2063/dev/ComfyUI-VideoHelperSuite.git") + .run_commands("comfy node install https://e.coding.net/g-ldyi2063/dev/CosyVoice-ComfyUI.git") + .run_commands("comfy node install https://github.com/jags111/efficiency-nodes-comfyui") + .run_commands("comfy node install https://github.com/WASasquatch/was-node-suite-comfyui") + .run_commands("comfy node install https://github.com/rgthree/rgthree-comfy") + .run_commands("comfy node install https://github.com/cubiq/ComfyUI_essentials") + .run_commands("comfy node install https://github.com/melMass/comfy_mtb") + .run_commands( + "mkdir -p /root/comfy/ComfyUI/models/ComfyUI-CustomNode/model && rm -rf /root/comfy/ComfyUI/custom_nodes/ComfyUI-CustomNode/model && ln -s /root/comfy/ComfyUI/models/ComfyUI-CustomNode/model /root/comfy/ComfyUI/custom_nodes/ComfyUI-CustomNode/model" + ).run_commands( + "mkdir -p /root/comfy/ComfyUI/models/ComfyUI-LatentSync-Node/checkpoints && rm -rf /root/comfy/ComfyUI/custom_nodes/ComfyUI-LatentSync-Node/checkpoints && ln -s /root/comfy/ComfyUI/models/ComfyUI-LatentSync-Node/checkpoints /root/comfy/ComfyUI/custom_nodes/ComfyUI-LatentSync-Node/checkpoints" + ).run_commands( + "mkdir -p /root/comfy/ComfyUI/models/CosyVoice-ComfyUI/pretrained_models/CosyVoice-300M-SFT && mkdir -p /root/comfy/ComfyUI/custom_nodes/CosyVoice-ComfyUI/pretrained_models/CosyVoice-300M-SFT && rm -rf /root/comfy/ComfyUI/custom_nodes/CosyVoice-ComfyUI/pretrained_models/CosyVoice-300M-SFT && ln -s /root/comfy/ComfyUI/models/CosyVoice-ComfyUI/pretrained_models/CosyVoice-300M-SFT /root/comfy/ComfyUI/custom_nodes/CosyVoice-ComfyUI/pretrained_models/CosyVoice-300M-SFT" + ).run_commands( + "mkdir -p /root/comfy/ComfyUI/models/.cache/torch/hub/checkpoints && mkdir -p /root/.cache/torch/hub/checkpoints && rm -rf /root/.cache/torch/hub/checkpoints && ln -s /root/comfy/ComfyUI/models/.cache/torch/hub/checkpoints /root/.cache/torch/hub/checkpoints" + ).run_commands( + "mkdir -p /root/comfy/ComfyUI/models/stabilityai && ln -s /root/comfy/ComfyUI/models/stabilityai /root/comfy/ComfyUI/stabilityai" + ).run_commands( + "rm -rf /root/comfy/ComfyUI/models" + ).run_commands( + "apt update && apt install -y ffmpeg && ffmpeg -version" + ).pip_install("av") + # Add .run_commands(...) calls for any other custom nodes you want to download +) + +image = image.add_local_file( + "highlight_v0.113_api.json", "/root/workflow_api.json" +) + +app = modal.App(name="highlight-comfyui", image=image) +vol = modal.Volume.from_name("comfyui-model", create_if_missing=True) +secret = modal.Secret.from_name("aws-s3-secret") + +@app.cls( + allow_concurrent_inputs=1, # allow 10 concurrent API calls + concurrency_limit=50, + container_idle_timeout=120, # 5 minute container keep alive after it processes an input; increasing this value is a great way to reduce ComfyUI cold start times + timeout=800, + gpu="T4", + secrets=[secret], + volumes={ + "/root/comfy/ComfyUI/models": vol, + # "/root/comfy/ComfyUI/input": modal.CloudBucketMount( + # bucket_name=os.environ["BUCKET_INPUT"], + # # bucket_endpoint_url="https://s3.%s.amazonaws.com" % os.environ["AWS_REGION"], + # secret=secret, + # key_prefix="comfyui" + # ), + # "/root/comfy/ComfyUI/output": modal.CloudBucketMount( + # bucket_name=os.environ["BUCKET_OUTPUT"], + # # bucket_endpoint_url="https://s3.%s.amazonaws.com" % os.environ["AWS_REGION"], + # secret=secret, + # key_prefix="comfyui" + # ), + }, +) +class ComfyUI: + @modal.enter() + def launch_comfy_background(self): + # starts the ComfyUI server in the background exactly once when the first input is received + cmd = "comfy launch --background" + subprocess.run(cmd, shell=True, check=True) + + @modal.method() + def infer(self, workflow_json: str = ""): + # runs the comfy run --workflow command as a subprocess + session_id = str(uuid.uuid4()) + with open(f"/root/{session_id}.json", "w", encoding="utf-8") as f: + f.write(workflow_json) + cmd = f"comfy run --workflow /root/{session_id}.json --wait --timeout 1200" + # TODO 接收返回值 + subprocess.run(cmd, shell=True, check=True) + + # completed workflows write output images to this directory + output_dir = "/root/comfy/ComfyUI/output" + + # looks up the name of the output image file based on the workflow + workflow = json.loads(workflow_json) + file_prefix = [ + node.get("inputs") + for node in workflow.values() + if node.get("class_type") == "VHS_VideoCombine" + ][0]["filename_prefix"] + + # returns the image as bytes + file_list = os.listdir(output_dir) + # 获取按照文件时间创建排序的列表,默认是按时间升序 + new_file_list = sorted(file_list, key=lambda file: os.path.getctime(os.path.join(output_dir, file)), reverse=True) + print("file_list", new_file_list) + for f in new_file_list: + if f.startswith(file_prefix): + return f + + @modal.web_endpoint(method="POST") + def api(self, item: Dict): + from fastapi import Response + + # save this updated workflow to a new file + new_workflow_file = item["prompt"] + + # run inference on the currently running container + fname = self.infer.local(new_workflow_file) + j = { + "file_name": fname + } + print("json", j) + + return Response(content=json.dumps(j), media_type="application/json") diff --git a/server_with_s3.py b/server_with_s3.py new file mode 100644 index 0000000..6e8935a --- /dev/null +++ b/server_with_s3.py @@ -0,0 +1,151 @@ +import json +import os +import subprocess +import uuid +from pathlib import Path +from typing import Dict + +import modal + + +image = ( # build up a Modal Image to run ComfyUI, step by step + modal.Image.debian_slim( # start from basic Linux with Python + python_version="3.10" + ) + .apt_install("git") # install git to clone ComfyUI + .pip_install("fastapi[standard]==0.115.4") # install web dependencies + .pip_install("comfy-cli==1.3.5") # install comfy-cli + .pip_install("cos-python-sdk-v5") + .pip_install("sqlalchemy") + .pip_install("ultralytics") + .pip_install("tencentcloud-sdk-python") + .pip_install("pymysql") + .pip_install("Pillow") + .pip_install("ffmpy") + .pip_install("opencv-python") + .run_commands( # use comfy-cli to install ComfyUI and its dependencies + "comfy --skip-prompt install --nvidia --version 0.3.10" + ).add_local_file("snapshot.json","/root/snapshot.json", copy=True) +) + +image = ( + image.run_commands("comfy node install https://github.com/M1kep/ComfyLiterals") + .run_commands("comfy node install https://github.com/evanspearman/ComfyMath") + .run_commands("comfy node install https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved") + .run_commands("comfy node install https://e.coding.net/g-ldyi2063/dev/ComfyUI-Bowong.git") + .run_commands("comfy node install https://github.com/crystian/ComfyUI-Crystools") + .run_commands("comfy node install https://github.com/pythongosssss/ComfyUI-Custom-Scripts") + .run_commands("comfy node install https://e.coding.net/g-ldyi2063/dev/ComfyUI-CustomNode.git") + .run_commands("comfy node install https://github.com/BennyKok/comfyui-deploy") + .run_commands("comfy node install https://github.com/yolain/ComfyUI-Easy-Use") + .run_commands("comfy node install https://e.coding.net/g-ldyi2063/dev/ComfyUI-LatentSync-Node.git") + .run_commands("comfy node install https://e.coding.net/g-ldyi2063/dev/ComfyUI-VideoHelperSuite.git") + .run_commands("comfy node install https://e.coding.net/g-ldyi2063/dev/CosyVoice-ComfyUI.git") + .run_commands("comfy node install https://github.com/jags111/efficiency-nodes-comfyui") + .run_commands("comfy node install https://github.com/WASasquatch/was-node-suite-comfyui") + .run_commands("comfy node install https://github.com/rgthree/rgthree-comfy") + .run_commands("comfy node install https://github.com/cubiq/ComfyUI_essentials") + .run_commands("comfy node install https://github.com/melMass/comfy_mtb") + .run_commands( + "mkdir -p /root/comfy/ComfyUI/models/ComfyUI-CustomNode/model && rm -rf /root/comfy/ComfyUI/custom_nodes/ComfyUI-CustomNode/model && ln -s /root/comfy/ComfyUI/models/ComfyUI-CustomNode/model /root/comfy/ComfyUI/custom_nodes/ComfyUI-CustomNode/model" + ).run_commands( + "mkdir -p /root/comfy/ComfyUI/models/ComfyUI-LatentSync-Node/checkpoints && rm -rf /root/comfy/ComfyUI/custom_nodes/ComfyUI-LatentSync-Node/checkpoints && ln -s /root/comfy/ComfyUI/models/ComfyUI-LatentSync-Node/checkpoints /root/comfy/ComfyUI/custom_nodes/ComfyUI-LatentSync-Node/checkpoints" + ).run_commands( + "mkdir -p /root/comfy/ComfyUI/models/CosyVoice-ComfyUI/pretrained_models/CosyVoice-300M-SFT && mkdir -p /root/comfy/ComfyUI/custom_nodes/CosyVoice-ComfyUI/pretrained_models/CosyVoice-300M-SFT && rm -rf /root/comfy/ComfyUI/custom_nodes/CosyVoice-ComfyUI/pretrained_models/CosyVoice-300M-SFT && ln -s /root/comfy/ComfyUI/models/CosyVoice-ComfyUI/pretrained_models/CosyVoice-300M-SFT /root/comfy/ComfyUI/custom_nodes/CosyVoice-ComfyUI/pretrained_models/CosyVoice-300M-SFT" + ).run_commands( + "mkdir -p /root/comfy/ComfyUI/models/.cache/torch/hub/checkpoints && mkdir -p /root/.cache/torch/hub/checkpoints && rm -rf /root/.cache/torch/hub/checkpoints && ln -s /root/comfy/ComfyUI/models/.cache/torch/hub/checkpoints /root/.cache/torch/hub/checkpoints" + ).run_commands( + "mkdir -p /root/comfy/ComfyUI/models/stabilityai && ln -s /root/comfy/ComfyUI/models/stabilityai /root/comfy/ComfyUI/stabilityai" + ).run_commands( + "rm -rf /root/comfy/ComfyUI/models" + ).run_commands( + "apt update && apt install -y ffmpeg && ffmpeg -version" + ).pip_install("av") + # Add .run_commands(...) calls for any other custom nodes you want to download +) + +image = image.add_local_file( + "highlight_v0.113_api.json", "/root/workflow_api.json" +) + +app = modal.App(name="highlight-comfyui-s3", image=image) +vol = modal.Volume.from_name("comfyui-model", create_if_missing=True) +bucket_dict = modal.Dict.from_name("aws_s3_bucket", create_if_missing=True) +bucket_input = str(bucket_dict.get("INPUT")) +bucket_output = str(bucket_dict.get("OUTPUT")) +secret = modal.Secret.from_name("aws-s3-secret") +# completed workflows write output images to this directory +output_dir = "/root/comfy/ComfyUI/output" + +@app.cls( + allow_concurrent_inputs=1, # allow 10 concurrent API calls + concurrency_limit=50, + container_idle_timeout=120, # 5 minute container keep alive after it processes an input; increasing this value is a great way to reduce ComfyUI cold start times + timeout=800, + gpu="T4", + secrets=[secret], + volumes={ + "/root/comfy/ComfyUI/models": vol, + "/root/comfy/ComfyUI/input": modal.CloudBucketMount( + bucket_name=bucket_input, + # bucket_endpoint_url="https://s3.%s.amazonaws.com" % os.environ["AWS_REGION"], + secret=secret, + key_prefix="comfyui/" + ), + "/root/comfy/ComfyUI/output": modal.CloudBucketMount( + bucket_name=bucket_output, + # bucket_endpoint_url="https://s3.%s.amazonaws.com" % os.environ["AWS_REGION"], + secret=secret, + key_prefix="comfyui/" + ), + }, +) +class ComfyUI: + @modal.enter() + def launch_comfy_background(self): + # starts the ComfyUI server in the background exactly once when the first input is received + cmd = "comfy launch --background" + subprocess.run(cmd, shell=True, check=True) + + @modal.method() + def infer(self, workflow_json: str = ""): + # runs the comfy run --workflow command as a subprocess + session_id = str(uuid.uuid4()) + with open(f"/root/{session_id}.json", "w", encoding="utf-8") as f: + f.write(workflow_json) + cmd = f"comfy run --workflow /root/{session_id}.json --wait --timeout 1200" + # TODO 接收返回值 + subprocess.run(cmd, shell=True, check=True) + + # looks up the name of the output image file based on the workflow + workflow = json.loads(workflow_json) + file_prefix = [ + node.get("inputs") + for node in workflow.values() + if node.get("class_type") == "VHS_VideoCombine" + ][0]["filename_prefix"] + + # returns the image as bytes + file_list = os.listdir(output_dir) + # 获取按照文件时间创建排序的列表,默认是按时间升序 + new_file_list = sorted(file_list, key=lambda file: os.path.getctime(os.path.join(output_dir, file)), reverse=True) + # print("file_list", new_file_list) + for f in new_file_list: + if f.startswith(file_prefix): + return f + + @modal.web_endpoint(method="POST") + def api(self, item: Dict): + from fastapi import Response + + # save this updated workflow to a new file + new_workflow_file = item["prompt"] + + # run inference on the currently running container + fname = self.infer.local(new_workflow_file) + j = { + "file_name": os.path.join("comfyui",fname) + } + print("json", j) + + return Response(content=json.dumps(j), media_type="application/json") diff --git a/upload.py b/upload.py new file mode 100644 index 0000000..6674c45 --- /dev/null +++ b/upload.py @@ -0,0 +1,8 @@ +import modal + +vol = modal.Volume.from_name("comfyui-model") + +with vol.batch_upload() as batch: + # batch.put_directory("D:\ComfyUI-aki-v1.6\ComfyUI\custom_nodes\ComfyUI-LatentSync-Node\checkpoints", "ComfyUI-LatentSync-Node/checkpoints") + # batch.put_directory("D:\ComfyUI-aki-v1.6\ComfyUI\custom_nodes\ComfyUI-CustomNode\model", "ComfyUI-CustomNode/model") + batch.put_directory(r"D:\ComfyUI-aki-v1.6\ComfyUI\custom_nodes\CosyVoice-ComfyUI\pretrained_models\CosyVoice-300M-SFT","CosyVoice-ComfyUI/pretrained_models/CosyVoice-300M-SFT") \ No newline at end of file