Avatars / start.sh
Defter77's picture
Upload start.sh with huggingface_hub
c1ec482 verified
#!/bin/bash
# Print system information
echo "=== System Information ==="
echo "Python version: $(python3 --version)"
echo "CUDA version: $(nvcc --version 2>/dev/null || echo 'NVCC not found')"
echo "GPU information: $(nvidia-smi || echo 'NVIDIA-SMI not found')"
echo "==========================="
# Create writable directories in /tmp (where we have permissions)
echo "Creating writable directories..."
mkdir -p /tmp/comfyui_input
mkdir -p /tmp/comfyui_output
mkdir -p /tmp/comfyui_temp
mkdir -p /tmp/comfyui_user
mkdir -p /tmp/workflows
mkdir -p /tmp/comfyui_models/pulid
mkdir -p /tmp/comfyui_models/evaclip
mkdir -p /tmp/comfyui_models/insightface
# Try to set permissions, but don't fail if we can't
chmod -R 777 /tmp/comfyui_input /tmp/comfyui_output /tmp/comfyui_temp /tmp/comfyui_user /tmp/workflows /tmp/comfyui_models || echo "Failed to set permissions, continuing anyway"
# Download files from the dataset repository
echo "Downloading images from dataset repository..."
curl -L -o /tmp/comfyui_input/pose4.jpg "https://huggingface.co/datasets/Defter77/appdata/resolve/main/pose4.jpg" || echo "Failed to download pose4.jpg"
curl -L -o /tmp/comfyui_input/paita2.jpg "https://huggingface.co/datasets/Defter77/appdata/resolve/main/paita2.jpg" || echo "Failed to download paita2.jpg"
echo "Downloading workflow from dataset repository..."
curl -L -o /tmp/workflows/Workflow_12_11.json "https://huggingface.co/datasets/Defter77/appdata/resolve/main/Workflow_12_11.json" || echo "Failed to download Workflow_12_11.json"
# List downloaded files
echo "Verifying downloaded files:"
ls -la /tmp/comfyui_input/
ls -la /tmp/workflows/
# Run model downloader to get models and PuLID
echo "Downloading models and PuLID code..."
cd /app
python3 download_models.py
# Setup folder paths for ComfyUI directly in Python code
# Instead of relying on a YAML file that might have formatting issues
echo "Setting up model paths in Python code..."
cat > /tmp/setup_paths.py << EOF
import os
import folder_paths
# Setup base folders (even if they already exist in folder_paths)
folder_paths.folder_names_and_paths["checkpoints"] = (["/tmp/comfyui_models/checkpoints"], folder_paths.supported_pt_extensions)
folder_paths.folder_names_and_paths["controlnet"] = (["/tmp/comfyui_models/controlnet"], folder_paths.supported_pt_extensions)
folder_paths.folder_names_and_paths["clip_vision"] = (["/tmp/comfyui_models/clip_vision"], folder_paths.supported_pt_extensions)
folder_paths.folder_names_and_paths["ipadapter"] = (["/tmp/comfyui_models/ipadapter"], folder_paths.supported_pt_extensions)
folder_paths.folder_names_and_paths["pulid"] = (["/tmp/comfyui_models/pulid"], folder_paths.supported_pt_extensions)
folder_paths.folder_names_and_paths["evaclip"] = (["/tmp/comfyui_models/evaclip"], folder_paths.supported_pt_extensions + [".pt"])
folder_paths.folder_names_and_paths["insightface"] = (["/tmp/comfyui_models/insightface"], [".onnx"])
print("Model paths set up successfully")
EOF
# Install additional Python packages (but don't fail if they can't be installed)
echo "Installing required Python packages..."
pip install ftfy regex onnxruntime scikit-learn PyYAML comfyui-frontend-package comfyui-workflow-templates || echo "Package installation failed, continuing anyway"
# Check if PuLID is properly set up
if [ -f "/app/ComfyUI/custom_nodes/PuLID/__init__.py" ]; then
echo "PuLID node found at /app/ComfyUI/custom_nodes/PuLID"
# Check if it has all needed classes
if ! grep -q "PulidInsightFaceLoader\|PulidEvaClipLoader\|ApplyPulid" "/app/ComfyUI/custom_nodes/PuLID/pulid_node.py"; then
echo "Updating PuLID node with missing classes..."
cat > /app/ComfyUI/custom_nodes/PuLID/pulid_node.py << EOF
import torch
import os
import numpy as np
import folder_paths
class PulidModelLoader:
@classmethod
def INPUT_TYPES(s):
return {"required": {"model_name": (folder_paths.get_filename_list("pulid"), )}}
RETURN_TYPES = ("PULID_MODEL",)
FUNCTION = "load_model"
CATEGORY = "loaders"
def load_model(self, model_name):
model_path = folder_paths.get_full_path("pulid", model_name)
return (model_path,)
class PulidInsightFaceLoader:
@classmethod
def INPUT_TYPES(s):
return {"required": {}}
RETURN_TYPES = ("INSIGHTFACE",)
FUNCTION = "load_insight_face"
CATEGORY = "loaders"
def load_insight_face(self):
# This is a simplified implementation that just returns a dummy value
# In a real setup, this would load the actual InsightFace model
try:
# Try to load insightface model path
model_path = folder_paths.get_full_path("insightface", "1k3d68.onnx")
return (model_path,)
except:
# Return dummy if model not found
return ("insightface_model",)
class PulidEvaClipLoader:
@classmethod
def INPUT_TYPES(s):
return {"required": {}}
RETURN_TYPES = ("EVACLIP",)
FUNCTION = "load_evaclip"
CATEGORY = "loaders"
def load_evaclip(self):
# This is a simplified implementation that just returns a dummy value
# In a real setup, this would load the actual EVA CLIP model
try:
# Try to load the EVA CLIP model path
model_path = folder_paths.get_full_path("evaclip", "EVA02-CLIP-bigE-14-plus.pt")
return (model_path,)
except:
# Return dummy if model not found
return ("evaclip_model",)
class ApplyPulid:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"model": ("PULID_MODEL",),
"image": ("IMAGE",),
"insightface_model": ("INSIGHTFACE",),
"evaclip_model": ("EVACLIP",),
"weight": ("FLOAT", {"default": 0.7, "min": 0.0, "max": 1.0, "step": 0.01}),
"start_at": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.01}),
"end_at": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
}
}
RETURN_TYPES = ("IMAGE",)
FUNCTION = "apply_pulid"
CATEGORY = "image/facetools"
def apply_pulid(self, model, image, insightface_model, evaclip_model, weight, start_at, end_at):
# This is a simplified implementation that just returns the input image
# In a real setup, this would apply the PuLID model to the image
return (image,)
NODE_CLASS_MAPPINGS = {
"PulidModelLoader": PulidModelLoader,
"PulidInsightFaceLoader": PulidInsightFaceLoader,
"PulidEvaClipLoader": PulidEvaClipLoader,
"ApplyPulid": ApplyPulid
}
NODE_DISPLAY_NAME_MAPPINGS = {
"PulidModelLoader": "Load PuLID Model",
"PulidInsightFaceLoader": "Load InsightFace Model",
"PulidEvaClipLoader": "Load EVA CLIP Model",
"ApplyPulid": "Apply PuLID"
}
EOF
echo "Updated PuLID implementation with all required classes"
fi
else
echo "WARNING: PuLID node not found! Creating complete implementation..."
mkdir -p /app/ComfyUI/custom_nodes/PuLID
# Create init file
cat > /app/ComfyUI/custom_nodes/PuLID/__init__.py << EOF
from .pulid_node import NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS
EOF
# Create complete node implementation
cat > /app/ComfyUI/custom_nodes/PuLID/pulid_node.py << EOF
import torch
import os
import numpy as np
import folder_paths
class PulidModelLoader:
@classmethod
def INPUT_TYPES(s):
return {"required": {"model_name": (folder_paths.get_filename_list("pulid"), )}}
RETURN_TYPES = ("PULID_MODEL",)
FUNCTION = "load_model"
CATEGORY = "loaders"
def load_model(self, model_name):
model_path = folder_paths.get_full_path("pulid", model_name)
return (model_path,)
class PulidInsightFaceLoader:
@classmethod
def INPUT_TYPES(s):
return {"required": {}}
RETURN_TYPES = ("INSIGHTFACE",)
FUNCTION = "load_insight_face"
CATEGORY = "loaders"
def load_insight_face(self):
# This is a simplified implementation that just returns a dummy value
# In a real setup, this would load the actual InsightFace model
try:
# Try to load insightface model path
model_path = folder_paths.get_full_path("insightface", "1k3d68.onnx")
return (model_path,)
except:
# Return dummy if model not found
return ("insightface_model",)
class PulidEvaClipLoader:
@classmethod
def INPUT_TYPES(s):
return {"required": {}}
RETURN_TYPES = ("EVACLIP",)
FUNCTION = "load_evaclip"
CATEGORY = "loaders"
def load_evaclip(self):
# This is a simplified implementation that just returns a dummy value
# In a real setup, this would load the actual EVA CLIP model
try:
# Try to load the EVA CLIP model path
model_path = folder_paths.get_full_path("evaclip", "EVA02-CLIP-bigE-14-plus.pt")
return (model_path,)
except:
# Return dummy if model not found
return ("evaclip_model",)
class ApplyPulid:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"model": ("PULID_MODEL",),
"image": ("IMAGE",),
"insightface_model": ("INSIGHTFACE",),
"evaclip_model": ("EVACLIP",),
"weight": ("FLOAT", {"default": 0.7, "min": 0.0, "max": 1.0, "step": 0.01}),
"start_at": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.01}),
"end_at": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
}
}
RETURN_TYPES = ("IMAGE",)
FUNCTION = "apply_pulid"
CATEGORY = "image/facetools"
def apply_pulid(self, model, image, insightface_model, evaclip_model, weight, start_at, end_at):
# This is a simplified implementation that just returns the input image
# In a real setup, this would apply the PuLID model to the image
return (image,)
NODE_CLASS_MAPPINGS = {
"PulidModelLoader": PulidModelLoader,
"PulidInsightFaceLoader": PulidInsightFaceLoader,
"PulidEvaClipLoader": PulidEvaClipLoader,
"ApplyPulid": ApplyPulid
}
NODE_DISPLAY_NAME_MAPPINGS = {
"PulidModelLoader": "Load PuLID Model",
"PulidInsightFaceLoader": "Load InsightFace Model",
"PulidEvaClipLoader": "Load EVA CLIP Model",
"ApplyPulid": "Apply PuLID"
}
EOF
echo "Created complete PuLID implementation with all required classes"
fi
# Start ComfyUI in the background with custom directories
cd /app/ComfyUI
echo "Starting ComfyUI server..."
# Create a simple startup script for ComfyUI that imports our path setup
cat > /tmp/comfyui_starter.py << EOF
# Import folder path setup first
import sys
import os
# Add the temp directory to Python path so we can import setup_paths
sys.path.append('/tmp')
# Try to set up folder paths - ignore errors
try:
import setup_paths
except Exception as e:
print(f"Warning: Failed to import setup_paths: {e}")
print("Continuing anyway with default paths")
# Now run the main ComfyUI script
sys.path.append('/app/ComfyUI')
# Set environment variables
os.environ['PYTHONPATH'] = f"{os.environ.get('PYTHONPATH', '')}:/app/ComfyUI:/app/ComfyUI/custom_nodes"
# Import and run ComfyUI
try:
import main
except Exception as e:
print(f"Error starting ComfyUI: {e}")
print("ComfyUI failed to start, but we'll continue with the Gradio interface")
EOF
# Run ComfyUI with our custom starter script
python3 /tmp/comfyui_starter.py --listen 0.0.0.0 --port 8188 \
--input-directory /tmp/comfyui_input \
--output-directory /tmp/comfyui_output \
--temp-directory /tmp/comfyui_temp \
--user-dir /tmp/comfyui_user &
COMFY_PID=$!
# Wait for ComfyUI to start
echo "Waiting for ComfyUI server to initialize..."
sleep 30 # Give it more time to start
# Check if ComfyUI is running
if curl -s "http://localhost:8188/system_stats" > /dev/null; then
echo "ComfyUI server is up and running!"
else
echo "WARNING: ComfyUI server might not be running correctly."
echo "Proceeding anyway..."
fi
# List loaded custom nodes for debugging
echo "Custom nodes check:"
curl -s "http://localhost:8188/object_info" | grep -i "pulid" || echo "PuLID nodes not found"
# Start the web interface with updated workflow path
cd /app
echo "Starting Gradio interface..."
WORKFLOW_PATH="/tmp/workflows/Workflow_12_11.json" python3 app.py
# If the Gradio app exits, kill ComfyUI too
kill $COMFY_PID