volume work
This commit is contained in:
		
							parent
							
								
									60471a8e01
								
							
						
					
					
						commit
						7b61fea849
					
				@ -312,7 +312,9 @@ async def build_logic(item: Item):
 | 
				
			|||||||
    config = {
 | 
					    config = {
 | 
				
			||||||
        "name": item.name,
 | 
					        "name": item.name,
 | 
				
			||||||
        "deploy_test": os.environ.get("DEPLOY_TEST_FLAG", "False"),
 | 
					        "deploy_test": os.environ.get("DEPLOY_TEST_FLAG", "False"),
 | 
				
			||||||
        "gpu": item.gpu
 | 
					        "gpu": item.gpu,
 | 
				
			||||||
 | 
					        "public_checkpoint_volume": "model-store",
 | 
				
			||||||
 | 
					        "private_checkpoint_volume": "private-model-store"
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    with open(f"{folder_path}/config.py", "w") as f:
 | 
					    with open(f"{folder_path}/config.py", "w") as f:
 | 
				
			||||||
        f.write("config = " + json.dumps(config))
 | 
					        f.write("config = " + json.dumps(config))
 | 
				
			||||||
 | 
				
			|||||||
@ -7,6 +7,7 @@ import urllib.parse
 | 
				
			|||||||
from pydantic import BaseModel
 | 
					from pydantic import BaseModel
 | 
				
			||||||
from fastapi import FastAPI, Request
 | 
					from fastapi import FastAPI, Request
 | 
				
			||||||
from fastapi.responses import HTMLResponse
 | 
					from fastapi.responses import HTMLResponse
 | 
				
			||||||
 | 
					from volume import volumes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# deploy_test = False
 | 
					# deploy_test = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -28,9 +29,6 @@ web_app = FastAPI()
 | 
				
			|||||||
print(config)
 | 
					print(config)
 | 
				
			||||||
print("deploy_test ", deploy_test)
 | 
					print("deploy_test ", deploy_test)
 | 
				
			||||||
stub = Stub(name=config["name"])
 | 
					stub = Stub(name=config["name"])
 | 
				
			||||||
volume = modal.Volume.persisted("model-store")
 | 
					 | 
				
			||||||
MODEL_DIR = "/comfyui/models/checkpoints/"
 | 
					 | 
				
			||||||
# print(stub.app_id)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
if not deploy_test:
 | 
					if not deploy_test:
 | 
				
			||||||
    # dockerfile_image = Image.from_dockerfile(f"{current_directory}/Dockerfile", context_mount=Mount.from_local_dir(f"{current_directory}/data", remote_path="/data"))
 | 
					    # dockerfile_image = Image.from_dockerfile(f"{current_directory}/Dockerfile", context_mount=Mount.from_local_dir(f"{current_directory}/data", remote_path="/data"))
 | 
				
			||||||
@ -58,7 +56,7 @@ if not deploy_test:
 | 
				
			|||||||
        #     # Install comfy deploy
 | 
					        #     # Install comfy deploy
 | 
				
			||||||
        #     "cd /comfyui/custom_nodes && git clone https://github.com/BennyKok/comfyui-deploy.git",
 | 
					        #     "cd /comfyui/custom_nodes && git clone https://github.com/BennyKok/comfyui-deploy.git",
 | 
				
			||||||
        # )
 | 
					        # )
 | 
				
			||||||
        # .copy_local_file(f"{current_directory}/data/extra_model_paths.yaml", "/comfyui")
 | 
					        .copy_local_file(f"{current_directory}/data/extra_model_paths.yaml", "/comfyui")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        .copy_local_file(f"{current_directory}/data/start.sh", "/start.sh")
 | 
					        .copy_local_file(f"{current_directory}/data/start.sh", "/start.sh")
 | 
				
			||||||
        .run_commands("chmod +x /start.sh")
 | 
					        .run_commands("chmod +x /start.sh")
 | 
				
			||||||
@ -74,7 +72,6 @@ if not deploy_test:
 | 
				
			|||||||
        .copy_local_file(f"{current_directory}/data/deps.json", "/")
 | 
					        .copy_local_file(f"{current_directory}/data/deps.json", "/")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        .run_commands("python install_deps.py")
 | 
					        .run_commands("python install_deps.py")
 | 
				
			||||||
        .run_commands(f"rm -rf {MODEL_DIR}") # clear model dir so volume can mount, NOTE: could instead use the extra_model_paths
 | 
					 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Time to wait between API check attempts in milliseconds
 | 
					# Time to wait between API check attempts in milliseconds
 | 
				
			||||||
@ -156,10 +153,9 @@ image = Image.debian_slim()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
target_image = image if deploy_test else dockerfile_image
 | 
					target_image = image if deploy_test else dockerfile_image
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
@stub.function(image=target_image, gpu=config["gpu"]
 | 
					@stub.function(image=target_image, gpu=config["gpu"]
 | 
				
			||||||
               , volumes={MODEL_DIR: volume}
 | 
					   ,volumes=volumes 
 | 
				
			||||||
               )
 | 
					)
 | 
				
			||||||
def run(input: Input):
 | 
					def run(input: Input):
 | 
				
			||||||
    import subprocess
 | 
					    import subprocess
 | 
				
			||||||
    import time
 | 
					    import time
 | 
				
			||||||
@ -168,6 +164,7 @@ def run(input: Input):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    command = ["python", "main.py",
 | 
					    command = ["python", "main.py",
 | 
				
			||||||
               "--disable-auto-launch", "--disable-metadata"]
 | 
					               "--disable-auto-launch", "--disable-metadata"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    server_process = subprocess.Popen(command, cwd="/comfyui")
 | 
					    server_process = subprocess.Popen(command, cwd="/comfyui")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    check_server(
 | 
					    check_server(
 | 
				
			||||||
@ -241,8 +238,8 @@ async def bar(request_input: RequestInput):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@stub.function(image=image
 | 
					@stub.function(image=image
 | 
				
			||||||
    , volumes={MODEL_DIR: volume}
 | 
					   ,volumes=volumes
 | 
				
			||||||
           )
 | 
					)
 | 
				
			||||||
@asgi_app()
 | 
					@asgi_app()
 | 
				
			||||||
def comfyui_api():
 | 
					def comfyui_api():
 | 
				
			||||||
    return web_app
 | 
					    return web_app
 | 
				
			||||||
@ -292,7 +289,7 @@ def spawn_comfyui_in_background():
 | 
				
			|||||||
    # to be on a single container.
 | 
					    # to be on a single container.
 | 
				
			||||||
    concurrency_limit=1,
 | 
					    concurrency_limit=1,
 | 
				
			||||||
    timeout=10 * 60,
 | 
					    timeout=10 * 60,
 | 
				
			||||||
    volumes={MODEL_DIR: volume}
 | 
					    volumes=volumes,
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@asgi_app()
 | 
					@asgi_app()
 | 
				
			||||||
def comfyui_app():
 | 
					def comfyui_app():
 | 
				
			||||||
 | 
				
			|||||||
@ -1 +1,7 @@
 | 
				
			|||||||
config = {"name": "my-app", "deploy_test": "True", "gpu": "T4"}
 | 
					config = {
 | 
				
			||||||
 | 
					    "name": "my-app",
 | 
				
			||||||
 | 
					    "deploy_test": "True",
 | 
				
			||||||
 | 
					    "gpu": "T4", 
 | 
				
			||||||
 | 
					    "public_checkpoint_volume": "model-store",
 | 
				
			||||||
 | 
					    "private_checkpoint_volume": "private-model-store"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,11 +1,30 @@
 | 
				
			|||||||
comfyui:
 | 
					comfyui:
 | 
				
			||||||
    base_path: /runpod-volume/ComfyUI/
 | 
					  base_path: /extra_models/
 | 
				
			||||||
    checkpoints: models/checkpoints/
 | 
					  checkpoints: |
 | 
				
			||||||
    clip: models/clip/
 | 
					    checkpoints
 | 
				
			||||||
    clip_vision: models/clip_vision/
 | 
					    private_checkpoints
 | 
				
			||||||
    configs: models/configs/
 | 
					  clip: |
 | 
				
			||||||
    controlnet: models/controlnet/
 | 
					    clip
 | 
				
			||||||
    embeddings: models/embeddings/
 | 
					    private_clip
 | 
				
			||||||
    loras: models/loras/
 | 
					  clip_vision: |
 | 
				
			||||||
    upscale_models: models/upscale_models/
 | 
					    clip_vision
 | 
				
			||||||
    vae: models/vae/
 | 
					    private_clip_vision
 | 
				
			||||||
 | 
					  configs: |
 | 
				
			||||||
 | 
					    configs
 | 
				
			||||||
 | 
					    private_configs
 | 
				
			||||||
 | 
					  controlnet: |
 | 
				
			||||||
 | 
					    controlnet
 | 
				
			||||||
 | 
					    private_controlnet
 | 
				
			||||||
 | 
					  embeddings: |
 | 
				
			||||||
 | 
					    embeddings
 | 
				
			||||||
 | 
					    private_embeddings
 | 
				
			||||||
 | 
					  loras: |
 | 
				
			||||||
 | 
					    loras
 | 
				
			||||||
 | 
					    private_loras
 | 
				
			||||||
 | 
					  upscale_models: |
 | 
				
			||||||
 | 
					    upscale_models
 | 
				
			||||||
 | 
					    private_upscale_models
 | 
				
			||||||
 | 
					  vae: |
 | 
				
			||||||
 | 
					    vae
 | 
				
			||||||
 | 
					    private_vae
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,15 @@
 | 
				
			|||||||
 | 
					"""
 | 
				
			||||||
 | 
					This is a standalone script to download models into a modal Volume using civitai
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Example Usage
 | 
				
			||||||
 | 
					`modal run insert_models::insert_model --civitai-url https://civitai.com/models/36520/ghostmix`
 | 
				
			||||||
 | 
					This inserts an individual model from a civitai url (public not API url)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`modal run insert_models::insert_models` 
 | 
				
			||||||
 | 
					This inserts a bunch of models based on the models retrieved by civitai
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					civitai's API reference https://github.com/civitai/civitai/wiki/REST-API-Reference
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
import modal
 | 
					import modal
 | 
				
			||||||
import subprocess
 | 
					import subprocess
 | 
				
			||||||
import requests
 | 
					import requests
 | 
				
			||||||
@ -5,7 +17,7 @@ import requests
 | 
				
			|||||||
stub = modal.Stub()
 | 
					stub = modal.Stub()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# NOTE: volume name can be variable
 | 
					# NOTE: volume name can be variable
 | 
				
			||||||
volume = modal.Volume.persisted("model-store")
 | 
					volume = modal.Volume.persisted("private-model-store")
 | 
				
			||||||
model_store_path = "/vol/models"
 | 
					model_store_path = "/vol/models"
 | 
				
			||||||
MODEL_ROUTE = "models"
 | 
					MODEL_ROUTE = "models"
 | 
				
			||||||
image = (
 | 
					image = (
 | 
				
			||||||
@ -15,8 +27,10 @@ image = (
 | 
				
			|||||||
@stub.function(volumes={model_store_path: volume}, gpu="any", image=image, timeout=600)
 | 
					@stub.function(volumes={model_store_path: volume}, gpu="any", image=image, timeout=600)
 | 
				
			||||||
def download_model(model):
 | 
					def download_model(model):
 | 
				
			||||||
    # wget https://civitai.com/api/download/models/{modelVersionId} --content-disposition
 | 
					    # wget https://civitai.com/api/download/models/{modelVersionId} --content-disposition
 | 
				
			||||||
    model_id = model['modelVersions'][0]['id']
 | 
					    # model_id = model['modelVersions'][0]['id']
 | 
				
			||||||
    download_url = f"https://civitai.com/api/download/models/{model_id}"
 | 
					    # download_url = f"https://civitai.com/api/download/models/{model_id}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    download_url = model['modelVersions'][0]['downloadUrl'] 
 | 
				
			||||||
    subprocess.run(["wget", download_url, "--content-disposition", "-P", model_store_path])
 | 
					    subprocess.run(["wget", download_url, "--content-disposition", "-P", model_store_path])
 | 
				
			||||||
    subprocess.run(["ls", "-la", model_store_path])
 | 
					    subprocess.run(["ls", "-la", model_store_path])
 | 
				
			||||||
    volume.commit()  
 | 
					    volume.commit()  
 | 
				
			||||||
@ -34,11 +48,44 @@ def get_civitai_models(model_type: str, sort: str = "Highest Rated", page: int =
 | 
				
			|||||||
        print(f"Error fetching models: {e}")
 | 
					        print(f"Error fetching models: {e}")
 | 
				
			||||||
        return None
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@stub.function()
 | 
				
			||||||
 | 
					def get_civitai_model_url(civitai_url: str):
 | 
				
			||||||
 | 
					    # Validate the URL
 | 
				
			||||||
 | 
					    if not civitai_url.startswith("https://civitai.com/models/"):
 | 
				
			||||||
 | 
					        return "Error: URL must be from civitai.com and contain /models/"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Extract the model ID
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        model_id = civitai_url.split("/")[4]
 | 
				
			||||||
 | 
					        int(model_id)  # Check if the ID is an integer
 | 
				
			||||||
 | 
					    except (IndexError, ValueError):
 | 
				
			||||||
 | 
					        return None #Error: Invalid model ID in URL
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Make the API request
 | 
				
			||||||
 | 
					    api_url = f"https://civitai.com/api/v1/models/{model_id}"
 | 
				
			||||||
 | 
					    response = requests.get(api_url)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Check for successful response
 | 
				
			||||||
 | 
					    if response.status_code != 200:
 | 
				
			||||||
 | 
					        return f"Error: Unable to fetch data from {api_url}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Return the response data
 | 
				
			||||||
 | 
					    return response.json()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@stub.local_entrypoint()
 | 
					@stub.local_entrypoint()
 | 
				
			||||||
def insert_model(type: str = "Checkpoint", sort = "Highest Rated", page: int = 1):
 | 
					def insert_models(type: str = "Checkpoint", sort = "Highest Rated", page: int = 1):
 | 
				
			||||||
    civitai_models = get_civitai_models.local(type, sort, page)
 | 
					    civitai_models = get_civitai_models.local(type, sort, page)
 | 
				
			||||||
    if civitai_models:
 | 
					    if civitai_models:
 | 
				
			||||||
        for _ in download_model.map(civitai_models['items'][1:]):
 | 
					        for _ in download_model.map(civitai_models['items'][1:]):
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        print("Failed to retrieve models.")
 | 
					        print("Failed to retrieve models.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@stub.local_entrypoint()
 | 
				
			||||||
 | 
					def insert_model(civitai_url: str):
 | 
				
			||||||
 | 
					    civitai_model = get_civitai_model_url.local(civitai_url)
 | 
				
			||||||
 | 
					    if civitai_model: 
 | 
				
			||||||
 | 
					        download_model.remote(civitai_model)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										10
									
								
								builder/modal-builder/src/template/volume.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								builder/modal-builder/src/template/volume.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					import modal
 | 
				
			||||||
 | 
					from config import config
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public_model_volume = modal.Volume.persisted(config["public_checkpoint_volume"])
 | 
				
			||||||
 | 
					private_volume = modal.Volume.persisted(config["private_checkpoint_volume"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BASEMODEL_DIR = "/extra_models/"
 | 
				
			||||||
 | 
					MODEL_DIR = BASEMODEL_DIR + "checkpoints"
 | 
				
			||||||
 | 
					PRIVATE_MODEL_DIR = BASEMODEL_DIR + "private_checkpoints"
 | 
				
			||||||
 | 
					volumes = {MODEL_DIR: public_model_volume, PRIVATE_MODEL_DIR: private_volume}
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user