ADD 增加HeyGem纯享服务器配置
ADD 增加AutoDL部署 FIX 修复json日志打印 ADD HeyGem允许多类型文件输入(http&upload)
This commit is contained in:
245
AutoDL/AutoDL_pure_heygem.py
Normal file
245
AutoDL/AutoDL_pure_heygem.py
Normal file
@@ -0,0 +1,245 @@
|
|||||||
|
import json
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import socket
|
||||||
|
import subprocess
|
||||||
|
import time
|
||||||
|
import traceback
|
||||||
|
import uuid
|
||||||
|
from typing import Any, Optional, Union
|
||||||
|
|
||||||
|
import httpx
|
||||||
|
import loguru
|
||||||
|
import requests
|
||||||
|
import uvicorn
|
||||||
|
from fastapi import UploadFile, HTTPException, Depends, FastAPI
|
||||||
|
from fastapi.routing import APIRoute
|
||||||
|
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
|
||||||
|
from starlette import status
|
||||||
|
|
||||||
|
|
||||||
|
class HeyGem:
|
||||||
|
def __init__(self):
|
||||||
|
def check_port_in_use(port, host='127.0.0.1'):
|
||||||
|
s = None
|
||||||
|
try:
|
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
s.settimeout(1)
|
||||||
|
s.connect((host, int(port)))
|
||||||
|
return True
|
||||||
|
except socket.error:
|
||||||
|
return False
|
||||||
|
finally:
|
||||||
|
if s:
|
||||||
|
s.close()
|
||||||
|
|
||||||
|
uid = str(uuid.uuid4())
|
||||||
|
cmd = "/bin/bash -c \"echo client_id: %s && source /root/.bashrc && nohup python /root/heygem.py >> /root/logs/%s.log 2>&1 &\"" % (uid, uid)
|
||||||
|
subprocess.run(cmd, shell=True, check=True)
|
||||||
|
timeout = 30
|
||||||
|
while timeout > 0:
|
||||||
|
check = check_port_in_use(8383)
|
||||||
|
if check:
|
||||||
|
loguru.logger.success("HeyGem Server started on port 8383")
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
timeout -= 1
|
||||||
|
time.sleep(2)
|
||||||
|
if timeout == 0:
|
||||||
|
raise TimeoutError("HeyGem Server Start timed out")
|
||||||
|
self.server = FastAPI()
|
||||||
|
self.server.routes.append(APIRoute(path='/', endpoint=self.api, methods=['POST']))
|
||||||
|
|
||||||
|
|
||||||
|
def infer(self, code, video_path, audio_path) -> str:
|
||||||
|
def task_submit(uid, video, audio, heygem_url):
|
||||||
|
"""Submit a task to the API"""
|
||||||
|
task_submit_api = f'{heygem_url}/easy/submit'
|
||||||
|
result_json = {
|
||||||
|
'status': False, 'data': {}, 'msg': ''
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
data = {
|
||||||
|
"code": uid,
|
||||||
|
"video_url": video,
|
||||||
|
"audio_url": audio,
|
||||||
|
"chaofen": 1,
|
||||||
|
"watermark_switch": 0,
|
||||||
|
"pn": 1
|
||||||
|
}
|
||||||
|
loguru.logger.info(f'data={json.dumps(data, ensure_ascii=False)}')
|
||||||
|
with httpx.Client() as client:
|
||||||
|
resp = client.post(task_submit_api, json=data)
|
||||||
|
resp_dict = resp.json()
|
||||||
|
loguru.logger.info(f'submit data: {json.dumps(resp_dict, ensure_ascii=False)}')
|
||||||
|
if resp_dict['code'] != 10000:
|
||||||
|
result_json['status'] = False
|
||||||
|
result_json['msg'] = result_json['msg']
|
||||||
|
else:
|
||||||
|
result_json['status'] = True
|
||||||
|
result_json['data'] = uid
|
||||||
|
result_json['msg'] = '任务提交成功'
|
||||||
|
return result_json
|
||||||
|
except Exception as e:
|
||||||
|
loguru.logger.info(f'submit task fail case by:{str(e)}')
|
||||||
|
raise RuntimeError(str(e))
|
||||||
|
|
||||||
|
def query_task_progress(heygem_url, heygem_temp_path, task_id: str, interval: int = 10, timeout: int = 60 * 35):
|
||||||
|
"""Query task progress and wait for completion"""
|
||||||
|
result_json = {'status': False, 'data': {}, 'msg': ''}
|
||||||
|
|
||||||
|
def query_result(t_id: str):
|
||||||
|
tmp_dict = {'status': True, 'data': dict(), 'msg': ''}
|
||||||
|
try:
|
||||||
|
query_task_url = f'{heygem_url}/easy/query'
|
||||||
|
params = {
|
||||||
|
'code': t_id
|
||||||
|
}
|
||||||
|
with httpx.Client() as client:
|
||||||
|
resp = client.get(query_task_url, params=params)
|
||||||
|
resp_dict = resp.json()
|
||||||
|
loguru.logger.info(f'query task data: {json.dumps(resp_dict, ensure_ascii=False)}')
|
||||||
|
status_code = resp_dict['code']
|
||||||
|
if status_code in (9999, 10002, 10003, 10001):
|
||||||
|
tmp_dict['status'] = False
|
||||||
|
tmp_dict['msg'] = resp_dict['msg']
|
||||||
|
elif status_code == 10000:
|
||||||
|
status_code = resp_dict['data'].get('status', 1)
|
||||||
|
if status_code == 3:
|
||||||
|
tmp_dict['status'] = False
|
||||||
|
tmp_dict['msg'] = resp_dict['data']['msg']
|
||||||
|
else:
|
||||||
|
process = resp_dict['data'].get('progress', 20)
|
||||||
|
if status_code == 2:
|
||||||
|
process = 100
|
||||||
|
else:
|
||||||
|
process = process
|
||||||
|
result = resp_dict['data'].get('result', '')
|
||||||
|
tmp_dict['data'] = {'progress': process,
|
||||||
|
'path': result,
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
except Exception as e:
|
||||||
|
loguru.logger.info(f'query task fail case by:{str(e)}')
|
||||||
|
raise RuntimeError(str(e))
|
||||||
|
return tmp_dict
|
||||||
|
|
||||||
|
end = time.time() + timeout
|
||||||
|
while time.time() < end:
|
||||||
|
tmp_result = query_result(task_id)
|
||||||
|
if not tmp_result['status'] or tmp_result['data'].__eq__({}):
|
||||||
|
result_json['status'] = False
|
||||||
|
result_json['msg'] = tmp_result['msg']
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
process = tmp_result['data']['progress']
|
||||||
|
loguru.logger.info(f'query task progress :{process}')
|
||||||
|
if tmp_result['data']['progress'] < 100:
|
||||||
|
time.sleep(interval)
|
||||||
|
loguru.logger.info(f'wait next interval:{interval}')
|
||||||
|
else:
|
||||||
|
p = tmp_result['data']['path']
|
||||||
|
p = p.replace('/', '').replace('\\', '')
|
||||||
|
result_json['data'] = "%s/%s" % (heygem_temp_path, p)
|
||||||
|
result_json['status'] = True
|
||||||
|
break
|
||||||
|
return result_json
|
||||||
|
|
||||||
|
try:
|
||||||
|
heygem_url = "http://127.0.0.1:8383"
|
||||||
|
heygem_temp_path = "/code/data/temp"
|
||||||
|
submit_result = task_submit(code, video_path, audio_path, heygem_url)
|
||||||
|
if not submit_result['status']:
|
||||||
|
raise Exception(f"Task submission failed: {submit_result['msg']}")
|
||||||
|
|
||||||
|
task_id = submit_result['data']
|
||||||
|
loguru.logger.info(f'Submitted task: {task_id}')
|
||||||
|
|
||||||
|
# Query task progress
|
||||||
|
progress_result = query_task_progress(heygem_url, heygem_temp_path, task_id, interval=5)
|
||||||
|
|
||||||
|
if not progress_result['status']:
|
||||||
|
raise RuntimeError(f"Task processing failed: {progress_result['msg']}")
|
||||||
|
|
||||||
|
# Return the file for download
|
||||||
|
file_path = progress_result['data']
|
||||||
|
if not os.path.exists(file_path):
|
||||||
|
raise FileNotFoundError(f"Output file not found at {file_path}")
|
||||||
|
return file_path
|
||||||
|
except Exception as e:
|
||||||
|
loguru.logger.error(f"Error processing request || {str(e)}")
|
||||||
|
raise Exception(str(e))
|
||||||
|
finally:
|
||||||
|
try:
|
||||||
|
os.remove(video_path)
|
||||||
|
os.remove(audio_path)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def download_file(self, url, path):
|
||||||
|
with requests.get(url, stream=True) as r:
|
||||||
|
with open(path, 'wb') as f:
|
||||||
|
shutil.copyfileobj(r.raw, f)
|
||||||
|
|
||||||
|
async def api(self, video_file: Optional[Union[UploadFile, str]], audio_file: Optional[Union[UploadFile, str]], token: HTTPAuthorizationCredentials = Depends(HTTPBearer())):
|
||||||
|
if token.credentials != os.environ["AUTH_TOKEN"]:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||||
|
detail="Incorrect bearer token",
|
||||||
|
headers={"WWW-Authenticate": "Bearer"},
|
||||||
|
)
|
||||||
|
code = str(uuid.uuid4())
|
||||||
|
try:
|
||||||
|
if isinstance(video_file, UploadFile):
|
||||||
|
video_path = "/root/%s" % video_file.filename
|
||||||
|
with open(video_path, "wb") as f:
|
||||||
|
data = await video_file.read()
|
||||||
|
f.write(data)
|
||||||
|
elif isinstance(video_file, str) and video_file.startswith("http"):
|
||||||
|
video_path = "/root/%s" % video_file.split("?")[0].split("/")[-1]
|
||||||
|
self.download_file(video_file, video_path)
|
||||||
|
else:
|
||||||
|
return {"status": "fail", "msg": "video file save failed: Not a valid input"}
|
||||||
|
|
||||||
|
if isinstance(audio_file, UploadFile):
|
||||||
|
audio_path = "/root/%s" % audio_file.filename
|
||||||
|
with open(audio_path, "wb") as f:
|
||||||
|
data = await audio_file.read()
|
||||||
|
f.write(data)
|
||||||
|
elif isinstance(audio_file, str) and audio_file.startswith("http"):
|
||||||
|
audio_path = "/root/%s" % audio_file.split("?")[0].split("/")[-1]
|
||||||
|
self.download_file(audio_file, audio_path)
|
||||||
|
else:
|
||||||
|
return {"status": "fail", "msg": "audio file save failed: Not a valid input"}
|
||||||
|
except Exception as e:
|
||||||
|
return {"status": "fail", "msg": f"video or audio file save failed: {str(e)}"}
|
||||||
|
|
||||||
|
loguru.logger.info(f"Enter Inference Module")
|
||||||
|
try:
|
||||||
|
file_path = self.infer(code, video_path, audio_path)
|
||||||
|
try:
|
||||||
|
loguru.logger.info("Try move file to S3 manually")
|
||||||
|
# S3 Fallback
|
||||||
|
import boto3
|
||||||
|
import yaml
|
||||||
|
with open("/root/config.yaml", encoding="utf-8",
|
||||||
|
mode="r+") as config:
|
||||||
|
yaml_config = yaml.load(config, Loader=yaml.FullLoader)
|
||||||
|
awss3 = boto3.resource('s3', aws_access_key_id=yaml_config["aws_key_id"],
|
||||||
|
aws_secret_access_key=yaml_config["aws_access_key"])
|
||||||
|
awss3.meta.client.upload_file(file_path, "bw-heygem-output", file_path.split(os.path.sep)[-1])
|
||||||
|
except Exception as e:
|
||||||
|
return {"status": "fail", "msg": "Failed to move file to S3 manually: " + str(e)}
|
||||||
|
# resp = FileResponse(path=file_path, filename=Path(file_path).name, status_code=200, headers={
|
||||||
|
# "Content-Type": "application/octet-stream",
|
||||||
|
# "Content-Disposition": f"attachment; filename={Path(file_path).name}",
|
||||||
|
# })
|
||||||
|
return {"status": "success", "msg":f"{file_path.split(os.path.sep)[-1]}"}
|
||||||
|
except Exception as e:
|
||||||
|
traceback.print_exc()
|
||||||
|
return {"status": "fail", "msg": "Inference module failed: "+str(e)}
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
heygem = HeyGem()
|
||||||
|
uvicorn.run(app=heygem.server, host="0.0.0.0", port=6006)
|
||||||
12
AutoDL/heygem.py
Normal file
12
AutoDL/heygem.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import site
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
pkg_path = site.getsitepackages()[0]
|
||||||
|
sys.path.append(f"{pkg_path}/heygem/code")
|
||||||
|
|
||||||
|
p = subprocess.Popen(f"cd {pkg_path}/heygem/code && "
|
||||||
|
"python3.8 app_local.py", shell=True)
|
||||||
|
p.communicate()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -7,16 +7,14 @@ import subprocess
|
|||||||
import time
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
import uuid
|
import uuid
|
||||||
from pathlib import Path
|
from typing import Any, Optional, Union
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
import loguru
|
import loguru
|
||||||
import modal
|
import modal
|
||||||
|
import requests
|
||||||
from fastapi import Depends, HTTPException, status, UploadFile
|
from fastapi import Depends, HTTPException, status, UploadFile
|
||||||
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
||||||
from fastapi.responses import Response, FileResponse
|
|
||||||
|
|
||||||
image = (
|
image = (
|
||||||
modal.Image.debian_slim( # start from basic Linux with Python
|
modal.Image.debian_slim( # start from basic Linux with Python
|
||||||
python_version="3.10"
|
python_version="3.10"
|
||||||
@@ -39,7 +37,7 @@ image = (
|
|||||||
.run_commands("python3.8 -m pip install https://github.com/pydata/numexpr/releases/download/v2.8.6/numexpr-2.8.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl")
|
.run_commands("python3.8 -m pip install https://github.com/pydata/numexpr/releases/download/v2.8.6/numexpr-2.8.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl")
|
||||||
.add_local_file("heygem.py", "/root/heygem.py", copy=True)
|
.add_local_file("heygem.py", "/root/heygem.py", copy=True)
|
||||||
.add_local_file("config.yaml", "/root/config.yaml", copy=True)
|
.add_local_file("config.yaml", "/root/config.yaml", copy=True)
|
||||||
.workdir("/root").pip_install("boto3").pip_install("PyYAML")
|
.workdir("/root").pip_install("boto3").pip_install("PyYAML").pip_install("requests")
|
||||||
)
|
)
|
||||||
|
|
||||||
app = modal.App(name="heygem", image=image)
|
app = modal.App(name="heygem", image=image)
|
||||||
@@ -50,7 +48,7 @@ bucket_output = "bw-heygem-output"
|
|||||||
@app.cls(
|
@app.cls(
|
||||||
allow_concurrent_inputs=1, # required for UI startup process which runs several API calls concurrently
|
allow_concurrent_inputs=1, # required for UI startup process which runs several API calls concurrently
|
||||||
max_containers=25, # limit interactive session to 1 container
|
max_containers=25, # limit interactive session to 1 container
|
||||||
gpu="T4", # good starter GPU for inference
|
gpu="L40S", # good starter GPU for inference
|
||||||
cpu=(2,32),
|
cpu=(2,32),
|
||||||
memory=(6144, 32768),
|
memory=(6144, 32768),
|
||||||
timeout=2160,
|
timeout=2160,
|
||||||
@@ -104,7 +102,7 @@ class HeyGem:
|
|||||||
|
|
||||||
@modal.method()
|
@modal.method()
|
||||||
def infer(self, code, video_path, audio_path) -> str:
|
def infer(self, code, video_path, audio_path) -> str:
|
||||||
def task_submit(uid, video, audio, heygem_url) -> dict[str, Any]:
|
def task_submit(uid, video, audio, heygem_url):
|
||||||
"""Submit a task to the API"""
|
"""Submit a task to the API"""
|
||||||
task_submit_api = f'{heygem_url}/easy/submit'
|
task_submit_api = f'{heygem_url}/easy/submit'
|
||||||
result_json = {
|
result_json = {
|
||||||
@@ -119,11 +117,11 @@ class HeyGem:
|
|||||||
"watermark_switch": 0,
|
"watermark_switch": 0,
|
||||||
"pn": 1
|
"pn": 1
|
||||||
}
|
}
|
||||||
loguru.logger.info(f'data={data}')
|
loguru.logger.info(f'data={json.dumps(data, ensure_ascii=False)}')
|
||||||
with httpx.Client() as client:
|
with httpx.Client() as client:
|
||||||
resp = client.post(task_submit_api, json=data)
|
resp = client.post(task_submit_api, json=data)
|
||||||
resp_dict = resp.json()
|
resp_dict = resp.json()
|
||||||
loguru.logger.info(f'submit data: {resp_dict}')
|
loguru.logger.info(f'submit data: {json.dumps(resp_dict, ensure_ascii=False)}')
|
||||||
if resp_dict['code'] != 10000:
|
if resp_dict['code'] != 10000:
|
||||||
result_json['status'] = False
|
result_json['status'] = False
|
||||||
result_json['msg'] = result_json['msg']
|
result_json['msg'] = result_json['msg']
|
||||||
@@ -136,7 +134,7 @@ class HeyGem:
|
|||||||
loguru.logger.info(f'submit task fail case by:{str(e)}')
|
loguru.logger.info(f'submit task fail case by:{str(e)}')
|
||||||
raise RuntimeError(str(e))
|
raise RuntimeError(str(e))
|
||||||
|
|
||||||
def query_task_progress(heygem_url, heygem_temp_path, task_id: str, interval: int = 10, timeout: int = 60 * 35) -> dict[str, Any]:
|
def query_task_progress(heygem_url, heygem_temp_path, task_id: str, interval: int = 10, timeout: int = 60 * 35):
|
||||||
"""Query task progress and wait for completion"""
|
"""Query task progress and wait for completion"""
|
||||||
result_json = {'status': False, 'data': {}, 'msg': ''}
|
result_json = {'status': False, 'data': {}, 'msg': ''}
|
||||||
|
|
||||||
@@ -150,7 +148,7 @@ class HeyGem:
|
|||||||
with httpx.Client() as client:
|
with httpx.Client() as client:
|
||||||
resp = client.get(query_task_url, params=params)
|
resp = client.get(query_task_url, params=params)
|
||||||
resp_dict = resp.json()
|
resp_dict = resp.json()
|
||||||
loguru.logger.info(f'query task data: {json.dumps(resp_dict)}')
|
loguru.logger.info(f'query task data: {json.dumps(resp_dict, ensure_ascii=False)}')
|
||||||
status_code = resp_dict['code']
|
status_code = resp_dict['code']
|
||||||
if status_code in (9999, 10002, 10003, 10001):
|
if status_code in (9999, 10002, 10003, 10001):
|
||||||
tmp_dict['status'] = False
|
tmp_dict['status'] = False
|
||||||
@@ -229,9 +227,13 @@ class HeyGem:
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def download_file(self, url, path):
|
||||||
|
with requests.get(url, stream=True) as r:
|
||||||
|
with open(path, 'wb') as f:
|
||||||
|
shutil.copyfileobj(r.raw, f)
|
||||||
|
|
||||||
@modal.fastapi_endpoint(method="POST")
|
@modal.fastapi_endpoint(method="POST")
|
||||||
async def api(self, video_file: UploadFile, audio_file: UploadFile, token: HTTPAuthorizationCredentials = Depends(auth_scheme)) -> Response:
|
async def api(self, video_file: Optional[Union[UploadFile, str]], audio_file: Optional[Union[UploadFile, str]], token: HTTPAuthorizationCredentials = Depends(auth_scheme)):
|
||||||
if token.credentials != os.environ["AUTH_TOKEN"]:
|
if token.credentials != os.environ["AUTH_TOKEN"]:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||||
@@ -240,17 +242,29 @@ class HeyGem:
|
|||||||
)
|
)
|
||||||
code = str(uuid.uuid4())
|
code = str(uuid.uuid4())
|
||||||
try:
|
try:
|
||||||
video_path = "/root/%s" % video_file.filename
|
if isinstance(video_file, UploadFile):
|
||||||
with open(video_path, "wb") as f:
|
video_path = "/root/%s" % video_file.filename
|
||||||
data = await video_file.read()
|
with open(video_path, "wb") as f:
|
||||||
f.write(data)
|
data = await video_file.read()
|
||||||
|
f.write(data)
|
||||||
|
elif isinstance(video_file, str) and video_file.startswith("http"):
|
||||||
|
video_path = "/root/%s" % video_file.split("?")[0].split("/")[-1]
|
||||||
|
self.download_file(video_file, video_path)
|
||||||
|
else:
|
||||||
|
return {"status": "fail", "msg": "video file save failed: Not a valid input"}
|
||||||
|
|
||||||
audio_path = "/root/%s" % audio_file.filename
|
if isinstance(audio_file, UploadFile):
|
||||||
with open(audio_path, "wb") as f:
|
audio_path = "/root/%s" % audio_file.filename
|
||||||
data = await audio_file.read()
|
with open(audio_path, "wb") as f:
|
||||||
f.write(data)
|
data = await audio_file.read()
|
||||||
|
f.write(data)
|
||||||
|
elif isinstance(audio_file, str) and audio_file.startswith("http"):
|
||||||
|
audio_path = "/root/%s" % audio_file.split("?")[0].split("/")[-1]
|
||||||
|
self.download_file(audio_file, audio_path)
|
||||||
|
else:
|
||||||
|
return {"status": "fail", "msg": "audio file save failed: Not a valid input"}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return Response({"status": "fail", "msg": f"video or audio file save failed: {str(e)}"})
|
return {"status": "fail", "msg": f"video or audio file save failed: {str(e)}"}
|
||||||
|
|
||||||
loguru.logger.info(f"Enter Inference Module")
|
loguru.logger.info(f"Enter Inference Module")
|
||||||
try:
|
try:
|
||||||
@@ -271,14 +285,14 @@ class HeyGem:
|
|||||||
aws_secret_access_key=yaml_config["aws_access_key"])
|
aws_secret_access_key=yaml_config["aws_access_key"])
|
||||||
awss3.meta.client.upload_file(file_path, bucket_output, file_path.split(os.path.sep)[-1])
|
awss3.meta.client.upload_file(file_path, bucket_output, file_path.split(os.path.sep)[-1])
|
||||||
except:
|
except:
|
||||||
raise Exception("Failed to move file to S3 manually")
|
return {"status": "fail", "msg": "Failed to move file to S3 manually: " + str(e)}
|
||||||
resp = FileResponse(path=file_path, filename=Path(file_path).name, status_code=200, headers={
|
# resp = FileResponse(path=file_path, filename=Path(file_path).name, status_code=200, headers={
|
||||||
"Content-Type": "application/octet-stream",
|
# "Content-Type": "application/octet-stream",
|
||||||
"Content-Disposition": f"attachment; filename={Path(file_path).name}",
|
# "Content-Disposition": f"attachment; filename={Path(file_path).name}",
|
||||||
})
|
# })
|
||||||
return resp
|
return {"status": "success", "msg":f"{file_path.split(os.path.sep)[-1]}"}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
return Response({"status": "fail", "msg": "Inference module failed: "+str(e)})
|
return {"status": "fail", "msg": "Inference module failed: "+str(e)}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import subprocess
|
|||||||
import uuid
|
import uuid
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
|
||||||
|
import loguru
|
||||||
import modal
|
import modal
|
||||||
|
|
||||||
image = ( # build up a Modal Image to run ComfyUI, step by step
|
image = ( # build up a Modal Image to run ComfyUI, step by step
|
||||||
@@ -53,7 +54,7 @@ image = (
|
|||||||
.run_commands("comfy node install https://github.com/melMass/comfy_mtb")
|
.run_commands("comfy node install https://github.com/melMass/comfy_mtb")
|
||||||
.run_commands("echo 3 && comfy node install https://e.coding.net/g-ldyi2063/dev/ComfyUI_SparkTTS.git")
|
.run_commands("echo 3 && 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/ComfyUI-CustomNode.git")
|
||||||
.run_commands("comfy node install https://e.coding.net/g-ldyi2063/dev/cosyvoice_comfyui.git")
|
.run_commands("echo 04111 && comfy node install https://e.coding.net/g-ldyi2063/dev/cosyvoice_comfyui.git")
|
||||||
.run_commands("echo 4 && comfy node install https://e.coding.net/g-ldyi2063/dev/ComfyUI-LatentSync-Node.git")
|
.run_commands("echo 4 && comfy node install https://e.coding.net/g-ldyi2063/dev/ComfyUI-LatentSync-Node.git")
|
||||||
.run_commands(
|
.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"
|
"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"
|
||||||
@@ -98,8 +99,7 @@ output_dir = "/root/comfy/ComfyUI/output"
|
|||||||
cpu=(2,16),
|
cpu=(2,16),
|
||||||
# memory=(32768, 32768), # (内存预留量, 内存使用上限)
|
# memory=(32768, 32768), # (内存预留量, 内存使用上限)
|
||||||
memory=(20480,40960),
|
memory=(20480,40960),
|
||||||
retries=1,
|
enable_memory_snapshot=False,
|
||||||
enable_memory_snapshot=True,
|
|
||||||
secrets=[secret],
|
secrets=[secret],
|
||||||
volumes={
|
volumes={
|
||||||
"/root/comfy/ComfyUI/models": vol,
|
"/root/comfy/ComfyUI/models": vol,
|
||||||
@@ -198,7 +198,6 @@ class ComfyUI:
|
|||||||
|
|
||||||
@modal.fastapi_endpoint(method="POST")
|
@modal.fastapi_endpoint(method="POST")
|
||||||
def api(self, item: Dict):
|
def api(self, item: Dict):
|
||||||
from fastapi import Response
|
|
||||||
try:
|
try:
|
||||||
# save this updated workflow to a new file
|
# save this updated workflow to a new file
|
||||||
new_workflow_file = item["prompt"]
|
new_workflow_file = item["prompt"]
|
||||||
@@ -207,8 +206,8 @@ class ComfyUI:
|
|||||||
if fname is None:
|
if fname is None:
|
||||||
raise RuntimeError("Output File not found")
|
raise RuntimeError("Output File not found")
|
||||||
j = {"file_name": fname}
|
j = {"file_name": fname}
|
||||||
print("json", j)
|
loguru.logger.success(j)
|
||||||
return Response(content=json.dumps(j), media_type="application/json")
|
return j
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise RuntimeError(str(e))
|
raise RuntimeError(str(e))
|
||||||
finally:
|
finally:
|
||||||
@@ -222,7 +221,7 @@ class ComfyUI:
|
|||||||
try:
|
try:
|
||||||
subprocess.run(cmd, shell=True, check=True)
|
subprocess.run(cmd, shell=True, check=True)
|
||||||
except:
|
except:
|
||||||
raise Exception("Failed to launch ComfyUI")
|
pass
|
||||||
|
|
||||||
|
|
||||||
def poll_server_health(self):
|
def poll_server_health(self):
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import subprocess
|
|||||||
import uuid
|
import uuid
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
|
||||||
|
import loguru
|
||||||
import modal
|
import modal
|
||||||
from fastapi import Depends, HTTPException, status
|
from fastapi import Depends, HTTPException, status
|
||||||
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
||||||
@@ -55,7 +56,7 @@ image = (
|
|||||||
.run_commands("comfy node install https://github.com/melMass/comfy_mtb")
|
.run_commands("comfy node install https://github.com/melMass/comfy_mtb")
|
||||||
.run_commands("echo 3 && comfy node install https://e.coding.net/g-ldyi2063/dev/ComfyUI_SparkTTS.git")
|
.run_commands("echo 3 && 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/ComfyUI-CustomNode.git")
|
||||||
.run_commands("comfy node install https://e.coding.net/g-ldyi2063/dev/cosyvoice_comfyui.git")
|
.run_commands("echo 04111 && comfy node install https://e.coding.net/g-ldyi2063/dev/cosyvoice_comfyui.git")
|
||||||
.run_commands("echo 4 && comfy node install https://e.coding.net/g-ldyi2063/dev/ComfyUI-LatentSync-Node.git")
|
.run_commands("echo 4 && comfy node install https://e.coding.net/g-ldyi2063/dev/ComfyUI-LatentSync-Node.git")
|
||||||
.run_commands(
|
.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"
|
"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"
|
||||||
@@ -101,8 +102,7 @@ auth_scheme = HTTPBearer()
|
|||||||
cpu=(2,16),
|
cpu=(2,16),
|
||||||
# memory=(32768, 32768), # (内存预留量, 内存使用上限)
|
# memory=(32768, 32768), # (内存预留量, 内存使用上限)
|
||||||
memory=(20480,40960),
|
memory=(20480,40960),
|
||||||
retries=1,
|
enable_memory_snapshot=False,
|
||||||
enable_memory_snapshot=True,
|
|
||||||
secrets=[secret, modal.Secret.from_name("web_auth_token")],
|
secrets=[secret, modal.Secret.from_name("web_auth_token")],
|
||||||
volumes={
|
volumes={
|
||||||
"/root/comfy/ComfyUI/models": vol,
|
"/root/comfy/ComfyUI/models": vol,
|
||||||
@@ -204,7 +204,6 @@ class ComfyUI:
|
|||||||
detail="Incorrect bearer token",
|
detail="Incorrect bearer token",
|
||||||
headers={"WWW-Authenticate": "Bearer"},
|
headers={"WWW-Authenticate": "Bearer"},
|
||||||
)
|
)
|
||||||
from fastapi import Response
|
|
||||||
try:
|
try:
|
||||||
# save this updated workflow to a new file
|
# save this updated workflow to a new file
|
||||||
new_workflow_file = item["prompt"]
|
new_workflow_file = item["prompt"]
|
||||||
@@ -212,11 +211,13 @@ class ComfyUI:
|
|||||||
fname = self.infer.local(new_workflow_file)
|
fname = self.infer.local(new_workflow_file)
|
||||||
if fname is None:
|
if fname is None:
|
||||||
raise RuntimeError("Output File not found")
|
raise RuntimeError("Output File not found")
|
||||||
j = {"file_name": fname}
|
j = {"status":"success", "file_name": fname}
|
||||||
print("json", j)
|
loguru.logger.success(j)
|
||||||
return Response(content=json.dumps(j), media_type="application/json")
|
return j
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise RuntimeError(str(e))
|
j = {"status":"fail", "msg": str(e)}
|
||||||
|
loguru.logger.error(j)
|
||||||
|
return j
|
||||||
finally:
|
finally:
|
||||||
print("Purge Garbage By Restart Comfy")
|
print("Purge Garbage By Restart Comfy")
|
||||||
cmd = "comfy stop"
|
cmd = "comfy stop"
|
||||||
@@ -228,7 +229,7 @@ class ComfyUI:
|
|||||||
try:
|
try:
|
||||||
subprocess.run(cmd, shell=True, check=True)
|
subprocess.run(cmd, shell=True, check=True)
|
||||||
except:
|
except:
|
||||||
raise Exception("Failed to launch ComfyUI")
|
pass
|
||||||
|
|
||||||
def poll_server_health(self):
|
def poll_server_health(self):
|
||||||
import socket
|
import socket
|
||||||
@@ -257,8 +258,4 @@ class ComfyUI:
|
|||||||
modal.experimental.stop_fetching_inputs()
|
modal.experimental.stop_fetching_inputs()
|
||||||
raise Exception("ComfyUI server is not healthy, restart failed, stopping container")
|
raise Exception("ComfyUI server is not healthy, restart failed, stopping container")
|
||||||
|
|
||||||
# @modal.web_endpoint(method="POST", label="tk")
|
|
||||||
# def tk_api(self, item: Dict):
|
|
||||||
# pass
|
|
||||||
#
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import subprocess
|
|||||||
import uuid
|
import uuid
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
|
||||||
|
import loguru
|
||||||
import modal
|
import modal
|
||||||
from fastapi import Depends, HTTPException, status
|
from fastapi import Depends, HTTPException, status
|
||||||
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
||||||
@@ -55,7 +56,7 @@ image = (
|
|||||||
.run_commands("comfy node install https://github.com/melMass/comfy_mtb")
|
.run_commands("comfy node install https://github.com/melMass/comfy_mtb")
|
||||||
.run_commands("echo 3 && comfy node install https://e.coding.net/g-ldyi2063/dev/ComfyUI_SparkTTS.git")
|
.run_commands("echo 3 && comfy node install https://e.coding.net/g-ldyi2063/dev/ComfyUI_SparkTTS.git")
|
||||||
.run_commands("echo 4 && comfy node install https://e.coding.net/g-ldyi2063/dev/ComfyUI-CustomNode.git")
|
.run_commands("echo 4 && 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("echo 04111 && comfy node install https://e.coding.net/g-ldyi2063/dev/cosyvoice_comfyui.git")
|
||||||
.run_commands("echo 4 && comfy node install https://e.coding.net/g-ldyi2063/dev/ComfyUI-LatentSync-Node.git")
|
.run_commands("echo 4 && comfy node install https://e.coding.net/g-ldyi2063/dev/ComfyUI-LatentSync-Node.git")
|
||||||
.run_commands(
|
.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"
|
"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"
|
||||||
@@ -258,7 +259,6 @@ class ComfyUI:
|
|||||||
detail="Incorrect bearer token",
|
detail="Incorrect bearer token",
|
||||||
headers={"WWW-Authenticate": "Bearer"},
|
headers={"WWW-Authenticate": "Bearer"},
|
||||||
)
|
)
|
||||||
from fastapi import Response
|
|
||||||
try:
|
try:
|
||||||
# save this updated workflow to a new file
|
# save this updated workflow to a new file
|
||||||
new_workflow_file = item["prompt"]
|
new_workflow_file = item["prompt"]
|
||||||
@@ -266,11 +266,13 @@ class ComfyUI:
|
|||||||
fname = self.infer.local(new_workflow_file)
|
fname = self.infer.local(new_workflow_file)
|
||||||
if fname is None:
|
if fname is None:
|
||||||
raise RuntimeError("Output File not found")
|
raise RuntimeError("Output File not found")
|
||||||
j = {"file_name": fname}
|
j = {"status": "success", "file_name": fname}
|
||||||
print("json", j)
|
loguru.logger.success(j)
|
||||||
return Response(content=json.dumps(j), media_type="application/json")
|
return j
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise RuntimeError(str(e))
|
j = {"status":"fail", "msg": str(e)}
|
||||||
|
loguru.logger.error(j)
|
||||||
|
return j
|
||||||
finally:
|
finally:
|
||||||
print("Purge Garbage By Restart Comfy")
|
print("Purge Garbage By Restart Comfy")
|
||||||
cmd = "comfy stop"
|
cmd = "comfy stop"
|
||||||
@@ -282,7 +284,7 @@ class ComfyUI:
|
|||||||
try:
|
try:
|
||||||
subprocess.run(cmd, shell=True, check=True)
|
subprocess.run(cmd, shell=True, check=True)
|
||||||
except:
|
except:
|
||||||
raise Exception("Failed to launch ComfyUI")
|
pass
|
||||||
|
|
||||||
def poll_server_health(self):
|
def poll_server_health(self):
|
||||||
import socket
|
import socket
|
||||||
|
|||||||
Reference in New Issue
Block a user