diff --git a/.runtime.env b/.runtime.env index dbc5e5b..5229e3c 100644 --- a/.runtime.env +++ b/.runtime.env @@ -1,5 +1,5 @@ MODAL_ENVIRONMENT=dev -modal_app_name=bowong-ai-video +modal_app_name=cluster-test S3_mount_dir=/mntS3 S3_bucket_name=modal-media-cache S3_region=ap-northeast-2 diff --git a/src/BowongModalFunctions/api.py b/src/BowongModalFunctions/api.py index ad79a64..fb35dab 100644 --- a/src/BowongModalFunctions/api.py +++ b/src/BowongModalFunctions/api.py @@ -1,23 +1,11 @@ -import modal -from typing import Annotated -from fastapi import FastAPI, Response, Depends, Header, Request -from starlette import status +from fastapi import FastAPI, Request from scalar_fastapi import get_scalar_api_reference import sentry_sdk from sentry_sdk.integrations.loguru import LoguruIntegration, LoggingLevels from sentry_sdk.integrations.fastapi import FastApiIntegration from fastapi.middleware.cors import CORSMiddleware -from .middleware.authorization import verify_token from .utils.KVCache import KVCache -from .utils.ModalUtils import ModalUtils -from .models.media_model import MediaSource -from .models.web_model import (SentryTransactionInfo, - SentryTransactionHeader, - ModalTaskResponse, - ComfyTaskRequest, - ComfyTaskStatusResponse - ) -from .router import ffmpeg, cache +from .router import ffmpeg, cache, comfyui from .config import WorkerConfig config = WorkerConfig() @@ -93,100 +81,4 @@ async def scalar(): web_app.include_router(ffmpeg.router) web_app.include_router(cache.router) - - -@web_app.post("/comfyui/v1", tags=["ComfyUI"], summary="发起ComfyUIBase任务", description="发起ComfyUIBase任务", - responses={ - status.HTTP_200_OK: { - "description": "", - "headers": sentry_header_schema - }, - }, - dependencies=[Depends(verify_token)] - ) -async def comfyui_v1(item: ComfyTaskRequest, headers: Annotated[SentryTransactionHeader, Header()]): - sentry_trace = None - if headers.x_trace_id and headers.x_baggage: - sentry_trace = SentryTransactionInfo(x_trace_id=headers.x_trace_id, x_baggage=headers.x_baggage) - cls = modal.Cls.from_name(config.modal_app_name, "ComfyUI", environment_name=config.modal_environment) - fn_call = cls().api.spawn(item.video_path.path, item.start_time, item.filename_prefix, item.tts_text1, - item.tts_text2, item.tts_text3, item.tts_text4, item.anchor_id, item.speed, sentry_trace, - item.webhook) - return ModalTaskResponse(success=True, taskId=fn_call.object_id) - - -@web_app.get("/comfyui/v1/{task_id}", tags=["ComfyUI"], summary="查询ComfyUIBase任务", - description="查询ComfyUIBase任务", - responses={ - status.HTTP_200_OK: { - "description": "", - "headers": sentry_header_schema - }, - }, - dependencies=[Depends(verify_token)] - ) -async def comfyui_v1_status(task_id: str, response: Response): - task_status, code, reason, result, transaction = await ModalUtils.get_modal_task_status(task_id) - media = None - if transaction: - response.headers["x-trace-id"] = transaction.x_trace_id - response.headers["x-baggage"] = transaction.x_baggage - if task_status == "success": - task_status = result["status"] - if task_status != "success": - reason = result["msg"] - else: - media = MediaSource.from_str("s3://" + "/".join( - [config.S3_region, config.S3_bucket_name, config.comfyui_s3_output, result["file_name"]])) - return ComfyTaskStatusResponse(taskId=task_id, status=task_status, code=code, - error=reason, result=media.urn if media else None) - - -@web_app.post("/comfyui/v2", tags=["ComfyUI"], summary="发起ComfyUILatentSync1.5任务", - description="发起ComfyUILatentSync1.5任务", - responses={ - status.HTTP_200_OK: { - "description": "", - "headers": sentry_header_schema - }, - }, - dependencies=[Depends(verify_token)] - ) -async def comfyui_v2(item: ComfyTaskRequest, headers: Annotated[SentryTransactionHeader, Header()]): - sentry_trace = None - if headers.x_trace_id and headers.x_baggage: - sentry_trace = SentryTransactionInfo(x_trace_id=headers.x_trace_id, x_baggage=headers.x_baggage) - cls = modal.Cls.from_name(config.modal_app_name, "ComfyUILatentSync15", environment_name=config.modal_environment) - fn_call = cls().api.spawn(item.video_path.path, item.start_time, item.filename_prefix, item.tts_text1, - item.tts_text2, item.tts_text3, item.tts_text4, item.anchor_id, item.speed, sentry_trace, - item.webhook) - return ModalTaskResponse(success=True, taskId=fn_call.object_id) - - -@web_app.get("/comfyui/v2/{task_id}", tags=["ComfyUI"], summary="查询ComfyUILatentSync1.5任务", - description="查询ComfyUILatentSync1.5任务", - responses={ - status.HTTP_200_OK: { - "description": "", - "headers": sentry_header_schema - }, - }, - dependencies=[Depends(verify_token)] - ) -async def comfyui_v2_status(task_id: str, response: Response): - task_status, code, reason, result, transaction = await ModalUtils.get_modal_task_status(task_id) - media = None - - if transaction: - response.headers["x-trace-id"] = transaction.x_trace_id - response.headers["x-baggage"] = transaction.x_baggage - if task_status == "success": - task_status = result["status"] - if task_status != "success": - reason = result["msg"] - else: - media = MediaSource.from_str("s3://" + "/".join( - [config.S3_region, config.S3_bucket_name, config.comfyui_s3_output, result["file_name"]])) - return ComfyTaskStatusResponse(taskId=task_id, status=task_status, code=code, - error=reason, - result=media.urn if media else "") +web_app.include_router(comfyui.router) diff --git a/src/BowongModalFunctions/router/comfyui.py b/src/BowongModalFunctions/router/comfyui.py new file mode 100644 index 0000000..35125a5 --- /dev/null +++ b/src/BowongModalFunctions/router/comfyui.py @@ -0,0 +1,129 @@ +from typing import Annotated + +import modal +from fastapi import APIRouter, Depends, Header +from fastapi.responses import Response +from starlette import status + +from ..config import WorkerConfig +from ..middleware.authorization import verify_token +from ..models.media_model import MediaSource +from ..utils.ModalUtils import ModalUtils +from ..models.web_model import (SentryTransactionHeader, + ModalTaskResponse, SentryTransactionInfo, + ComfyTaskRequest, ComfyTaskStatusResponse) + +config = WorkerConfig() + +router = APIRouter(prefix="/comfyui") + +sentry_header_schema = { + "x-trace-id": { + "description": "Sentry Transaction ID", + "schema": { + "type": "string", + } + }, + "x-baggage": { + "description": "Sentry Transaction baggage", + "schema": { + "type": "string", + } + } +} + +@router.post("/v1", tags=["ComfyUI"], summary="发起ComfyUIBase任务", description="发起ComfyUIBase任务", + responses={ + status.HTTP_200_OK: { + "description": "", + "headers": sentry_header_schema + }, + }, + dependencies=[Depends(verify_token)] + ) +async def comfyui_v1(item: ComfyTaskRequest, headers: Annotated[SentryTransactionHeader, Header()]): + sentry_trace = None + if headers.x_trace_id and headers.x_baggage: + sentry_trace = SentryTransactionInfo(x_trace_id=headers.x_trace_id, x_baggage=headers.x_baggage) + cls = modal.Cls.from_name(config.modal_app_name, "ComfyUI", environment_name=config.modal_environment) + fn_call = cls().api.spawn(item.video_path.path, item.start_time, item.filename_prefix, item.tts_text1, + item.tts_text2, item.tts_text3, item.tts_text4, item.anchor_id, item.speed, sentry_trace, + item.webhook) + return ModalTaskResponse(success=True, taskId=fn_call.object_id) + + +@router.get("/v1/{task_id}", tags=["ComfyUI"], summary="查询ComfyUIBase任务", + description="查询ComfyUIBase任务", + responses={ + status.HTTP_200_OK: { + "description": "", + "headers": sentry_header_schema + }, + }, + dependencies=[Depends(verify_token)] + ) +async def comfyui_v1_status(task_id: str, response: Response): + task_status, code, reason, result, transaction = await ModalUtils.get_modal_task_status(task_id) + media = None + if transaction: + response.headers["x-trace-id"] = transaction.x_trace_id + response.headers["x-baggage"] = transaction.x_baggage + if task_status == "success": + task_status = result["status"] + if task_status != "success": + reason = result["msg"] + else: + media = MediaSource.from_str("s3://" + "/".join( + [config.S3_region, config.S3_bucket_name, config.comfyui_s3_output, result["file_name"]])) + return ComfyTaskStatusResponse(taskId=task_id, status=task_status, code=code, + error=reason, result=media.urn if media else None) + + +@router.post("/v2", tags=["ComfyUI"], summary="发起ComfyUILatentSync1.5任务", + description="发起ComfyUILatentSync1.5任务", + responses={ + status.HTTP_200_OK: { + "description": "", + "headers": sentry_header_schema + }, + }, + dependencies=[Depends(verify_token)] + ) +async def comfyui_v2(item: ComfyTaskRequest, headers: Annotated[SentryTransactionHeader, Header()]): + sentry_trace = None + if headers.x_trace_id and headers.x_baggage: + sentry_trace = SentryTransactionInfo(x_trace_id=headers.x_trace_id, x_baggage=headers.x_baggage) + cls = modal.Cls.from_name(config.modal_app_name, "ComfyUILatentSync15", environment_name=config.modal_environment) + fn_call = cls().api.spawn(item.video_path.path, item.start_time, item.filename_prefix, item.tts_text1, + item.tts_text2, item.tts_text3, item.tts_text4, item.anchor_id, item.speed, sentry_trace, + item.webhook) + return ModalTaskResponse(success=True, taskId=fn_call.object_id) + + +@router.get("/v2/{task_id}", tags=["ComfyUI"], summary="查询ComfyUILatentSync1.5任务", + description="查询ComfyUILatentSync1.5任务", + responses={ + status.HTTP_200_OK: { + "description": "", + "headers": sentry_header_schema + }, + }, + dependencies=[Depends(verify_token)] + ) +async def comfyui_v2_status(task_id: str, response: Response): + task_status, code, reason, result, transaction = await ModalUtils.get_modal_task_status(task_id) + media = None + + if transaction: + response.headers["x-trace-id"] = transaction.x_trace_id + response.headers["x-baggage"] = transaction.x_baggage + if task_status == "success": + task_status = result["status"] + if task_status != "success": + reason = result["msg"] + else: + media = MediaSource.from_str("s3://" + "/".join( + [config.S3_region, config.S3_bucket_name, config.comfyui_s3_output, result["file_name"]])) + return ComfyTaskStatusResponse(taskId=task_id, status=task_status, code=code, + error=reason, + result=media.urn if media else "") \ No newline at end of file diff --git a/src/cluster/app.py b/src/cluster/app.py index eaa291f..344e116 100644 --- a/src/cluster/app.py +++ b/src/cluster/app.py @@ -16,5 +16,5 @@ app = modal.App(config.modal_app_name, app.include(media_app) app.include(ffmpeg_app) app.include(web_app) -# app.include(comfyui_v1_app) -# app.include(comfyui_v2_app) +app.include(comfyui_v1_app) +app.include(comfyui_v2_app) diff --git a/src/cluster/comfyui_v1.py b/src/cluster/comfyui_v1.py index d5952a5..2a65be4 100644 --- a/src/cluster/comfyui_v1.py +++ b/src/cluster/comfyui_v1.py @@ -33,7 +33,7 @@ comfyui_image = ( .run_commands("comfy node install https://github.com/cubiq/ComfyUI_essentials") .run_commands("comfy node install https://github.com/melMass/comfy_mtb") .run_commands("comfy node install https://e.coding.net/g-ldyi2063/dev/ComfyUI_SparkTTS.git") - .run_commands("comfy node install https://e.coding.net/g-ldyi2063/dev/ComfyUI-CustomNode.git", force_build=True) + .run_commands("comfy node install https://e.coding.net/g-ldyi2063/dev/ComfyUI-CustomNode.git") .run_commands("comfy node install https://e.coding.net/g-ldyi2063/dev/cosyvoice_comfyui.git") .run_commands("comfy node install https://e.coding.net/g-ldyi2063/dev/ComfyUI-LatentSync-Node.git") .run_commands( @@ -73,11 +73,7 @@ with comfyui_image.imports(): import uuid import psutil from typing import Tuple, Any, Dict, Optional - import loguru import sentry_sdk - import datetime - import tempfile - import traceback from modal import current_function_call_id from BowongModalFunctions.config import WorkerConfig from BowongModalFunctions.models.web_model import SentryTransactionInfo, WebhookNotify diff --git a/src/cluster/comfyui_v2.py b/src/cluster/comfyui_v2.py index c67f1a8..ee2fdd3 100644 --- a/src/cluster/comfyui_v2.py +++ b/src/cluster/comfyui_v2.py @@ -3,42 +3,45 @@ import modal from dotenv import dotenv_values comfyui_latentsync_1_5_image = ( - modal.Image.debian_slim(python_version="3.10").pip_install_from_pyproject("../pyproject_comfyui.toml").apt_install( - "wget", "software-properties-common").run_commands("add-apt-repository -y contrib " - "&& wget https://developer.download.nvidia.com/compute/cuda/repos/debian12/x86_64/cuda-keyring_1.1-1_all.deb&&dpkg -i cuda-keyring_1.1-1_all.deb").apt_install( - "git", "gcc", "libportaudio2", "cuda-toolkit", "ffmpeg").pip_install("comfy_cli==0.0.0", - index_url="https://packages-1747622887395:0ee15474ccd7b27b57ca63a9306327678e6c2631@g-ldyi2063-pypi.pkg.coding.net/dev/packages/simple").run_commands( - "comfy --skip-prompt install --nvidia --version 0.3.10").env(dotenv_values("../.runtime.env")).workdir( - "/root/comfy")) + modal.Image.debian_slim(python_version="3.10") + .pip_install_from_pyproject("../pyproject_comfyui.toml") + .apt_install("wget", "software-properties-common") + .run_commands("add-apt-repository -y contrib " + "&& wget https://developer.download.nvidia.com/compute/cuda/repos/debian12/x86_64/cuda-keyring_1.1-1_all.deb&&dpkg -i cuda-keyring_1.1-1_all.deb") + .apt_install("git", "gcc", "libportaudio2", "cuda-toolkit", "ffmpeg") + .pip_install("comfy_cli==0.0.0",index_url="https://packages-1747622887395:0ee15474ccd7b27b57ca63a9306327678e6c2631@g-ldyi2063-pypi.pkg.coding.net/dev/packages/simple") + .run_commands("comfy --skip-prompt install --nvidia --version 0.3.10") + .env(dotenv_values("../.runtime.env")) + .workdir("/root/comfy")) comfyui_latentsync_1_5_image = ( - comfyui_latentsync_1_5_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://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-VideoHelperSuite.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( - "comfy node install https://e.coding.net/g-ldyi2063/dev/ComfyUI_SparkTTS.git").run_commands( - "comfy node install https://e.coding.net/g-ldyi2063/dev/ComfyUI-CustomNode.git", force_build=True).run_commands( - "comfy node install https://e.coding.net/g-ldyi2063/dev/cosyvoice_comfyui.git").run_commands( - "comfy node install https://e.coding.net/g-ldyi2063/dev/Comfy-LatentSync-Next-Node.git").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-Next-Node/checkpoints && rm -rf /root/comfy/ComfyUI/custom_nodes/Comfy-LatentSync-Next-Node/checkpoints && ln -s /root/comfy/ComfyUI/models/ComfyUI-LatentSync-Next-Node/checkpoints /root/comfy/ComfyUI/custom_nodes/Comfy-LatentSync-Next-Node/checkpoints").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( - "mkdir -p /root/comfy/ComfyUI/models/CosyVoice-ComfyUI/pretrained_models/CosyVoice-300M && mkdir -p /root/comfy/ComfyUI/custom_nodes/cosyvoice_comfyui/pretrained_models/CosyVoice-300M && rm -rf /root/comfy/ComfyUI/custom_nodes/cosyvoice_comfyui/pretrained_models/CosyVoice-300M && ln -s /root/comfy/ComfyUI/models/CosyVoice-ComfyUI/pretrained_models/CosyVoice-300M /root/comfy/ComfyUI/custom_nodes/cosyvoice_comfyui/pretrained_models/CosyVoice-300M").run_commands( - "rm -rf /root/comfy/ComfyUI/models").add_local_file("BowongModalFunctions/template/template_v2.json", - "/root/src/BowongModalFunctions/template/template_v2.json", - copy=True).add_local_python_source( - 'cluster').add_local_python_source('BowongModalFunctions')) + comfyui_latentsync_1_5_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://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-VideoHelperSuite.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("comfy node install https://e.coding.net/g-ldyi2063/dev/ComfyUI_SparkTTS.git") + .run_commands("comfy node install https://e.coding.net/g-ldyi2063/dev/ComfyUI-CustomNode.git") + .run_commands("comfy node install https://e.coding.net/g-ldyi2063/dev/cosyvoice_comfyui.git") + .run_commands("comfy node install https://e.coding.net/g-ldyi2063/dev/Comfy-LatentSync-Next-Node.git") + .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-Next-Node/checkpoints && rm -rf /root/comfy/ComfyUI/custom_nodes/Comfy-LatentSync-Next-Node/checkpoints && ln -s /root/comfy/ComfyUI/models/ComfyUI-LatentSync-Next-Node/checkpoints /root/comfy/ComfyUI/custom_nodes/Comfy-LatentSync-Next-Node/checkpoints") + .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("mkdir -p /root/comfy/ComfyUI/models/CosyVoice-ComfyUI/pretrained_models/CosyVoice-300M && mkdir -p /root/comfy/ComfyUI/custom_nodes/cosyvoice_comfyui/pretrained_models/CosyVoice-300M && rm -rf /root/comfy/ComfyUI/custom_nodes/cosyvoice_comfyui/pretrained_models/CosyVoice-300M && ln -s /root/comfy/ComfyUI/models/CosyVoice-ComfyUI/pretrained_models/CosyVoice-300M /root/comfy/ComfyUI/custom_nodes/cosyvoice_comfyui/pretrained_models/CosyVoice-300M") + .run_commands("rm -rf /root/comfy/ComfyUI/models") + .add_local_file("BowongModalFunctions/template/template_v2.json","/root/src/BowongModalFunctions/template/template_v2.json",copy=True) + .add_local_python_source('cluster') + .add_local_python_source('BowongModalFunctions')) app = modal.App(name="ComfyUI v2", image=comfyui_latentsync_1_5_image, include_source=False) app.set_description("ComfyUI v2 Server")