Compare commits

...

103 Commits

Author SHA1 Message Date
2189697734 refactor: remove type field from models_huggingface.yaml and include type in dest paths
All checks were successful
Build and Push RunPod Docker Image / build-and-push (push) Successful in 14s
- Prepended ComfyUI model type folder (checkpoints/, clip/, vae/, etc.) to all dest paths
- Removed separate 'type' field from all model entries
- Consolidated SD3.5 duplicate entries (5 → 1)
- Simplified model configuration by embedding directory structure directly in destination paths

This change eliminates the need to parse the 'type' field separately in artifact_huggingface_download.sh,
making the configuration more explicit and easier to understand.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 19:19:42 +01:00
ff6c1369ae feat: add three new SDXL/SD1.5 image generation models
All checks were successful
Build and Push RunPod Docker Image / build-and-push (push) Successful in 14s
Add the following models to models_huggingface.yaml:
- John6666/diving-illustrious-real-asian-v50-sdxl: SDXL fine-tune for photorealistic Asian subjects
- playgroundai/playground-v2.5-1024px-aesthetic: High-aesthetic 1024px SDXL-based model
- Lykon/dreamshaper-8: Versatile SD1.5 fine-tune with multi-style support

All models marked as non-essential and will download .safetensors files.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 17:29:04 +01:00
aa2cc5973b fix: update CogVideoX models to link sharded transformer files
All checks were successful
Build and Push RunPod Docker Image / build-and-push (push) Successful in 14s
- CogVideoX-5b: Link 2 shards + index.json instead of single non-existent file
- CogVideoX-5b-I2V: Link 3 shards + index.json instead of single non-existent file  - Fixes link command failures for these video generation models
- Shards are now properly symlinked to ComfyUI diffusion_models directory

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 15:47:09 +01:00
3c6904a253 feat: add comfyui-workspace-manager custom node
All checks were successful
Build and Push RunPod Docker Image / build-and-push (push) Successful in 14s
Added comfyui-workspace-manager plugin to arty.yml for ComfyUI workflow and model management.

Repository: https://github.com/11cafe/comfyui-workspace-manager

Features:
- Workflow management with version history
- Model browser with one-click CivitAI downloads
- Image gallery per workflow
- Auto-save and keyboard shortcuts

Note: Plugin is marked as obsolete (April 2025) as ComfyUI now has built-in workspace features, but added per user request.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 12:33:00 +01:00
6efb55c59f feat: add complete HunyuanVideo and Wan2.2 video generation integration
All checks were successful
Build and Push RunPod Docker Image / build-and-push (push) Successful in 15s
Integrated 35+ video generation models and 13 production workflows from ComfyUI docs tutorials for state-of-the-art text-to-video and image-to-video generation.

Models Added (models_huggingface.yaml):
- HunyuanVideo (5 models): Original T2V/I2V (720p), v1.5 (720p/1080p) with Qwen 2.5 VL
- Wan2.2 diffusion models (18 models):
  - 5B TI2V hybrid (8GB VRAM, efficient)
  - 14B variants: T2V, I2V (high/low noise), Animate, S2V (FP8/BF16), Fun Camera/Control (high/low noise)
- Support models (12): VAEs, UMT5-XXL, CLIP Vision H, Wav2Vec2, LLaVA encoders
- LoRA accelerators (4): Lightx2v 4-step distillation for 5x speedup

Workflows Added (comfyui/workflows/image-to-video/):
- HunyuanVideo (5 workflows): T2V original, I2V v1/v2 (webp embedded), v1.5 T2V/I2V (JSON)
- Wan2.2 (8 workflows): 5B TI2V, 14B T2V/I2V/FLF2V/Animate/S2V/Fun Camera/Fun Control
- Asset files (10): Reference images, videos, audio for workflow testing

Custom Nodes Added (arty.yml):
- ComfyUI-KJNodes: Kijai optimizations for HunyuanVideo/Wan2.2 (FP8 scaling, video helpers)
- comfyui_controlnet_aux: ControlNet preprocessors (Canny, Depth, OpenPose, MLSD) for Fun Control
- ComfyUI-GGUF: GGUF quantization support for memory optimization

VRAM Requirements:
- HunyuanVideo original: 24GB (720p T2V/I2V, 129 frames, 5s generation)
- HunyuanVideo 1.5: 30-60GB (720p/1080p, improved quality with Qwen 2.5 VL)
- Wan2.2 5B: 8GB (efficient dual-expert architecture with native offloading)
- Wan2.2 14B: 24GB (high-quality video generation, all modes)

Note: Wan2.2 Fun Inpaint workflow not available in official templates repository (404).

Tutorial Sources:
- https://docs.comfy.org/tutorials/video/hunyuan/hunyuan-video
- https://docs.comfy.org/tutorials/video/hunyuan/hunyuan-video-1-5
- https://docs.comfy.org/tutorials/video/wan/wan2_2
- https://docs.comfy.org/tutorials/video/wan/wan2-2-animate
- https://docs.comfy.org/tutorials/video/wan/wan2-2-s2v
- https://docs.comfy.org/tutorials/video/wan/wan2-2-fun-camera
- https://docs.comfy.org/tutorials/video/wan/wan2-2-fun-control

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 10:43:39 +01:00
06b8ec0064 refactor: remove simple ACE Step workflow in favor of official workflows
All checks were successful
Build and Push RunPod Docker Image / build-and-push (push) Successful in 14s
Removed acestep-simple-t2m-v1.json as the official Comfy-Org workflows provide better quality:
- acestep-official-t2m-v1.json - Advanced T2M with specialized nodes
- acestep-m2m-editing-v1.json - Music-to-music editing capability

🤖 Generated with Claude Code (https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 09:46:24 +01:00
e610330b91 feat: add official Comfy-Org ACE Step workflows and example assets
All checks were successful
Build and Push RunPod Docker Image / build-and-push (push) Successful in 14s
Added 2 official workflows from Comfy-Org/example_workflows:
- acestep-official-t2m-v1.json - Advanced T2M with specialized nodes (50 steps, multiple formats)
- acestep-m2m-editing-v1.json - Music-to-music editing with denoise control

Added 3 audio example assets:
- acestep-m2m-input.mp3 (973 KB) - Example input for M2M editing
- acestep-t2m-output.flac (3.4 MB) - T2M output reference
- acestep-m2m-output.mp3 (998 KB) - M2M output reference

Total: 3 workflows (simple + official T2M + M2M editing) with audio examples

🤖 Generated with Claude Code (https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 09:34:57 +01:00
55b37894b1 fix: remove empty ACE Step workflow placeholders
All checks were successful
Build and Push RunPod Docker Image / build-and-push (push) Successful in 13s
Removed 3 empty placeholder workflows that only contained metadata:
- acestep-multilang-t2m-v1.json
- acestep-remix-m2m-v1.json
- acestep-chinese-rap-v1.json

Kept only the functional workflow:
- acestep-simple-t2m-v1.json (6 nodes, fully operational)

Users can use the simple workflow and modify the prompt for different use cases:
- Multi-language: prefix lyrics with language tags like [zh], [ja], [ko]
- Remixing: load audio input and adjust denoise strength (0.1-0.7)
- Chinese RAP: use Chinese RAP LoRA with strength 0.8-1.0

🤖 Generated with Claude Code (https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 08:51:37 +01:00
513062623c feat: integrate ACE Step music generation with 19-language support
All checks were successful
Build and Push RunPod Docker Image / build-and-push (push) Successful in 14s
Added ACE Step v1 3.5B model for state-of-the-art music generation:
- 15x faster than LLM baselines with superior structural coherence
- Supports 19 languages (en, zh, ja, ko, fr, es, de, it, pt, ru + 9 more)
- Voice cloning, lyric alignment, and multi-genre capabilities

Changes:
- Added ACE Step models to models_huggingface.yaml (checkpoint + Chinese RAP LoRA)
- Added ComfyUI_ACE-Step custom node to arty.yml with installation script
- Created 4 comprehensive workflows in comfyui/workflows/text-to-music/:
  * acestep-simple-t2m-v1.json - Basic 60s text-to-music generation
  * acestep-multilang-t2m-v1.json - 19-language music generation
  * acestep-remix-m2m-v1.json - Music-to-music remixing with style transfer
  * acestep-chinese-rap-v1.json - Chinese hip-hop with specialized LoRA

🤖 Generated with Claude Code (https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 08:40:17 +01:00
5af3eeb333 feat: add BGE embedding service and reorganize supervisor groups
All checks were successful
Build and Push RunPod Docker Image / build-and-push (push) Successful in 14s
- Add vLLM embedding server for BAAI/bge-large-en-v1.5 (port 8002)
- Reorganize supervisor into two logical groups:
  - comfyui-services: comfyui, webdav-sync
  - vllm-services: vllm-qwen, vllm-llama, vllm-embedding
- Update arty.yml service management scripts for new group structure
- Add individual service control scripts for all vLLM models

Note: Embedding server currently uses placeholder implementation
For production use, switch to sentence-transformers or native vLLM embedding mode

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 06:32:01 +01:00
e12a8add61 feat: add vLLM models configuration file
All checks were successful
Build and Push RunPod Docker Image / build-and-push (push) Successful in 35s
Add models_huggingface_vllm.yaml with three vLLM models:
- Qwen/Qwen2.5-7B-Instruct (14GB) - Advanced multilingual reasoning
- meta-llama/Llama-3.1-8B-Instruct (17GB) - Extended 128K context
- BAAI/bge-large-en-v1.5 (1.3GB) - High-quality text embeddings

Total storage: ~32GB

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 06:12:18 +01:00
6ce989dd91 Remove unused diffrhythm-random-generation workflow
All checks were successful
Build and Push RunPod Docker Image / build-and-push (push) Successful in 15s
Removed diffrhythm-random-generation-v1.json as it's no longer needed.
Keeping only the essential DiffRhythm workflows:
- simple text-to-music (95s)
- full-length generation (4m45s)
- reference-based style transfer

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 20:34:53 +01:00
d74a7cb7cb fix: replace custom Pivoine node with direct DiffRhythm patch
All checks were successful
Build and Push RunPod Docker Image / build-and-push (push) Successful in 14s
- Remove custom PivoineDiffRhythmRun wrapper node
- Add git patch file for ComfyUI_DiffRhythm __init__.py
- Patch adds LlamaConfig fix at import time
- Add arty script 'fix/diffrhythm-patch' to apply patch
- Revert all workflows to use original DiffRhythmRun
- Remove startup_patch.py and revert start.sh

This approach is cleaner and more maintainable than wrapping the node.
The patch directly fixes the tensor dimension mismatch (32 vs 64) in
DiffRhythm's rotary position embeddings by ensuring num_attention_heads
and num_key_value_heads are properly set based on hidden_size.

References:
- https://github.com/billwuhao/ComfyUI_DiffRhythm/issues/44
- https://github.com/billwuhao/ComfyUI_DiffRhythm/issues/48
2025-11-24 19:27:18 +01:00
f74457b049 fix: apply LlamaConfig patch globally at import time
All checks were successful
Build and Push RunPod Docker Image / build-and-push (push) Successful in 14s
Previous approach patched DiT.__init__ at runtime, but models were already
instantiated and cached. This version patches LlamaConfig globally BEFORE
any DiffRhythm imports, ensuring all model instances use the correct config.

Key changes:
- Created PatchedLlamaConfig subclass that auto-calculates attention heads
- Replaced LlamaConfig in transformers.models.llama module at import time
- Patch applies to all LlamaConfig instances, including pre-loaded models

This should finally fix the tensor dimension mismatch error.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 19:00:29 +01:00
91f6e9bd59 fix: patch DiffRhythm DIT to add missing LlamaConfig attention head parameters
All checks were successful
Build and Push RunPod Docker Image / build-and-push (push) Successful in 15s
Adds monkey-patch for DiT.__init__() to properly configure LlamaConfig with
num_attention_heads and num_key_value_heads parameters, which are missing
in the upstream DiffRhythm code.

Root cause: transformers 4.49.0+ requires these parameters but DiffRhythm's
dit.py only specifies hidden_size, causing the library to incorrectly infer
head_dim as 32 instead of 64, leading to tensor dimension mismatches.

Solution:
- Sets num_attention_heads = hidden_size // 64 (standard Llama architecture)
- Sets num_key_value_heads = num_attention_heads // 4 (GQA configuration)
- Ensures head_dim = 64, fixing the "tensor a (32) vs tensor b (64)" error

This is a proper fix rather than just downgrading transformers version.

References:
- https://github.com/billwuhao/ComfyUI_DiffRhythm/issues/44
- https://github.com/billwuhao/ComfyUI_DiffRhythm/issues/48

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 18:53:18 +01:00
60ca8b08d0 feat: add arty script to fix DiffRhythm transformers version
All checks were successful
Build and Push RunPod Docker Image / build-and-push (push) Successful in 14s
Adds 'fix/diffrhythm-transformers' command to quickly downgrade
transformers library to 4.49.0 for DiffRhythm compatibility.

Usage: arty fix/diffrhythm-transformers

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 18:15:30 +01:00
8c4eb8c3f1 fix: pin transformers to 4.49.0 for DiffRhythm compatibility
All checks were successful
Build and Push RunPod Docker Image / build-and-push (push) Successful in 13s
Resolves tensor dimension mismatch error in rotary position embeddings.
DiffRhythm requires transformers 4.49.0 - newer versions (4.50+) cause
"The size of tensor a (32) must match the size of tensor b (64)" error
due to transformer block initialization changes.

Updated pivoine_diffrhythm.py documentation to reflect actual root cause
and link to upstream GitHub issues #44 and #48.

References:
- https://github.com/billwuhao/ComfyUI_DiffRhythm/issues/44
- https://github.com/billwuhao/ComfyUI_DiffRhythm/issues/48

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 18:14:40 +01:00
67d41c3923 fix: patch infer_utils.decode_audio instead of DiffRhythmNode.infer
All checks were successful
Build and Push RunPod Docker Image / build-and-push (push) Successful in 13s
The correct function to patch is decode_audio from infer_utils module,
which is where chunked VAE decoding actually happens. This intercepts
the call at the right level to force chunked=False.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 17:28:30 +01:00
1981b7b256 fix: monkey-patch DiffRhythm infer function to force chunked=False
All checks were successful
Build and Push RunPod Docker Image / build-and-push (push) Successful in 14s
The previous approach of overriding diffrhythmgen wasn't working because
ComfyUI doesn't pass the chunked parameter when it's not in INPUT_TYPES.
This fix monkey-patches the infer() function at module level to always
force chunked=False, preventing the tensor dimension mismatch error.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 17:24:22 +01:00
5096e3ffb5 feat: add Pivoine custom ComfyUI nodes for DiffRhythm
All checks were successful
Build and Push RunPod Docker Image / build-and-push (push) Successful in 14s
Add custom node wrapper PivoineDiffRhythmRun that fixes tensor dimension
mismatch error by disabling chunked VAE decoding. The original DiffRhythm
node's overlap=32 parameter conflicts with the VAE's 64-channel architecture.

Changes:
- Add comfyui/nodes/pivoine_diffrhythm.py: Custom node wrapper
- Add comfyui/nodes/__init__.py: Package initialization
- Add arty.yml setup/pivoine-nodes: Deployment script for symlink
- Update all 4 DiffRhythm workflows to use PivoineDiffRhythmRun

Technical details:
- Inherits from DiffRhythmRun to avoid upstream patching
- Forces chunked=False in diffrhythmgen() override
- Requires more VRAM (~12-16GB) but RTX 4090 has 24GB
- Category: 🌸Pivoine/Audio for easy identification

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 16:28:54 +01:00
073711c017 fix: use correct DiffRhythm parameter order from UI testing
All checks were successful
Build and Push RunPod Docker Image / build-and-push (push) Successful in 14s
Correct widgets_values order (11 parameters):
0: model (string)
1: prompt/style_prompt (text)
2: unload_model (boolean)
3: odeint_method (enum)
4: steps (int)
5: cfg (int)
6: quality_or_speed (enum)
7: seed (int)
8: control_after_generate (string)
9: edit (boolean)
10: segments/edit_segments (text)

Updated all four workflows:
- diffrhythm-simple-t2m-v1.json
- diffrhythm-random-generation-v1.json
- diffrhythm-reference-based-v1.json
- diffrhythm-full-length-t2m-v1.json

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 15:57:25 +01:00
279f703591 fix: correct DiffRhythm workflow parameter order to match function signature
All checks were successful
Build and Push RunPod Docker Image / build-and-push (push) Successful in 14s
The parameters must match the diffrhythmgen() function signature order,
not the INPUT_TYPES order. The function has 'edit' as the first parameter.

Correct widgets_values order (11 parameters):
0: edit (boolean)
1: model (string)
2: style_prompt (string)
3: lyrics_or_edit_lyrics (string)
4: edit_segments (string)
5: odeint_method (enum)
6: steps (int)
7: cfg (int)
8: quality_or_speed (enum)
9: unload_model (boolean)
10: seed (int)

Note: style_audio_or_edit_song comes from input connection (not in widgets)
Note: chunked parameter is hidden (not in widgets)

Updated workflows:
- diffrhythm-simple-t2m-v1.json
- diffrhythm-random-generation-v1.json
- diffrhythm-reference-based-v1.json
- diffrhythm-full-length-t2m-v1.json

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 15:53:15 +01:00
64db634ab5 fix: correct DiffRhythm workflow parameter order for all three workflows
All checks were successful
Build and Push RunPod Docker Image / build-and-push (push) Successful in 15s
Changed edit_segments from "[-1, 20], [60, -1]" to empty string "" at position 11.
This fixes validation errors where parameters were being interpreted as wrong types.

The correct 12-parameter structure is:
0: model (string)
1: style_prompt (string)
2: unload_model (boolean)
3: odeint_method (enum)
4: steps (int)
5: cfg (int)
6: quality_or_speed (enum)
7: seed (int)
8: edit (boolean)
9: edit_lyrics (string, empty)
10: edit_song (string, empty)
11: edit_segments (string, empty)

Updated workflows:
- diffrhythm-random-generation-v1.json
- diffrhythm-reference-based-v1.json
- diffrhythm-full-length-t2m-v1.json

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 15:48:56 +01:00
56476f4230 fix: add missing edit_song and edit_lyrics parameters to DiffRhythm workflows
All checks were successful
Build and Push RunPod Docker Image / build-and-push (push) Successful in 14s
Fix "edit song, edit lyrics, edit segments must be provided" error by adding
the two missing parameters to all three DiffRhythm workflow files:

- diffrhythm-random-generation-v1.json
- diffrhythm-reference-based-v1.json
- diffrhythm-full-length-t2m-v1.json

Added empty string parameters at positions 9 and 10 in widgets_values array:
- edit_song: "" (empty when edit=false)
- edit_lyrics: "" (empty when edit=false)

The DiffRhythmRun node requires 12 parameters total, not 10. These workflows
use edit=false (no editing), so the edit parameters should be empty strings.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 12:55:58 +01:00
744bbd0190 fix: correct FFmpeg version extraction in verification
All checks were successful
Build and Push RunPod Docker Image / build-and-push (push) Successful in 14s
2025-11-24 12:49:41 +01:00
b011c192f8 feat: add FFmpeg dependencies to system packages
All checks were successful
Build and Push RunPod Docker Image / build-and-push (push) Successful in 14s
Add FFmpeg and its development libraries to setup/system-packages script:
- ffmpeg: Main FFmpeg executable
- libavcodec-dev: Audio/video codec library
- libavformat-dev: Audio/video format library
- libavutil-dev: Utility library for FFmpeg
- libswscale-dev: Video scaling library

These libraries are required for torchcodec to function properly with
DiffRhythm audio generation. Also added FFmpeg version verification
after installation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 12:48:57 +01:00
a249dfc941 feat: add torchcodec dependency for DiffRhythm audio caching
All checks were successful
Build and Push RunPod Docker Image / build-and-push (push) Successful in 14s
Add torchcodec to ComfyUI requirements.txt to fix audio tensor caching
error in DiffRhythm. This package is required for save_with_torchcodec
function used by DiffRhythm audio nodes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 12:44:05 +01:00
19376d90a7 feat: add DiffRhythm eval-model download script
All checks were successful
Build and Push RunPod Docker Image / build-and-push (push) Successful in 15s
Add arty script to download eval.yaml and eval.safetensors files from
HuggingFace space for DiffRhythm node support. These files are required
for DiffRhythm evaluation model functionality.

- Add models/diffrhythm-eval script to download eval-model files
- Update setup/comfyui-nodes to create eval-model directory
- Files downloaded from ASLP-lab/DiffRhythm HuggingFace space
- Script includes file verification and size reporting

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 12:38:44 +01:00
cf3fcafbae feat: add DiffRhythm music generation support
All checks were successful
Build and Push RunPod Docker Image / build-and-push (push) Successful in 15s
- Add DiffRhythm dependencies to requirements.txt (19 packages)
- Add reference audio placeholder for style transfer workflow
- DiffRhythm nodes now loading in ComfyUI
- All four workflows ready for music generation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 12:17:46 +01:00
8fe87064f8 feat: add DiffRhythm dependencies to ComfyUI requirements
All checks were successful
Build and Push RunPod Docker Image / build-and-push (push) Successful in 14s
Added all required packages for ComfyUI_DiffRhythm extension:
- torchdiffeq: ODE solvers for diffusion models
- x-transformers: Transformer architecture components
- librosa: Audio analysis and feature extraction
- pandas, pyarrow: Data handling
- ema-pytorch, prefigure: Training utilities
- muq: Music quality model
- mutagen: Audio metadata handling
- pykakasi, jieba, cn2an, pypinyin: Chinese/Japanese text processing
- Unidecode, phonemizer, inflect: Text normalization and phonetic conversion
- py3langid: Language identification

These dependencies enable the DiffRhythm node to load and function properly in ComfyUI, fixing the "ModuleNotFoundError: No module named 'infer_utils'" error.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 10:51:50 +01:00
44762a063c fix: update DiffRhythm workflows with correct node names and parameters
All checks were successful
Build and Push RunPod Docker Image / build-and-push (push) Successful in 14s
Updated all 4 DiffRhythm workflow JSON files to use actual node class names from ComfyUI_DiffRhythm:

**Node Name Changes:**
- DiffRhythmTextToMusic → DiffRhythmRun
- DiffRhythmRandomGeneration → DiffRhythmRun (with empty style_prompt)
- DiffRhythmReferenceBasedGeneration → DiffRhythmRun (with audio input)

**Corrected Parameter Structure:**
All workflows now use proper widgets_values array matching DiffRhythmRun INPUT_TYPES:
1. model (string: "cfm_model_v1_2.pt", "cfm_model.pt", or "cfm_full_model.pt")
2. style_prompt (string: multiline text or empty for random)
3. unload_model (boolean: default true)
4. odeint_method (string: "euler", "midpoint", "rk4", "implicit_adams")
5. steps (int: 1-100, default 30)
6. cfg (int: 1-10, default 4)
7. quality_or_speed (string: "quality" or "speed")
8. seed (int: -1 for random, or specific number)
9. edit (boolean: default false)
10. edit_segments (string: "[-1, 20], [60, -1]")

**Workflow-Specific Updates:**

**diffrhythm-simple-t2m-v1.json:**
- Text-to-music workflow for 95s generation
- Uses cfm_model_v1_2.pt with text prompt guidance
- Default settings: steps=30, cfg=4, speed mode, seed=42

**diffrhythm-full-length-t2m-v1.json:**
- Full-length 4m45s (285s) generation
- Uses cfm_full_model.pt for extended compositions
- Quality mode enabled for better results
- Default seed=123

**diffrhythm-reference-based-v1.json:**
- Reference audio + text prompt workflow
- Uses LoadAudio node connected to style_audio_or_edit_song input
- Higher cfg=5 for stronger prompt adherence
- Demonstrates optional audio input connection

**diffrhythm-random-generation-v1.json:**
- Pure random generation (no prompt/guidance)
- Empty style_prompt string
- Minimal cfg=1 for maximum randomness
- Random seed=-1 for unique output each time

**Documentation Updates:**
- Removed PLACEHOLDER notes
- Updated usage sections with correct parameter descriptions
- Added notes about optional MultiLineLyricsDR node for lyrics
- Clarified parameter behavior and recommendations

These workflows are now ready to use in ComfyUI with the installed DiffRhythm extension.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 10:46:31 +01:00
e9a1536f1d chore: clean up arty.yml - remove unused scripts and envs
All checks were successful
Build and Push RunPod Docker Image / build-and-push (push) Successful in 14s
- Remove deprecated legacy setup scripts
- Remove unused environment definitions (prod, dev, minimal)
- Remove WebDAV setup script
- Remove redundant model linking script
- Streamline configuration

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 10:26:52 +01:00
f2186db78e feat: integrate ComfyUI_DiffRhythm extension with 7 models and 4 workflows
All checks were successful
Build and Push RunPod Docker Image / build-and-push (push) Successful in 15s
- Add DiffRhythm to arty.yml references and setup/comfyui-nodes
- Install espeak-ng system dependency for phoneme processing
- Add 7 DiffRhythm models to models_huggingface.yaml with file mappings:
  * ASLP-lab/DiffRhythm-1_2 (95s generation)
  * ASLP-lab/DiffRhythm-full (4m45s generation)
  * ASLP-lab/DiffRhythm-base
  * ASLP-lab/DiffRhythm-vae
  * OpenMuQ/MuQ-MuLan-large
  * OpenMuQ/MuQ-large-msd-iter
  * FacebookAI/xlm-roberta-base
- Create 4 comprehensive workflows:
  * diffrhythm-simple-t2m-v1.json (basic 95s text-to-music)
  * diffrhythm-full-length-t2m-v1.json (4m45s full-length)
  * diffrhythm-reference-based-v1.json (style transfer with reference audio)
  * diffrhythm-random-generation-v1.json (no-prompt random generation)
- Update storage requirements: 90GB essential, 149GB total

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 09:50:45 +01:00
9439185b3d fix: update Docker registry from Docker Hub to dev.pivoine.art
All checks were successful
Build and Push RunPod Docker Image / build-and-push (push) Successful in 2m8s
- Use Gitea container registry instead of Docker Hub
- Update workflow to use gitea.actor and REGISTRY_TOKEN
- Update documentation to reflect correct registry URL
- Match supervisor-ui workflow configuration
2025-11-23 21:57:14 +01:00
571431955d feat: add RunPod Docker template with automated build workflow
- Add Dockerfile with minimal setup (supervisor, tailscale)
- Add start.sh bootstrap script for container initialization
- Add Gitea workflow for automated Docker image builds
- Add comprehensive RUNPOD_TEMPLATE.md documentation
- Add bootstrap-venvs.sh for Python venv health checks

This enables deployment of the AI orchestrator on RunPod using:
- Minimal Docker image (~2-3GB) for fast deployment
- Network volume for models and data persistence (~80-200GB)
- Automated builds on push to main or version tags
- Full Tailscale VPN integration
- Supervisor process management
2025-11-23 21:53:56 +01:00
0e3150e26c fix: correct Pony Diffusion workflow checkpoint reference
- Changed checkpoint from waiIllustriousSDXL_v150.safetensors to ponyDiffusionV6XL_v6StartWithThisOne.safetensors
- Fixed metadata model reference (was incorrectly referencing LoRA)
- Added files field to models_civitai.yaml for explicit filename mapping
- Aligns workflow with actual Pony Diffusion V6 XL model
2025-11-23 19:57:45 +01:00
f6de19bec1 feat: add files field for embeddings with different filenames
- Add files field to badx-sdxl, pony-pdxl-hq-v3, pony-pdxl-xxx
- Specifies actual downloaded filenames (BadX-neg.pt, zPDXL3.safetensors, zPDXLxxx.pt)
- Allows script to properly link embeddings where YAML name != filename
2025-11-23 19:54:41 +01:00
5770563d9a feat: add comprehensive negative embeddings support (SD 1.5, SDXL, Pony)
- Add 3 new embedding categories to models_civitai.yaml:
  - embeddings_sd15: 6 embeddings (BadDream, UnrealisticDream, badhandv4, EasyNegative, FastNegativeV2, BadNegAnatomyV1-neg)
  - embeddings_sdxl: 1 embedding (BadX v1.1)
  - embeddings_pony: 2 embeddings (zPDXL3, zPDXLxxx)
- Total storage: ~1.1 MB (9 embeddings)
- Add comprehensive embeddings documentation to NSFW README
- Include usage examples, compatibility notes, and syntax guide
- Document embedding weights and recommended combinations
2025-11-23 19:39:18 +01:00
68d3606cab fix: use WAI-NSFW-Illustrious checkpoint instead of non-existent Pony model
Changed checkpoint from 'add-detail-xl.safetensors' (which is a LoRA) to
'waiIllustriousSDXL_v150.safetensors' which is the downloaded anime NSFW model
2025-11-23 19:13:22 +01:00
9ca62724d0 feat: add LoRA models category to CivitAI config with add-detail-xl and siesta 2025-11-23 19:04:19 +01:00
5e7c65a95c feat: add NSFW workflow linking to arty workflow manager
Updated arty.yml workflow linking script to include NSFW workflows:
- Added nsfw_ prefix for NSFW workflow category
- Links 4 NSFW workflows (LUSTIFY, Pony, RealVisXL, Ultimate Upscale)
- Updated workflow count from 20 to 25 total production workflows
- Updated documentation to list all 7 workflow categories

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 18:48:46 +01:00
1d851bb11c feat: add NSFW ComfyUI workflow suite with LoRA fusion and upscaling
Added 5 production-ready workflows to leverage downloaded CivitAI NSFW models:

**NSFW Text-to-Image Workflows (3):**
- lustify-realistic-t2i-production-v1.json - Photorealistic NSFW with LUSTIFY v7.0
  - DPM++ 2M SDE, Exponential scheduler, 30 steps, CFG 6.0
  - Optimized for women in realistic scenarios with professional photography quality
- pony-anime-t2i-production-v1.json - Anime/cartoon/furry with Pony Diffusion V6 XL
  - Euler Ancestral, Normal scheduler, 35 steps, CFG 7.5
  - Danbooru tag support, balanced safe/questionable/explicit content
- realvisxl-lightning-t2i-production-v1.json - Ultra-fast photorealistic with RealVisXL V5.0 Lightning
  - DPM++ SDE Karras, 6 steps (vs 30+), CFG 2.0
  - 4-6 step generation for rapid high-quality output

**Enhancement Workflows (2):**
- lora-fusion-t2i-production-v1.json - Multi-LoRA stacking (text-to-image directory)
  - Stack up to 3 LoRAs with adjustable weights (0.2-1.0)
  - Compatible with all SDXL checkpoints including NSFW models
  - Hierarchical strength control for style mixing and enhancement
- nsfw-ultimate-upscale-production-v1.json - Professional 2x upscaling with LUSTIFY
  - RealESRGAN_x2 + diffusion refinement via Ultimate SD Upscale
  - Tiled processing, optimized for detailed skin texture
  - Denoise 0.25 preserves original composition

**Documentation:**
- Comprehensive README.md with usage examples, API integration, model comparison
- Optimized settings for each workflow based on model recommendations
- Advanced usage guide for LoRA stacking and upscaling pipelines
- Version history tracking

**Total additions:** 1,768 lines across 6 files

These workflows complement the 27GB of CivitAI NSFW models downloaded in previous commit.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 18:46:22 +01:00
5944767d3f fix: update CivitAI model version IDs to latest versions
- RealVisXL: 904692 → 798204 (V5.0 Lightning)
- WAI-NSFW-illustrious: 1239648 → 2167369 (v15.0)
- Big Lust: 649023 → 1081768 (v1.6)

Fixes 404 errors when downloading these models.
2025-11-23 18:16:32 +01:00
e29f77c90b feat: add dedicated CivitAI NSFW model downloader
- Add models_civitai.yaml with 6 NSFW SDXL checkpoints
- Create artifact_civitai_download.sh with beautiful purple/magenta CLI
- Update .env.example with CIVITAI_API_KEY documentation
- Update CLAUDE.md with CivitAI usage instructions
- Rename comfyui_models.yaml to models_huggingface.yaml for clarity

Features:
- Dedicated config and downloader for CivitAI models
- Same elegant architecture as HuggingFace downloader
- Retry logic, rate limiting, progress bars
- Models: LUSTIFY, Pony Diffusion V6, RealVisXL, etc.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 17:58:25 +01:00
76cf5b5e31 docs: update CLAUDE.md to reflect direct vLLM architecture
- Remove all orchestrator references
- Update to dedicated vLLM server model
- Update service management commands
- Update LiteLLM integration details
- Update testing examples
2025-11-23 16:26:59 +01:00
479201d338 chore: remove orchestrator - replaced with dedicated vLLM servers 2025-11-23 16:24:43 +01:00
1ad99cdb53 refactor: replace orchestrator with dedicated vLLM servers for Qwen and Llama 2025-11-23 16:00:03 +01:00
cc0f55df38 fix: reduce max_model_len to 20000 to fit in 24GB VRAM 2025-11-23 15:43:37 +01:00
5cfd03f1ef fix: improve streaming with proper delta format and increase max_model_len to 32768 2025-11-23 15:38:18 +01:00
3f812704a2 fix: use venv python for vLLM service startup 2025-11-23 15:21:52 +01:00
fdd724298a fix: increase max_tokens limit from 4096 to 32768 for LLMX CLI support 2025-11-23 15:10:06 +01:00
a8c2ee1b90 fix: make model name and port configurable via environment variables 2025-11-23 13:45:01 +01:00
16112e50f6 fix: relax dependency version constraints for vllm compatibility 2025-11-23 13:33:46 +01:00
e0a43259d4 fix: update pydantic version constraint to match vllm requirements 2025-11-23 13:33:22 +01:00
d351ec7172 fix: update service_script path to vllm/server.py
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 13:29:51 +01:00
b94df17845 feat: add requirements.txt for vLLM models
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 13:25:03 +01:00
d67667c79f fix: add psutil to orchestrator dependencies
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 13:11:30 +01:00
61fd0e9265 fix: correct widgets_values - remove upscale_model/custom params, fix seam_fix order (width before mask_blur) 2025-11-23 12:34:28 +01:00
b9afd68ddd fix: add control_after_generate parameter at position 2 (23 total params) 2025-11-23 12:26:27 +01:00
2f53f542e7 fix: add custom_sampler and custom_sigmas null placeholders (22 total parameters) 2025-11-23 12:21:40 +01:00
14a1fcf4a7 fix: add null placeholder for upscale_model in widgets_values (20th parameter) 2025-11-23 12:20:48 +01:00
626dab6f65 fix: back to function signature order for seam_fix params 2025-11-23 12:18:42 +01:00
abbd89981e fix: use USDU_base_inputs order (seam_fix_width before mask_blur) 2025-11-23 12:15:49 +01:00
f976dc2c74 fix: correct seam_fix parameter order - mask_blur comes before width in function signature 2025-11-23 12:14:19 +01:00
75c6c77391 fix: correct widgets_values array to match actual parameter order (19 widget values for unconnected parameters) 2025-11-23 12:11:54 +01:00
6f4ac14032 fix: correct seam_fix parameter order in widgets_values (seam_fix_denoise was 1.0, should be 0.3) 2025-11-23 12:10:23 +01:00
21efd3b86d fix: remove widget parameters from inputs array - they belong in widgets_values only 2025-11-23 12:09:11 +01:00
8b8a29a47e fix: add missing type fields to sampler_name and scheduler inputs 2025-11-23 12:07:43 +01:00
d6fbda38f1 fix: correct UltimateSDUpscale input indices in workflow
The upscale_model input was at index 5 instead of index 12, causing all
widget parameters to be misaligned. Fixed by:
- Updating link target index from 5 to 12 for upscale_model
- Adding explicit entries for widget parameters in inputs array
- Maintaining correct parameter order per custom node definition

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 12:06:25 +01:00
096d565f3d chore: reorganize workflow assets and remove unused files
- Move example images to their respective workflow directories
- Remove unused COMFYUI_MODELS.md (content consolidated elsewhere)
- Remove fix_workflows.py script (no longer needed)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 12:01:38 +01:00
d12c868e65 fix: add UpscaleModelLoader and correct widget order in UltimateSDUpscale workflow
- Added UpscaleModelLoader node (node 8) for RealESRGAN model
- Connected upscale_model input to UltimateSDUpscale
- Fixed widgets_values array to match correct parameter order:
  upscale_by, seed, steps, cfg, sampler_name, scheduler, denoise,
  mode_type, tile_width, tile_height, mask_blur, tile_padding,
  seam_fix_mode, seam_fix_denoise, seam_fix_width, seam_fix_mask_blur,
  seam_fix_padding, force_uniform_tiles, tiled_decode
- Updated version to 1.1.0
2025-11-23 11:45:28 +01:00
53a7faf2a8 feat: add RealESRGAN upscale models to configuration
Added RealESRGAN x2 and x4 upscaling models:
- RealESRGAN_x2.pth - Fast 2x upscaling
- RealESRGAN_x4.pth - High quality 4x upscaling
- Both marked as essential, minimal VRAM usage (~2-4GB)
- Total size: ~120MB combined
2025-11-23 11:35:04 +01:00
c114569309 feat: add placeholder input images for workflows
Added example images for testing workflows:
- input_image.png (512x512) - for general upscaling workflows
- input_portrait.png (512x768) - for portrait/face upscaling workflows
2025-11-23 11:33:00 +01:00
0df4c63412 fix: add missing links and rebuild upscaling workflows
- simple-upscale: Added proper node connections, changed ImageScale to ImageScaleBy
- ultimate-sd-upscale: Added CLIP text encoders, removed incorrect VAEDecode and UpscaleModelLoader nodes
- face-upscale: Simplified to basic upscaling workflow (FaceDetailer requires complex bbox detector setup)

All workflows now have proper inputs, outputs, and links arrays.
2025-11-23 11:30:29 +01:00
f1788f88ca fix: replace PreviewAudio with AudioPlay in MusicGen workflows
Sound Lab's Musicgen_ node outputs AUDIO format that is only compatible with Sound Lab nodes like AudioPlay, not the built-in ComfyUI audio nodes (SaveAudio/PreviewAudio).
2025-11-23 11:20:15 +01:00
b6ab524b79 fix: replace SaveAudio with PreviewAudio in MusicGen workflows
SaveAudio was erroring on 'waveform' key - the AUDIO output from
Musicgen_ node has a different internal structure than what SaveAudio
expects. PreviewAudio is more compatible with Sound Lab's AUDIO format.

Files are still saved to ComfyUI output directory, just through
PreviewAudio instead of SaveAudio.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 11:14:17 +01:00
c787b40311 fix: rebuild all MusicGen workflows with correct nodes and links
Fixed medium, small, and melody workflows:
- Replaced non-existent nodes with Musicgen_ from Sound Lab
- Added missing links arrays to connect nodes properly
- Updated all metadata and performance specs

Note: Melody workflow simplified to text-only as Sound Lab doesn't
currently support melody conditioning via audio input.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 11:09:33 +01:00
85b1831876 fix: rebuild MusicGen workflow with correct node types and links
Changed from non-existent nodes to actual Sound Lab nodes:
- Replaced MusicGenLoader/MusicGenTextEncode/MusicGenSampler with Musicgen_
- Replaced custom SaveAudio with standard SaveAudio node
- Added missing links array to connect nodes
- All parameters: prompt, duration, guidance_scale, seed, device

Node is called "Musicgen_" (with underscore) from comfyui-sound-lab.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 11:06:42 +01:00
5c1e9d092b fix: rebuild SD3.5 workflow with TripleCLIPLoader
SD3.5 checkpoint doesn't contain CLIP encoders. Now using:
- CheckpointLoaderSimple for MODEL and VAE
- TripleCLIPLoader for CLIP-L, CLIP-G, and T5-XXL
- Standard CLIPTextEncode for prompts

This fixes the "clip input is invalid: None" error.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 10:56:09 +01:00
91ed1aa9e3 fix: correct model paths in SD3.5 and SDXL Refiner workflows
Changed from diffusers paths to actual .safetensors filenames:
- sd3.5: diffusers/stable-diffusion-3.5-large -> sd3.5_large.safetensors
- sdxl-base: diffusers/stable-diffusion-xl-base-1.0 -> sd_xl_base_1.0.safetensors
- sdxl-refiner: diffusers/stable-diffusion-xl-refiner-1.0 -> sd_xl_refiner_1.0.safetensors

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 10:51:55 +01:00
ac74730ee2 fix: rebuild FLUX Schnell workflow with correct node types
Replaced CheckpointLoaderSimple with UNETLoader + DualCLIPLoader.
Replaced CLIPTextEncode with CLIPTextEncodeFlux.
Added proper VAELoader with ae.safetensors.
Added ConditioningZeroOut for empty negative conditioning.
Removed old negative prompt input (FLUX doesn't use it).

Changes match FLUX Dev workflow structure.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 10:48:13 +01:00
7dd6739f5e fix: add FLUX VAE autoencoder for proper image decoding
Added FLUX VAE (ae.safetensors) to model configuration and updated
workflow to use it instead of non-existent pixel_space VAE.

This fixes the SaveImage data type error (1, 1, 16), |u1.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 10:43:11 +01:00
3eced21d2a fix: add link 8 to CLIPTextEncodeFlux output links array
Node 3 (CLIPTextEncodeFlux) output feeds both KSampler (link 3) and
ConditioningZeroOut (link 8), so the output links array must include
both links.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 10:39:17 +01:00
30cc2513cb fix: add ConditioningZeroOut for FLUX workflow negative input
FLUX models require negative conditioning even though they don't use it.
Added ConditioningZeroOut node to create empty negative conditioning from
positive output, satisfying KSampler's required negative input.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 10:35:22 +01:00
a2455ae9ee fix: rebuild FLUX Dev workflow with correct node types
- Replace CheckpointLoaderSimple with UNETLoader
- Replace CLIPTextEncode with DualCLIPLoader + CLIPTextEncodeFlux
- Add VAELoader with pixel_space
- Remove negative prompt (FLUX uses guidance differently)
- Set CFG to 1.0, guidance in text encoder (3.5)
- Add all node connections in links array

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 10:30:47 +01:00
230175f33d fix: combine FLUX CLIP entries into single repo entry
Both CLIP-L and T5-XXL come from the same repo, so they should
be in one entry with multiple files, not two separate entries.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 10:27:47 +01:00
9eb8c26ff0 feat: add FLUX CLIP models to configuration
Add CLIP-L and T5-XXL entries with type: clip so they get
linked to /workspace/ComfyUI/models/clip/ directory for
FLUX model usage via DualCLIPLoader.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 10:25:56 +01:00
105830322a fix: change FLUX models type from diffusion_models to unet
FLUX models need to be in /workspace/ComfyUI/models/unet/ directory
for UNETLoader to find them, not in diffusion_models directory.

Changed type for:
- black-forest-labs/FLUX.1-schnell
- black-forest-labs/FLUX.1-dev

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 10:20:44 +01:00
8b4f141d82 fix: rebuild SVD-XT workflow with correct node types
- Replace DiffusersLoader with ImageOnlyCheckpointLoader
- Replace SVDSampler with SVD_img2vid_Conditioning + KSampler
- Add VideoLinearCFGGuidance for temporal consistency
- Add all node connections in links array
- Configure VHS_VideoCombine with correct parameters (25 frames)
- Increase steps to 30 for better quality with longer video

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 10:15:43 +01:00
d7bae9cde5 fix: correct VHS_VideoCombine parameters for SVD workflow
Remove format-specific parameters from widgets_values array.
Only base parameters should be in widgets_values:
- frame_rate, loop_count, filename_prefix, format, pingpong, save_output

Format-specific params (pix_fmt, crf) are added dynamically by ComfyUI.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 10:11:52 +01:00
764cb5d2d7 fix: rebuild SVD workflow with correct node types
- Replace DiffusersLoader with ImageOnlyCheckpointLoader
- Replace SVDSampler with SVD_img2vid_Conditioning + KSampler
- Add VideoLinearCFGGuidance for temporal consistency
- Add all node connections in links array
- Configure VHS_VideoCombine with H.264 parameters

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 10:10:38 +01:00
22afe18957 fix: change input image to 720x480 for CogVideoX-5b-I2V
- CogVideoX-5b-I2V requires specific resolution (720x480)
- Cannot generate videos at different resolutions
- Update placeholder image to match model requirements
2025-11-23 09:51:12 +01:00
385b36b062 feat: enable CPU offload for CogVideoX model to reduce VRAM usage
- Add enable_sequential_cpu_offload=true to DownloadAndLoadCogVideoModel
- Reduces VRAM from ~20GB to ~12GB at cost of slower inference
- Widget values: [model, precision, quantization, cpu_offload] = ['THUDM/CogVideoX-5b-I2V', 'bf16', 'disabled', true]
- Necessary for 24GB GPU with other services running
2025-11-23 09:47:02 +01:00
404eb6ad0e feat: add placeholder input image for CogVideoX I2V workflow
- Create 1024x1024 white placeholder with 'Input Frame' text
- Allows workflow validation without external image upload
- Will be replaced by API input in production use
2025-11-23 09:43:38 +01:00
47824ab987 fix: completely rebuild CogVideoX I2V workflow with correct configurations
Major fixes:
- Replace DualCLIPLoader with CLIPLoader using t5xxl_fp16.safetensors
- Fix CogVideoSampler parameter order: [num_frames, steps, cfg, seed, control, scheduler, denoise]
- Fix CogVideoImageEncode input: 'image' -> 'start_image'
- Remove CogVideoXVAELoader, use VAE directly from DownloadAndLoadCogVideoModel
- Add CogVideoTextEncode strength and force_offload parameters
- Simplify to 8 nodes (removed node 10)
- All nodes properly connected with correct link IDs

Version: 1.2.0
Tested against: ComfyUI-CogVideoXWrapper example workflows
2025-11-23 09:41:01 +01:00
80a81aa12f feat: add CogVideoX-I2V and text encoders to model configuration
- Add THUDM/CogVideoX-5b-I2V model entry (20GB, I2V-specific model)
- Add T5-XXL FP16 text encoder for CogVideoX (9GB)
- Add CLIP-L text encoder for CogVideoX and SD3 (1GB)
- Add CLIP-G text encoder for SD3 (3GB)

Note: CogVideoX models are auto-downloaded by DownloadAndLoadCogVideoModel node
Text encoders already linked manually to /workspace/ComfyUI/models/text_encoders/
2025-11-23 09:36:15 +01:00
5cd9237d82 fix: add h264-mp4 format parameters to VHS_VideoCombine
- Add required format-specific parameters: pix_fmt, crf, save_metadata, trim_to_audio
- Values: [8, 0, 'cogvideox_output', 'video/h264-mp4', 'yuv420p', 19, true, false]
- Fixes red node error in ComfyUI UI
2025-11-23 09:09:35 +01:00
6fab6386d7 feat: complete CogVideoX I2V workflow with proper node connections
- Add all necessary nodes: DualCLIPLoader, CogVideoImageEncode, CogVideoXVAELoader
- Add negative prompt support (node 8)
- Properly connect all nodes with links array (11 connections)
- Workflow now fully functional for image-to-video generation

Node flow:
1. LoadImage -> CogVideoImageEncode
2. DownloadAndLoadCogVideoModel -> CogVideoSampler (model)
3. DownloadAndLoadCogVideoModel -> CogVideoImageEncode (vae)
4. DualCLIPLoader -> CogVideoTextEncode (positive & negative)
5. CogVideoTextEncode (pos/neg) -> CogVideoSampler
6. CogVideoImageEncode -> CogVideoSampler (image conditioning)
7. CogVideoSampler -> CogVideoDecode
8. CogVideoXVAELoader -> CogVideoDecode
9. CogVideoDecode -> VHS_VideoCombine

Version: 1.1.0
2025-11-23 09:07:36 +01:00
a9c26861a4 fix: correct CogVideoX node types for I2V workflow
- Change CogVideoXSampler -> CogVideoSampler
- Change DiffusersLoader -> DownloadAndLoadCogVideoModel
- Change CLIPTextEncode -> CogVideoTextEncode
- Change VAEDecode -> CogVideoDecode
- Update model path to THUDM/CogVideoX-5b-I2V
- Fix sampler parameters: [seed, scheduler, num_frames, steps, cfg]
- Add CogVideoDecode tiling parameters

Note: Workflow still needs proper node connections (links array is empty)
2025-11-23 09:04:05 +01:00
862bbe2740 fix: use VIT-G preset instead of PLUS for SDXL compatibility
- Change IPAdapterUnifiedLoader preset from 'PLUS (high strength)' to 'VIT-G (medium strength)'
- PLUS preset expects ViT-H (1024 dim) but loads ViT-bigG (1280 dim) causing shape mismatch
- VIT-G preset works correctly with SDXL models
- Fixes: size mismatch error in Resampler proj_in.weight
2025-11-23 08:59:34 +01:00
2bfc189c70 fix: correct IPAdapter widget parameter order
- IPAdapter node expects 4 parameters: weight, start_at, end_at, weight_type
- Previous had 6 parameters with wrong order causing validation errors
- Now correctly ordered: [0.75, 0.0, 1.0, 'style transfer']
- Fixes: 'end_at' receiving 'style transfer' and weight_type receiving 0
2025-11-23 08:57:27 +01:00
c1014cbbde fix: correct SDXL checkpoint name and IPAdapter weight_type in style workflow
- Change checkpoint from 'diffusers/stable-diffusion-xl-base-1.0' to 'sd_xl_base_1.0.safetensors'
- Change IPAdapter weight_type from 'original' to 'style transfer' (valid option)
- Fixes validation errors: invalid checkpoint name and invalid weight_type
2025-11-23 08:54:22 +01:00
4b4c23d16e fix: use venv Python directly instead of source activation
- Change from 'source venv/bin/activate' to direct venv/bin/python execution
- Use exec to replace shell process with Python process
- Fixes issue where supervisor doesn't properly activate venv
- Ensures all extension dependencies are available
2025-11-23 08:38:14 +01:00
80 changed files with 41833 additions and 3680 deletions

View File

@@ -15,10 +15,33 @@ HF_TOKEN=hf_your_token_here
# Get it with: tailscale ip -4 # Get it with: tailscale ip -4
# GPU_TAILSCALE_IP=100.100.108.13 # GPU_TAILSCALE_IP=100.100.108.13
# ============================================================================
# CivitAI API Key (Optional, for NSFW models)
# ============================================================================
# Get your API key from: https://civitai.com/user/account
# Required for downloading NSFW models with artifact_civitai_download.sh
# CIVITAI_API_KEY=your_civitai_api_key_here
# ============================================================================
# Tailscale VPN (Optional, for remote access)
# ============================================================================
# Get your authkey from: https://login.tailscale.com/admin/settings/keys
# TAILSCALE_AUTHKEY=tskey-auth-your_tailscale_authkey_here
# ============================================================================
# WebDAV Sync (Optional, for output synchronization)
# ============================================================================
# WebDAV credentials for syncing ComfyUI outputs to cloud storage
# WEBDAV_URL=https://webdav.example.com/
# WEBDAV_USERNAME=your_username
# WEBDAV_PASSWORD=your_password
# WEBDAV_REMOTE_PATH=/path/to/comfyui/outputs
# ============================================================================ # ============================================================================
# Notes # Notes
# ============================================================================ # ============================================================================
# - HF_TOKEN is the only required variable for basic operation # - HF_TOKEN is the only required variable for basic operation
# - CIVITAI_API_KEY is required for downloading NSFW models from CivitAI
# - Models will be cached in /workspace/ directories on RunPod # - Models will be cached in /workspace/ directories on RunPod
# - Orchestrator automatically manages model switching # - Orchestrator automatically manages model switching
# - No database credentials needed (stateless architecture) # - No database credentials needed (stateless architecture)

View File

@@ -0,0 +1,114 @@
name: Build and Push RunPod Docker Image
on:
push:
branches:
- main
tags:
- 'v*.*.*'
pull_request:
branches:
- main
workflow_dispatch:
inputs:
tag:
description: 'Custom tag for the image'
required: false
default: 'manual'
env:
REGISTRY: dev.pivoine.art
IMAGE_NAME: valknar/runpod-ai-orchestrator
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
platforms: linux/amd64
- name: Log in to Gitea Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ gitea.actor }}
password: ${{ secrets.REGISTRY_TOKEN }}
- name: Extract metadata (tags, labels)
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
# Tag as 'latest' for main branch
type=raw,value=latest,enable={{is_default_branch}}
# Tag with branch name
type=ref,event=branch
# Tag with PR number
type=ref,event=pr
# Tag with git tag (semver)
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
# Tag with commit SHA
type=sha,prefix={{branch}}-
# Custom tag from workflow_dispatch
type=raw,value=${{ gitea.event.inputs.tag }},enable=${{ gitea.event_name == 'workflow_dispatch' }}
labels: |
org.opencontainers.image.title=RunPod AI Orchestrator
org.opencontainers.image.description=Minimal Docker template for RunPod deployment with ComfyUI + vLLM orchestration, Supervisor process management, and Tailscale VPN integration
org.opencontainers.image.vendor=valknar
org.opencontainers.image.source=https://dev.pivoine.art/${{ gitea.repository }}
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
platforms: linux/amd64
push: ${{ gitea.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache
cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache,mode=max
- name: Generate image digest
if: gitea.event_name != 'pull_request'
run: |
echo "### Docker Image Published :rocket:" >> $GITEA_STEP_SUMMARY
echo "" >> $GITEA_STEP_SUMMARY
echo "**Registry:** \`${{ env.REGISTRY }}\`" >> $GITEA_STEP_SUMMARY
echo "**Image:** \`${{ env.IMAGE_NAME }}\`" >> $GITEA_STEP_SUMMARY
echo "" >> $GITEA_STEP_SUMMARY
echo "**Tags:**" >> $GITEA_STEP_SUMMARY
echo "\`\`\`" >> $GITEA_STEP_SUMMARY
echo "${{ steps.meta.outputs.tags }}" >> $GITEA_STEP_SUMMARY
echo "\`\`\`" >> $GITEA_STEP_SUMMARY
echo "" >> $GITEA_STEP_SUMMARY
echo "**Pull command:**" >> $GITEA_STEP_SUMMARY
echo "\`\`\`bash" >> $GITEA_STEP_SUMMARY
echo "docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest" >> $GITEA_STEP_SUMMARY
echo "\`\`\`" >> $GITEA_STEP_SUMMARY
echo "" >> $GITEA_STEP_SUMMARY
echo "**Use in RunPod template:**" >> $GITEA_STEP_SUMMARY
echo "\`\`\`" >> $GITEA_STEP_SUMMARY
echo "Container Image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest" >> $GITEA_STEP_SUMMARY
echo "\`\`\`" >> $GITEA_STEP_SUMMARY
- name: PR Comment - Image built but not pushed
if: gitea.event_name == 'pull_request'
run: |
echo "### Docker Image Built Successfully :white_check_mark:" >> $GITEA_STEP_SUMMARY
echo "" >> $GITEA_STEP_SUMMARY
echo "Image was built successfully but **not pushed** (PR builds are not published)." >> $GITEA_STEP_SUMMARY
echo "" >> $GITEA_STEP_SUMMARY
echo "**Would be tagged as:**" >> $GITEA_STEP_SUMMARY
echo "\`\`\`" >> $GITEA_STEP_SUMMARY
echo "${{ steps.meta.outputs.tags }}" >> $GITEA_STEP_SUMMARY
echo "\`\`\`" >> $GITEA_STEP_SUMMARY

286
CLAUDE.md
View File

@@ -4,49 +4,39 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## Overview ## Overview
This is a lightweight, process-based AI model orchestrator designed for RunPod GPU instances (specifically RTX 4090 with 24GB VRAM). It manages sequential loading of multiple large AI models on a single GPU, providing OpenAI-compatible API endpoints for text, image, and audio generation. This is a lightweight AI model serving infrastructure for RunPod GPU instances (specifically RTX 4090 with 24GB VRAM). It provides OpenAI-compatible API endpoints for text, image, and audio generation via dedicated vLLM servers and ComfyUI.
**Key Design Philosophy:** **Key Design Philosophy:**
- **Sequential model loading** - Only one model active at a time to fit within GPU memory constraints - **Direct vLLM access** - Dedicated FastAPI servers for each text model (no proxy layer)
- **Process-based architecture** - Uses Python subprocess instead of Docker-in-Docker for RunPod compatibility - **Process-based architecture** - Managed by Supervisor for reliability
- **Automatic model switching** - Orchestrator detects request types and switches models on-demand - **Simple service management** - Start/stop models independently as needed
- **OpenAI-compatible APIs** - Works seamlessly with LiteLLM proxy and other AI tools - **OpenAI-compatible APIs** - Works seamlessly with LiteLLM proxy and other AI tools
## Architecture ## Architecture
### Core Components ### Core Components
1. **Orchestrator** (`model-orchestrator/orchestrator_subprocess.py`) 1. **vLLM Servers** (`vllm/server_qwen.py`, `vllm/server_llama.py`)
- FastAPI proxy server listening on port 9000 - Dedicated FastAPI servers for each text model
- Manages model lifecycle via Python subprocesses - Qwen 2.5 7B on port 8000, Llama 3.1 8B on port 8001
- Routes requests to appropriate model services - Direct AsyncLLMEngine access for optimal streaming performance
- Handles sequential model loading/unloading - max_model_len=20000 optimized for 24GB VRAM
2. **Model Registry** (`model-orchestrator/models.yaml`) 2. **ComfyUI** (`comfyui/`)
- YAML configuration defining available models - Image/video/audio generation server on port 8188
- Specifies: type, framework, service script, port, VRAM requirements, startup time - FLUX, SDXL, CogVideoX, MusicGen models
- Easy to extend with new models - Advanced workflow system with custom nodes
3. **Model Services** (`models/*/`) 3. **Supervisor** (`supervisord.conf`)
- Individual Python servers running specific AI models - Process manager for all AI services
- vLLM for text generation (Qwen 2.5 7B, Llama 3.1 8B) - Auto-restart, centralized logging
- ComfyUI for image/video/audio generation (FLUX, SDXL, CogVideoX, MusicGen) - Web interface on port 9001
4. **Ansible Provisioning** (`playbook.yml`) 4. **Ansible Provisioning** (`playbook.yml`)
- Complete infrastructure-as-code setup - Complete infrastructure-as-code setup
- Installs dependencies, downloads models, configures services - Installs dependencies, downloads models, configures services
- Supports selective installation via tags - Supports selective installation via tags
### Why Process-Based Instead of Docker?
The subprocess implementation (`orchestrator_subprocess.py`) is preferred over the Docker version (`orchestrator.py`) because:
- RunPod instances run in containers - Docker-in-Docker adds complexity
- Faster model startup (direct Python process spawning)
- Simpler debugging (single process tree)
- Reduced overhead (no container management layer)
**Note:** Always use `orchestrator_subprocess.py` for RunPod deployments.
## Common Commands ## Common Commands
### Repository Management with Arty ### Repository Management with Arty
@@ -57,17 +47,16 @@ This project uses Arty for repository and deployment management. See `arty.yml`
# Clone all repositories (fresh deployment) # Clone all repositories (fresh deployment)
arty sync --env prod # Production: Essential nodes only arty sync --env prod # Production: Essential nodes only
arty sync --env dev # Development: All nodes including optional arty sync --env dev # Development: All nodes including optional
arty sync --env minimal # Minimal: Just orchestrator + ComfyUI base arty sync --env minimal # Minimal: Just vLLM + ComfyUI base
# Run deployment scripts # Run deployment scripts
arty run setup/full # Show setup instructions arty run setup/full # Show setup instructions
arty run models/link-comfyui # Link downloaded models to ComfyUI arty run models/link-comfyui # Link downloaded models to ComfyUI
arty run deps/comfyui-nodes # Install custom node dependencies arty run deps/comfyui-nodes # Install custom node dependencies
arty run services/start # Start orchestrator arty run services/start # Start supervisor
arty run services/stop # Stop all services arty run services/stop # Stop all services
# Health checks # Health checks
arty run health/orchestrator # Check orchestrator
arty run health/comfyui # Check ComfyUI arty run health/comfyui # Check ComfyUI
arty run check/gpu # nvidia-smi arty run check/gpu # nvidia-smi
arty run check/models # Show cache size arty run check/models # Show cache size
@@ -119,14 +108,16 @@ arty run services/status # Same via arty
supervisorctl status # Direct supervisor command supervisorctl status # Direct supervisor command
# Individual service control # Individual service control
supervisorctl start orchestrator # Start orchestrator supervisorctl start vllm-qwen # Start Qwen vLLM server
supervisorctl start vllm-llama # Start Llama vLLM server
supervisorctl restart comfyui # Restart ComfyUI supervisorctl restart comfyui # Restart ComfyUI
supervisorctl stop orchestrator # Stop orchestrator supervisorctl stop vllm-qwen # Stop Qwen vLLM server
arty run services/restart-comfyui # Restart ComfyUI via arty arty run services/restart-comfyui # Restart ComfyUI via arty
# View logs # View logs
supervisorctl tail -f comfyui # Follow ComfyUI logs supervisorctl tail -f comfyui # Follow ComfyUI logs
supervisorctl tail -f orchestrator # Follow orchestrator logs supervisorctl tail -f vllm-qwen # Follow Qwen vLLM logs
supervisorctl tail -f vllm-llama # Follow Llama vLLM logs
arty run services/logs # Follow ComfyUI logs via arty arty run services/logs # Follow ComfyUI logs via arty
# Web interface # Web interface
@@ -141,20 +132,80 @@ arty run services/logs # Follow ComfyUI logs via arty
**Services managed:** **Services managed:**
- `comfyui` - ComfyUI server (port 8188, autostart enabled) - `comfyui` - ComfyUI server (port 8188, autostart enabled)
- `orchestrator` - Model orchestrator (port 9000, autostart disabled) - `vllm-qwen` - Qwen 2.5 7B vLLM server (port 8000, autostart disabled)
- `vllm-llama` - Llama 3.1 8B vLLM server (port 8001, autostart disabled)
- `webdav-sync` - WebDAV sync service for ComfyUI outputs
### GPU Memory Management and Mode Switching
**VRAM Constraints (RTX 4090 - 24GB total):**
The GPU has limited memory, which requires manual service switching:
| Service | Model | VRAM Usage | Compatible With |
|---------|-------|------------|-----------------|
| ComfyUI | FLUX Schnell FP16 | ~23GB | None (uses all VRAM) |
| ComfyUI | SDXL Base | ~12GB | Small vLLM models |
| vLLM | Qwen 2.5 7B | ~14GB | None (conflicts with ComfyUI) |
| vLLM | Llama 3.1 8B | ~17GB | None (conflicts with ComfyUI) |
**Mode Switching Workflow:**
Since ComfyUI and vLLM models cannot run simultaneously (they exceed 24GB combined), you must manually switch modes:
**Switch to Text Generation Mode (vLLM):**
```bash
# 1. Stop ComfyUI
supervisorctl stop comfyui
# 2. Start desired vLLM server
supervisorctl start vllm-qwen # or vllm-llama
# 3. Verify
supervisorctl status
nvidia-smi # Check VRAM usage
```
**Switch to Image/Video/Audio Generation Mode (ComfyUI):**
```bash
# 1. Stop vLLM servers
supervisorctl stop vllm-qwen vllm-llama
# 2. Start ComfyUI
supervisorctl start comfyui
# 3. Verify
supervisorctl status
nvidia-smi # Check VRAM usage
```
**Access via Supervisor Web UI:**
You can also switch modes using the Supervisor web interface:
- URL: `https://supervisor.ai.pivoine.art` (via VPS proxy) or `http://100.114.60.40:9001` (direct Tailscale)
- Username: `admin`
- Password: `runpod2024`
- Click "Start" or "Stop" buttons for each service
**Integration with LiteLLM:**
The vLLM servers integrate with LiteLLM on the VPS for unified API access:
- vLLM models (qwen-2.5-7b, llama-3.1-8b) available via direct connections
- Requests route directly to vLLM servers (ports 8000, 8001)
- Environment variables `GPU_VLLM_QWEN_URL` and `GPU_VLLM_LLAMA_URL` configure connections
- LiteLLM config uses `os.environ/GPU_VLLM_*_URL` syntax for dynamic URLs
### Testing ### Testing
```bash ```bash
# Health check # Health check (Qwen vLLM server)
curl http://localhost:9000/health curl http://localhost:8000/health
# List available models # List available models
curl http://localhost:9000/v1/models curl http://localhost:8000/v1/models
# Test text generation (streaming) # Test text generation (streaming)
curl -s -N -X POST http://localhost:9000/v1/chat/completions \ curl -s -N -X POST http://localhost:8000/v1/chat/completions \
-H 'Content-Type: application/json' \ -H 'Content-Type: application/json' \
-d '{ -d '{
"model": "qwen-2.5-7b", "model": "qwen-2.5-7b",
@@ -163,12 +214,10 @@ curl -s -N -X POST http://localhost:9000/v1/chat/completions \
"stream": true "stream": true
}' }'
# Test image generation # Test ComfyUI (image generation)
curl -X POST http://localhost:9000/v1/images/generations \ curl -X POST http://localhost:8188/prompt \
-H 'Content-Type: application/json' \ -H 'Content-Type: application/json' \
-d '{ -d '{
"model": "flux-schnell",
"prompt": "A serene mountain landscape at sunset",
"size": "1024x1024" "size": "1024x1024"
}' }'
``` ```
@@ -197,65 +246,132 @@ curl -X POST http://localhost:9000/v1/images/generations \
- `systemd` - Configure systemd services (use `never` - not for RunPod) - `systemd` - Configure systemd services (use `never` - not for RunPod)
- `validate` - Health checks (use `never` - run explicitly) - `validate` - Health checks (use `never` - run explicitly)
### Adding New Models ### Adding New vLLM Models
1. **Add model definition to `model-orchestrator/models.yaml`:** 1. **Create dedicated server script** (e.g., `vllm/server_mistral.py`):
```yaml
llama-3.1-8b:
type: text
framework: vllm
service_script: models/vllm/server_llama.py
port: 8001
vram_gb: 17
startup_time_seconds: 120
endpoint: /v1/chat/completions
description: "Llama 3.1 8B Instruct"
```
2. **Create service script** (`models/vllm/server_llama.py`):
```python ```python
import os #!/usr/bin/env python3
from vllm.entrypoints.openai.api_server import run_server from vllm import AsyncLLMEngine, AsyncEngineArgs
# ... (copy structure from server_qwen.py)
model = "meta-llama/Llama-3.1-8B-Instruct" model_name: str = "mistralai/Mistral-7B-Instruct-v0.3"
port = int(os.getenv("PORT", 8001)) port = 8002 # Choose unique port
run_server(model=model, port=port) ```
2. **Add supervisor configuration** (`supervisord.conf`):
```ini
[program:vllm-mistral]
command=vllm/venv/bin/python vllm/server_mistral.py
directory=.
autostart=false
autorestart=true
environment=HF_HOME="../huggingface_cache",HF_TOKEN="%(ENV_HF_TOKEN)s"
``` ```
3. **Download model** (handled by Ansible playbook or manually via HuggingFace CLI) 3. **Download model** (handled by Ansible playbook or manually via HuggingFace CLI)
4. **Restart orchestrator:** 4. **Add to LiteLLM config** (on VPS):
```yaml
- model_name: mistral-7b
litellm_params:
model: hosted_vllm/openai/mistral-7b
api_base: os.environ/GPU_VLLM_MISTRAL_URL
api_key: "EMPTY"
```
5. **Start the service:**
```bash ```bash
bash scripts/stop-all.sh && bash scripts/start-all.sh supervisorctl start vllm-mistral
``` ```
### Downloading NSFW Models from CivitAI
The project includes dedicated tooling for downloading NSFW models from CivitAI, separate from the HuggingFace downloader.
**Files:**
- Configuration: `models_civitai.yaml` - Defines available CivitAI models
- Downloader: `artifact_civitai_download.sh` - Beautiful CLI tool for downloading models
**Requirements:**
- CivitAI API key (set in `.env` file as `CIVITAI_API_KEY`)
- Get your key from: https://civitai.com/user/account
**Available Models (Essential):**
1. **LUSTIFY v7.0 GGWP** (6.31GB) - Photoreal NSFW checkpoint for women
2. **Pony Diffusion V6 XL** (6.5GB) - Anime/furry NSFW with balanced content
3. **RealVisXL V5.0** (6.8GB) - Photorealistic NSFW model
**Usage:**
```bash
# Download all essential NSFW models (19.61GB)
artifact_civitai_download.sh
# Download only (no symlinks)
artifact_civitai_download.sh download
# Create symlinks only (models already downloaded)
artifact_civitai_download.sh link
# Custom configuration file
artifact_civitai_download.sh -c /path/to/models_civitai.yaml
# Help
artifact_civitai_download.sh --help
```
**Directory Structure:**
- Models downloaded to: `/workspace/models/civitai/` (cache)
- Symlinks created in: `/workspace/ComfyUI/models/checkpoints/`
**Features:**
- Beautiful purple/magenta themed CLI (vs cyan for HuggingFace)
- Automatic retry with exponential backoff for rate limiting
- Resume interrupted downloads
- Progress bars and status indicators
- Parallel download support (respects rate limits)
**Configuration Example (`models_civitai.yaml`):**
```yaml
model_categories:
nsfw_checkpoints:
- name: lustify-v7-ggwp
version_id: "1094291"
model_id: "573152"
description: "LUSTIFY v7.0 GGWP - Photoreal NSFW checkpoint"
size_gb: 6.31
essential: true
type: checkpoints
```
**Installation Profiles:**
- `essential`: 3 models (LUSTIFY, Pony, RealVisXL) - 19.61GB, 30-60 min
- `complete`: All 6 models - 39.21GB, 1-2 hours
- `realistic_only`: LUSTIFY + RealVisXL - 13.11GB, 20-40 min
- `anime_only`: Pony + WAI-NSFW - 13.0GB, 20-40 min
**Important Notes:**
- All models are SDXL-based (require ~12GB VRAM)
- Cannot run simultaneously with FLUX models (both use ~23GB)
- Can run with smaller models like standard SDXL (~12GB total)
- Rate limiting: 5 second delay between downloads (configurable)
## Key Implementation Details ## Key Implementation Details
### Model Switching Logic ### Direct vLLM Server Architecture
The orchestrator automatically switches models based on: Each vLLM model runs as a dedicated FastAPI server:
- **Endpoint path** - `/v1/chat/completions` → text models, `/v1/images/generations` → image models - Independent process management via Supervisor
- **Model name in request** - Matches against model registry - Direct AsyncLLMEngine access for optimal performance
- **Sequential loading** - Stops current model before starting new one to conserve VRAM - OpenAI-compatible `/v1/chat/completions` endpoint
- Streaming support with proper delta formatting
See `orchestrator_subprocess.py:64-100` for process management implementation. See `vllm/server_qwen.py` for reference implementation.
### Model Registry Structure
Each model in `models.yaml` requires:
- `type` - text, image, or audio
- `framework` - vllm, openedai-images, audiocraft, comfyui
- `service_script` - Relative path to Python/shell script
- `port` - Service port (8000+)
- `vram_gb` - GPU memory requirement
- `startup_time_seconds` - Max health check timeout
- `endpoint` - API endpoint path
- `description` - Human-readable description
### Environment Variables
Set in `.env` file: Set in `.env` file:
- `HF_TOKEN` - **Required** - HuggingFace API token for model downloads - `HF_TOKEN` - **Required** - HuggingFace API token for model downloads

View File

@@ -1,320 +0,0 @@
# ComfyUI Models & Nodes - Usage Guide
This document explains how to use the extended playbook.yml for installing ComfyUI models and custom nodes.
## What's Been Added
### Model Categories
**Image Generation Models:**
- FLUX.1 Schnell (23GB, essential) - Fast 4-step inference
- FLUX.1 Dev (23GB, optional) - Balanced quality/speed
- SDXL Base 1.0 (7GB, essential) - Industry standard
- SDXL Refiner 1.0 (6GB, optional) - Enhances base output
- SD 3.5 Large (18GB, optional) - Latest Stability AI
**Video Generation Models:**
- CogVideoX-5B (20GB, essential) - Professional text-to-video
- SVD (8GB, essential) - 14 frame image-to-video
- SVD-XT (8GB, optional) - 25 frame image-to-video
**Audio Generation Models:**
- MusicGen Small (3GB, optional) - Fast generation
- MusicGen Medium (11GB, essential) - Balanced quality
- MusicGen Large (22GB, optional) - Highest quality
**Support Models:**
- CLIP H (2GB, essential) - For SD 1.5 IP-Adapter
- CLIP G (7GB, essential) - For SDXL IP-Adapter
- SigLIP (2GB, essential) - For FLUX models
### Custom Nodes
**Essential Nodes (installed by default):**
- ComfyUI-Manager - Install/manage custom nodes and models
- ComfyUI-VideoHelperSuite - Video operations
- ComfyUI-AnimateDiff-Evolved - Video generation
- ComfyUI_IPAdapter_plus - Style transfer
- ComfyUI-Impact-Pack - Auto face enhancement
- comfyui-sound-lab - Audio generation
**Optional Nodes:**
- ComfyUI-CogVideoXWrapper - CogVideoX integration
- Comfyui-Inspire-Pack - Additional tools
- ComfyUI-Advanced-ControlNet - Advanced control
- ComfyUI-3D-Pack - 3D asset generation
## Usage Examples
### Quick Setup (Essential Only)
Install ComfyUI with only essential models and nodes:
```bash
ansible-playbook playbook.yml --tags comfyui-essential
```
This downloads:
- Image: FLUX Schnell (23GB) + SDXL Base (7GB)
- Video: CogVideoX-5B (20GB) + SVD (8GB)
- Audio: MusicGen Medium (11GB)
- Support: All 3 CLIP models (11GB)
- **Total: ~80GB**
### Selective Installation
#### Install ComfyUI Base Only
```bash
ansible-playbook playbook.yml --tags comfyui
```
#### Install All Image Models
```bash
ansible-playbook playbook.yml --tags comfyui-models-image
```
#### Install All Video Models
```bash
ansible-playbook playbook.yml --tags comfyui-models-video
```
#### Install All Audio Models
```bash
ansible-playbook playbook.yml --tags comfyui-models-audio
```
#### Install Support Models (CLIP, IP-Adapter)
```bash
ansible-playbook playbook.yml --tags comfyui-models-support
```
#### Install Custom Nodes
```bash
ansible-playbook playbook.yml --tags comfyui-nodes
```
### Combined Installation
#### Full ComfyUI Setup
```bash
ansible-playbook playbook.yml --tags comfyui,comfyui-models-all,comfyui-nodes
```
#### ComfyUI + Image + Video Only
```bash
ansible-playbook playbook.yml --tags comfyui,comfyui-models-image,comfyui-models-video,comfyui-nodes
```
## Adding New Models
### Add Image Model
Edit `playbook.yml` and append to `comfyui_image_models`:
```yaml
- name: "author/model-name"
type: "checkpoint"
category: "image"
size_gb: 15
vram_gb: 18
format: "fp16"
description: "Model description"
essential: false # Set to true for default installs
```
### Add Custom Node
Append to `comfyui_custom_nodes`:
```yaml
- name: "NodeName"
repo: "https://github.com/author/repo.git"
category: "image" # or video, audio, control, etc.
description: "What it does"
essential: false
```
## VRAM Requirements Summary
For your **24GB GPU**, you can run:
### Simultaneously Loadable Combinations
**Option 1: Image Generation Focus**
- FLUX Schnell FP16 (23GB) → Full model, leaves 1GB for operations
- FLUX Schnell FP8 (12GB) + SDXL (12GB) → Both loaded
- SDXL (12GB) + Refiner (12GB) → Both loaded with room
**Option 2: Video Generation**
- CogVideoX-5B with optimizations (12GB) + SDXL (12GB)
- SVD-XT (20GB) → Good frame count
**Option 3: Multi-Modal**
- SDXL (12GB) + MusicGen Medium (8GB)
- CogVideoX-5B (12GB) + MusicGen Small (4GB)
## Storage Requirements
### Essential Models Only
- Image: 30GB
- Video: 28GB
- Audio: 11GB
- Support: 11GB
- **Total: ~80GB**
### All Models (including optional)
- Image: 54GB
- Video: 36GB
- Audio: 36GB
- Support: 11GB
- **Total: ~137GB**
## Directory Structure Created
```
/workspace/ComfyUI/
├── models/
│ ├── checkpoints/ # FLUX, SDXL, SD3 models
│ ├── unet/ # Diffusion U-Nets
│ ├── vae/ # VAE models
│ ├── loras/ # LoRA adapters
│ ├── clip/ # CLIP text encoders
│ ├── clip_vision/ # CLIP vision models
│ ├── controlnet/ # ControlNet models
│ ├── ipadapter/ # IP-Adapter models
│ ├── embeddings/ # Text embeddings
│ ├── upscale_models/ # Upscalers
│ ├── video_models/ # Video generation models
│ ├── animatediff_models/ # AnimateDiff models
│ ├── audio_models/ # Audio generation models
│ └── configs/ # Model configs
└── custom_nodes/ # Extension nodes
```
## Extending the Playbook
### Add a New Model Category
1. Add variable list in `vars` section:
```yaml
comfyui_new_category_models:
- name: "model-repo-id"
type: "new_type"
category: "new_category"
size_gb: 10
description: "Description"
essential: true
```
2. Create download task section:
```yaml
- name: Download New Category Models
tags: [comfyui-models-newcat, comfyui-models-all]
block:
# Copy pattern from existing model download tasks
```
3. Update tags documentation at top of file
## Model Download Notes
- **Async Downloads**: Large models download asynchronously with 1-hour timeouts
- **Smart Caching**: Models are only downloaded if not already cached
- **HuggingFace Token**: Set `HF_TOKEN` environment variable for gated models
- **Error Handling**: Download failures are ignored to allow partial installations
## Performance Tips
### For 24GB GPU:
1. **Use FP8 Quantized FLUX** when you need multiple models loaded
2. **Use Full FP16 FLUX** when you want maximum quality
3. **Enable CogVideoX Optimizations** to fit in 12GB (edit model config)
4. **Use GGUF variants** for FLUX to save VRAM (manually download)
### Recommended First Install:
```bash
# Essential setup (~80GB, ~1 hour)
ansible-playbook playbook.yml --tags comfyui-essential
```
Then add specific models as needed:
```bash
# Add video models later
ansible-playbook playbook.yml --tags comfyui-models-video
```
## Troubleshooting
### Downloads Failing
Check HuggingFace token:
```bash
export HF_TOKEN="your_token_here"
ansible-playbook playbook.yml --tags comfyui-models-image
```
### Out of Space
Check available storage:
```bash
df -h /workspace
du -sh /workspace/huggingface_cache
```
Remove optional models:
```bash
# Keep only essential models in playbook vars
```
### Custom Node Dependencies
Some nodes require manual intervention:
```bash
cd /workspace/ComfyUI/custom_nodes/NodeName
pip3 install -r requirements.txt
```
## Next Steps
After installation:
1. **Start ComfyUI:**
```bash
cd /workspace/ComfyUI
python3 main.py --listen 0.0.0.0 --port 8188
```
2. **Access via Browser:**
```
http://your-runpod-ip:8188
```
3. **Install Additional Nodes via Manager:**
- ComfyUI Manager provides GUI for installing more nodes
- Browse and install from the manager interface
4. **Download Model Variants:**
- Use ComfyUI Manager to download LoRAs
- Download ControlNet models as needed
- Get additional checkpoints from Civitai
## Support
For issues or questions:
- Check Ansible logs for download status
- Verify HuggingFace token is valid
- Ensure sufficient storage space
- Check VRAM requirements for your GPU

26
Dockerfile Normal file
View File

@@ -0,0 +1,26 @@
# RunPod AI Orchestrator Template
# Minimal Docker image for ComfyUI + vLLM orchestration
# Models and application code live on network volume at /workspace
FROM runpod/pytorch:2.4.0-py3.11-cuda12.4.1-devel-ubuntu22.04
# Install Supervisor for process management
RUN pip install --no-cache-dir supervisor
# Install Tailscale for VPN connectivity
RUN curl -fsSL https://tailscale.com/install.sh | sh
# Install additional system utilities
RUN apt-get update && apt-get install -y \
wget \
&& rm -rf /var/lib/apt/lists/*
# Copy the startup script
COPY start.sh /start.sh
RUN chmod +x /start.sh
# Set working directory to /workspace (network volume mount point)
WORKDIR /workspace
# RunPod calls /start.sh by default
CMD ["/start.sh"]

503
RUNPOD_TEMPLATE.md Normal file
View File

@@ -0,0 +1,503 @@
# RunPod Template Setup Guide
This guide explains how to deploy the AI Orchestrator (ComfyUI + vLLM) on RunPod using a custom Docker template and network volume.
## Architecture Overview
The deployment uses a **two-tier strategy**:
1. **Docker Image** (software layer) - Contains system packages, Supervisor, Tailscale
2. **Network Volume** (data layer) - Contains models, ComfyUI installation, venvs, configuration
This approach allows fast pod deployment (~2-3 minutes) while keeping all large files (models, ~80-200GB) on a persistent network volume.
## Prerequisites
- RunPod account with credits
- Docker Hub account (for hosting the template image)
- HuggingFace account with API token (for model downloads)
- Tailscale account with auth key (optional, for VPN access)
## Step 1: Build and Push Docker Image
### Option A: Automated Build (Recommended)
The repository includes a Gitea workflow that automatically builds and pushes the Docker image to your Gitea container registry when you push to the `main` branch or create a version tag.
1. **Configure Gitea Secret:**
- Go to your Gitea repository → Settings → Secrets
- Add `REGISTRY_TOKEN` = your Gitea access token with registry permissions
- (The workflow automatically uses your Gitea username via `gitea.actor`)
2. **Trigger Build:**
```bash
# Push to main branch
git push origin main
# Or create a version tag
git tag v1.0.0
git push origin v1.0.0
```
3. **Monitor Build:**
- Go to Actions tab in Gitea
- Wait for build to complete (~5-10 minutes)
- Note the Docker image name: `dev.pivoine.art/valknar/runpod-ai-orchestrator:latest`
### Option B: Manual Build
If you prefer to build manually:
```bash
# From the repository root
cd /path/to/runpod
# Build the image
docker build -t dev.pivoine.art/valknar/runpod-ai-orchestrator:latest .
# Login to your Gitea registry
docker login dev.pivoine.art
# Push to Gitea registry
docker push dev.pivoine.art/valknar/runpod-ai-orchestrator:latest
```
## Step 2: Create Network Volume
Network volumes persist your models and data across pod restarts and rebuilds.
1. **Go to RunPod Dashboard → Storage → Network Volumes**
2. **Click "New Network Volume"**
3. **Configure:**
- **Name**: `ai-orchestrator-models`
- **Size**: `200GB` (adjust based on your needs)
- Essential models only: ~80GB
- All models: ~137-200GB
- **Datacenter**: Choose closest to you (volume tied to datacenter)
4. **Click "Create Volume"**
5. **Note the Volume ID** (e.g., `vol-abc123def456`) for pod deployment
### Storage Requirements
| Configuration | Size | Models Included |
|--------------|------|-----------------|
| Essential | ~80GB | FLUX Schnell, 1-2 SDXL checkpoints, MusicGen Medium |
| Complete | ~137GB | All image/video/audio models from playbook |
| Full + vLLM | ~200GB | Complete + Qwen 2.5 7B + Llama 3.1 8B |
## Step 3: Create RunPod Template
1. **Go to RunPod Dashboard → Templates**
2. **Click "New Template"**
3. **Configure Template Settings:**
**Container Configuration:**
- **Template Name**: `AI Orchestrator (ComfyUI + vLLM)`
- **Template Type**: Docker
- **Container Image**: `dev.pivoine.art/valknar/runpod-ai-orchestrator:latest`
- **Container Disk**: `50GB` (for system and temp files)
- **Docker Command**: Leave empty (uses default `/start.sh`)
**Volume Configuration:**
- **Volume Mount Path**: `/workspace`
- **Attach to Network Volume**: Select your volume ID from Step 2
**Port Configuration:**
- **Expose HTTP Ports**: `8188, 9000, 9001`
- `8188` - ComfyUI web interface
- `9000` - Model orchestrator API
- `9001` - Supervisor web UI
- **Expose TCP Ports**: `22` (SSH access)
**Environment Variables:**
```
HF_TOKEN=your_huggingface_token_here
TAILSCALE_AUTHKEY=tskey-auth-your_tailscale_authkey_here
SUPERVISOR_BACKEND_HOST=localhost
SUPERVISOR_BACKEND_PORT=9001
```
**Advanced Settings:**
- **Start Jupyter**: No
- **Start SSH**: Yes (handled by base image)
4. **Click "Save Template"**
## Step 4: First Deployment (Initial Setup)
The first time you deploy, you need to set up the network volume with models and configuration.
### 4.1 Deploy Pod
1. **Go to RunPod Dashboard → Pods**
2. **Click "Deploy"** or "GPU Pods"
3. **Select your custom template**: `AI Orchestrator (ComfyUI + vLLM)`
4. **Configure GPU:**
- **GPU Type**: RTX 4090 (24GB VRAM) or higher
- **Network Volume**: Select your volume from Step 2
- **On-Demand vs Spot**: Choose based on budget
5. **Click "Deploy"**
### 4.2 SSH into Pod
```bash
# Get pod SSH command from RunPod dashboard
ssh root@<pod-ip> -p <port> -i ~/.ssh/id_ed25519
# Or use RunPod web terminal
```
### 4.3 Initial Setup on Network Volume
```bash
# 1. Clone the repository to /workspace/ai
cd /workspace
git clone https://github.com/your-username/runpod.git ai
cd ai
# 2. Create .env file with your credentials
cp .env.example .env
nano .env
# Edit and add:
# HF_TOKEN=your_huggingface_token
# TAILSCALE_AUTHKEY=tskey-auth-your_key
# GPU_TAILSCALE_IP=<will be set automatically>
# 3. Download essential models (this takes 30-60 minutes)
ansible-playbook playbook.yml --tags comfyui-essential
# OR download all models (1-2 hours)
ansible-playbook playbook.yml --tags comfyui-models-all
# 4. Link models to ComfyUI
bash scripts/link-comfyui-models.sh
# OR if arty is available
arty run models/link-comfyui
# 5. Install ComfyUI custom nodes dependencies
cd /workspace/ComfyUI/custom_nodes/ComfyUI-Manager
pip install -r requirements.txt
cd /workspace/ai
# 6. Restart the container to apply all changes
exit
# Go to RunPod dashboard → Stop pod → Start pod
```
### 4.4 Verify Services
After restart, SSH back in and check:
```bash
# Check supervisor status
supervisorctl -c /workspace/supervisord.conf status
# Expected output:
# comfyui RUNNING pid 123, uptime 0:01:00
# (orchestrator is disabled by default - enable for vLLM)
# Test ComfyUI
curl -I http://localhost:8188
# Test Supervisor web UI
curl -I http://localhost:9001
```
## Step 5: Subsequent Deployments
After initial setup, deploying new pods is quick (2-3 minutes):
1. **Deploy pod** with same template + network volume
2. **Wait for startup** (~1-2 minutes for services to start)
3. **Access services:**
- ComfyUI: `http://<pod-ip>:8188`
- Supervisor: `http://<pod-ip>:9001`
**All models, configuration, and data persist on the network volume!**
## Step 6: Access Services
### Via Direct IP (HTTP)
Get pod IP and ports from RunPod dashboard:
```
ComfyUI: http://<pod-ip>:8188
Supervisor UI: http://<pod-ip>:9001
Orchestrator API: http://<pod-ip>:9000
SSH: ssh root@<pod-ip> -p <port>
```
### Via Tailscale VPN (Recommended)
If you configured `TAILSCALE_AUTHKEY`, the pod automatically joins your Tailscale network:
1. **Get Tailscale IP:**
```bash
ssh root@<pod-ip> -p <port>
tailscale ip -4
# Example output: 100.114.60.40
```
2. **Access via Tailscale:**
```
ComfyUI: http://<tailscale-ip>:8188
Supervisor: http://<tailscale-ip>:9001
Orchestrator: http://<tailscale-ip>:9000
SSH: ssh root@<tailscale-ip>
```
3. **Update LiteLLM config** on your VPS with the Tailscale IP
## Service Management
### Start/Stop Services
```bash
# Start all services
supervisorctl -c /workspace/supervisord.conf start all
# Stop all services
supervisorctl -c /workspace/supervisord.conf stop all
# Restart specific service
supervisorctl -c /workspace/supervisord.conf restart comfyui
# View status
supervisorctl -c /workspace/supervisord.conf status
```
### Enable vLLM Models (Text Generation)
By default, only ComfyUI runs (to save VRAM). To enable vLLM:
1. **Stop ComfyUI** (frees up VRAM):
```bash
supervisorctl -c /workspace/supervisord.conf stop comfyui
```
2. **Start orchestrator** (manages vLLM models):
```bash
supervisorctl -c /workspace/supervisord.conf start orchestrator
```
3. **Test text generation:**
```bash
curl -X POST http://localhost:9000/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{"model":"qwen-2.5-7b","messages":[{"role":"user","content":"Hello"}]}'
```
### Switch Back to ComfyUI
```bash
# Stop orchestrator (stops all vLLM models)
supervisorctl -c /workspace/supervisord.conf stop orchestrator
# Start ComfyUI
supervisorctl -c /workspace/supervisord.conf start comfyui
```
## Updating the Template
When you make changes to code or configuration:
### Update Docker Image
```bash
# 1. Make changes to Dockerfile or start.sh
# 2. Push to repository
git add .
git commit -m "Update template configuration"
git push origin main
# 3. Gitea workflow auto-builds new image
# 4. Terminate old pod and deploy new one with updated image
```
### Update Network Volume Data
```bash
# SSH into running pod
ssh root@<pod-ip> -p <port>
# Update repository
cd /workspace/ai
git pull
# Re-run Ansible if needed
ansible-playbook playbook.yml --tags <specific-tag>
# Restart services
supervisorctl -c /workspace/supervisord.conf restart all
```
## Troubleshooting
### Pod fails to start
**Check logs:**
```bash
# Via SSH
cat /workspace/logs/supervisord.log
cat /workspace/logs/comfyui.err.log
# Via RunPod web terminal
tail -f /workspace/logs/*.log
```
**Common issues:**
- Missing `.env` file → Create `/workspace/ai/.env` with required vars
- Supervisor config not found → Ensure `/workspace/ai/supervisord.conf` exists
- Port conflicts → Check if services are already running
### Tailscale not connecting
**Check Tailscale status:**
```bash
tailscale status
tailscale ip -4
```
**Common issues:**
- Missing or invalid `TAILSCALE_AUTHKEY` in `.env`
- Auth key expired → Generate new key in Tailscale admin
- Firewall blocking → RunPod should allow Tailscale by default
### Services not starting
**Check Supervisor:**
```bash
supervisorctl -c /workspace/supervisord.conf status
supervisorctl -c /workspace/supervisord.conf tail -f comfyui
```
**Common issues:**
- venv broken → Re-run `scripts/bootstrap-venvs.sh`
- Models not downloaded → Run Ansible playbook again
- Python version mismatch → Rebuild venvs
### Out of VRAM
**Check GPU memory:**
```bash
nvidia-smi
```
**RTX 4090 (24GB) capacity:**
- ComfyUI (FLUX Schnell): ~23GB (can't run with vLLM)
- vLLM (Qwen 2.5 7B): ~14GB
- vLLM (Llama 3.1 8B): ~17GB
**Solution:** Only run one service at a time (see Service Management section)
### Network volume full
**Check disk usage:**
```bash
df -h /workspace
du -sh /workspace/*
```
**Clean up:**
```bash
# Remove old HuggingFace cache
rm -rf /workspace/huggingface_cache
# Re-download essential models only
cd /workspace/ai
ansible-playbook playbook.yml --tags comfyui-essential
```
## Cost Optimization
### Spot vs On-Demand
- **Spot instances**: ~70% cheaper, can be interrupted
- **On-Demand**: More expensive, guaranteed availability
**Recommendation:** Use spot for development, on-demand for production
### Network Volume Pricing
- First 1TB: $0.07/GB/month
- Beyond 1TB: $0.05/GB/month
**200GB volume cost:** ~$14/month
### Pod Auto-Stop
Configure auto-stop in RunPod pod settings to save costs when idle:
- Stop after 15 minutes idle
- Stop after 1 hour idle
- Manual stop only
## Advanced Configuration
### Custom Environment Variables
Add to template or pod environment variables:
```bash
# Model cache locations
HF_HOME=/workspace/huggingface_cache
TRANSFORMERS_CACHE=/workspace/huggingface_cache
# ComfyUI settings
COMFYUI_PORT=8188
COMFYUI_LISTEN=0.0.0.0
# Orchestrator settings
ORCHESTRATOR_PORT=9000
# GPU settings
CUDA_VISIBLE_DEVICES=0
```
### Multiple Network Volumes
You can attach multiple network volumes for organization:
1. **Models volume** - `/workspace/models` (read-only, shared)
2. **Data volume** - `/workspace/data` (read-write, per-project)
### Custom Startup Script
Override `/start.sh` behavior by creating `/workspace/custom-start.sh`:
```bash
#!/bin/bash
# Custom startup commands
# Source default startup
source /start.sh
# Add your custom commands here
echo "Running custom initialization..."
```
## References
- [RunPod Documentation](https://docs.runpod.io/)
- [RunPod Templates Overview](https://docs.runpod.io/pods/templates/overview)
- [Network Volumes Guide](https://docs.runpod.io/storage/network-volumes)
- [ComfyUI Documentation](https://github.com/comfyanonymous/ComfyUI)
- [Supervisor Documentation](http://supervisord.org/)
- [Tailscale Documentation](https://tailscale.com/kb/)
## Support
For issues or questions:
- Check troubleshooting section above
- Review `/workspace/logs/` files
- Check RunPod community forums
- Open issue in project repository

479
arty.yml
View File

@@ -63,11 +63,41 @@ references:
description: "MusicGen and Stable Audio integration" description: "MusicGen and Stable Audio integration"
essential: false essential: false
- url: https://github.com/billwuhao/ComfyUI_DiffRhythm.git
into: $COMFYUI_ROOT/custom_nodes/ComfyUI_DiffRhythm
description: "DiffRhythm - Full-length song generation (up to 4m45s) with text/audio conditioning"
essential: false
- url: https://github.com/billwuhao/ComfyUI_ACE-Step.git
into: $COMFYUI_ROOT/custom_nodes/ComfyUI_ACE-Step
description: "ACE Step - State-of-the-art music generation with 19-language support, voice cloning, and superior coherence"
essential: false
- url: https://github.com/ssitu/ComfyUI_UltimateSDUpscale.git - url: https://github.com/ssitu/ComfyUI_UltimateSDUpscale.git
into: $COMFYUI_ROOT/custom_nodes/ComfyUI_UltimateSDUpscale into: $COMFYUI_ROOT/custom_nodes/ComfyUI_UltimateSDUpscale
description: "Ultimate SD Upscale for high-quality image upscaling" description: "Ultimate SD Upscale for high-quality image upscaling"
essential: false essential: false
- url: https://github.com/kijai/ComfyUI-KJNodes.git
into: $COMFYUI_ROOT/custom_nodes/ComfyUI-KJNodes
description: "Kijai optimizations for HunyuanVideo and Wan2.2 (FP8 scaling, video helpers, model loading)"
essential: true
- url: https://github.com/Fannovel16/comfyui_controlnet_aux.git
into: $COMFYUI_ROOT/custom_nodes/comfyui_controlnet_aux
description: "ControlNet preprocessors (Canny, Depth, OpenPose, MLSD) for Wan2.2 Fun Control"
essential: true
- url: https://github.com/city96/ComfyUI-GGUF.git
into: $COMFYUI_ROOT/custom_nodes/ComfyUI-GGUF
description: "GGUF quantization support for memory-efficient model loading"
essential: false
- url: https://github.com/11cafe/comfyui-workspace-manager.git
into: $COMFYUI_ROOT/custom_nodes/comfyui-workspace-manager
description: "Workspace manager for ComfyUI - workflow/model organization (obsolete but requested)"
essential: false
# Environment profiles for selective repository management # Environment profiles for selective repository management
envs: envs:
# RunPod environment variables # RunPod environment variables
@@ -78,37 +108,6 @@ envs:
LOGS_DIR: /workspace/logs LOGS_DIR: /workspace/logs
BIN_DIR: /workspace/bin BIN_DIR: /workspace/bin
# Production: Only essential components
prod:
- $AI_ROOT
- $COMFYUI_ROOT
- $COMFYUI_ROOT/custom_nodes/ComfyUI-Manager
- $COMFYUI_ROOT/custom_nodes/ComfyUI-VideoHelperSuite
- $COMFYUI_ROOT/custom_nodes/ComfyUI-AnimateDiff-Evolved
- $COMFYUI_ROOT/custom_nodes/ComfyUI_IPAdapter_plus
- $COMFYUI_ROOT/custom_nodes/ComfyUI-Impact-Pack
# Development: All repositories including optional nodes
dev:
- $AI_ROOT
- $COMFYUI_ROOT
- $COMFYUI_ROOT/custom_nodes/ComfyUI-Manager
- $COMFYUI_ROOT/custom_nodes/ComfyUI-VideoHelperSuite
- $COMFYUI_ROOT/custom_nodes/ComfyUI-AnimateDiff-Evolved
- $COMFYUI_ROOT/custom_nodes/ComfyUI_IPAdapter_plus
- $COMFYUI_ROOT/custom_nodes/ComfyUI-Impact-Pack
- $COMFYUI_ROOT/custom_nodes/ComfyUI-CogVideoXWrapper
- $COMFYUI_ROOT/custom_nodes/ComfyUI-Inspire-Pack
- $COMFYUI_ROOT/custom_nodes/ComfyUI-Advanced-ControlNet
- $COMFYUI_ROOT/custom_nodes/ComfyUI-3D-Pack
- $COMFYUI_ROOT/custom_nodes/comfyui-sound-lab
# Minimal: Only orchestrator and ComfyUI base
minimal:
- $AI_ROOT
- $COMFYUI_ROOT
- $COMFYUI_ROOT/custom_nodes/ComfyUI-Manager
# Deployment scripts for RunPod instances # Deployment scripts for RunPod instances
scripts: scripts:
# #
@@ -165,11 +164,23 @@ scripts:
htop \ htop \
tmux \ tmux \
net-tools \ net-tools \
davfs2 davfs2 \
ffmpeg \
libavcodec-dev \
libavformat-dev \
libavutil-dev \
libswscale-dev
echo "" echo ""
echo "✓ System packages installed successfully" echo "✓ System packages installed successfully"
# Verify FFmpeg installation
if ffmpeg -version > /dev/null 2>&1; then
echo "✓ FFmpeg installed: $(ffmpeg -version | head -1 | cut -d ' ' -f3)"
else
echo "❌ WARNING: FFmpeg not found"
fi
setup/python-env: | setup/python-env: |
echo "=========================================" echo "========================================="
echo " Setting Up Python Environment" echo " Setting Up Python Environment"
@@ -279,43 +290,67 @@ scripts:
echo "=========================================" echo "========================================="
echo "" echo ""
# Install system dependencies
echo "Installing system dependencies..."
sudo apt-get update -qq
sudo apt-get install -y -qq espeak-ng
echo "✓ System dependencies installed (espeak-ng)"
echo ""
cd $COMFYUI_ROOT/custom_nodes cd $COMFYUI_ROOT/custom_nodes
# ComfyUI Manager # ComfyUI Manager
echo "[1/5] Installing ComfyUI-Manager..." echo "[1/6] Installing ComfyUI-Manager..."
if [ ! -d "ComfyUI-Manager" ]; then if [ ! -d "ComfyUI-Manager" ]; then
git clone https://github.com/ltdrdata/ComfyUI-Manager.git git clone https://github.com/ltdrdata/ComfyUI-Manager.git
fi fi
[ -f "ComfyUI-Manager/requirements.txt" ] && sudo pip3 install -r ComfyUI-Manager/requirements.txt [ -f "ComfyUI-Manager/requirements.txt" ] && sudo pip3 install -r ComfyUI-Manager/requirements.txt
# VideoHelperSuite # VideoHelperSuite
echo "[2/5] Installing ComfyUI-VideoHelperSuite..." echo "[2/6] Installing ComfyUI-VideoHelperSuite..."
if [ ! -d "ComfyUI-VideoHelperSuite" ]; then if [ ! -d "ComfyUI-VideoHelperSuite" ]; then
git clone https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git git clone https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git
fi fi
[ -f "ComfyUI-VideoHelperSuite/requirements.txt" ] && sudo pip3 install -r ComfyUI-VideoHelperSuite/requirements.txt [ -f "ComfyUI-VideoHelperSuite/requirements.txt" ] && sudo pip3 install -r ComfyUI-VideoHelperSuite/requirements.txt
# AnimateDiff-Evolved # AnimateDiff-Evolved
echo "[3/5] Installing ComfyUI-AnimateDiff-Evolved..." echo "[3/6] Installing ComfyUI-AnimateDiff-Evolved..."
if [ ! -d "ComfyUI-AnimateDiff-Evolved" ]; then if [ ! -d "ComfyUI-AnimateDiff-Evolved" ]; then
git clone https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git git clone https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git
fi fi
[ -f "ComfyUI-AnimateDiff-Evolved/requirements.txt" ] && sudo pip3 install -r ComfyUI-AnimateDiff-Evolved/requirements.txt [ -f "ComfyUI-AnimateDiff-Evolved/requirements.txt" ] && sudo pip3 install -r ComfyUI-AnimateDiff-Evolved/requirements.txt
# IPAdapter Plus # IPAdapter Plus
echo "[4/5] Installing ComfyUI_IPAdapter_plus..." echo "[4/6] Installing ComfyUI_IPAdapter_plus..."
if [ ! -d "ComfyUI_IPAdapter_plus" ]; then if [ ! -d "ComfyUI_IPAdapter_plus" ]; then
git clone https://github.com/cubiq/ComfyUI_IPAdapter_plus.git git clone https://github.com/cubiq/ComfyUI_IPAdapter_plus.git
fi fi
[ -f "ComfyUI_IPAdapter_plus/requirements.txt" ] && sudo pip3 install -r ComfyUI_IPAdapter_plus/requirements.txt [ -f "ComfyUI_IPAdapter_plus/requirements.txt" ] && sudo pip3 install -r ComfyUI_IPAdapter_plus/requirements.txt
# Impact-Pack # Impact-Pack
echo "[5/5] Installing ComfyUI-Impact-Pack..." echo "[5/6] Installing ComfyUI-Impact-Pack..."
if [ ! -d "ComfyUI-Impact-Pack" ]; then if [ ! -d "ComfyUI-Impact-Pack" ]; then
git clone https://github.com/ltdrdata/ComfyUI-Impact-Pack.git git clone https://github.com/ltdrdata/ComfyUI-Impact-Pack.git
fi fi
[ -f "ComfyUI-Impact-Pack/requirements.txt" ] && sudo pip3 install -r ComfyUI-Impact-Pack/requirements.txt [ -f "ComfyUI-Impact-Pack/requirements.txt" ] && sudo pip3 install -r ComfyUI-Impact-Pack/requirements.txt
# DiffRhythm
echo "[6/6] Installing ComfyUI_DiffRhythm..."
if [ ! -d "ComfyUI_DiffRhythm" ]; then
git clone https://github.com/billwuhao/ComfyUI_DiffRhythm.git
fi
if [ -f "ComfyUI_DiffRhythm/requirements.txt" ]; then
cd $COMFYUI_ROOT
source venv/bin/activate
pip install -r custom_nodes/ComfyUI_DiffRhythm/requirements.txt
deactivate
cd custom_nodes
fi
# Create DiffRhythm model directories
echo "Creating DiffRhythm model directories..."
mkdir -p $COMFYUI_ROOT/models/TTS/DiffRhythm/{MuQ-large-msd-iter,MuQ-MuLan-large,xlm-roberta-base,eval-model}
# Fix numpy version for vLLM compatibility # Fix numpy version for vLLM compatibility
echo "Fixing numpy version..." echo "Fixing numpy version..."
sudo pip3 install 'numpy<2.0.0' --force-reinstall sudo pip3 install 'numpy<2.0.0' --force-reinstall
@@ -327,6 +362,144 @@ scripts:
echo " - AnimateDiff-Evolved: Video generation" echo " - AnimateDiff-Evolved: Video generation"
echo " - IPAdapter_plus: Style transfer" echo " - IPAdapter_plus: Style transfer"
echo " - Impact-Pack: Face enhancement" echo " - Impact-Pack: Face enhancement"
echo " - DiffRhythm: Full-length song generation"
models/diffrhythm-eval: |
echo "========================================="
echo " Downloading DiffRhythm Eval Model"
echo "========================================="
echo ""
# Create eval-model directory
mkdir -p $COMFYUI_ROOT/models/TTS/DiffRhythm/eval-model
cd $COMFYUI_ROOT/models/TTS/DiffRhythm/eval-model
# Download eval.yaml (129 bytes)
echo "Downloading eval.yaml..."
curl -L -o eval.yaml "https://huggingface.co/spaces/ASLP-lab/DiffRhythm/resolve/main/pretrained/eval.yaml"
# Download eval.safetensors (101 MB)
echo "Downloading eval.safetensors (101 MB)..."
curl -L -o eval.safetensors "https://huggingface.co/spaces/ASLP-lab/DiffRhythm/resolve/main/pretrained/eval.safetensors"
# Verify files
if [ -f "eval.yaml" ] && [ -f "eval.safetensors" ]; then
echo ""
echo "✓ DiffRhythm eval-model files downloaded successfully"
echo " - eval.yaml: $(du -h eval.yaml | cut -f1)"
echo " - eval.safetensors: $(du -h eval.safetensors | cut -f1)"
else
echo "❌ ERROR: Failed to download eval-model files"
exit 1
fi
setup/comfyui-acestep: |
echo "========================================="
echo " Installing ACE Step Custom Node"
echo "========================================="
echo ""
cd $COMFYUI_ROOT/custom_nodes
# Clone repository if not exists
if [ ! -d "ComfyUI_ACE-Step" ]; then
echo "Cloning ComfyUI_ACE-Step repository..."
git clone https://github.com/billwuhao/ComfyUI_ACE-Step.git
else
echo "ComfyUI_ACE-Step already exists, skipping clone"
fi
# Install dependencies in ComfyUI venv
echo ""
echo "Installing ACE Step dependencies..."
cd $COMFYUI_ROOT
source venv/bin/activate
pip install -r custom_nodes/ComfyUI_ACE-Step/requirements.txt
deactivate
echo ""
echo "✓ ACE Step custom node installed successfully"
echo " Note: Download models separately using:"
echo " bash /workspace/bin/artifact_huggingface_download.sh download -c models_huggingface.yaml --category audio_models"
setup/pivoine-nodes: |
echo "========================================="
echo " Linking Pivoine Custom Nodes"
echo "========================================="
echo ""
NODES_SRC="/workspace/ai/comfyui/nodes"
NODES_DEST="/workspace/ComfyUI/custom_nodes/ComfyUI_Pivoine"
# Remove existing symlink if present
if [ -L "$NODES_DEST" ] || [ -d "$NODES_DEST" ]; then
echo "Removing existing: $NODES_DEST"
rm -rf "$NODES_DEST"
fi
# Create symlink
ln -s "$NODES_SRC" "$NODES_DEST"
echo ""
echo "✓ Pivoine custom nodes linked"
echo " Source: $NODES_SRC"
echo " Linked: $NODES_DEST"
echo ""
echo "Available Pivoine nodes:"
echo " 🌸 PivoineDiffRhythmRun - DiffRhythm with chunked disabled"
echo ""
echo "Category: 🌸Pivoine/Audio"
fix/diffrhythm-patch: |
echo "========================================="
echo " Apply DiffRhythm LlamaConfig Patch"
echo "========================================="
echo ""
echo "Issue: Tensor dimension mismatch (32 vs 64) in rotary embeddings"
echo "Solution: Patch DiffRhythm __init__.py to fix LlamaConfig"
echo ""
echo "References:"
echo " - https://github.com/billwuhao/ComfyUI_DiffRhythm/issues/44"
echo " - https://github.com/billwuhao/ComfyUI_DiffRhythm/issues/48"
echo ""
DIFF_RHYTHM_DIR="/workspace/ComfyUI/custom_nodes/ComfyUI_DiffRhythm"
PATCH_FILE="/workspace/ai/comfyui/patches/diffrhythm-llamaconfig-fix.patch"
if [ ! -d "$DIFF_RHYTHM_DIR" ]; then
echo "✗ Error: DiffRhythm not found at $DIFF_RHYTHM_DIR"
exit 1
fi
if [ ! -f "$PATCH_FILE" ]; then
echo "✗ Error: Patch file not found at $PATCH_FILE"
exit 1
fi
cd "$DIFF_RHYTHM_DIR"
echo "Checking if patch already applied..."
if grep -q "PatchedLlamaConfig" __init__.py; then
echo "✓ Patch already applied!"
exit 0
fi
echo "Applying patch..."
patch -p1 < "$PATCH_FILE"
if [ $? -eq 0 ]; then
echo ""
echo "✓ Patch applied successfully!"
echo ""
echo "Next steps:"
echo " 1. Restart ComfyUI: arty services/comfyui/restart"
echo " 2. Test DiffRhythm workflows"
else
echo ""
echo "✗ Failed to apply patch"
echo "You may need to manually apply the patch or check for conflicts"
exit 1
fi
setup/comfyui-extensions-deps: | setup/comfyui-extensions-deps: |
echo "=========================================" echo "========================================="
@@ -436,58 +609,6 @@ scripts:
echo "To manage: supervisorctl status" echo "To manage: supervisorctl status"
echo "Web UI: http://localhost:9001 (admin/runpod2024)" echo "Web UI: http://localhost:9001 (admin/runpod2024)"
setup/webdav: |
echo "========================================="
echo " Setting Up WebDAV Mount (HiDrive)"
echo "========================================="
echo ""
# Install davfs2 if not present
if ! command -v mount.davfs >/dev/null 2>&1; then
echo "Installing davfs2..."
DEBIAN_FRONTEND=noninteractive apt update && DEBIAN_FRONTEND=noninteractive apt install -y davfs2
fi
# Create mount point
echo "Creating mount point..."
mkdir -p /mnt/hidrive
# Create davfs2 secrets file
echo "Configuring WebDAV credentials..."
mkdir -p /etc/davfs2
echo "https://webdav.hidrive.ionos.com/ valknar MwRTW4hR.eRbipQ" | tee /etc/davfs2/secrets > /dev/null
chmod 600 /etc/davfs2/secrets
# Configure davfs2
sed -i 's/# use_locks 1/use_locks 0/' /etc/davfs2/davfs2.conf 2>/dev/null || true
# Mount WebDAV
echo "Mounting HiDrive WebDAV..."
if mount -t davfs https://webdav.hidrive.ionos.com/ /mnt/hidrive; then
echo "✓ HiDrive mounted successfully"
else
echo "⚠ Warning: Mount failed, you may need to mount manually"
echo " Try: mount -t davfs https://webdav.hidrive.ionos.com/ /mnt/hidrive"
fi
# Create ComfyUI output directory
echo "Creating ComfyUI output directory..."
mkdir -p /mnt/hidrive/users/valknar/Pictures/AI/ComfyUI
# Create symlink in ComfyUI
echo "Creating symlink in ComfyUI..."
ln -sf /mnt/hidrive/users/valknar/Pictures/AI/ComfyUI $COMFYUI_ROOT/output_hidrive
echo ""
echo "✓ WebDAV setup complete"
echo ""
echo "Mount point: /mnt/hidrive"
echo "ComfyUI output: /mnt/hidrive/users/valknar/Pictures/AI/ComfyUI"
echo "ComfyUI symlink: $COMFYUI_ROOT/output_hidrive"
echo ""
echo "To unmount: umount /mnt/hidrive"
echo "To remount: mount -t davfs https://webdav.hidrive.ionos.com/ /mnt/hidrive"
# #
# Utility Scripts # Utility Scripts
# #
@@ -575,53 +696,6 @@ scripts:
echo " 3. Name: multi-modal-ai-v2.0" echo " 3. Name: multi-modal-ai-v2.0"
echo " 4. Save and test deployment" echo " 4. Save and test deployment"
#
# Orchestration Scripts
#
install/minimal: |
echo "========================================="
echo " Minimal Installation"
echo "========================================="
echo ""
echo "Installing: System + Python + ComfyUI + Supervisor"
echo ""
arty run setup/system-packages && \
arty run setup/python-env && \
arty run setup/comfyui-base && \
arty run setup/supervisor
echo ""
echo "✓ Minimal installation complete"
echo ""
echo "Next steps:"
echo " 1. Download models: Use Ansible playbook"
echo " 2. Link models: arty run models/link-comfyui"
echo " 3. Start services: arty run services/start"
install/essential: |
echo "========================================="
echo " Essential Installation"
echo "========================================="
echo ""
echo "Installing: System + Python + ComfyUI + Nodes + Supervisor"
echo ""
arty run setup/system-packages && \
arty run setup/python-env && \
arty run setup/comfyui-base && \
arty run setup/comfyui-nodes && \
arty run setup/supervisor
echo ""
echo "✓ Essential installation complete"
echo ""
echo "Next steps:"
echo " 1. Download models: ansible-playbook playbook.yml --tags comfyui-essential"
echo " 2. Link models: arty run models/link-comfyui"
echo " 3. Link workflows: arty run workflows/link-comfyui"
echo " 4. Start services: arty run services/start"
install/full: | install/full: |
echo "=========================================" echo "========================================="
echo " Full Installation" echo " Full Installation"
@@ -647,39 +721,6 @@ scripts:
echo " 4. Configure Tailscale (see instructions above)" echo " 4. Configure Tailscale (see instructions above)"
echo " 5. Start services: arty run services/start" echo " 5. Start services: arty run services/start"
#
# Legacy Setup (deprecated - use install/* instead)
#
setup/full-legacy: |
cd $AI_ROOT
cp .env.example .env
echo "⚠ DEPRECATED: Use 'arty run install/full' instead"
echo "Edit .env and set HF_TOKEN, then run: ansible-playbook playbook.yml"
setup/essential-legacy: |
cd $AI_ROOT
cp .env.example .env
echo "⚠ DEPRECATED: Use 'arty run install/essential' instead"
echo "Edit .env and set HF_TOKEN, then run: ansible-playbook playbook.yml --tags comfyui-essential"
# Model linking (run after models are downloaded)
models/link-comfyui: |
cd $COMFYUI_ROOT/models/diffusers
ln -sf $HF_CACHE/models--black-forest-labs--FLUX.1-schnell FLUX.1-schnell
ln -sf $HF_CACHE/models--black-forest-labs--FLUX.1-dev FLUX.1-dev
ln -sf $HF_CACHE/models--stabilityai--stable-diffusion-xl-base-1.0 stable-diffusion-xl-base-1.0
ln -sf $HF_CACHE/models--stabilityai--stable-diffusion-xl-refiner-1.0 stable-diffusion-xl-refiner-1.0
ln -sf $HF_CACHE/models--stabilityai--stable-diffusion-3.5-large stable-diffusion-3.5-large
cd $COMFYUI_ROOT/models/clip_vision
ln -sf $HF_CACHE/models--openai--clip-vit-large-patch14 clip-vit-large-patch14
ln -sf $HF_CACHE/models--laion--CLIP-ViT-bigG-14-laion2B-39B-b160k CLIP-ViT-bigG-14
ln -sf $HF_CACHE/models--google--siglip-so400m-patch14-384 siglip-so400m-patch14-384
cd $COMFYUI_ROOT/models/diffusion_models
ln -sf $HF_CACHE/models--THUDM--CogVideoX-5b CogVideoX-5b
ln -sf $HF_CACHE/models--stabilityai--stable-video-diffusion-img2vid stable-video-diffusion-img2vid
ln -sf $HF_CACHE/models--stabilityai--stable-video-diffusion-img2vid-xt stable-video-diffusion-img2vid-xt
echo "Models linked to ComfyUI"
# Workflow linking (link production workflows with category prefixes) # Workflow linking (link production workflows with category prefixes)
workflows/link-comfyui: | workflows/link-comfyui: |
# Create ComfyUI user workflows directory # Create ComfyUI user workflows directory
@@ -743,6 +784,14 @@ scripts:
fi fi
done done
# NSFW workflows (prefix: nsfw_)
for file in "$SOURCE_DIR/nsfw"/*.json; do
if [ -f "$file" ]; then
basename=$(basename "$file")
ln -sf "$file" "nsfw_${basename}"
fi
done
# Count workflows # Count workflows
WORKFLOW_COUNT=$(ls -1 *.json 2>/dev/null | wc -l) WORKFLOW_COUNT=$(ls -1 *.json 2>/dev/null | wc -l)
@@ -751,51 +800,80 @@ scripts:
echo " Location: $COMFYUI_ROOT/user/default/workflows/" echo " Location: $COMFYUI_ROOT/user/default/workflows/"
echo "" echo ""
echo "Categories (by prefix):" echo "Categories (by prefix):"
echo " - t2i_ : 4 text-to-image workflows (FLUX, SDXL, SD3.5)" echo " - t2i_ : 5 text-to-image workflows (FLUX, SDXL, SD3.5, LoRA Fusion)"
echo " - i2i_ : 3 image-to-image workflows (IP-Adapter)" echo " - i2i_ : 3 image-to-image workflows (IP-Adapter)"
echo " - i2v_ : 3 image-to-video workflows (CogVideoX, SVD)" echo " - i2v_ : 3 image-to-video workflows (CogVideoX, SVD)"
echo " - t2m_ : 4 text-to-music workflows (MusicGen)" echo " - t2m_ : 4 text-to-music workflows (MusicGen)"
echo " - upscale_: 3 upscaling workflows" echo " - upscale_: 3 upscaling workflows (Ultimate SD, Simple, Face)"
echo " - adv_ : 3 advanced workflows (ControlNet, AnimateDiff, Batch)" echo " - adv_ : 3 advanced workflows (ControlNet, AnimateDiff, Batch)"
echo " - nsfw_ : 4 NSFW workflows (LUSTIFY, Pony, RealVisXL, Ultimate Upscale)"
echo "" echo ""
echo "Total: 25 production workflows"
echo "Workflows will appear in ComfyUI's workflow browser, sorted by category prefix" echo "Workflows will appear in ComfyUI's workflow browser, sorted by category prefix"
# #
# Service Management (Supervisor-based) # Service Management (Supervisor-based)
# #
# All services # All services
services/start: supervisorctl -c /workspace/supervisord.conf start ai-services:* services/start: supervisorctl -c /workspace/supervisord.conf start all
services/stop: supervisorctl -c /workspace/supervisord.conf stop ai-services:* services/stop: supervisorctl -c /workspace/supervisord.conf stop all
services/restart: supervisorctl -c /workspace/supervisord.conf restart ai-services:* services/restart: supervisorctl -c /workspace/supervisord.conf restart all
services/status: supervisorctl -c /workspace/supervisord.conf status services/status: supervisorctl -c /workspace/supervisord.conf status
# ComfyUI service # ComfyUI services group
services/comfyui/start: supervisorctl -c /workspace/supervisord.conf start ai-services:comfyui services/comfyui-group/start: supervisorctl -c /workspace/supervisord.conf start comfyui-services:*
services/comfyui/stop: supervisorctl -c /workspace/supervisord.conf stop ai-services:comfyui services/comfyui-group/stop: supervisorctl -c /workspace/supervisord.conf stop comfyui-services:*
services/comfyui/restart: supervisorctl -c /workspace/supervisord.conf restart ai-services:comfyui services/comfyui-group/restart: supervisorctl -c /workspace/supervisord.conf restart comfyui-services:*
services/comfyui/status: supervisorctl -c /workspace/supervisord.conf status ai-services:comfyui services/comfyui-group/status: supervisorctl -c /workspace/supervisord.conf status comfyui-services:*
services/comfyui/logs: supervisorctl -c /workspace/supervisord.conf tail -f ai-services:comfyui
# Orchestrator service # vLLM services group
services/orchestrator/start: supervisorctl -c /workspace/supervisord.conf start ai-services:orchestrator services/vllm-group/start: supervisorctl -c /workspace/supervisord.conf start vllm-services:*
services/orchestrator/stop: supervisorctl -c /workspace/supervisord.conf stop ai-services:orchestrator services/vllm-group/stop: supervisorctl -c /workspace/supervisord.conf stop vllm-services:*
services/orchestrator/restart: supervisorctl -c /workspace/supervisord.conf restart ai-services:orchestrator services/vllm-group/restart: supervisorctl -c /workspace/supervisord.conf restart vllm-services:*
services/orchestrator/status: supervisorctl -c /workspace/supervisord.conf status ai-services:orchestrator services/vllm-group/status: supervisorctl -c /workspace/supervisord.conf status vllm-services:*
services/orchestrator/logs: supervisorctl -c /workspace/supervisord.conf tail -f ai-services:orchestrator
# ComfyUI service
services/comfyui/start: supervisorctl -c /workspace/supervisord.conf start comfyui-services:comfyui
services/comfyui/stop: supervisorctl -c /workspace/supervisord.conf stop comfyui-services:comfyui
services/comfyui/restart: supervisorctl -c /workspace/supervisord.conf restart comfyui-services:comfyui
services/comfyui/status: supervisorctl -c /workspace/supervisord.conf status comfyui-services:comfyui
services/comfyui/logs: supervisorctl -c /workspace/supervisord.conf tail -f comfyui-services:comfyui
# WebDAV Sync service # WebDAV Sync service
services/webdav-sync/start: supervisorctl -c /workspace/supervisord.conf start ai-services:webdav-sync services/webdav-sync/start: supervisorctl -c /workspace/supervisord.conf start comfyui-services:webdav-sync
services/webdav-sync/stop: supervisorctl -c /workspace/supervisord.conf stop ai-services:webdav-sync services/webdav-sync/stop: supervisorctl -c /workspace/supervisord.conf stop comfyui-services:webdav-sync
services/webdav-sync/restart: supervisorctl -c /workspace/supervisord.conf restart ai-services:webdav-sync services/webdav-sync/restart: supervisorctl -c /workspace/supervisord.conf restart comfyui-services:webdav-sync
services/webdav-sync/status: supervisorctl -c /workspace/supervisord.conf status ai-services:webdav-sync services/webdav-sync/status: supervisorctl -c /workspace/supervisord.conf status comfyui-services:webdav-sync
services/webdav-sync/logs: supervisorctl -c /workspace/supervisord.conf tail -f ai-services:webdav-sync services/webdav-sync/logs: supervisorctl -c /workspace/supervisord.conf tail -f comfyui-services:webdav-sync
# vLLM Qwen service
services/vllm-qwen/start: supervisorctl -c /workspace/supervisord.conf start vllm-services:vllm-qwen
services/vllm-qwen/stop: supervisorctl -c /workspace/supervisord.conf stop vllm-services:vllm-qwen
services/vllm-qwen/restart: supervisorctl -c /workspace/supervisord.conf restart vllm-services:vllm-qwen
services/vllm-qwen/status: supervisorctl -c /workspace/supervisord.conf status vllm-services:vllm-qwen
services/vllm-qwen/logs: supervisorctl -c /workspace/supervisord.conf tail -f vllm-services:vllm-qwen
# vLLM Llama service
services/vllm-llama/start: supervisorctl -c /workspace/supervisord.conf start vllm-services:vllm-llama
services/vllm-llama/stop: supervisorctl -c /workspace/supervisord.conf stop vllm-services:vllm-llama
services/vllm-llama/restart: supervisorctl -c /workspace/supervisord.conf restart vllm-services:vllm-llama
services/vllm-llama/status: supervisorctl -c /workspace/supervisord.conf status vllm-services:vllm-llama
services/vllm-llama/logs: supervisorctl -c /workspace/supervisord.conf tail -f vllm-services:vllm-llama
# vLLM Embedding service
services/vllm-embedding/start: supervisorctl -c /workspace/supervisord.conf start vllm-services:vllm-embedding
services/vllm-embedding/stop: supervisorctl -c /workspace/supervisord.conf stop vllm-services:vllm-embedding
services/vllm-embedding/restart: supervisorctl -c /workspace/supervisord.conf restart vllm-services:vllm-embedding
services/vllm-embedding/status: supervisorctl -c /workspace/supervisord.conf status vllm-services:vllm-embedding
services/vllm-embedding/logs: supervisorctl -c /workspace/supervisord.conf tail -f vllm-services:vllm-embedding
# #
# Health Checks # Health Checks
# #
health/orchestrator: curl http://localhost:9000/health
health/comfyui: curl http://localhost:8188 health/comfyui: curl http://localhost:8188
health/vllm: curl http://localhost:8000/health health/vllm-qwen: curl http://localhost:8000/health
health/vllm-llama: curl http://localhost:8001/health
health/vllm-embedding: curl http://localhost:8002/health
# #
# System Checks # System Checks
@@ -913,15 +991,16 @@ notes: |
Link workflows: arty run workflows/link-comfyui Link workflows: arty run workflows/link-comfyui
20 Production Workflows: 25 Production Workflows:
- Text-to-Image: FLUX Schnell, FLUX Dev, SDXL+Refiner, SD3.5 - Text-to-Image: FLUX Schnell, FLUX Dev, SDXL+Refiner, SD3.5, LoRA Fusion
- Image-to-Image: IP-Adapter (style, face, composition) - Image-to-Image: IP-Adapter (style, face, composition)
- Image-to-Video: CogVideoX, SVD, SVD-XT - Image-to-Video: CogVideoX, SVD, SVD-XT
- Text-to-Music: MusicGen (small/medium/large/melody) - Text-to-Music: MusicGen (small/medium/large/melody)
- Upscaling: Ultimate SD, Simple, Face-focused - Upscaling: Ultimate SD, Simple, Face-focused
- Advanced: ControlNet, AnimateDiff, Batch processing - Advanced: ControlNet, AnimateDiff, Batch processing
- NSFW: LUSTIFY Realistic, Pony Diffusion, RealVisXL Lightning, Ultimate Upscale
Documentation: README.md, WORKFLOW_STANDARDS.md Documentation: README.md, WORKFLOW_STANDARDS.md, nsfw/README.md
======================================== ========================================
ENVIRONMENT PROFILES ENVIRONMENT PROFILES

View File

@@ -1,309 +0,0 @@
#!/usr/bin/env python3
"""
ComfyUI Workflow Schema Fixer
Fixes missing schema fields in ComfyUI workflow JSON files:
- Adds missing 'flags', 'order', 'mode', 'properties', 'size' fields to nodes
- Reconstructs 'inputs' and 'outputs' arrays from links
- Builds complete 'links' array
- Updates outdated node names
Usage:
python3 fix_workflows.py <workflow_directory>
"""
import json
import sys
from pathlib import Path
from typing import Dict, List, Any
# Node name mapping (old → new)
NODE_NAME_MAPPING = {
'AnimateDiffLoader': 'AnimateDiffLoaderV1',
'VHSVideoCombine': 'VHS_VideoCombine',
'PreviewVideo': None, # Remove - use VHS_VideoCombine with preview enabled
'SaveVideo': None, # Remove - use VHS_VideoCombine
'IPAdapterApply': 'IPAdapter',
'IPAdapterApplyFace': 'IPAdapterFaceID',
'AudioSave': 'SaveAudio',
'AnimateDiffSampler': 'KSamplerAdvanced', # AnimateDiff uses standard KSampler
'ADE_AnimateDiffSampler': 'KSamplerAdvanced',
'SeedGenerator': 'ImpactInt', # Use Impact Pack integer node for seed generation
'BatchKSampler': 'KSampler', # Standard KSampler can handle batches
'ImageBatchToList': 'GetImageSize', # Placeholder - may need manual adjustment
}
# Default node sizes by category
NODE_SIZES = {
'Loader': {'0': 350, '1': 100},
'Sampler': {'0': 315, '1': 474},
'Encoder': {'0': 400, '1': 200},
'Default': {'0': 315, '1': 100},
}
def get_node_size(node_type: str) -> Dict[str, int]:
"""Get appropriate size for node based on type"""
if 'Loader' in node_type or 'Load' in node_type:
return NODE_SIZES['Loader']
elif 'Sampler' in node_type or 'KSampler' in node_type:
return NODE_SIZES['Sampler']
elif 'Encode' in node_type or 'CLIP' in node_type:
return NODE_SIZES['Encoder']
else:
return NODE_SIZES['Default']
def fix_workflow(workflow_path: Path) -> bool:
"""Fix a single workflow file"""
print(f"\n{'='*60}")
print(f"Processing: {workflow_path.name}")
print(f"{'='*60}")
try:
with open(workflow_path, 'r') as f:
workflow = json.load(f)
except json.JSONDecodeError as e:
print(f"✗ ERROR: Invalid JSON - {e}")
return False
if 'nodes' not in workflow:
print(f"✗ ERROR: No 'nodes' key in workflow")
return False
nodes = workflow['nodes']
links = workflow.get('links', [])
# Track changes
changes = {
'added_flags': 0,
'added_order': 0,
'added_mode': 0,
'added_properties': 0,
'added_size': 0,
'added_inputs': 0,
'added_outputs': 0,
'updated_node_names': 0,
'removed_nodes': 0,
'added_last_link_id': 0,
'added_links': 0,
}
# Build link index for quick lookup
link_index = {}
for link in links:
if len(link) >= 6:
link_id, src_node_id, src_slot, tgt_node_id, tgt_slot, data_type = link[:6]
link_index[link_id] = {
'source': {'node_id': src_node_id, 'slot': src_slot},
'target': {'node_id': tgt_node_id, 'slot': tgt_slot},
'type': data_type
}
# Build node ID index
node_by_id = {node['id']: node for node in nodes}
# Process each node
nodes_to_remove = []
for i, node in enumerate(nodes):
node_id = node.get('id')
node_type = node.get('type', '')
# Update node name if needed
if node_type in NODE_NAME_MAPPING:
new_name = NODE_NAME_MAPPING[node_type]
if new_name is None:
# Mark for removal
nodes_to_remove.append(i)
changes['removed_nodes'] += 1
print(f" Removing deprecated node {node_id}: {node_type}")
continue
else:
print(f" Updating node {node_id}: {node_type}{new_name}")
node['type'] = new_name
node_type = new_name
changes['updated_node_names'] += 1
# Add missing flags
if 'flags' not in node:
node['flags'] = {}
changes['added_flags'] += 1
# Add missing order (will recalculate later based on dependencies)
if 'order' not in node:
node['order'] = i # Temporary order
changes['added_order'] += 1
# Add missing mode (0 = execute, 4 = bypass)
if 'mode' not in node:
node['mode'] = 0
changes['added_mode'] += 1
# Add missing properties
if 'properties' not in node:
node['properties'] = {"Node name for S&R": node_type}
changes['added_properties'] += 1
# Add missing size
if 'size' not in node:
node['size'] = get_node_size(node_type)
changes['added_size'] += 1
# Reconstruct inputs from links
if 'inputs' not in node or not node['inputs']:
node_inputs = []
for link_id, link_data in link_index.items():
if link_data['target']['node_id'] == node_id:
# This link targets this node
# We need to know the input name, but we don't have it
# For now, create a placeholder
node_inputs.append({
'name': f'input_{link_data["target"]["slot"]}',
'type': link_data['type'],
'link': link_id
})
if node_inputs:
node['inputs'] = node_inputs
changes['added_inputs'] += 1
# Reconstruct outputs from links
if 'outputs' not in node or not node['outputs']:
node_outputs = {}
for link_id, link_data in link_index.items():
if link_data['source']['node_id'] == node_id:
slot = link_data['source']['slot']
if slot not in node_outputs:
node_outputs[slot] = {
'name': f'output_{slot}',
'type': link_data['type'],
'links': [],
'slot_index': slot
}
node_outputs[slot]['links'].append(link_id)
if node_outputs:
node['outputs'] = list(node_outputs.values())
changes['added_outputs'] += 1
# Remove deprecated nodes
for i in reversed(nodes_to_remove):
del nodes[i]
# Recalculate execution order based on dependencies
if changes['added_order'] > 0 or changes['removed_nodes'] > 0:
calculate_execution_order(nodes, link_index)
# Add missing links array
if 'links' not in workflow:
workflow['links'] = []
changes['added_links'] = 1
# Add missing last_link_id
if 'last_link_id' not in workflow:
# Calculate from existing links
max_link_id = 0
if workflow.get('links'):
for link in workflow['links']:
if link and len(link) > 0:
max_link_id = max(max_link_id, link[0])
workflow['last_link_id'] = max_link_id
changes['added_last_link_id'] = 1
# Update workflow
workflow['nodes'] = nodes
# Print summary
print(f"\nChanges made:")
for key, value in changes.items():
if value > 0:
print(f"{key.replace('_', ' ').title()}: {value}")
total_changes = sum(changes.values())
if total_changes == 0:
print(f" ✓ No changes needed - workflow already valid")
return True
# Save fixed workflow
try:
with open(workflow_path, 'w') as f:
json.dump(workflow, f, indent=2)
print(f"\n✓ Successfully fixed and saved workflow")
return True
except Exception as e:
print(f"\n✗ ERROR saving workflow: {e}")
return False
def calculate_execution_order(nodes: List[Dict], link_index: Dict):
"""Calculate execution order based on node dependencies"""
# Build dependency graph
dependencies = {}
node_by_id = {node['id']: node for node in nodes}
for node in nodes:
node_id = node['id']
dependencies[node_id] = set()
# Find all nodes this node depends on (inputs)
for link_id, link_data in link_index.items():
if link_data['target']['node_id'] == node_id:
# This node depends on the source node
dependencies[node_id].add(link_data['source']['node_id'])
# Topological sort to determine execution order
visited = set()
order_counter = [0]
def visit(node_id):
if node_id in visited:
return
visited.add(node_id)
# Visit dependencies first
for dep_id in dependencies.get(node_id, []):
if dep_id in node_by_id: # Skip if dependency not in current nodes
visit(dep_id)
# Assign order
if node_id in node_by_id:
node_by_id[node_id]['order'] = order_counter[0]
order_counter[0] += 1
# Visit all nodes
for node_id in node_by_id.keys():
visit(node_id)
def main():
if len(sys.argv) < 2:
print("Usage: python3 fix_workflows.py <workflow_directory>")
sys.exit(1)
workflow_dir = Path(sys.argv[1])
if not workflow_dir.exists():
print(f"Error: Directory {workflow_dir} does not exist")
sys.exit(1)
# Find all JSON files recursively
workflow_files = list(workflow_dir.rglob('*.json'))
if not workflow_files:
print(f"No workflow JSON files found in {workflow_dir}")
sys.exit(1)
print(f"\nFound {len(workflow_files)} workflow files")
# Process each workflow
success_count = 0
for workflow_path in sorted(workflow_files):
if fix_workflow(workflow_path):
success_count += 1
# Summary
print(f"\n{'='*60}")
print(f"SUMMARY")
print(f"{'='*60}")
print(f"Total workflows: {len(workflow_files)}")
print(f"Successfully fixed: {success_count}")
print(f"Failed: {len(workflow_files) - success_count}")
print(f"{'='*60}\n")
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,56 @@
diff --git a/__init__.py b/__init__.py
index 1234567..abcdefg 100644
--- a/__init__.py
+++ b/__init__.py
@@ -1,3 +1,51 @@
+"""
+DiffRhythm ComfyUI Node with LlamaConfig Patch
+
+PATCH: Fixes "The size of tensor a (32) must match the size of tensor b (64)" error
+in DiffRhythm's rotary position embeddings by patching LlamaConfig initialization.
+
+Issue: DiffRhythm's DIT model doesn't specify num_attention_heads and
+num_key_value_heads when creating LlamaConfig, causing transformers 4.49.0+
+to incorrectly infer head_dim = 32 instead of 64.
+
+Solution: Patch LlamaConfig globally before importing DiffRhythmNode.
+
+Reference: https://github.com/billwuhao/ComfyUI_DiffRhythm/issues/44
+Reference: https://github.com/billwuhao/ComfyUI_DiffRhythm/issues/48
+
+Patch author: valknar@pivoine.art
+"""
+
+# CRITICAL: Patch LlamaConfig BEFORE importing DiffRhythmNode
+from transformers.models.llama import LlamaConfig as _OriginalLlamaConfig
+
+class PatchedLlamaConfig(_OriginalLlamaConfig):
+ """
+ Patched LlamaConfig that automatically adds missing attention head parameters.
+
+ Standard Llama architecture assumptions:
+ - head_dim = 64 (fixed)
+ - num_attention_heads = hidden_size // head_dim
+ - num_key_value_heads = num_attention_heads // 4 (for GQA)
+ """
+ def __init__(self, *args, **kwargs):
+ # If hidden_size is provided but num_attention_heads is not, calculate it
+ if 'hidden_size' in kwargs and 'num_attention_heads' not in kwargs:
+ hidden_size = kwargs['hidden_size']
+ kwargs['num_attention_heads'] = hidden_size // 64
+
+ # If num_key_value_heads is not provided, use GQA configuration
+ if 'num_attention_heads' in kwargs and 'num_key_value_heads' not in kwargs:
+ kwargs['num_key_value_heads'] = max(1, kwargs['num_attention_heads'] // 4)
+
+ super().__init__(*args, **kwargs)
+
+# Replace LlamaConfig in transformers module BEFORE DiffRhythm imports it
+import transformers.models.llama
+transformers.models.llama.LlamaConfig = PatchedLlamaConfig
+import transformers.models.llama.modeling_llama
+transformers.models.llama.modeling_llama.LlamaConfig = PatchedLlamaConfig
+
from .DiffRhythmNode import NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS
__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS"]

View File

@@ -1,7 +1,7 @@
torch torch
torchvision torchvision
torchaudio torchaudio
transformers transformers==4.49.0
diffusers>=0.31.0 diffusers>=0.31.0
accelerate accelerate
safetensors safetensors
@@ -19,3 +19,4 @@ insightface
onnxruntime onnxruntime
pyyaml pyyaml
imageio-ffmpeg imageio-ffmpeg
torchcodec

View File

@@ -16,20 +16,22 @@ export TQDM_DISABLE=1
# Navigate to ComfyUI directory # Navigate to ComfyUI directory
cd "${COMFYUI_DIR}" || exit 1 cd "${COMFYUI_DIR}" || exit 1
# Activate virtual environment # Determine which Python to use
if [ -d "venv" ]; then if [ -f "venv/bin/python" ]; then
echo "Activating ComfyUI virtual environment..." PYTHON_BIN="venv/bin/python"
source venv/bin/activate echo "Using ComfyUI virtual environment Python..."
else else
PYTHON_BIN="python3"
echo "WARNING: venv not found, using system Python" echo "WARNING: venv not found, using system Python"
fi fi
echo "Starting ComfyUI on port 8188..." echo "Starting ComfyUI on port 8188..."
echo "Access at: http://localhost:8188" echo "Access at: http://localhost:8188"
echo "Using HuggingFace cache: ${HF_CACHE}" echo "Using HuggingFace cache: ${HF_CACHE}"
echo "Python: ${PYTHON_BIN}"
# Start ComfyUI with GPU support # Start ComfyUI with GPU support
python main.py \ exec "${PYTHON_BIN}" main.py \
--listen 0.0.0.0 \ --listen 0.0.0.0 \
--port 8188 \ --port 8188 \
--enable-cors-header \ --enable-cors-header \

View File

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -47,7 +47,7 @@
"Node name for S&R": "CheckpointLoaderSimple" "Node name for S&R": "CheckpointLoaderSimple"
}, },
"widgets_values": [ "widgets_values": [
"diffusers/stable-diffusion-xl-base-1.0" "sd_xl_base_1.0.safetensors"
], ],
"title": "SDXL Base Checkpoint Loader" "title": "SDXL Base Checkpoint Loader"
}, },
@@ -140,7 +140,7 @@
"Node name for S&R": "IPAdapterUnifiedLoader" "Node name for S&R": "IPAdapterUnifiedLoader"
}, },
"widgets_values": [ "widgets_values": [
"PLUS (high strength)" "VIT-G (medium strength)"
], ],
"title": "IP-Adapter Loader" "title": "IP-Adapter Loader"
}, },
@@ -197,10 +197,8 @@
"widgets_values": [ "widgets_values": [
0.75, 0.75,
0.0, 0.0,
"original",
0.0,
1.0, 1.0,
false "style transfer"
], ],
"title": "Apply IP-Adapter Style" "title": "Apply IP-Adapter Style"
}, },

View File

@@ -1,201 +1,420 @@
{ {
"last_node_id": 10, "last_node_id": 8,
"last_link_id": 12, "last_link_id": 10,
"nodes": [ "nodes": [
{ {
"id": 1, "id": 1,
"type": "LoadImage", "type": "LoadImage",
"pos": [ "pos": [50, 100],
50, "size": [315, 314],
100 "widgets_values": ["input_frame.png", "image"],
],
"size": [
315,
314
],
"widgets_values": [
"input_frame.png",
"image"
],
"title": "API Input Image", "title": "API Input Image",
"flags": {}, "flags": {},
"order": 0, "order": 0,
"mode": 0, "mode": 0,
"properties": { "properties": {
"Node name for S&R": "LoadImage" "Node name for S&R": "LoadImage"
} },
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [1],
"slot_index": 0
},
{
"name": "MASK",
"type": "MASK",
"links": null
}
]
}, },
{ {
"id": 2, "id": 2,
"type": "DiffusersLoader", "type": "DownloadAndLoadCogVideoModel",
"pos": [ "pos": [50, 500],
50, "size": [350, 100],
500 "widgets_values": ["THUDM/CogVideoX-5b-I2V", "bf16", "disabled", true],
], "title": "CogVideoX-5b-I2V Loader",
"widgets_values": [
"diffusion_models/CogVideoX-5b"
],
"title": "CogVideoX-5b Loader",
"flags": {}, "flags": {},
"order": 1, "order": 1,
"mode": 0, "mode": 0,
"properties": { "properties": {
"Node name for S&R": "DiffusersLoader" "Node name for S&R": "DownloadAndLoadCogVideoModel"
}, },
"size": { "outputs": [
"0": 350, {
"1": 100 "name": "model",
} "type": "COGVIDEOMODEL",
"links": [2],
"slot_index": 0
},
{
"name": "vae",
"type": "VAE",
"links": [3, 10],
"slot_index": 1
}
]
}, },
{ {
"id": 3, "id": 7,
"type": "CLIPTextEncode", "type": "CLIPLoader",
"pos": [ "pos": [50, 650],
450, "size": [350, 100],
100 "widgets_values": ["t5xxl_fp16.safetensors", "sd3"],
], "title": "T5 CLIP Loader",
"widgets_values": [
"Camera movement description, action, scene details"
],
"title": "API Video Prompt",
"flags": {}, "flags": {},
"order": 2, "order": 2,
"mode": 0, "mode": 0,
"properties": { "properties": {
"Node name for S&R": "CLIPTextEncode" "Node name for S&R": "CLIPLoader"
}, },
"size": { "outputs": [
"0": 400, {
"1": 200 "name": "CLIP",
} "type": "CLIP",
"links": [4, 5],
"slot_index": 0
}
]
}, },
{ {
"id": 4, "id": 3,
"type": "CogVideoXSampler", "type": "CogVideoTextEncode",
"pos": [ "pos": [450, 100],
800, "size": [400, 200],
100 "widgets_values": ["Camera movement description, action, scene details", 1, false],
], "title": "API Video Prompt (Positive)",
"widgets_values": [
42,
"fixed",
50,
6.0,
49,
6
],
"title": "CogVideoX Sampler (6s @ 8fps)",
"flags": {}, "flags": {},
"order": 3, "order": 3,
"mode": 0, "mode": 0,
"properties": { "properties": {
"Node name for S&R": "CogVideoXSampler" "Node name for S&R": "CogVideoTextEncode"
}, },
"size": { "inputs": [
"0": 315, {
"1": 474 "name": "clip",
} "type": "CLIP",
"link": 4
}
],
"outputs": [
{
"name": "conditioning",
"type": "CONDITIONING",
"links": [6],
"slot_index": 0
},
{
"name": "clip",
"type": "CLIP",
"links": null
}
]
}, },
{ {
"id": 5, "id": 8,
"type": "VAEDecode", "type": "CogVideoTextEncode",
"pos": [ "pos": [450, 350],
1150, "size": [400, 200],
100 "widgets_values": ["low quality, blurry, distorted, watermark", 1, true],
], "title": "API Video Prompt (Negative)",
"title": "VAE Decode Video",
"flags": {}, "flags": {},
"order": 4, "order": 4,
"mode": 0, "mode": 0,
"properties": { "properties": {
"Node name for S&R": "VAEDecode" "Node name for S&R": "CogVideoTextEncode"
}, },
"size": { "inputs": [
"0": 315, {
"1": 100 "name": "clip",
} "type": "CLIP",
"link": 5
}
],
"outputs": [
{
"name": "conditioning",
"type": "CONDITIONING",
"links": [7],
"slot_index": 0
},
{
"name": "clip",
"type": "CLIP",
"links": null
}
]
}, },
{ {
"id": 6, "id": 9,
"type": "VHS_VideoCombine", "type": "CogVideoImageEncode",
"pos": [ "pos": [450, 600],
1450, "size": [315, 100],
100 "widgets_values": [],
], "title": "Encode Input Image",
"widgets_values": [
8,
0,
"cogvideox_output",
"video/h264-mp4"
],
"title": "Combine Video Frames",
"flags": {}, "flags": {},
"order": 5, "order": 5,
"mode": 0, "mode": 0,
"properties": {
"Node name for S&R": "CogVideoImageEncode"
},
"inputs": [
{
"name": "vae",
"type": "VAE",
"link": 3
},
{
"name": "start_image",
"type": "IMAGE",
"link": 1
}
],
"outputs": [
{
"name": "samples",
"type": "LATENT",
"links": [8],
"slot_index": 0
}
]
},
{
"id": 4,
"type": "CogVideoSampler",
"pos": [900, 100],
"size": [315, 474],
"widgets_values": [49, 50, 6.0, 42, "fixed", "CogVideoXDDIM", 1.0],
"title": "CogVideoX Sampler (6s @ 8fps)",
"flags": {},
"order": 6,
"mode": 0,
"properties": {
"Node name for S&R": "CogVideoSampler"
},
"inputs": [
{
"name": "model",
"type": "COGVIDEOMODEL",
"link": 2
},
{
"name": "positive",
"type": "CONDITIONING",
"link": 6
},
{
"name": "negative",
"type": "CONDITIONING",
"link": 7
},
{
"name": "image_cond_latents",
"type": "LATENT",
"link": 8
}
],
"outputs": [
{
"name": "samples",
"type": "LATENT",
"links": [9],
"slot_index": 0
}
]
},
{
"id": 5,
"type": "CogVideoDecode",
"pos": [1250, 100],
"size": [315, 200],
"widgets_values": [true, 240, 360, 0.25, 0.25],
"title": "VAE Decode Video",
"flags": {},
"order": 7,
"mode": 0,
"properties": {
"Node name for S&R": "CogVideoDecode"
},
"inputs": [
{
"name": "vae",
"type": "VAE",
"link": 10
},
{
"name": "samples",
"type": "LATENT",
"link": 9
}
],
"outputs": [
{
"name": "images",
"type": "IMAGE",
"links": [11],
"slot_index": 0
}
]
},
{
"id": 6,
"type": "VHS_VideoCombine",
"pos": [1600, 100],
"size": [315, 200],
"widgets_values": [8, 0, "cogvideox_output", "video/h264-mp4", "yuv420p", 19, true, false],
"title": "Combine Video Frames",
"flags": {},
"order": 8,
"mode": 0,
"properties": { "properties": {
"Node name for S&R": "VHS_VideoCombine" "Node name for S&R": "VHS_VideoCombine"
}, },
"size": { "inputs": [
"0": 315, {
"1": 100 "name": "images",
} "type": "IMAGE",
"link": 11
}
],
"outputs": [
{
"name": "Filenames",
"type": "VHS_FILENAMES",
"links": null
}
]
} }
], ],
"links": [], "links": [
[1, 1, 0, 9, 1, "IMAGE"],
[2, 2, 0, 4, 0, "COGVIDEOMODEL"],
[3, 2, 1, 9, 0, "VAE"],
[4, 7, 0, 3, 0, "CLIP"],
[5, 7, 0, 8, 0, "CLIP"],
[6, 3, 0, 4, 1, "CONDITIONING"],
[7, 8, 0, 4, 2, "CONDITIONING"],
[8, 9, 0, 4, 3, "LATENT"],
[9, 4, 0, 5, 1, "LATENT"],
[10, 2, 1, 5, 0, "VAE"],
[11, 5, 0, 6, 0, "IMAGE"]
],
"groups": [],
"config": {},
"extra": { "extra": {
"workflow_info": { "workflow_info": {
"name": "CogVideoX Image-to-Video Production", "name": "CogVideoX Image-to-Video Production",
"version": "1.0.0", "version": "1.2.0",
"description": "AI-driven image-to-video using CogVideoX-5b. Generate 6-second videos (48 frames @ 8fps) from input images with camera movement and action.", "description": "AI-driven image-to-video using CogVideoX-5b-I2V. Generate 6-second videos (49 frames @ 8fps) from input images with camera movement and action.",
"category": "image-to-video", "category": "image-to-video",
"tags": [ "tags": ["cogvideox", "i2v", "video-generation", "production"],
"cogvideox",
"i2v",
"video-generation",
"production"
],
"requirements": { "requirements": {
"models": [ "models": ["CogVideoX-5b-I2V", "T5-XXL FP16"],
"CogVideoX-5b" "custom_nodes": ["ComfyUI-VideoHelperSuite", "ComfyUI-CogVideoXWrapper"],
], "vram_min": "20GB",
"custom_nodes": [ "vram_recommended": "24GB"
"ComfyUI-VideoHelperSuite",
"ComfyUI-CogVideoXWrapper"
],
"vram_min": "20GB"
}, },
"parameters": { "parameters": {
"input_image": { "input_image": {
"node_id": 1, "node_id": 1,
"widget_index": 0,
"type": "image", "type": "image",
"required": true, "required": true,
"description": "Starting frame for video" "description": "Starting frame for video generation"
}, },
"video_prompt": { "positive_prompt": {
"node_id": 3, "node_id": 3,
"widget_index": 0,
"type": "string", "type": "string",
"required": true, "required": true,
"description": "Describe camera movement and action" "default": "Camera movement description, action, scene details",
"description": "Describe desired camera movement, actions, and scene"
},
"negative_prompt": {
"node_id": 8,
"widget_index": 0,
"type": "string",
"required": false,
"default": "low quality, blurry, distorted, watermark",
"description": "Undesired elements to avoid"
},
"num_frames": {
"node_id": 4,
"widget_index": 0,
"type": "integer",
"required": false,
"default": 49,
"min": 1,
"max": 1024,
"description": "Number of frames to generate (49 = ~6s @ 8fps)"
}, },
"steps": { "steps": {
"node_id": 4, "node_id": 4,
"widget_index": 1,
"type": "integer", "type": "integer",
"required": false,
"default": 50, "default": 50,
"description": "Sampling steps (50 recommended)" "min": 20,
"max": 100,
"description": "Sampling steps (50 recommended for quality)"
},
"cfg": {
"node_id": 4,
"widget_index": 2,
"type": "float",
"required": false,
"default": 6.0,
"min": 1.0,
"max": 30.0,
"description": "Classifier-free guidance scale"
},
"seed": {
"node_id": 4,
"widget_index": 3,
"type": "integer",
"required": false,
"default": 42,
"description": "Random seed for reproducibility"
}, },
"fps": { "fps": {
"node_id": 6, "node_id": 6,
"widget_index": 0,
"type": "integer", "type": "integer",
"required": false,
"default": 8, "default": 8,
"description": "Output framerate" "description": "Output video framerate"
}
},
"outputs": {
"video": {
"node_id": 6,
"type": "video",
"format": "MP4 (H.264)",
"resolution": "Based on input image",
"duration": "~6 seconds @ 8fps (49 frames)"
} }
}, },
"performance": { "performance": {
"avg_generation_time": "120-180 seconds", "avg_generation_time": "120-180 seconds",
"vram_usage": "~20-22GB", "vram_usage": "~20-22GB",
"output": "6 seconds @ 8fps (48 frames)" "gpu_utilization": "95-100%"
} },
"use_cases": [
"Animate static images with camera motion",
"Create video loops from single frames",
"Add dynamic movement to product shots",
"Generate cinematic camera movements"
],
"notes": [
"CogVideoX-5b-I2V is specifically trained for image-to-video generation",
"Model will download automatically on first use (~10GB)",
"Enable VAE tiling to reduce VRAM usage",
"Higher steps (50-100) improve quality but increase generation time",
"T5-XXL text encoder required - automatically linked from SD3.5"
]
} }
}, },
"version": 0.4 "version": 0.4
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,733 @@
{
"id": "91f6bbe2-ed41-4fd6-bac7-71d5b5864ecb",
"revision": 0,
"last_node_id": 59,
"last_link_id": 108,
"nodes": [
{
"id": 37,
"type": "UNETLoader",
"pos": [
-30,
50
],
"size": [
346.7470703125,
82
],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"slot_index": 0,
"links": [
94
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.45",
"Node name for S&R": "UNETLoader",
"models": [
{
"name": "wan2.2_ti2v_5B_fp16.safetensors",
"url": "https://huggingface.co/Comfy-Org/Wan_2.2_ComfyUI_Repackaged/resolve/main/split_files/diffusion_models/wan2.2_ti2v_5B_fp16.safetensors",
"directory": "diffusion_models"
}
]
},
"widgets_values": [
"wan2.2_ti2v_5B_fp16.safetensors",
"default"
]
},
{
"id": 38,
"type": "CLIPLoader",
"pos": [
-30,
190
],
"size": [
350,
110
],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "CLIP",
"type": "CLIP",
"slot_index": 0,
"links": [
74,
75
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.45",
"Node name for S&R": "CLIPLoader",
"models": [
{
"name": "umt5_xxl_fp8_e4m3fn_scaled.safetensors",
"url": "https://huggingface.co/Comfy-Org/Wan_2.1_ComfyUI_repackaged/resolve/main/split_files/text_encoders/umt5_xxl_fp8_e4m3fn_scaled.safetensors",
"directory": "text_encoders"
}
]
},
"widgets_values": [
"umt5_xxl_fp8_e4m3fn_scaled.safetensors",
"wan",
"default"
]
},
{
"id": 39,
"type": "VAELoader",
"pos": [
-30,
350
],
"size": [
350,
60
],
"flags": {},
"order": 2,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "VAE",
"type": "VAE",
"slot_index": 0,
"links": [
76,
105
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.45",
"Node name for S&R": "VAELoader",
"models": [
{
"name": "wan2.2_vae.safetensors",
"url": "https://huggingface.co/Comfy-Org/Wan_2.2_ComfyUI_Repackaged/resolve/main/split_files/vae/wan2.2_vae.safetensors",
"directory": "vae"
}
]
},
"widgets_values": [
"wan2.2_vae.safetensors"
]
},
{
"id": 8,
"type": "VAEDecode",
"pos": [
1190,
150
],
"size": [
210,
46
],
"flags": {},
"order": 10,
"mode": 0,
"inputs": [
{
"name": "samples",
"type": "LATENT",
"link": 35
},
{
"name": "vae",
"type": "VAE",
"link": 76
}
],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"slot_index": 0,
"links": [
107
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.45",
"Node name for S&R": "VAEDecode"
},
"widgets_values": []
},
{
"id": 57,
"type": "CreateVideo",
"pos": [
1200,
240
],
"size": [
270,
78
],
"flags": {},
"order": 11,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 107
},
{
"name": "audio",
"shape": 7,
"type": "AUDIO",
"link": null
}
],
"outputs": [
{
"name": "VIDEO",
"type": "VIDEO",
"links": [
108
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.45",
"Node name for S&R": "CreateVideo"
},
"widgets_values": [
24
]
},
{
"id": 58,
"type": "SaveVideo",
"pos": [
1200,
370
],
"size": [
660,
450
],
"flags": {},
"order": 12,
"mode": 0,
"inputs": [
{
"name": "video",
"type": "VIDEO",
"link": 108
}
],
"outputs": [],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.45",
"Node name for S&R": "SaveVideo"
},
"widgets_values": [
"video/ComfyUI",
"auto",
"auto"
]
},
{
"id": 55,
"type": "Wan22ImageToVideoLatent",
"pos": [
380,
540
],
"size": [
271.9126892089844,
150
],
"flags": {},
"order": 8,
"mode": 0,
"inputs": [
{
"name": "vae",
"type": "VAE",
"link": 105
},
{
"name": "start_image",
"shape": 7,
"type": "IMAGE",
"link": 106
}
],
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"links": [
104
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.45",
"Node name for S&R": "Wan22ImageToVideoLatent"
},
"widgets_values": [
1280,
704,
121,
1
]
},
{
"id": 56,
"type": "LoadImage",
"pos": [
0,
540
],
"size": [
274.080078125,
314
],
"flags": {},
"order": 3,
"mode": 4,
"inputs": [],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [
106
]
},
{
"name": "MASK",
"type": "MASK",
"links": null
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.45",
"Node name for S&R": "LoadImage"
},
"widgets_values": [
"example.png",
"image"
]
},
{
"id": 7,
"type": "CLIPTextEncode",
"pos": [
380,
260
],
"size": [
425.27801513671875,
180.6060791015625
],
"flags": {},
"order": 7,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 75
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"slot_index": 0,
"links": [
52
]
}
],
"title": "CLIP Text Encode (Negative Prompt)",
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.45",
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": [
"色调艳丽过曝静态细节模糊不清字幕风格作品画作画面静止整体发灰最差质量低质量JPEG压缩残留丑陋的残缺的多余的手指画得不好的手部画得不好的脸部畸形的毁容的形态畸形的肢体手指融合静止不动的画面杂乱的背景三条腿背景人很多倒着走"
],
"color": "#322",
"bgcolor": "#533"
},
{
"id": 6,
"type": "CLIPTextEncode",
"pos": [
380,
50
],
"size": [
422.84503173828125,
164.31304931640625
],
"flags": {},
"order": 6,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 74
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"slot_index": 0,
"links": [
46
]
}
],
"title": "CLIP Text Encode (Positive Prompt)",
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.45",
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": [
"Low contrast. In a retro 1970s-style subway station, a street musician plays in dim colors and rough textures. He wears an old jacket, playing guitar with focus. Commuters hurry by, and a small crowd gathers to listen. The camera slowly moves right, capturing the blend of music and city noise, with old subway signs and mottled walls in the background."
],
"color": "#232",
"bgcolor": "#353"
},
{
"id": 3,
"type": "KSampler",
"pos": [
850,
130
],
"size": [
315,
262
],
"flags": {},
"order": 9,
"mode": 0,
"inputs": [
{
"name": "model",
"type": "MODEL",
"link": 95
},
{
"name": "positive",
"type": "CONDITIONING",
"link": 46
},
{
"name": "negative",
"type": "CONDITIONING",
"link": 52
},
{
"name": "latent_image",
"type": "LATENT",
"link": 104
}
],
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"slot_index": 0,
"links": [
35
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.45",
"Node name for S&R": "KSampler"
},
"widgets_values": [
898471028164125,
"randomize",
20,
5,
"uni_pc",
"simple",
1
]
},
{
"id": 48,
"type": "ModelSamplingSD3",
"pos": [
850,
20
],
"size": [
210,
58
],
"flags": {
"collapsed": false
},
"order": 5,
"mode": 0,
"inputs": [
{
"name": "model",
"type": "MODEL",
"link": 94
}
],
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"slot_index": 0,
"links": [
95
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.45",
"Node name for S&R": "ModelSamplingSD3"
},
"widgets_values": [
8
]
},
{
"id": 59,
"type": "MarkdownNote",
"pos": [
-550,
10
],
"size": [
480,
340
],
"flags": {},
"order": 4,
"mode": 0,
"inputs": [],
"outputs": [],
"title": "Model Links",
"properties": {},
"widgets_values": [
"[Tutorial](https://docs.comfy.org/tutorials/video/wan/wan2_2\n) \n\n**Diffusion Model**\n- [wan2.2_ti2v_5B_fp16.safetensors](https://huggingface.co/Comfy-Org/Wan_2.2_ComfyUI_Repackaged/resolve/main/split_files/diffusion_models/wan2.2_ti2v_5B_fp16.safetensors)\n\n**VAE**\n- [wan2.2_vae.safetensors](https://huggingface.co/Comfy-Org/Wan_2.2_ComfyUI_Repackaged/resolve/main/split_files/vae/wan2.2_vae.safetensors)\n\n**Text Encoder** \n- [umt5_xxl_fp8_e4m3fn_scaled.safetensors](https://huggingface.co/Comfy-Org/Wan_2.1_ComfyUI_repackaged/resolve/main/split_files/text_encoders/umt5_xxl_fp8_e4m3fn_scaled.safetensors)\n\n\nFile save location\n\n```\nComfyUI/\n├───📂 models/\n│ ├───📂 diffusion_models/\n│ │ └───wan2.2_ti2v_5B_fp16.safetensors\n│ ├───📂 text_encoders/\n│ │ └─── umt5_xxl_fp8_e4m3fn_scaled.safetensors \n│ └───📂 vae/\n│ └── wan2.2_vae.safetensors\n```\n"
],
"color": "#432",
"bgcolor": "#653"
}
],
"links": [
[
35,
3,
0,
8,
0,
"LATENT"
],
[
46,
6,
0,
3,
1,
"CONDITIONING"
],
[
52,
7,
0,
3,
2,
"CONDITIONING"
],
[
74,
38,
0,
6,
0,
"CLIP"
],
[
75,
38,
0,
7,
0,
"CLIP"
],
[
76,
39,
0,
8,
1,
"VAE"
],
[
94,
37,
0,
48,
0,
"MODEL"
],
[
95,
48,
0,
3,
0,
"MODEL"
],
[
104,
55,
0,
3,
3,
"LATENT"
],
[
105,
39,
0,
55,
0,
"VAE"
],
[
106,
56,
0,
55,
1,
"IMAGE"
],
[
107,
8,
0,
57,
0,
"IMAGE"
],
[
108,
57,
0,
58,
0,
"VIDEO"
]
],
"groups": [
{
"id": 1,
"title": "Step1 - Load models",
"bounding": [
-50,
-20,
400,
453.6000061035156
],
"color": "#3f789e",
"font_size": 24,
"flags": {}
},
{
"id": 2,
"title": "Step3 - Prompt",
"bounding": [
370,
-20,
448.27801513671875,
473.2060852050781
],
"color": "#3f789e",
"font_size": 24,
"flags": {}
},
{
"id": 3,
"title": "For i2v, use Ctrl + B to enable",
"bounding": [
-50,
450,
400,
420
],
"color": "#3f789e",
"font_size": 24,
"flags": {}
},
{
"id": 4,
"title": "Video Size & length",
"bounding": [
370,
470,
291.9127197265625,
233.60000610351562
],
"color": "#3f789e",
"font_size": 24,
"flags": {}
}
],
"config": {},
"extra": {
"ds": {
"scale": 0.46462425349300085,
"offset": [
847.5372059811432,
288.7938392118285
]
},
"frontendVersion": "1.27.10",
"VHS_latentpreview": false,
"VHS_latentpreviewrate": 0,
"VHS_MetadataImage": true,
"VHS_KeepIntermediate": true
},
"version": 0.4
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

@@ -1,18 +1,13 @@
{ {
"last_node_id": 8, "last_node_id": 7,
"last_link_id": 10, "last_link_id": 10,
"nodes": [ "nodes": [
{ {
"id": 1, "id": 1,
"type": "LoadImage", "type": "LoadImage",
"pos": [ "pos": [50, 100],
50, "size": [315, 314],
100 "widgets_values": ["input_frame.png", "image"],
],
"widgets_values": [
"input_frame.png",
"image"
],
"title": "API Input Image", "title": "API Input Image",
"flags": {}, "flags": {},
"order": 0, "order": 0,
@@ -20,158 +15,402 @@
"properties": { "properties": {
"Node name for S&R": "LoadImage" "Node name for S&R": "LoadImage"
}, },
"size": { "outputs": [
"0": 350, {
"1": 100 "name": "IMAGE",
} "type": "IMAGE",
"links": [1],
"slot_index": 0
},
{
"name": "MASK",
"type": "MASK",
"links": null
}
]
}, },
{ {
"id": 2, "id": 2,
"type": "DiffusersLoader", "type": "ImageOnlyCheckpointLoader",
"pos": [ "pos": [50, 500],
50, "size": [350, 100],
400 "widgets_values": ["svd_xt.safetensors"],
], "title": "SVD-XT Model Loader",
"widgets_values": [
"diffusion_models/stable-video-diffusion-img2vid"
],
"title": "SVD Model Loader",
"flags": {}, "flags": {},
"order": 1, "order": 1,
"mode": 0, "mode": 0,
"properties": { "properties": {
"Node name for S&R": "DiffusersLoader" "Node name for S&R": "ImageOnlyCheckpointLoader"
}, },
"size": { "outputs": [
"0": 350, {
"1": 100 "name": "MODEL",
} "type": "MODEL",
"links": [2],
"slot_index": 0
},
{
"name": "CLIP_VISION",
"type": "CLIP_VISION",
"links": [3],
"slot_index": 1
},
{
"name": "VAE",
"type": "VAE",
"links": [4, 5],
"slot_index": 2
}
]
}, },
{ {
"id": 3, "id": 3,
"type": "SVDSampler", "type": "VideoLinearCFGGuidance",
"pos": [ "pos": [450, 500],
450, "size": [315, 100],
100 "widgets_values": [1.0],
], "title": "Linear CFG Guidance",
"widgets_values": [
42,
"fixed",
25,
14,
127,
0.02
],
"title": "SVD Sampler (14 frames)",
"flags": {}, "flags": {},
"order": 2, "order": 2,
"mode": 0, "mode": 0,
"properties": { "properties": {
"Node name for S&R": "SVDSampler" "Node name for S&R": "VideoLinearCFGGuidance"
}, },
"size": { "inputs": [
"0": 315, {
"1": 474 "name": "model",
} "type": "MODEL",
"link": 2
}
],
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"links": [6],
"slot_index": 0
}
]
}, },
{ {
"id": 4, "id": 4,
"type": "VAEDecode", "type": "SVD_img2vid_Conditioning",
"pos": [ "pos": [450, 100],
800, "size": [315, 350],
100 "widgets_values": [1024, 576, 14, 127, 6, 0.0],
], "title": "SVD Image-to-Video Conditioning",
"title": "VAE Decode Video",
"flags": {}, "flags": {},
"order": 3, "order": 3,
"mode": 0, "mode": 0,
"properties": { "properties": {
"Node name for S&R": "VAEDecode" "Node name for S&R": "SVD_img2vid_Conditioning"
}, },
"size": { "inputs": [
"0": 315, {
"1": 100 "name": "clip_vision",
} "type": "CLIP_VISION",
"link": 3
},
{
"name": "init_image",
"type": "IMAGE",
"link": 1
},
{
"name": "vae",
"type": "VAE",
"link": 4
}
],
"outputs": [
{
"name": "positive",
"type": "CONDITIONING",
"links": [7],
"slot_index": 0
},
{
"name": "negative",
"type": "CONDITIONING",
"links": [8],
"slot_index": 1
},
{
"name": "latent",
"type": "LATENT",
"links": [9],
"slot_index": 2
}
]
}, },
{ {
"id": 5, "id": 5,
"type": "VHS_VideoCombine", "type": "KSampler",
"pos": [ "pos": [800, 100],
1100, "size": [315, 474],
100 "widgets_values": [42, "fixed", 25, 6.0, "euler", "karras", 1.0],
], "title": "KSampler (25 steps)",
"widgets_values": [
6,
0,
"svd_output",
"video/h264-mp4"
],
"title": "Combine Frames",
"flags": {}, "flags": {},
"order": 4, "order": 4,
"mode": 0, "mode": 0,
"properties": {
"Node name for S&R": "KSampler"
},
"inputs": [
{
"name": "model",
"type": "MODEL",
"link": 6
},
{
"name": "positive",
"type": "CONDITIONING",
"link": 7
},
{
"name": "negative",
"type": "CONDITIONING",
"link": 8
},
{
"name": "latent_image",
"type": "LATENT",
"link": 9
}
],
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"links": [10],
"slot_index": 0
}
]
},
{
"id": 6,
"type": "VAEDecode",
"pos": [1150, 100],
"size": [210, 46],
"widgets_values": [],
"title": "VAE Decode Video Frames",
"flags": {},
"order": 5,
"mode": 0,
"properties": {
"Node name for S&R": "VAEDecode"
},
"inputs": [
{
"name": "samples",
"type": "LATENT",
"link": 10
},
{
"name": "vae",
"type": "VAE",
"link": 5
}
],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [11],
"slot_index": 0
}
]
},
{
"id": 7,
"type": "VHS_VideoCombine",
"pos": [1400, 100],
"size": [315, 200],
"widgets_values": [6, 0, "svd_output", "video/h264-mp4", false, true],
"title": "Combine Video Frames",
"flags": {},
"order": 6,
"mode": 0,
"properties": { "properties": {
"Node name for S&R": "VHS_VideoCombine" "Node name for S&R": "VHS_VideoCombine"
}, },
"size": { "inputs": [
"0": 315, {
"1": 100 "name": "images",
} "type": "IMAGE",
"link": 11
}
],
"outputs": [
{
"name": "Filenames",
"type": "VHS_FILENAMES",
"links": null
}
]
} }
], ],
"links": [], "links": [
[1, 1, 0, 4, 1, "IMAGE"],
[2, 2, 0, 3, 0, "MODEL"],
[3, 2, 1, 4, 0, "CLIP_VISION"],
[4, 2, 2, 4, 2, "VAE"],
[5, 2, 2, 6, 1, "VAE"],
[6, 3, 0, 5, 0, "MODEL"],
[7, 4, 0, 5, 1, "CONDITIONING"],
[8, 4, 1, 5, 2, "CONDITIONING"],
[9, 4, 2, 5, 3, "LATENT"],
[10, 5, 0, 6, 0, "LATENT"],
[11, 6, 0, 7, 0, "IMAGE"]
],
"groups": [],
"config": {},
"extra": { "extra": {
"workflow_info": { "workflow_info": {
"name": "Stable Video Diffusion Image-to-Video Production", "name": "Stable Video Diffusion Image-to-Video Production",
"version": "1.0.0", "version": "1.2.0",
"description": "Quick animation using SVD. Generate 14-frame video from single image with motion and camera movement.", "description": "Quick animation using SVD-XT. Generate 14-frame video from single image with motion and camera movement.",
"category": "image-to-video", "category": "image-to-video",
"tags": [ "tags": ["svd", "svd-xt", "stable-video-diffusion", "i2v", "animation", "production"],
"svd",
"stable-video-diffusion",
"i2v",
"animation",
"production"
],
"requirements": { "requirements": {
"models": [ "models": ["SVD-XT"],
"stable-video-diffusion-img2vid" "custom_nodes": ["ComfyUI-VideoHelperSuite"],
], "vram_min": "16GB",
"custom_nodes": [ "vram_recommended": "20GB"
"ComfyUI-VideoHelperSuite"
],
"vram_min": "16GB"
}, },
"parameters": { "parameters": {
"input_image": { "input_image": {
"node_id": 1, "node_id": 1,
"widget_index": 0,
"type": "image", "type": "image",
"required": true "required": true,
"description": "Starting frame for video generation (1024x576 recommended)"
},
"width": {
"node_id": 4,
"widget_index": 0,
"type": "integer",
"required": false,
"default": 1024,
"min": 16,
"max": 16384,
"description": "Output video width"
},
"height": {
"node_id": 4,
"widget_index": 1,
"type": "integer",
"required": false,
"default": 576,
"min": 16,
"max": 16384,
"description": "Output video height"
},
"video_frames": {
"node_id": 4,
"widget_index": 2,
"type": "integer",
"required": false,
"default": 14,
"min": 1,
"max": 4096,
"description": "Number of frames to generate (14 or 25 for SVD/SVD-XT)"
},
"motion_bucket_id": {
"node_id": 4,
"widget_index": 3,
"type": "integer",
"required": false,
"default": 127,
"min": 1,
"max": 1023,
"description": "Motion amount (higher = more motion)"
},
"fps": {
"node_id": 4,
"widget_index": 4,
"type": "integer",
"required": false,
"default": 6,
"min": 1,
"max": 1024,
"description": "Frames per second for conditioning"
},
"augmentation_level": {
"node_id": 4,
"widget_index": 5,
"type": "float",
"required": false,
"default": 0.0,
"min": 0.0,
"max": 10.0,
"description": "Noise augmentation level"
}, },
"steps": { "steps": {
"node_id": 3, "node_id": 5,
"widget_index": 2,
"type": "integer", "type": "integer",
"default": 25 "required": false,
"default": 25,
"min": 1,
"max": 150,
"description": "Sampling steps (25 recommended)"
}, },
"frames": { "cfg": {
"node_id": 3, "node_id": 5,
"type": "integer", "widget_index": 3,
"default": 14, "type": "float",
"description": "Number of output frames" "required": false,
"default": 6.0,
"min": 0.0,
"max": 30.0,
"description": "Classifier-free guidance scale"
}, },
"motion_bucket": { "seed": {
"node_id": 3, "node_id": 5,
"widget_index": 0,
"type": "integer", "type": "integer",
"default": 127, "required": false,
"description": "Motion amount (0-255)" "default": 42,
"description": "Random seed for reproducibility"
},
"output_fps": {
"node_id": 7,
"widget_index": 0,
"type": "integer",
"required": false,
"default": 6,
"description": "Output video framerate"
}
},
"outputs": {
"video": {
"node_id": 7,
"type": "video",
"format": "MP4 (H.264)",
"resolution": "1024x576 (configurable)",
"duration": "~2.3 seconds @ 6fps (14 frames)"
} }
}, },
"performance": { "performance": {
"avg_generation_time": "25-35 seconds", "avg_generation_time": "25-35 seconds",
"vram_usage": "~14-16GB", "vram_usage": "~16-18GB",
"output": "14 frames (~2.3s @ 6fps)" "gpu_utilization": "95-100%"
} },
"use_cases": [
"Animate static images with natural motion",
"Create short video loops from single frames",
"Add subtle camera movements to still images",
"Generate product animation previews"
],
"notes": [
"SVD-XT extends frame count from 14 to 25 frames",
"Model auto-downloads on first use (~9GB)",
"Recommended resolution: 1024x576 (16:9)",
"Higher motion_bucket_id = more movement",
"Linear CFG guidance improves temporal consistency"
]
} }
}, },
"version": 0.4 "version": 0.4
} }

View File

@@ -1,18 +1,13 @@
{ {
"last_node_id": 8, "last_node_id": 7,
"last_link_id": 10, "last_link_id": 10,
"nodes": [ "nodes": [
{ {
"id": 1, "id": 1,
"type": "LoadImage", "type": "LoadImage",
"pos": [ "pos": [50, 100],
50, "size": [315, 314],
100 "widgets_values": ["input_frame.png", "image"],
],
"widgets_values": [
"input_frame.png",
"image"
],
"title": "API Input Image", "title": "API Input Image",
"flags": {}, "flags": {},
"order": 0, "order": 0,
@@ -20,157 +15,403 @@
"properties": { "properties": {
"Node name for S&R": "LoadImage" "Node name for S&R": "LoadImage"
}, },
"size": { "outputs": [
"0": 350, {
"1": 100 "name": "IMAGE",
} "type": "IMAGE",
"links": [1],
"slot_index": 0
},
{
"name": "MASK",
"type": "MASK",
"links": null
}
]
}, },
{ {
"id": 2, "id": 2,
"type": "DiffusersLoader", "type": "ImageOnlyCheckpointLoader",
"pos": [ "pos": [50, 500],
50, "size": [350, 100],
400 "widgets_values": ["svd_xt.safetensors"],
],
"widgets_values": [
"diffusion_models/stable-video-diffusion-img2vid-xt"
],
"title": "SVD-XT Model Loader", "title": "SVD-XT Model Loader",
"flags": {}, "flags": {},
"order": 1, "order": 1,
"mode": 0, "mode": 0,
"properties": { "properties": {
"Node name for S&R": "DiffusersLoader" "Node name for S&R": "ImageOnlyCheckpointLoader"
}, },
"size": { "outputs": [
"0": 350, {
"1": 100 "name": "MODEL",
} "type": "MODEL",
"links": [2],
"slot_index": 0
},
{
"name": "CLIP_VISION",
"type": "CLIP_VISION",
"links": [3],
"slot_index": 1
},
{
"name": "VAE",
"type": "VAE",
"links": [4, 5],
"slot_index": 2
}
]
}, },
{ {
"id": 3, "id": 3,
"type": "SVDSampler", "type": "VideoLinearCFGGuidance",
"pos": [ "pos": [450, 500],
450, "size": [315, 100],
100 "widgets_values": [1.0],
], "title": "Linear CFG Guidance",
"widgets_values": [
42,
"fixed",
30,
25,
127,
0.02
],
"title": "SVD-XT Sampler (25 frames)",
"flags": {}, "flags": {},
"order": 2, "order": 2,
"mode": 0, "mode": 0,
"properties": { "properties": {
"Node name for S&R": "SVDSampler" "Node name for S&R": "VideoLinearCFGGuidance"
}, },
"size": { "inputs": [
"0": 315, {
"1": 474 "name": "model",
} "type": "MODEL",
"link": 2
}
],
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"links": [6],
"slot_index": 0
}
]
}, },
{ {
"id": 4, "id": 4,
"type": "VAEDecode", "type": "SVD_img2vid_Conditioning",
"pos": [ "pos": [450, 100],
800, "size": [315, 350],
100 "widgets_values": [1024, 576, 25, 127, 6, 0.0],
], "title": "SVD-XT Image-to-Video Conditioning (25 frames)",
"title": "VAE Decode Video",
"flags": {}, "flags": {},
"order": 3, "order": 3,
"mode": 0, "mode": 0,
"properties": { "properties": {
"Node name for S&R": "VAEDecode" "Node name for S&R": "SVD_img2vid_Conditioning"
}, },
"size": { "inputs": [
"0": 315, {
"1": 100 "name": "clip_vision",
} "type": "CLIP_VISION",
"link": 3
},
{
"name": "init_image",
"type": "IMAGE",
"link": 1
},
{
"name": "vae",
"type": "VAE",
"link": 4
}
],
"outputs": [
{
"name": "positive",
"type": "CONDITIONING",
"links": [7],
"slot_index": 0
},
{
"name": "negative",
"type": "CONDITIONING",
"links": [8],
"slot_index": 1
},
{
"name": "latent",
"type": "LATENT",
"links": [9],
"slot_index": 2
}
]
}, },
{ {
"id": 5, "id": 5,
"type": "VHS_VideoCombine", "type": "KSampler",
"pos": [ "pos": [800, 100],
1100, "size": [315, 474],
100 "widgets_values": [42, "fixed", 30, 6.0, "euler", "karras", 1.0],
], "title": "KSampler (30 steps)",
"widgets_values": [
6,
0,
"svd_xt_output",
"video/h264-mp4"
],
"title": "Combine Frames",
"flags": {}, "flags": {},
"order": 4, "order": 4,
"mode": 0, "mode": 0,
"properties": {
"Node name for S&R": "KSampler"
},
"inputs": [
{
"name": "model",
"type": "MODEL",
"link": 6
},
{
"name": "positive",
"type": "CONDITIONING",
"link": 7
},
{
"name": "negative",
"type": "CONDITIONING",
"link": 8
},
{
"name": "latent_image",
"type": "LATENT",
"link": 9
}
],
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"links": [10],
"slot_index": 0
}
]
},
{
"id": 6,
"type": "VAEDecode",
"pos": [1150, 100],
"size": [210, 46],
"widgets_values": [],
"title": "VAE Decode Video Frames",
"flags": {},
"order": 5,
"mode": 0,
"properties": {
"Node name for S&R": "VAEDecode"
},
"inputs": [
{
"name": "samples",
"type": "LATENT",
"link": 10
},
{
"name": "vae",
"type": "VAE",
"link": 5
}
],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [11],
"slot_index": 0
}
]
},
{
"id": 7,
"type": "VHS_VideoCombine",
"pos": [1400, 100],
"size": [315, 200],
"widgets_values": [6, 0, "svd_xt_output", "video/h264-mp4", false, true],
"title": "Combine Video Frames",
"flags": {},
"order": 6,
"mode": 0,
"properties": { "properties": {
"Node name for S&R": "VHS_VideoCombine" "Node name for S&R": "VHS_VideoCombine"
}, },
"size": { "inputs": [
"0": 315, {
"1": 100 "name": "images",
} "type": "IMAGE",
"link": 11
}
],
"outputs": [
{
"name": "Filenames",
"type": "VHS_FILENAMES",
"links": null
}
]
} }
], ],
"links": [], "links": [
[1, 1, 0, 4, 1, "IMAGE"],
[2, 2, 0, 3, 0, "MODEL"],
[3, 2, 1, 4, 0, "CLIP_VISION"],
[4, 2, 2, 4, 2, "VAE"],
[5, 2, 2, 6, 1, "VAE"],
[6, 3, 0, 5, 0, "MODEL"],
[7, 4, 0, 5, 1, "CONDITIONING"],
[8, 4, 1, 5, 2, "CONDITIONING"],
[9, 4, 2, 5, 3, "LATENT"],
[10, 5, 0, 6, 0, "LATENT"],
[11, 6, 0, 7, 0, "IMAGE"]
],
"groups": [],
"config": {},
"extra": { "extra": {
"workflow_info": { "workflow_info": {
"name": "Stable Video Diffusion XT Image-to-Video Production", "name": "Stable Video Diffusion XT Image-to-Video Production",
"version": "1.0.0", "version": "1.2.0",
"description": "Extended animation using SVD-XT. Generate 25-frame video for longer animations with smooth motion.", "description": "Extended animation using SVD-XT. Generate 25-frame video for longer animations with smooth motion.",
"category": "image-to-video", "category": "image-to-video",
"tags": [ "tags": ["svd-xt", "stable-video-diffusion", "i2v", "extended", "production"],
"svd-xt",
"stable-video-diffusion",
"i2v",
"extended",
"production"
],
"requirements": { "requirements": {
"models": [ "models": ["SVD-XT"],
"stable-video-diffusion-img2vid-xt" "custom_nodes": ["ComfyUI-VideoHelperSuite"],
], "vram_min": "18GB",
"custom_nodes": [ "vram_recommended": "20GB"
"ComfyUI-VideoHelperSuite"
],
"vram_min": "18GB"
}, },
"parameters": { "parameters": {
"input_image": { "input_image": {
"node_id": 1, "node_id": 1,
"widget_index": 0,
"type": "image", "type": "image",
"required": true "required": true,
"description": "Starting frame for video generation (1024x576 recommended)"
},
"width": {
"node_id": 4,
"widget_index": 0,
"type": "integer",
"required": false,
"default": 1024,
"min": 16,
"max": 16384,
"description": "Output video width"
},
"height": {
"node_id": 4,
"widget_index": 1,
"type": "integer",
"required": false,
"default": 576,
"min": 16,
"max": 16384,
"description": "Output video height"
},
"video_frames": {
"node_id": 4,
"widget_index": 2,
"type": "integer",
"required": false,
"default": 25,
"min": 1,
"max": 4096,
"description": "Number of frames to generate (25 for SVD-XT)"
},
"motion_bucket_id": {
"node_id": 4,
"widget_index": 3,
"type": "integer",
"required": false,
"default": 127,
"min": 1,
"max": 1023,
"description": "Motion amount (higher = more motion)"
},
"fps": {
"node_id": 4,
"widget_index": 4,
"type": "integer",
"required": false,
"default": 6,
"min": 1,
"max": 1024,
"description": "Frames per second for conditioning"
},
"augmentation_level": {
"node_id": 4,
"widget_index": 5,
"type": "float",
"required": false,
"default": 0.0,
"min": 0.0,
"max": 10.0,
"description": "Noise augmentation level"
}, },
"steps": { "steps": {
"node_id": 3, "node_id": 5,
"widget_index": 2,
"type": "integer", "type": "integer",
"default": 30 "required": false,
"default": 30,
"min": 1,
"max": 150,
"description": "Sampling steps (30 recommended)"
}, },
"frames": { "cfg": {
"node_id": 3, "node_id": 5,
"type": "integer", "widget_index": 3,
"default": 25, "type": "float",
"description": "Number of output frames" "required": false,
"default": 6.0,
"min": 0.0,
"max": 30.0,
"description": "Classifier-free guidance scale"
}, },
"motion_bucket": { "seed": {
"node_id": 3, "node_id": 5,
"widget_index": 0,
"type": "integer", "type": "integer",
"default": 127 "required": false,
"default": 42,
"description": "Random seed for reproducibility"
},
"output_fps": {
"node_id": 7,
"widget_index": 0,
"type": "integer",
"required": false,
"default": 6,
"description": "Output video framerate"
}
},
"outputs": {
"video": {
"node_id": 7,
"type": "video",
"format": "MP4 (H.264)",
"resolution": "1024x576 (configurable)",
"duration": "~4.2 seconds @ 6fps (25 frames)"
} }
}, },
"performance": { "performance": {
"avg_generation_time": "40-55 seconds", "avg_generation_time": "40-55 seconds",
"vram_usage": "~16-18GB", "vram_usage": "~18-20GB",
"output": "25 frames (~4.2s @ 6fps)" "gpu_utilization": "95-100%"
} },
"use_cases": [
"Extended animations with smooth motion",
"Longer video loops from single frames",
"Cinematic camera movements",
"Product animation showcases"
],
"notes": [
"SVD-XT generates 25 frames vs 14 frames in base SVD",
"Requires more VRAM (~18GB vs ~16GB)",
"Model auto-downloads on first use (~9GB)",
"Recommended resolution: 1024x576 (16:9)",
"Higher motion_bucket_id = more movement",
"Linear CFG guidance improves temporal consistency"
]
} }
}, },
"version": 0.4 "version": 0.4
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 906 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 925 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 712 KiB

View File

@@ -0,0 +1,373 @@
# NSFW ComfyUI Workflows
Production-ready workflows for NSFW content generation using CivitAI models.
## Available Workflows
### 1. LUSTIFY Realistic Text-to-Image
**File:** `lustify-realistic-t2i-production-v1.json`
**Model:** LUSTIFY v7.0 GGWP (`lustifySDXLNSFW_endgame.safetensors`)
**Optimized Settings:**
- Sampler: DPM++ 2M SDE
- Scheduler: Exponential
- Steps: 30
- CFG Scale: 6.0
- Resolution: 1024x1024 (SDXL)
**Features:**
- Photorealistic NSFW generation
- Optimized negative prompts for LUSTIFY
- Professional photography quality
- Detailed skin texture and natural lighting
- Supports both danbooru tags and natural language
**Use Case:** High-quality photorealistic NSFW images focusing on women in various scenarios
**Example Prompt:**
```
A beautiful woman in elegant dress, photorealistic, professional photography, high quality, detailed skin texture, natural lighting, 8k, masterpiece, best quality
```
**Negative Prompt:**
```
(worst quality, low quality:1.4), illustration, 3d, 2d, painting, cartoons, sketch, open mouth, bad anatomy, deformed, blurry, watermark, text
```
---
### 2. Pony Diffusion Anime/Furry Text-to-Image
**File:** `pony-anime-t2i-production-v1.json`
**Model:** Pony Diffusion V6 XL (`add-detail-xl.safetensors`)
**Optimized Settings:**
- Sampler: Euler Ancestral
- Scheduler: Normal
- Steps: 35
- CFG Scale: 7.5
- Resolution: 1024x1024 (SDXL)
**Features:**
- Anime, cartoon, and furry NSFW generation
- Danbooru tag support (optimized for tags)
- Balanced content training (1:1:1 safe/questionable/explicit)
- 2.6M aesthetically ranked training images
- Versatile style support
**Use Case:** High-quality anime/cartoon/furry NSFW content with tag-based prompting
**Example Prompt (Danbooru Tags):**
```
1girl, solo, long_hair, breasts, smile, looking_at_viewer, anime style, high quality, detailed, masterpiece, best quality
```
**Example Prompt (Natural Language):**
```
Anime girl with long flowing hair, smiling and looking at viewer, detailed anime art style, high quality, masterpiece
```
**Negative Prompt:**
```
(worst quality, low quality:1.4), bad anatomy, deformed, blurry, watermark, text, signature, artist name
```
---
### 3. RealVisXL Lightning Fast Text-to-Image
**File:** `realvisxl-lightning-t2i-production-v1.json`
**Model:** RealVisXL V5.0 Lightning (`realvisxlV50_v50LightningBakedvae.safetensors`)
**Optimized Settings:**
- Sampler: DPM++ SDE
- Scheduler: Karras
- Steps: 6 (Lightning fast!)
- CFG Scale: 2.0
- Resolution: 1024x1024 (SDXL)
**Features:**
- Ultra-fast 4-6 step generation (vs 30+ for standard models)
- High-quality photorealistic output
- Baked VAE for optimal quality
- Professional portraits and scenes
- Both SFW and NSFW capable
**Use Case:** Rapid photorealistic NSFW generation when speed is priority
**Example Prompt:**
```
Beautiful woman portrait, professional photography, natural lighting, high quality, detailed, 8k
```
**Negative Prompt:**
```
(worst quality, low quality:1.4), bad anatomy, deformed, blurry, watermark, text, ugly, cartoon, anime
```
---
---
## Advanced Workflows
### 4. NSFW Ultimate SD Upscale
**File:** `nsfw-ultimate-upscale-production-v1.json`
**Model:** LUSTIFY v7.0 GGWP (`lustifySDXLNSFW_endgame.safetensors`)
**Upscale Settings:**
- Upscale Factor: 2x
- Upscale Model: RealESRGAN_x2.pth
- Denoise: 0.25 (preserves original composition)
- Sampler: DPM++ 2M SDE
- Scheduler: Exponential
- Steps: 20
- CFG Scale: 7.0
- Tile Size: 512x512
**Features:**
- Professional 2x upscaling for NSFW images
- Combines RealESRGAN with diffusion refinement
- Tiled processing for handling large images
- Optimized for detailed skin texture
- Low denoise preserves original composition
- Can swap checkpoint for different styles
**Use Case:** Upscale NSFW images from 1024x1024 to 2048x2048 with enhanced detail
**Enhancement Prompt:**
```
photorealistic, professional photography, high quality, detailed skin texture, natural lighting, 8k, masterpiece, best quality, sharp details
```
**Refinement Negative:**
```
(worst quality, low quality:1.4), blurry, pixelated, jpeg artifacts, bad anatomy, deformed, watermark, text
```
**Tips:**
- Use denoise 0.2-0.3 for subtle enhancement
- Match enhancement prompt to original generation prompt
- Swap checkpoint node for different model styles (Pony, RealVisXL)
- Processing time: ~90-150 seconds for 2x upscale
---
## Installation
These workflows use models downloaded via `artifact_civitai_download.sh`:
```bash
# Models are already downloaded to /workspace/models/civitai/
# and symlinked to /workspace/ComfyUI/models/checkpoints/
# Verify models are available:
ls -lh /workspace/ComfyUI/models/checkpoints/lustify*
ls -lh /workspace/ComfyUI/models/checkpoints/*pony*
ls -lh /workspace/ComfyUI/models/checkpoints/realvisx*
```
## Usage
### Via ComfyUI API:
```bash
# Load workflow
curl -X POST http://localhost:8188/api/prompt \
-H "Content-Type: application/json" \
-d @lustify-realistic-t2i-production-v1.json
# Modify prompt and generate
curl -X POST http://localhost:8188/api/prompt \
-H "Content-Type: application/json" \
-d '{
"prompt": {
"2": {
"inputs": {
"text": "Your custom NSFW prompt here"
}
}
}
}'
```
### Via ComfyUI UI:
1. Open ComfyUI at `http://localhost:8188`
2. Click "Load" and select workflow file
3. Modify prompt in the "API Positive Prompt" node
4. Click "Queue Prompt" to generate
## Model Comparison
| Model | Type | Speed | Quality | Best For | Prompt Style |
|-------|------|-------|---------|----------|--------------|
| LUSTIFY v7 | Photoreal | Medium (30 steps) | Excellent | Women, realistic scenes | Natural language |
| Pony Diffusion v6 | Anime/Furry | Medium (35 steps) | Excellent | Anime, cartoon, furry | Danbooru tags |
| RealVisXL Lightning | Photoreal | Very Fast (4-6 steps) | Excellent | Quick realistic generations | Natural language |
## Tips
### For LUSTIFY:
- Use detailed prompts describing scene, lighting, quality
- Avoid abstract/artistic terms
- Include photography keywords: "professional photography", "8k", "detailed"
- CFG 4-7 range works best
### For Pony Diffusion:
- Danbooru tags work very well (recommended over natural language)
- Use tag format: `1girl, solo, breasts, smile, looking_at_viewer`
- Mix safe/questionable/explicit content naturally
- Can do anime, cartoon, and furry styles
- Supports wide range of artistic styles
- CFG 7-8.5 range works best
### For RealVisXL Lightning:
- Keep prompts concise for best results
- Use lower CFG (1-2) for Lightning models
- 4-6 steps is optimal balance
- Great for batch generation
## Advanced Usage
### Adding LoRAs:
Use the `../text-to-image/lora-fusion-t2i-production-v1.json` workflow for multi-LoRA stacking support.
**How to use with NSFW models:**
1. Load the LoRA fusion workflow
2. Change checkpoint (node 1) to your NSFW model (LUSTIFY, Pony, RealVisXL)
3. Stack up to 3 LoRAs with adjustable weights:
- LoRA 1 (Primary): 0.7-1.0 strength
- LoRA 2 (Secondary): 0.4-0.7 strength
- LoRA 3 (Accent): 0.2-0.5 strength
4. Common use cases:
- Detail enhancer + skin texture + lighting style
- Character LoRA + pose enhancer + background style
- Primary art style + secondary blend + color grading
### Upscaling:
Use `nsfw-ultimate-upscale-production-v1.json` for professional 2x upscaling with LUSTIFY checkpoint.
**Workflow:**
1. Generate image with any NSFW T2I workflow (LUSTIFY, Pony, RealVisXL)
2. Load the generated image into Ultimate SD Upscale workflow
3. Use denoise 0.2-0.3 for subtle enhancement
4. Match enhancement prompt to original generation prompt
5. Output: 2048x2048 high-quality upscaled image
### Style Transfer:
Use IP-Adapter workflows in `../image-to-image/` directory to combine with style references.
## Using Negative Embeddings
Negative embeddings (textual inversions) are small trained models that significantly improve image quality when used in negative prompts. They help avoid common artifacts like bad anatomy, unrealistic features, and low-quality outputs.
### Available Embeddings
**For SDXL Models (LUSTIFY, RealVisXL):**
- `BadX` - Fixes facial/hand artifacts, improves overall realism
**For Pony/WAI-Illustrious Models:**
- `zPDXL3` - Quality enhancement + removes censoring
- `zPDXLxxx` - Enables explicit NSFW content
**For SD 1.5 Models (future workflows):**
- `BadDream` + `UnrealisticDream` - Dreamshaper artifacts + realism
- `badhandv4` - Improves hand details
- `FastNegativeV2` - General quality enhancement
- `BadNegAnatomyV1-neg` - Better anatomy and body joints
- `easynegative` - General-purpose quality
### Installation
Embeddings are automatically downloaded and linked to `/workspace/ComfyUI/models/embeddings/` when you run:
```bash
cd /workspace/ai && bash /workspace/bin/artifact_civitai_download.sh both -c models_civitai.yaml
```
### Usage Syntax
**Basic usage in negative prompt:**
```
embedding:BadX
embedding:zPDXL3
```
**Multiple embeddings:**
```
embedding:zPDXL3, embedding:zPDXLxxx, score_4, score_5, low quality
```
**With weight adjustment:**
```
(embedding:zPDXL3:1.5), (embedding:BadX.pt:1.2), ugly, deformed
```
**Note:** When using weights, include the full filename with extension (.pt or .safetensors).
### Recommended Usage by Workflow
**LUSTIFY Realistic T2I:**
```
Negative: embedding:BadX, (worst quality, low quality:1.4), bad anatomy, deformed, blurry, watermark, text
```
**RealVisXL Lightning T2I:**
```
Negative: embedding:BadX, (worst quality, low quality:1.4), ugly, cartoon, anime
```
**Pony Anime / WAI-Illustrious T2I:**
```
Negative: embedding:zPDXL3, embedding:zPDXLxxx, score_4, score_5, score_6, bad anatomy, deformed
```
Or with custom strength:
```
Negative: (embedding:zPDXL3:1.5), (embedding:zPDXLxxx:1.2), score_4, score_5, low quality
```
**NSFW Ultimate SD Upscale:**
```
Negative: embedding:BadX, (worst quality, low quality:1.4), blurry, pixelated, jpeg artifacts
```
### Important Compatibility Notes
**CRITICAL:** SD 1.5 embeddings (BadDream, badhandv4, etc.) DO NOT work with SDXL models due to different CLIP architectures. Always use:
- **SDXL models** → `BadX` embedding
- **Pony models** → `zPDXL3` and `zPDXLxxx` embeddings
- **SD 1.5 models** → SD 1.5 embeddings only
Using the wrong embedding type will cause errors or unexpected results.
### Tips
- Start with recommended strength 1.0-2.0 for Pony embeddings
- `zPDXL3` removes censoring, ideal for NSFW Pony workflows
- Combine multiple embeddings for best results
- `BadX` works with all general SDXL checkpoints (LUSTIFY, RealVisXL, etc.)
- Higher CFG scales (≥11) work better with `badhandv4` (SD 1.5)
## Notes
- All workflows follow production naming standards
- VRAM requirement: ~12GB per SDXL model
- Can run one NSFW model at a time on 24GB GPU
- Models automatically use BakedVAE when available
- Face enhancement can be added via Impact-Pack nodes
## Version History
- v1.0 (2025-11-23): Initial release with complete NSFW workflow suite
- **Text-to-Image Workflows:**
- LUSTIFY realistic T2I (DPM++ 2M SDE, 30 steps, CFG 6.0)
- Pony Diffusion anime/furry T2I (Euler A, 35 steps, CFG 7.5)
- RealVisXL Lightning fast T2I (DPM++ SDE Karras, 6 steps, CFG 2.0)
- **Enhancement Workflows:**
- LoRA Fusion multi-stack (in ../text-to-image/, compatible with all NSFW checkpoints)
- NSFW Ultimate SD Upscale (2x upscaling with LUSTIFY + RealESRGAN)
- **Total:** 3 NSFW-specific workflows + 2 enhancement workflows = 5 production workflows

View File

@@ -0,0 +1,256 @@
{
"last_node_id": 11,
"last_link_id": 16,
"nodes": [
{
"id": 1,
"type": "CheckpointLoaderSimple",
"pos": [50, 100],
"size": {"0": 380, "1": 100},
"flags": {},
"order": 0,
"mode": 0,
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"links": [1],
"slot_index": 0
},
{
"name": "CLIP",
"type": "CLIP",
"links": [2, 3],
"slot_index": 1
},
{
"name": "VAE",
"type": "VAE",
"links": [4],
"slot_index": 2
}
],
"properties": {
"Node name for S&R": "CheckpointLoaderSimple"
},
"widgets_values": ["lustifySDXLNSFW_endgame.safetensors"],
"title": "LUSTIFY v7.0 GGWP Checkpoint"
},
{
"id": 2,
"type": "CLIPTextEncode",
"pos": [480, 100],
"size": {"0": 450, "1": 250},
"flags": {},
"order": 1,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 2
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"links": [5],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": ["A beautiful woman in elegant dress, photorealistic, professional photography, high quality, detailed skin texture, natural lighting, 8k, masterpiece, best quality"],
"title": "API Positive Prompt"
},
{
"id": 3,
"type": "CLIPTextEncode",
"pos": [480, 400],
"size": {"0": 450, "1": 150},
"flags": {},
"order": 2,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 3
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"links": [6],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": ["(worst quality, low quality:1.4), illustration, 3d, 2d, painting, cartoons, sketch, open mouth, bad anatomy, deformed, blurry, watermark, text"],
"title": "Negative Prompt (LUSTIFY Optimized)"
},
{
"id": 4,
"type": "EmptyLatentImage",
"pos": [480, 600],
"size": {"0": 315, "1": 110},
"flags": {},
"order": 3,
"mode": 0,
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"links": [7],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "EmptyLatentImage"
},
"widgets_values": [1024, 1024, 1],
"title": "Latent Image (SDXL Resolution)"
},
{
"id": 5,
"type": "KSampler",
"pos": [980, 100],
"size": {"0": 350, "1": 290},
"flags": {},
"order": 4,
"mode": 0,
"inputs": [
{
"name": "model",
"type": "MODEL",
"link": 1
},
{
"name": "positive",
"type": "CONDITIONING",
"link": 5
},
{
"name": "negative",
"type": "CONDITIONING",
"link": 6
},
{
"name": "latent_image",
"type": "LATENT",
"link": 7
}
],
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"links": [8],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "KSampler"
},
"widgets_values": [
0,
"randomize",
30,
6.0,
"dpmpp_2m_sde",
"exponential",
1.0
],
"title": "LUSTIFY Sampler (DPM++ 2M SDE / Exponential)"
},
{
"id": 6,
"type": "VAEDecode",
"pos": [1380, 100],
"size": {"0": 210, "1": 50},
"flags": {},
"order": 5,
"mode": 0,
"inputs": [
{
"name": "samples",
"type": "LATENT",
"link": 8
},
{
"name": "vae",
"type": "VAE",
"link": 4
}
],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [9],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "VAEDecode"
},
"title": "VAE Decode"
},
{
"id": 7,
"type": "SaveImage",
"pos": [1640, 100],
"size": {"0": 320, "1": 290},
"flags": {},
"order": 6,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 9
}
],
"properties": {
"Node name for S&R": "SaveImage"
},
"widgets_values": ["lustify_realistic"],
"title": "API Output Image"
}
],
"links": [
[1, 1, 0, 5, 0, "MODEL"],
[2, 1, 1, 2, 0, "CLIP"],
[3, 1, 1, 3, 0, "CLIP"],
[4, 1, 2, 6, 1, "VAE"],
[5, 2, 0, 5, 1, "CONDITIONING"],
[6, 3, 0, 5, 2, "CONDITIONING"],
[7, 4, 0, 5, 3, "LATENT"],
[8, 5, 0, 6, 0, "LATENT"],
[9, 6, 0, 7, 0, "IMAGE"]
],
"groups": [],
"config": {},
"extra": {
"workflow_info": {
"name": "LUSTIFY Realistic NSFW Text-to-Image",
"version": "1.0",
"description": "Production workflow for LUSTIFY v7.0 GGWP checkpoint optimized for photorealistic NSFW generation with recommended settings (DPM++ 2M SDE, Exponential scheduler, 30 steps, CFG 6.0)",
"category": "nsfw",
"model": "lustifySDXLNSFW_endgame.safetensors",
"recommended_settings": {
"sampler": "dpmpp_2m_sde or dpmpp_3m_sde",
"scheduler": "exponential or karras",
"steps": 30,
"cfg_scale": "4.0-7.0"
},
"tags": ["nsfw", "realistic", "photography", "women", "sdxl"]
}
},
"version": 0.4
}

View File

@@ -0,0 +1,300 @@
{
"last_node_id": 8,
"last_link_id": 10,
"nodes": [
{
"id": 1,
"type": "LoadImage",
"pos": [50, 100],
"size": [350, 100],
"flags": {},
"order": 0,
"mode": 0,
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [1],
"slot_index": 0
},
{
"name": "MASK",
"type": "MASK",
"links": null,
"slot_index": 1
}
],
"properties": {
"Node name for S&R": "LoadImage"
},
"widgets_values": ["input_image.png", "image"],
"title": "API Input Image"
},
{
"id": 2,
"type": "CheckpointLoaderSimple",
"pos": [50, 250],
"size": [350, 100],
"flags": {},
"order": 1,
"mode": 0,
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"links": [2],
"slot_index": 0
},
{
"name": "CLIP",
"type": "CLIP",
"links": [3, 4],
"slot_index": 1
},
{
"name": "VAE",
"type": "VAE",
"links": [5],
"slot_index": 2
}
],
"properties": {
"Node name for S&R": "CheckpointLoaderSimple"
},
"widgets_values": ["lustifySDXLNSFW_endgame.safetensors"],
"title": "LUSTIFY v7.0 GGWP Checkpoint"
},
{
"id": 3,
"type": "CLIPTextEncode",
"pos": [450, 100],
"size": [400, 200],
"flags": {},
"order": 2,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 3
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"links": [6],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": ["photorealistic, professional photography, high quality, detailed skin texture, natural lighting, 8k, masterpiece, best quality, sharp details"],
"title": "API Positive Prompt (Enhancement)"
},
{
"id": 4,
"type": "CLIPTextEncode",
"pos": [450, 350],
"size": [400, 200],
"flags": {},
"order": 3,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 4
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"links": [7],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": ["(worst quality, low quality:1.4), blurry, pixelated, jpeg artifacts, bad anatomy, deformed, watermark, text"],
"title": "API Negative Prompt (Refinement)"
},
{
"id": 8,
"type": "UpscaleModelLoader",
"pos": [50, 400],
"size": [350, 100],
"flags": {},
"order": 4,
"mode": 0,
"outputs": [
{
"name": "UPSCALE_MODEL",
"type": "UPSCALE_MODEL",
"links": [10],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "UpscaleModelLoader"
},
"widgets_values": ["RealESRGAN_x2.pth"],
"title": "Upscale Model Loader (2x)"
},
{
"id": 5,
"type": "UltimateSDUpscale",
"pos": [900, 100],
"size": [315, 100],
"flags": {},
"order": 5,
"mode": 0,
"inputs": [
{
"name": "image",
"type": "IMAGE",
"link": 1
},
{
"name": "model",
"type": "MODEL",
"link": 2
},
{
"name": "positive",
"type": "CONDITIONING",
"link": 6
},
{
"name": "negative",
"type": "CONDITIONING",
"link": 7
},
{
"name": "vae",
"type": "VAE",
"link": 5
},
{
"name": "upscale_model",
"type": "UPSCALE_MODEL",
"link": 10
}
],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [8, 9],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "UltimateSDUpscale"
},
"widgets_values": [2, 42, "randomize", 20, 7.0, "dpmpp_2m_sde", "exponential", 0.25, "Linear", 512, 512, 8, 32, "None", 1.0, 64, 8, 16, true, false],
"title": "Ultimate SD Upscale NSFW (2x)"
},
{
"id": 6,
"type": "PreviewImage",
"pos": [1270, 100],
"size": [315, 100],
"flags": {},
"order": 6,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 8
}
],
"properties": {
"Node name for S&R": "PreviewImage"
},
"title": "Preview Output"
},
{
"id": 7,
"type": "SaveImage",
"pos": [1270, 400],
"size": [315, 100],
"flags": {},
"order": 7,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 9
}
],
"properties": {
"Node name for S&R": "SaveImage"
},
"widgets_values": ["nsfw_upscale_output"],
"title": "API Image Output"
}
],
"links": [
[1, 1, 0, 5, 0, "IMAGE"],
[2, 2, 0, 5, 1, "MODEL"],
[3, 2, 1, 3, 0, "CLIP"],
[4, 2, 1, 4, 0, "CLIP"],
[5, 2, 2, 5, 4, "VAE"],
[6, 3, 0, 5, 2, "CONDITIONING"],
[7, 4, 0, 5, 3, "CONDITIONING"],
[8, 5, 0, 6, 0, "IMAGE"],
[9, 5, 0, 7, 0, "IMAGE"],
[10, 8, 0, 5, 5, "UPSCALE_MODEL"]
],
"groups": [],
"config": {},
"extra": {
"workflow_info": {
"name": "NSFW Ultimate SD Upscale Production",
"version": "1.0",
"description": "Professional 2x upscaling for NSFW images using Ultimate SD Upscale with LUSTIFY checkpoint. Combines RealESRGAN upscaling with diffusion refinement for superior detail, skin texture, and photorealistic quality in adult content.",
"category": "nsfw",
"model": "lustifySDXLNSFW_endgame.safetensors",
"recommended_settings": {
"upscale_factor": "2x (use RealESRGAN_x2.pth)",
"denoise": "0.2-0.3 (lower preserves original, higher adds detail)",
"sampler": "dpmpp_2m_sde",
"scheduler": "exponential",
"steps": 20,
"cfg_scale": "6.0-8.0",
"tile_size": "512x512 (optimal for SDXL)"
},
"features": [
"2x upscaling with RealESRGAN + diffusion refinement",
"LUSTIFY checkpoint for photorealistic NSFW enhancement",
"Tiled processing for handling large images",
"Optimized for detailed skin texture and natural lighting",
"Low denoise (0.25) preserves original composition",
"Can swap checkpoint for different styles (Pony, RealVisXL)"
],
"tags": ["nsfw", "upscaling", "ultimate-sd-upscale", "lustify", "enhancement", "production"],
"requirements": {
"models": ["lustifySDXLNSFW_endgame.safetensors", "RealESRGAN_x2.pth"],
"custom_nodes": ["ComfyUI_UltimateSDUpscale"],
"vram_min": "18GB"
},
"usage_notes": {
"checkpoint_swap": "Change node 2 to use different NSFW models (pony, realvisxl, etc.)",
"denoise_tuning": "0.2 = subtle enhancement, 0.3 = moderate refinement, 0.4+ = creative upscaling",
"prompt_matching": "Match enhancement prompt to original generation prompt for best results",
"tile_overlap": "8px overlap prevents visible seams in large upscales"
},
"performance": {
"avg_generation_time": "90-150 seconds (1024x1024 -> 2048x2048)",
"vram_usage": "~20-22GB (LUSTIFY + tiled processing)"
}
}
},
"version": 0.4
}

View File

@@ -0,0 +1,260 @@
{
"last_node_id": 11,
"last_link_id": 16,
"nodes": [
{
"id": 1,
"type": "CheckpointLoaderSimple",
"pos": [50, 100],
"size": {"0": 380, "1": 100},
"flags": {},
"order": 0,
"mode": 0,
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"links": [1],
"slot_index": 0
},
{
"name": "CLIP",
"type": "CLIP",
"links": [2, 3],
"slot_index": 1
},
{
"name": "VAE",
"type": "VAE",
"links": [4],
"slot_index": 2
}
],
"properties": {
"Node name for S&R": "CheckpointLoaderSimple"
},
"widgets_values": ["ponyDiffusionV6XL_v6StartWithThisOne.safetensors"],
"title": "Pony Diffusion V6 XL Checkpoint (Anime/Furry)"
},
{
"id": 2,
"type": "CLIPTextEncode",
"pos": [480, 100],
"size": {"0": 450, "1": 250},
"flags": {},
"order": 1,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 2
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"links": [5],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": ["1girl, solo, long_hair, breasts, smile, looking_at_viewer, anime style, high quality, detailed, masterpiece, best quality"],
"title": "API Positive Prompt (Danbooru Tags)"
},
{
"id": 3,
"type": "CLIPTextEncode",
"pos": [480, 400],
"size": {"0": 450, "1": 150},
"flags": {},
"order": 2,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 3
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"links": [6],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": ["(worst quality, low quality:1.4), bad anatomy, deformed, blurry, watermark, text, signature, artist name"],
"title": "Negative Prompt (Pony Optimized)"
},
{
"id": 4,
"type": "EmptyLatentImage",
"pos": [480, 600],
"size": {"0": 315, "1": 110},
"flags": {},
"order": 3,
"mode": 0,
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"links": [7],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "EmptyLatentImage"
},
"widgets_values": [1024, 1024, 1],
"title": "Latent Image (SDXL Resolution)"
},
{
"id": 5,
"type": "KSampler",
"pos": [980, 100],
"size": {"0": 350, "1": 290},
"flags": {},
"order": 4,
"mode": 0,
"inputs": [
{
"name": "model",
"type": "MODEL",
"link": 1
},
{
"name": "positive",
"type": "CONDITIONING",
"link": 5
},
{
"name": "negative",
"type": "CONDITIONING",
"link": 6
},
{
"name": "latent_image",
"type": "LATENT",
"link": 7
}
],
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"links": [8],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "KSampler"
},
"widgets_values": [
0,
"randomize",
35,
7.5,
"euler_ancestral",
"normal",
1.0
],
"title": "Pony Sampler (Euler A / Normal)"
},
{
"id": 6,
"type": "VAEDecode",
"pos": [1380, 100],
"size": {"0": 210, "1": 50},
"flags": {},
"order": 5,
"mode": 0,
"inputs": [
{
"name": "samples",
"type": "LATENT",
"link": 8
},
{
"name": "vae",
"type": "VAE",
"link": 4
}
],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [9],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "VAEDecode"
},
"title": "VAE Decode"
},
{
"id": 7,
"type": "SaveImage",
"pos": [1640, 100],
"size": {"0": 320, "1": 290},
"flags": {},
"order": 6,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 9
}
],
"properties": {
"Node name for S&R": "SaveImage"
},
"widgets_values": ["pony_anime"],
"title": "API Output Image"
}
],
"links": [
[1, 1, 0, 5, 0, "MODEL"],
[2, 1, 1, 2, 0, "CLIP"],
[3, 1, 1, 3, 0, "CLIP"],
[4, 1, 2, 6, 1, "VAE"],
[5, 2, 0, 5, 1, "CONDITIONING"],
[6, 3, 0, 5, 2, "CONDITIONING"],
[7, 4, 0, 5, 3, "LATENT"],
[8, 5, 0, 6, 0, "LATENT"],
[9, 6, 0, 7, 0, "IMAGE"]
],
"groups": [],
"config": {},
"extra": {
"workflow_info": {
"name": "Pony Diffusion V6 XL Anime/Furry NSFW Text-to-Image",
"version": "1.0",
"description": "Production workflow for Pony Diffusion V6 XL optimized for anime, cartoon, and furry NSFW generation with danbooru tag support and balanced content (safe/questionable/explicit)",
"category": "nsfw",
"model": "ponyDiffusionV6XL_v6StartWithThisOne.safetensors",
"recommended_settings": {
"sampler": "euler_ancestral or dpmpp_2m",
"scheduler": "normal or karras",
"steps": "30-40",
"cfg_scale": "7.0-8.5"
},
"training_info": {
"images": "2.6M aesthetically ranked",
"ratio": "1:1:1 safe/questionable/explicit"
},
"tags": ["nsfw", "anime", "furry", "cartoon", "versatile", "danbooru", "sdxl"]
}
},
"version": 0.4
}

View File

@@ -0,0 +1,263 @@
{
"last_node_id": 11,
"last_link_id": 16,
"nodes": [
{
"id": 1,
"type": "CheckpointLoaderSimple",
"pos": [50, 100],
"size": {"0": 380, "1": 100},
"flags": {},
"order": 0,
"mode": 0,
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"links": [1],
"slot_index": 0
},
{
"name": "CLIP",
"type": "CLIP",
"links": [2, 3],
"slot_index": 1
},
{
"name": "VAE",
"type": "VAE",
"links": [4],
"slot_index": 2
}
],
"properties": {
"Node name for S&R": "CheckpointLoaderSimple"
},
"widgets_values": ["realvisxlV50_v50LightningBakedvae.safetensors"],
"title": "RealVisXL V5.0 Lightning Checkpoint"
},
{
"id": 2,
"type": "CLIPTextEncode",
"pos": [480, 100],
"size": {"0": 450, "1": 250},
"flags": {},
"order": 1,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 2
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"links": [5],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": ["Beautiful woman portrait, professional photography, natural lighting, high quality, detailed, 8k"],
"title": "API Positive Prompt"
},
{
"id": 3,
"type": "CLIPTextEncode",
"pos": [480, 400],
"size": {"0": 450, "1": 150},
"flags": {},
"order": 2,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 3
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"links": [6],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": ["(worst quality, low quality:1.4), bad anatomy, deformed, blurry, watermark, text, ugly, cartoon, anime"],
"title": "Negative Prompt (RealVisXL Optimized)"
},
{
"id": 4,
"type": "EmptyLatentImage",
"pos": [480, 600],
"size": {"0": 315, "1": 110},
"flags": {},
"order": 3,
"mode": 0,
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"links": [7],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "EmptyLatentImage"
},
"widgets_values": [1024, 1024, 1],
"title": "Latent Image (SDXL Resolution)"
},
{
"id": 5,
"type": "KSampler",
"pos": [980, 100],
"size": {"0": 350, "1": 290},
"flags": {},
"order": 4,
"mode": 0,
"inputs": [
{
"name": "model",
"type": "MODEL",
"link": 1
},
{
"name": "positive",
"type": "CONDITIONING",
"link": 5
},
{
"name": "negative",
"type": "CONDITIONING",
"link": 6
},
{
"name": "latent_image",
"type": "LATENT",
"link": 7
}
],
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"links": [8],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "KSampler"
},
"widgets_values": [
0,
"randomize",
6,
2.0,
"dpmpp_sde",
"karras",
1.0
],
"title": "Lightning Sampler (DPM++ SDE Karras / 6 Steps)"
},
{
"id": 6,
"type": "VAEDecode",
"pos": [1380, 100],
"size": {"0": 210, "1": 50},
"flags": {},
"order": 5,
"mode": 0,
"inputs": [
{
"name": "samples",
"type": "LATENT",
"link": 8
},
{
"name": "vae",
"type": "VAE",
"link": 4
}
],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [9],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "VAEDecode"
},
"title": "VAE Decode"
},
{
"id": 7,
"type": "SaveImage",
"pos": [1640, 100],
"size": {"0": 320, "1": 290},
"flags": {},
"order": 6,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 9
}
],
"properties": {
"Node name for S&R": "SaveImage"
},
"widgets_values": ["realvisxl_lightning"],
"title": "API Output Image"
}
],
"links": [
[1, 1, 0, 5, 0, "MODEL"],
[2, 1, 1, 2, 0, "CLIP"],
[3, 1, 1, 3, 0, "CLIP"],
[4, 1, 2, 6, 1, "VAE"],
[5, 2, 0, 5, 1, "CONDITIONING"],
[6, 3, 0, 5, 2, "CONDITIONING"],
[7, 4, 0, 5, 3, "LATENT"],
[8, 5, 0, 6, 0, "LATENT"],
[9, 6, 0, 7, 0, "IMAGE"]
],
"groups": [],
"config": {},
"extra": {
"workflow_info": {
"name": "RealVisXL V5.0 Lightning Fast NSFW Text-to-Image",
"version": "1.0",
"description": "Production workflow for RealVisXL V5.0 Lightning checkpoint optimized for ultra-fast photorealistic NSFW generation with 4-6 step inference (vs 30+ for standard models)",
"category": "nsfw",
"model": "realvisxlV50_v50LightningBakedvae.safetensors",
"recommended_settings": {
"sampler": "dpmpp_sde with karras scheduler",
"scheduler": "karras",
"steps": "4-6 (Lightning optimized)",
"cfg_scale": "1.0-2.0 (lower for Lightning)"
},
"features": [
"Ultra-fast 4-6 step generation",
"High-quality photorealistic output",
"Baked VAE for optimal quality",
"Professional portraits and scenes",
"Both SFW and NSFW capable"
],
"tags": ["nsfw", "realistic", "photorealistic", "lightning", "fast", "sdxl"]
}
},
"version": 0.4
}

View File

@@ -1,12 +1,12 @@
{ {
"last_node_id": 12, "last_node_id": 9,
"last_link_id": 15, "last_link_id": 13,
"nodes": [ "nodes": [
{ {
"id": 1, "id": 1,
"type": "CheckpointLoaderSimple", "type": "UNETLoader",
"pos": [50, 100], "pos": [50, 100],
"size": {"0": 350, "1": 100}, "size": [350, 100],
"flags": {}, "flags": {},
"order": 0, "order": 0,
"mode": 0, "mode": 0,
@@ -16,34 +16,44 @@
"type": "MODEL", "type": "MODEL",
"links": [1], "links": [1],
"slot_index": 0 "slot_index": 0
},
{
"name": "CLIP",
"type": "CLIP",
"links": [2, 3],
"slot_index": 1
},
{
"name": "VAE",
"type": "VAE",
"links": [4],
"slot_index": 2
} }
], ],
"properties": { "properties": {
"Node name for S&R": "CheckpointLoaderSimple" "Node name for S&R": "UNETLoader"
}, },
"widgets_values": ["diffusers/FLUX.1-dev"], "widgets_values": ["flux1-dev.safetensors", "default"],
"title": "FLUX Dev Checkpoint Loader" "title": "FLUX Dev UNET Loader"
}, },
{ {
"id": 2, "id": 2,
"type": "CLIPTextEncode", "type": "DualCLIPLoader",
"pos": [450, 100], "pos": [50, 250],
"size": {"0": 400, "1": 200}, "size": [350, 100],
"flags": {}, "flags": {},
"order": 1, "order": 1,
"mode": 0, "mode": 0,
"outputs": [
{
"name": "CLIP",
"type": "CLIP",
"links": [2],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "DualCLIPLoader"
},
"widgets_values": ["t5xxl_fp16.safetensors", "clip_l.safetensors", "flux"],
"title": "FLUX CLIP Loader"
},
{
"id": 3,
"type": "CLIPTextEncodeFlux",
"pos": [450, 100],
"size": [400, 250],
"flags": {},
"order": 2,
"mode": 0,
"inputs": [ "inputs": [
{ {
"name": "clip", "name": "clip",
@@ -55,58 +65,61 @@
{ {
"name": "CONDITIONING", "name": "CONDITIONING",
"type": "CONDITIONING", "type": "CONDITIONING",
"links": [5], "links": [3, 8],
"slot_index": 0 "slot_index": 0
} }
], ],
"properties": { "properties": {
"Node name for S&R": "CLIPTextEncode" "Node name for S&R": "CLIPTextEncodeFlux"
}, },
"widgets_values": ["A beautiful mountain landscape at sunset, highly detailed, professional photography, cinematic lighting, 8k ultra HD"], "widgets_values": [
"A beautiful mountain landscape at sunset, highly detailed, professional photography, cinematic lighting, 8k ultra HD",
"A beautiful mountain landscape at sunset, highly detailed, professional photography, cinematic lighting, 8k ultra HD",
3.5
],
"title": "API Positive Prompt" "title": "API Positive Prompt"
}, },
{ {
"id": 3, "id": 9,
"type": "CLIPTextEncode", "type": "ConditioningZeroOut",
"pos": [450, 350], "pos": [450, 400],
"size": {"0": 400, "1": 200}, "size": [315, 60],
"flags": {}, "flags": {},
"order": 2, "order": 3,
"mode": 0, "mode": 0,
"inputs": [ "inputs": [
{ {
"name": "clip", "name": "conditioning",
"type": "CLIP", "type": "CONDITIONING",
"link": 3 "link": 8
} }
], ],
"outputs": [ "outputs": [
{ {
"name": "CONDITIONING", "name": "CONDITIONING",
"type": "CONDITIONING", "type": "CONDITIONING",
"links": [6], "links": [9],
"slot_index": 0 "slot_index": 0
} }
], ],
"properties": { "properties": {
"Node name for S&R": "CLIPTextEncode" "Node name for S&R": "ConditioningZeroOut"
}, },
"widgets_values": ["blurry, low quality, distorted, watermark, text, signature, cartoon"], "title": "Empty Negative Conditioning"
"title": "API Negative Prompt"
}, },
{ {
"id": 4, "id": 4,
"type": "EmptyLatentImage", "type": "EmptyLatentImage",
"pos": [450, 600], "pos": [450, 500],
"size": {"0": 315, "1": 106}, "size": [315, 106],
"flags": {}, "flags": {},
"order": 3, "order": 4,
"mode": 0, "mode": 0,
"outputs": [ "outputs": [
{ {
"name": "LATENT", "name": "LATENT",
"type": "LATENT", "type": "LATENT",
"links": [7], "links": [4],
"slot_index": 0 "slot_index": 0
} }
], ],
@@ -120,9 +133,9 @@
"id": 5, "id": 5,
"type": "KSampler", "type": "KSampler",
"pos": [900, 100], "pos": [900, 100],
"size": {"0": 315, "1": 474}, "size": [315, 474],
"flags": {}, "flags": {},
"order": 4, "order": 5,
"mode": 0, "mode": 0,
"inputs": [ "inputs": [
{ {
@@ -133,66 +146,80 @@
{ {
"name": "positive", "name": "positive",
"type": "CONDITIONING", "type": "CONDITIONING",
"link": 5 "link": 3
}, },
{ {
"name": "negative", "name": "negative",
"type": "CONDITIONING", "type": "CONDITIONING",
"link": 6 "link": 9
}, },
{ {
"name": "latent_image", "name": "latent_image",
"type": "LATENT", "type": "LATENT",
"link": 7 "link": 4
} }
], ],
"outputs": [ "outputs": [
{ {
"name": "LATENT", "name": "LATENT",
"type": "LATENT", "type": "LATENT",
"links": [8], "links": [5],
"slot_index": 0 "slot_index": 0
} }
], ],
"properties": { "properties": {
"Node name for S&R": "KSampler" "Node name for S&R": "KSampler"
}, },
"widgets_values": [ "widgets_values": [42, "fixed", 20, 1.0, "euler", "normal", 1.0],
42, "title": "FLUX Dev Sampler (20 steps)"
"fixed",
20,
3.5,
"euler",
"normal",
1
],
"title": "FLUX Dev Sampler (20-50 steps)"
}, },
{ {
"id": 6, "id": 6,
"type": "VAELoader",
"pos": [900, 600],
"size": [315, 60],
"flags": {},
"order": 6,
"mode": 0,
"outputs": [
{
"name": "VAE",
"type": "VAE",
"links": [6],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "VAELoader"
},
"widgets_values": ["ae.safetensors"],
"title": "FLUX VAE Loader"
},
{
"id": 7,
"type": "VAEDecode", "type": "VAEDecode",
"pos": [1270, 100], "pos": [1270, 100],
"size": {"0": 210, "1": 46}, "size": [210, 46],
"flags": {}, "flags": {},
"order": 5, "order": 7,
"mode": 0, "mode": 0,
"inputs": [ "inputs": [
{ {
"name": "samples", "name": "samples",
"type": "LATENT", "type": "LATENT",
"link": 8 "link": 5
}, },
{ {
"name": "vae", "name": "vae",
"type": "VAE", "type": "VAE",
"link": 4 "link": 6
} }
], ],
"outputs": [ "outputs": [
{ {
"name": "IMAGE", "name": "IMAGE",
"type": "IMAGE", "type": "IMAGE",
"links": [9, 10], "links": [7],
"slot_index": 0 "slot_index": 0
} }
], ],
@@ -201,39 +228,19 @@
}, },
"title": "VAE Decode" "title": "VAE Decode"
}, },
{
"id": 7,
"type": "PreviewImage",
"pos": [1530, 100],
"size": {"0": 400, "1": 400},
"flags": {},
"order": 6,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 9
}
],
"properties": {
"Node name for S&R": "PreviewImage"
},
"title": "Preview Output"
},
{ {
"id": 8, "id": 8,
"type": "SaveImage", "type": "SaveImage",
"pos": [1530, 550], "pos": [1530, 100],
"size": {"0": 400, "1": 100}, "size": [400, 100],
"flags": {}, "flags": {},
"order": 7, "order": 8,
"mode": 0, "mode": 0,
"inputs": [ "inputs": [
{ {
"name": "images", "name": "images",
"type": "IMAGE", "type": "IMAGE",
"link": 10 "link": 7
} }
], ],
"properties": { "properties": {
@@ -245,49 +252,39 @@
], ],
"links": [ "links": [
[1, 1, 0, 5, 0, "MODEL"], [1, 1, 0, 5, 0, "MODEL"],
[2, 1, 1, 2, 0, "CLIP"], [2, 2, 0, 3, 0, "CLIP"],
[3, 1, 1, 3, 0, "CLIP"], [3, 3, 0, 5, 1, "CONDITIONING"],
[4, 1, 2, 6, 1, "VAE"], [4, 4, 0, 5, 3, "LATENT"],
[5, 2, 0, 5, 1, "CONDITIONING"], [5, 5, 0, 7, 0, "LATENT"],
[6, 3, 0, 5, 2, "CONDITIONING"], [6, 6, 0, 7, 1, "VAE"],
[7, 4, 0, 5, 3, "LATENT"], [7, 7, 0, 8, 0, "IMAGE"],
[8, 5, 0, 6, 0, "LATENT"], [8, 3, 0, 9, 0, "CONDITIONING"],
[9, 6, 0, 7, 0, "IMAGE"], [9, 9, 0, 5, 2, "CONDITIONING"]
[10, 6, 0, 8, 0, "IMAGE"]
], ],
"groups": [], "groups": [],
"config": {}, "config": {},
"extra": { "extra": {
"workflow_info": { "workflow_info": {
"name": "FLUX Dev Text-to-Image Production", "name": "FLUX Dev Text-to-Image Production",
"version": "1.0.0", "version": "1.2.0",
"author": "RunPod AI Model Orchestrator",
"description": "High-quality text-to-image generation using FLUX.1-dev (20-50 steps). Optimized for final production outputs with excellent detail and coherence.", "description": "High-quality text-to-image generation using FLUX.1-dev (20-50 steps). Optimized for final production outputs with excellent detail and coherence.",
"category": "text-to-image", "category": "text-to-image",
"tags": ["flux", "dev", "high-quality", "production", "t2i"], "tags": ["flux", "dev", "high-quality", "production", "t2i"],
"requirements": { "requirements": {
"models": ["FLUX.1-dev"], "models": ["FLUX.1-dev", "CLIP-L", "T5-XXL FP16"],
"custom_nodes": [], "custom_nodes": [],
"vram_min": "20GB", "vram_min": "20GB",
"vram_recommended": "24GB" "vram_recommended": "24GB"
}, },
"parameters": { "parameters": {
"prompt": { "prompt": {
"node_id": 2, "node_id": 3,
"widget_index": 0, "widget_index": 0,
"type": "string", "type": "string",
"required": true, "required": true,
"default": "A beautiful mountain landscape at sunset", "default": "A beautiful mountain landscape at sunset",
"description": "Text description of desired image" "description": "Text description of desired image"
}, },
"negative_prompt": {
"node_id": 3,
"widget_index": 0,
"type": "string",
"required": false,
"default": "blurry, low quality",
"description": "Undesired elements to avoid"
},
"width": { "width": {
"node_id": 4, "node_id": 4,
"widget_index": 0, "widget_index": 0,
@@ -328,15 +325,15 @@
"max": 50, "max": 50,
"description": "Number of sampling steps (20-50 recommended for FLUX Dev)" "description": "Number of sampling steps (20-50 recommended for FLUX Dev)"
}, },
"cfg": { "guidance": {
"node_id": 5, "node_id": 3,
"widget_index": 3, "widget_index": 2,
"type": "float", "type": "float",
"required": false, "required": false,
"default": 3.5, "default": 3.5,
"min": 1.0, "min": 1.0,
"max": 10.0, "max": 10.0,
"description": "Classifier-free guidance scale (3.5 recommended)" "description": "Guidance scale (3.5 recommended for FLUX)"
} }
}, },
"outputs": { "outputs": {
@@ -351,7 +348,14 @@
"avg_generation_time": "25-35 seconds (20 steps), 60-75 seconds (50 steps)", "avg_generation_time": "25-35 seconds (20 steps), 60-75 seconds (50 steps)",
"vram_usage": "~20-22GB", "vram_usage": "~20-22GB",
"gpu_utilization": "95-100%" "gpu_utilization": "95-100%"
} },
"notes": [
"FLUX uses UNETLoader instead of CheckpointLoader",
"DualCLIPLoader loads both T5-XXL and CLIP-L text encoders",
"CLIPTextEncodeFlux is FLUX-specific text encoder",
"No negative prompt for FLUX - guidance is handled differently",
"CFG scale of 1.0 recommended, guidance in text encoder"
]
} }
}, },
"version": 0.4 "version": 0.4

View File

@@ -1,12 +1,12 @@
{ {
"last_node_id": 12, "last_node_id": 9,
"last_link_id": 15, "last_link_id": 9,
"nodes": [ "nodes": [
{ {
"id": 1, "id": 1,
"type": "CheckpointLoaderSimple", "type": "UNETLoader",
"pos": [50, 100], "pos": [50, 100],
"size": {"0": 350, "1": 100}, "size": [350, 100],
"flags": {}, "flags": {},
"order": 0, "order": 0,
"mode": 0, "mode": 0,
@@ -16,34 +16,44 @@
"type": "MODEL", "type": "MODEL",
"links": [1], "links": [1],
"slot_index": 0 "slot_index": 0
},
{
"name": "CLIP",
"type": "CLIP",
"links": [2, 3],
"slot_index": 1
},
{
"name": "VAE",
"type": "VAE",
"links": [4],
"slot_index": 2
} }
], ],
"properties": { "properties": {
"Node name for S&R": "CheckpointLoaderSimple" "Node name for S&R": "UNETLoader"
}, },
"widgets_values": ["diffusers/FLUX.1-schnell"], "widgets_values": ["flux1-schnell.safetensors", "default"],
"title": "FLUX Schnell Checkpoint Loader" "title": "FLUX Schnell UNET Loader"
}, },
{ {
"id": 2, "id": 2,
"type": "CLIPTextEncode", "type": "DualCLIPLoader",
"pos": [450, 100], "pos": [50, 250],
"size": {"0": 400, "1": 200}, "size": [350, 100],
"flags": {}, "flags": {},
"order": 1, "order": 1,
"mode": 0, "mode": 0,
"outputs": [
{
"name": "CLIP",
"type": "CLIP",
"links": [2],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "DualCLIPLoader"
},
"widgets_values": ["t5xxl_fp16.safetensors", "clip_l.safetensors", "flux"],
"title": "FLUX CLIP Loader"
},
{
"id": 3,
"type": "CLIPTextEncodeFlux",
"pos": [450, 100],
"size": [400, 250],
"flags": {},
"order": 2,
"mode": 0,
"inputs": [ "inputs": [
{ {
"name": "clip", "name": "clip",
@@ -55,58 +65,61 @@
{ {
"name": "CONDITIONING", "name": "CONDITIONING",
"type": "CONDITIONING", "type": "CONDITIONING",
"links": [5], "links": [3, 8],
"slot_index": 0 "slot_index": 0
} }
], ],
"properties": { "properties": {
"Node name for S&R": "CLIPTextEncode" "Node name for S&R": "CLIPTextEncodeFlux"
}, },
"widgets_values": ["A beautiful mountain landscape at sunset, highly detailed, cinematic lighting, 8k"], "widgets_values": [
"A beautiful mountain landscape at sunset, highly detailed, cinematic lighting, 8k",
"A beautiful mountain landscape at sunset, highly detailed, cinematic lighting, 8k",
3.5
],
"title": "API Positive Prompt" "title": "API Positive Prompt"
}, },
{ {
"id": 3, "id": 9,
"type": "CLIPTextEncode", "type": "ConditioningZeroOut",
"pos": [450, 350], "pos": [450, 400],
"size": {"0": 400, "1": 200}, "size": [315, 60],
"flags": {}, "flags": {},
"order": 2, "order": 3,
"mode": 0, "mode": 0,
"inputs": [ "inputs": [
{ {
"name": "clip", "name": "conditioning",
"type": "CLIP", "type": "CONDITIONING",
"link": 3 "link": 8
} }
], ],
"outputs": [ "outputs": [
{ {
"name": "CONDITIONING", "name": "CONDITIONING",
"type": "CONDITIONING", "type": "CONDITIONING",
"links": [6], "links": [9],
"slot_index": 0 "slot_index": 0
} }
], ],
"properties": { "properties": {
"Node name for S&R": "CLIPTextEncode" "Node name for S&R": "ConditioningZeroOut"
}, },
"widgets_values": ["blurry, low quality, distorted, watermark"], "title": "Empty Negative Conditioning"
"title": "API Negative Prompt"
}, },
{ {
"id": 4, "id": 4,
"type": "EmptyLatentImage", "type": "EmptyLatentImage",
"pos": [450, 600], "pos": [450, 500],
"size": {"0": 315, "1": 106}, "size": [315, 106],
"flags": {}, "flags": {},
"order": 3, "order": 4,
"mode": 0, "mode": 0,
"outputs": [ "outputs": [
{ {
"name": "LATENT", "name": "LATENT",
"type": "LATENT", "type": "LATENT",
"links": [7], "links": [4],
"slot_index": 0 "slot_index": 0
} }
], ],
@@ -120,9 +133,9 @@
"id": 5, "id": 5,
"type": "KSampler", "type": "KSampler",
"pos": [900, 100], "pos": [900, 100],
"size": {"0": 315, "1": 474}, "size": [315, 474],
"flags": {}, "flags": {},
"order": 4, "order": 5,
"mode": 0, "mode": 0,
"inputs": [ "inputs": [
{ {
@@ -133,66 +146,80 @@
{ {
"name": "positive", "name": "positive",
"type": "CONDITIONING", "type": "CONDITIONING",
"link": 5 "link": 3
}, },
{ {
"name": "negative", "name": "negative",
"type": "CONDITIONING", "type": "CONDITIONING",
"link": 6 "link": 9
}, },
{ {
"name": "latent_image", "name": "latent_image",
"type": "LATENT", "type": "LATENT",
"link": 7 "link": 4
} }
], ],
"outputs": [ "outputs": [
{ {
"name": "LATENT", "name": "LATENT",
"type": "LATENT", "type": "LATENT",
"links": [8], "links": [5],
"slot_index": 0 "slot_index": 0
} }
], ],
"properties": { "properties": {
"Node name for S&R": "KSampler" "Node name for S&R": "KSampler"
}, },
"widgets_values": [ "widgets_values": [42, "fixed", 4, 1.0, "euler", "normal", 1.0],
42,
"fixed",
4,
1.0,
"euler",
"normal",
1
],
"title": "FLUX Schnell Sampler (4 steps)" "title": "FLUX Schnell Sampler (4 steps)"
}, },
{ {
"id": 6, "id": 6,
"type": "VAELoader",
"pos": [900, 600],
"size": [315, 60],
"flags": {},
"order": 6,
"mode": 0,
"outputs": [
{
"name": "VAE",
"type": "VAE",
"links": [6],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "VAELoader"
},
"widgets_values": ["ae.safetensors"],
"title": "FLUX VAE Loader"
},
{
"id": 7,
"type": "VAEDecode", "type": "VAEDecode",
"pos": [1270, 100], "pos": [1270, 100],
"size": {"0": 210, "1": 46}, "size": [210, 46],
"flags": {}, "flags": {},
"order": 5, "order": 7,
"mode": 0, "mode": 0,
"inputs": [ "inputs": [
{ {
"name": "samples", "name": "samples",
"type": "LATENT", "type": "LATENT",
"link": 8 "link": 5
}, },
{ {
"name": "vae", "name": "vae",
"type": "VAE", "type": "VAE",
"link": 4 "link": 6
} }
], ],
"outputs": [ "outputs": [
{ {
"name": "IMAGE", "name": "IMAGE",
"type": "IMAGE", "type": "IMAGE",
"links": [9, 10], "links": [7],
"slot_index": 0 "slot_index": 0
} }
], ],
@@ -201,39 +228,19 @@
}, },
"title": "VAE Decode" "title": "VAE Decode"
}, },
{
"id": 7,
"type": "PreviewImage",
"pos": [1530, 100],
"size": {"0": 400, "1": 400},
"flags": {},
"order": 6,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 9
}
],
"properties": {
"Node name for S&R": "PreviewImage"
},
"title": "Preview Output"
},
{ {
"id": 8, "id": 8,
"type": "SaveImage", "type": "SaveImage",
"pos": [1530, 550], "pos": [1530, 100],
"size": {"0": 400, "1": 100}, "size": [400, 100],
"flags": {}, "flags": {},
"order": 7, "order": 8,
"mode": 0, "mode": 0,
"inputs": [ "inputs": [
{ {
"name": "images", "name": "images",
"type": "IMAGE", "type": "IMAGE",
"link": 10 "link": 7
} }
], ],
"properties": { "properties": {
@@ -245,49 +252,39 @@
], ],
"links": [ "links": [
[1, 1, 0, 5, 0, "MODEL"], [1, 1, 0, 5, 0, "MODEL"],
[2, 1, 1, 2, 0, "CLIP"], [2, 2, 0, 3, 0, "CLIP"],
[3, 1, 1, 3, 0, "CLIP"], [3, 3, 0, 5, 1, "CONDITIONING"],
[4, 1, 2, 6, 1, "VAE"], [4, 4, 0, 5, 3, "LATENT"],
[5, 2, 0, 5, 1, "CONDITIONING"], [5, 5, 0, 7, 0, "LATENT"],
[6, 3, 0, 5, 2, "CONDITIONING"], [6, 6, 0, 7, 1, "VAE"],
[7, 4, 0, 5, 3, "LATENT"], [7, 7, 0, 8, 0, "IMAGE"],
[8, 5, 0, 6, 0, "LATENT"], [8, 3, 0, 9, 0, "CONDITIONING"],
[9, 6, 0, 7, 0, "IMAGE"], [9, 9, 0, 5, 2, "CONDITIONING"]
[10, 6, 0, 8, 0, "IMAGE"]
], ],
"groups": [], "groups": [],
"config": {}, "config": {},
"extra": { "extra": {
"workflow_info": { "workflow_info": {
"name": "FLUX Schnell Text-to-Image Production", "name": "FLUX Schnell Text-to-Image Production",
"version": "1.0.0", "version": "1.2.0",
"author": "RunPod AI Model Orchestrator",
"description": "Fast text-to-image generation using FLUX.1-schnell (4 steps). Optimized for rapid prototyping and iteration.", "description": "Fast text-to-image generation using FLUX.1-schnell (4 steps). Optimized for rapid prototyping and iteration.",
"category": "text-to-image", "category": "text-to-image",
"tags": ["flux", "schnell", "fast", "production", "t2i"], "tags": ["flux", "schnell", "fast", "production", "t2i"],
"requirements": { "requirements": {
"models": ["FLUX.1-schnell"], "models": ["FLUX.1-schnell", "CLIP-L", "T5-XXL FP16"],
"custom_nodes": [], "custom_nodes": [],
"vram_min": "16GB", "vram_min": "16GB",
"vram_recommended": "24GB" "vram_recommended": "24GB"
}, },
"parameters": { "parameters": {
"prompt": { "prompt": {
"node_id": 2, "node_id": 3,
"widget_index": 0, "widget_index": 0,
"type": "string", "type": "string",
"required": true, "required": true,
"default": "A beautiful mountain landscape at sunset", "default": "A beautiful mountain landscape at sunset",
"description": "Text description of desired image" "description": "Text description of desired image"
}, },
"negative_prompt": {
"node_id": 3,
"widget_index": 0,
"type": "string",
"required": false,
"default": "blurry, low quality",
"description": "Undesired elements to avoid"
},
"width": { "width": {
"node_id": 4, "node_id": 4,
"widget_index": 0, "widget_index": 0,
@@ -326,17 +323,17 @@
"default": 4, "default": 4,
"min": 1, "min": 1,
"max": 10, "max": 10,
"description": "Number of sampling steps (4 recommended for Schnell)" "description": "Number of sampling steps (4 recommended for FLUX Schnell)"
}, },
"cfg": { "guidance": {
"node_id": 5, "node_id": 3,
"widget_index": 3, "widget_index": 2,
"type": "float", "type": "float",
"required": false, "required": false,
"default": 1.0, "default": 3.5,
"min": 1.0, "min": 1.0,
"max": 1.0, "max": 10.0,
"description": "Classifier-free guidance scale (1.0 for FLUX Schnell)" "description": "Guidance scale (3.5 recommended for FLUX)"
} }
}, },
"outputs": { "outputs": {
@@ -348,10 +345,18 @@
} }
}, },
"performance": { "performance": {
"avg_generation_time": "5-8 seconds", "avg_generation_time": "5-8 seconds (4 steps)",
"vram_usage": "~16GB", "vram_usage": "~16-18GB",
"gpu_utilization": "95-100%" "gpu_utilization": "95-100%"
} },
"notes": [
"FLUX uses UNETLoader instead of CheckpointLoader",
"DualCLIPLoader loads both T5-XXL and CLIP-L text encoders",
"CLIPTextEncodeFlux is FLUX-specific text encoder",
"No negative prompt for FLUX - guidance is handled differently",
"CFG scale of 1.0 recommended, guidance in text encoder",
"Schnell is optimized for 4 steps - fastest FLUX variant"
]
} }
}, },
"version": 0.4 "version": 0.4

View File

@@ -0,0 +1,408 @@
{
"last_node_id": 15,
"last_link_id": 24,
"nodes": [
{
"id": 1,
"type": "CheckpointLoaderSimple",
"pos": [50, 100],
"size": {"0": 380, "1": 100},
"flags": {},
"order": 0,
"mode": 0,
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"links": [1],
"slot_index": 0
},
{
"name": "CLIP",
"type": "CLIP",
"links": [2],
"slot_index": 1
},
{
"name": "VAE",
"type": "VAE",
"links": [3],
"slot_index": 2
}
],
"properties": {
"Node name for S&R": "CheckpointLoaderSimple"
},
"widgets_values": ["sd_xl_base_1.0.safetensors"],
"title": "Base Checkpoint Loader"
},
{
"id": 2,
"type": "LoraLoader",
"pos": [480, 100],
"size": {"0": 380, "1": 130},
"flags": {},
"order": 1,
"mode": 0,
"inputs": [
{
"name": "model",
"type": "MODEL",
"link": 1
},
{
"name": "clip",
"type": "CLIP",
"link": 2
}
],
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"links": [4],
"slot_index": 0
},
{
"name": "CLIP",
"type": "CLIP",
"links": [5],
"slot_index": 1
}
],
"properties": {
"Node name for S&R": "LoraLoader"
},
"widgets_values": ["add-detail-xl.safetensors", 0.8, 0.8],
"title": "LoRA 1 (Primary Style)"
},
{
"id": 3,
"type": "LoraLoader",
"pos": [920, 100],
"size": {"0": 380, "1": 130},
"flags": {},
"order": 2,
"mode": 0,
"inputs": [
{
"name": "model",
"type": "MODEL",
"link": 4
},
{
"name": "clip",
"type": "CLIP",
"link": 5
}
],
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"links": [6],
"slot_index": 0
},
{
"name": "CLIP",
"type": "CLIP",
"links": [7],
"slot_index": 1
}
],
"properties": {
"Node name for S&R": "LoraLoader"
},
"widgets_values": ["add-detail-xl.safetensors", 0.5, 0.5],
"title": "LoRA 2 (Secondary Style)"
},
{
"id": 4,
"type": "LoraLoader",
"pos": [1360, 100],
"size": {"0": 380, "1": 130},
"flags": {},
"order": 3,
"mode": 0,
"inputs": [
{
"name": "model",
"type": "MODEL",
"link": 6
},
{
"name": "clip",
"type": "CLIP",
"link": 7
}
],
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"links": [8],
"slot_index": 0
},
{
"name": "CLIP",
"type": "CLIP",
"links": [9, 10],
"slot_index": 1
}
],
"properties": {
"Node name for S&R": "LoraLoader"
},
"widgets_values": ["add-detail-xl.safetensors", 0.3, 0.3],
"title": "LoRA 3 (Accent/Detail)"
},
{
"id": 5,
"type": "CLIPTextEncode",
"pos": [50, 280],
"size": {"0": 450, "1": 250},
"flags": {},
"order": 4,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 9
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"links": [11],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": ["A beautiful scenic landscape with mountains, vibrant colors, detailed, high quality, masterpiece, best quality, 8k"],
"title": "API Positive Prompt"
},
{
"id": 6,
"type": "CLIPTextEncode",
"pos": [50, 580],
"size": {"0": 450, "1": 150},
"flags": {},
"order": 5,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 10
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"links": [12],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": ["(worst quality, low quality:1.4), bad anatomy, deformed, blurry, watermark, text"],
"title": "Negative Prompt"
},
{
"id": 7,
"type": "EmptyLatentImage",
"pos": [560, 580],
"size": {"0": 315, "1": 110},
"flags": {},
"order": 6,
"mode": 0,
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"links": [13],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "EmptyLatentImage"
},
"widgets_values": [1024, 1024, 1],
"title": "Latent Image (SDXL Resolution)"
},
{
"id": 8,
"type": "KSampler",
"pos": [920, 280],
"size": {"0": 350, "1": 290},
"flags": {},
"order": 7,
"mode": 0,
"inputs": [
{
"name": "model",
"type": "MODEL",
"link": 8
},
{
"name": "positive",
"type": "CONDITIONING",
"link": 11
},
{
"name": "negative",
"type": "CONDITIONING",
"link": 12
},
{
"name": "latent_image",
"type": "LATENT",
"link": 13
}
],
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"links": [14],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "KSampler"
},
"widgets_values": [
0,
"randomize",
30,
7.0,
"dpmpp_2m_sde",
"karras",
1.0
],
"title": "KSampler (Standard Settings)"
},
{
"id": 9,
"type": "VAEDecode",
"pos": [1320, 280],
"size": {"0": 210, "1": 50},
"flags": {},
"order": 8,
"mode": 0,
"inputs": [
{
"name": "samples",
"type": "LATENT",
"link": 14
},
{
"name": "vae",
"type": "VAE",
"link": 3
}
],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [15],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "VAEDecode"
},
"title": "VAE Decode"
},
{
"id": 10,
"type": "SaveImage",
"pos": [1580, 280],
"size": {"0": 320, "1": 290},
"flags": {},
"order": 9,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 15
}
],
"properties": {
"Node name for S&R": "SaveImage"
},
"widgets_values": ["lora_fusion"],
"title": "API Output Image"
}
],
"links": [
[1, 1, 0, 2, 0, "MODEL"],
[2, 1, 1, 2, 1, "CLIP"],
[3, 1, 2, 9, 1, "VAE"],
[4, 2, 0, 3, 0, "MODEL"],
[5, 2, 1, 3, 1, "CLIP"],
[6, 3, 0, 4, 0, "MODEL"],
[7, 3, 1, 4, 1, "CLIP"],
[8, 4, 0, 8, 0, "MODEL"],
[9, 4, 1, 5, 0, "CLIP"],
[10, 4, 1, 6, 0, "CLIP"],
[11, 5, 0, 8, 1, "CONDITIONING"],
[12, 6, 0, 8, 2, "CONDITIONING"],
[13, 7, 0, 8, 3, "LATENT"],
[14, 8, 0, 9, 0, "LATENT"],
[15, 9, 0, 10, 0, "IMAGE"]
],
"groups": [],
"config": {},
"extra": {
"workflow_info": {
"name": "LoRA Fusion Multi-Stack Text-to-Image",
"version": "1.0",
"description": "Production workflow for combining multiple LoRA models with adjustable weights. Stack up to 3 LoRAs with fine-tuned strength control for style mixing and enhancement. Works with any SDXL checkpoint including NSFW models.",
"category": "text-to-image",
"features": [
"Triple LoRA stacking with independent weight control",
"Compatible with any SDXL checkpoint (SFW/NSFW)",
"Hierarchical strength: Primary (0.7-1.0), Secondary (0.4-0.7), Accent (0.2-0.5)",
"Supports style LoRAs, detail enhancers, and character LoRAs",
"Easy to disable individual LoRAs by setting weights to 0.0"
],
"recommended_usage": {
"lora_1_strength": "0.7-1.0 (primary style influence)",
"lora_2_strength": "0.4-0.7 (secondary style blend)",
"lora_3_strength": "0.2-0.5 (subtle accent/details)",
"disable_lora": "Set both model and clip weights to 0.0"
},
"examples": [
{
"use_case": "Portrait Enhancement",
"lora_1": "Detail enhancer (0.8)",
"lora_2": "Skin texture LoRA (0.5)",
"lora_3": "Lighting style (0.3)"
},
{
"use_case": "Artistic Style Fusion",
"lora_1": "Primary art style (1.0)",
"lora_2": "Secondary style blend (0.6)",
"lora_3": "Color grading (0.4)"
},
{
"use_case": "Character + Style",
"lora_1": "Character LoRA (0.9)",
"lora_2": "Pose/anatomy enhancer (0.5)",
"lora_3": "Background style (0.3)"
}
],
"tags": ["lora", "multi-stack", "fusion", "style-mixing", "enhancement", "sdxl"]
}
},
"version": 0.4
}

View File

@@ -1,12 +1,12 @@
{ {
"last_node_id": 12, "last_node_id": 9,
"last_link_id": 15, "last_link_id": 10,
"nodes": [ "nodes": [
{ {
"id": 1, "id": 1,
"type": "CheckpointLoaderSimple", "type": "CheckpointLoaderSimple",
"pos": [50, 100], "pos": [50, 100],
"size": {"0": 350, "1": 100}, "size": [350, 100],
"flags": {}, "flags": {},
"order": 0, "order": 0,
"mode": 0, "mode": 0,
@@ -20,8 +20,7 @@
{ {
"name": "CLIP", "name": "CLIP",
"type": "CLIP", "type": "CLIP",
"links": [2, 3], "links": null
"slot_index": 1
}, },
{ {
"name": "VAE", "name": "VAE",
@@ -33,22 +32,44 @@
"properties": { "properties": {
"Node name for S&R": "CheckpointLoaderSimple" "Node name for S&R": "CheckpointLoaderSimple"
}, },
"widgets_values": ["diffusers/stable-diffusion-3.5-large"], "widgets_values": ["sd3.5_large.safetensors"],
"title": "SD3.5 Large Checkpoint Loader" "title": "SD3.5 Large Checkpoint Loader"
}, },
{
"id": 9,
"type": "TripleCLIPLoader",
"pos": [50, 250],
"size": [350, 150],
"flags": {},
"order": 1,
"mode": 0,
"outputs": [
{
"name": "CLIP",
"type": "CLIP",
"links": [9, 10],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "TripleCLIPLoader"
},
"widgets_values": ["clip_l.safetensors", "clip_g.safetensors", "t5xxl_fp16.safetensors"],
"title": "SD3.5 CLIP Loaders (L+G+T5)"
},
{ {
"id": 2, "id": 2,
"type": "CLIPTextEncode", "type": "CLIPTextEncode",
"pos": [450, 100], "pos": [450, 100],
"size": {"0": 400, "1": 200}, "size": [400, 200],
"flags": {}, "flags": {},
"order": 1, "order": 2,
"mode": 0, "mode": 0,
"inputs": [ "inputs": [
{ {
"name": "clip", "name": "clip",
"type": "CLIP", "type": "CLIP",
"link": 2 "link": 9
} }
], ],
"outputs": [ "outputs": [
@@ -69,15 +90,15 @@
"id": 3, "id": 3,
"type": "CLIPTextEncode", "type": "CLIPTextEncode",
"pos": [450, 350], "pos": [450, 350],
"size": {"0": 400, "1": 200}, "size": [400, 200],
"flags": {}, "flags": {},
"order": 2, "order": 3,
"mode": 0, "mode": 0,
"inputs": [ "inputs": [
{ {
"name": "clip", "name": "clip",
"type": "CLIP", "type": "CLIP",
"link": 3 "link": 10
} }
], ],
"outputs": [ "outputs": [
@@ -98,9 +119,9 @@
"id": 4, "id": 4,
"type": "EmptyLatentImage", "type": "EmptyLatentImage",
"pos": [450, 600], "pos": [450, 600],
"size": {"0": 315, "1": 106}, "size": [315, 106],
"flags": {}, "flags": {},
"order": 3, "order": 4,
"mode": 0, "mode": 0,
"outputs": [ "outputs": [
{ {
@@ -120,9 +141,9 @@
"id": 5, "id": 5,
"type": "KSampler", "type": "KSampler",
"pos": [900, 100], "pos": [900, 100],
"size": {"0": 315, "1": 474}, "size": [315, 474],
"flags": {}, "flags": {},
"order": 4, "order": 5,
"mode": 0, "mode": 0,
"inputs": [ "inputs": [
{ {
@@ -157,24 +178,16 @@
"properties": { "properties": {
"Node name for S&R": "KSampler" "Node name for S&R": "KSampler"
}, },
"widgets_values": [ "widgets_values": [42, "fixed", 28, 4.5, "dpmpp_2m", "karras", 1],
42,
"fixed",
28,
4.5,
"dpmpp_2m",
"karras",
1
],
"title": "SD3.5 Sampler (28 steps)" "title": "SD3.5 Sampler (28 steps)"
}, },
{ {
"id": 6, "id": 6,
"type": "VAEDecode", "type": "VAEDecode",
"pos": [1270, 100], "pos": [1270, 100],
"size": {"0": 210, "1": 46}, "size": [210, 46],
"flags": {}, "flags": {},
"order": 5, "order": 6,
"mode": 0, "mode": 0,
"inputs": [ "inputs": [
{ {
@@ -192,7 +205,7 @@
{ {
"name": "IMAGE", "name": "IMAGE",
"type": "IMAGE", "type": "IMAGE",
"links": [9, 10], "links": [2, 3],
"slot_index": 0 "slot_index": 0
} }
], ],
@@ -205,15 +218,15 @@
"id": 7, "id": 7,
"type": "PreviewImage", "type": "PreviewImage",
"pos": [1530, 100], "pos": [1530, 100],
"size": {"0": 400, "1": 400}, "size": [400, 400],
"flags": {}, "flags": {},
"order": 6, "order": 7,
"mode": 0, "mode": 0,
"inputs": [ "inputs": [
{ {
"name": "images", "name": "images",
"type": "IMAGE", "type": "IMAGE",
"link": 9 "link": 2
} }
], ],
"properties": { "properties": {
@@ -225,15 +238,15 @@
"id": 8, "id": 8,
"type": "SaveImage", "type": "SaveImage",
"pos": [1530, 550], "pos": [1530, 550],
"size": {"0": 400, "1": 100}, "size": [400, 100],
"flags": {}, "flags": {},
"order": 7, "order": 8,
"mode": 0, "mode": 0,
"inputs": [ "inputs": [
{ {
"name": "images", "name": "images",
"type": "IMAGE", "type": "IMAGE",
"link": 10 "link": 3
} }
], ],
"properties": { "properties": {
@@ -245,28 +258,27 @@
], ],
"links": [ "links": [
[1, 1, 0, 5, 0, "MODEL"], [1, 1, 0, 5, 0, "MODEL"],
[2, 1, 1, 2, 0, "CLIP"], [2, 6, 0, 7, 0, "IMAGE"],
[3, 1, 1, 3, 0, "CLIP"], [3, 6, 0, 8, 0, "IMAGE"],
[4, 1, 2, 6, 1, "VAE"], [4, 1, 2, 6, 1, "VAE"],
[5, 2, 0, 5, 1, "CONDITIONING"], [5, 2, 0, 5, 1, "CONDITIONING"],
[6, 3, 0, 5, 2, "CONDITIONING"], [6, 3, 0, 5, 2, "CONDITIONING"],
[7, 4, 0, 5, 3, "LATENT"], [7, 4, 0, 5, 3, "LATENT"],
[8, 5, 0, 6, 0, "LATENT"], [8, 5, 0, 6, 0, "LATENT"],
[9, 6, 0, 7, 0, "IMAGE"], [9, 9, 0, 2, 0, "CLIP"],
[10, 6, 0, 8, 0, "IMAGE"] [10, 9, 0, 3, 0, "CLIP"]
], ],
"groups": [], "groups": [],
"config": {}, "config": {},
"extra": { "extra": {
"workflow_info": { "workflow_info": {
"name": "Stable Diffusion 3.5 Large Text-to-Image Production", "name": "Stable Diffusion 3.5 Large Text-to-Image Production",
"version": "1.0.0", "version": "1.2.0",
"author": "RunPod AI Model Orchestrator",
"description": "Latest generation text-to-image using Stable Diffusion 3.5 Large (28 steps). Provides excellent photorealism and prompt adherence.", "description": "Latest generation text-to-image using Stable Diffusion 3.5 Large (28 steps). Provides excellent photorealism and prompt adherence.",
"category": "text-to-image", "category": "text-to-image",
"tags": ["sd3.5", "stable-diffusion", "large", "production", "t2i", "photorealistic"], "tags": ["sd3.5", "stable-diffusion", "large", "production", "t2i", "photorealistic"],
"requirements": { "requirements": {
"models": ["stable-diffusion-3.5-large"], "models": ["SD3.5-large", "CLIP-L", "CLIP-G", "T5-XXL FP16"],
"custom_nodes": [], "custom_nodes": [],
"vram_min": "18GB", "vram_min": "18GB",
"vram_recommended": "24GB" "vram_recommended": "24GB"
@@ -351,7 +363,13 @@
"avg_generation_time": "35-45 seconds", "avg_generation_time": "35-45 seconds",
"vram_usage": "~18-20GB", "vram_usage": "~18-20GB",
"gpu_utilization": "95-100%" "gpu_utilization": "95-100%"
} },
"notes": [
"SD3.5 uses CheckpointLoaderSimple for MODEL+VAE",
"TripleCLIPLoader loads CLIP-L, CLIP-G, and T5-XXL separately",
"Checkpoint file doesn't include CLIP encoders",
"All three CLIP encoders required for best quality"
]
} }
}, },
"version": 0.4 "version": 0.4

View File

@@ -33,7 +33,7 @@
"properties": { "properties": {
"Node name for S&R": "CheckpointLoaderSimple" "Node name for S&R": "CheckpointLoaderSimple"
}, },
"widgets_values": ["diffusers/stable-diffusion-xl-base-1.0"], "widgets_values": ["sd_xl_base_1.0.safetensors"],
"title": "SDXL Base Checkpoint Loader" "title": "SDXL Base Checkpoint Loader"
}, },
{ {
@@ -67,7 +67,7 @@
"properties": { "properties": {
"Node name for S&R": "CheckpointLoaderSimple" "Node name for S&R": "CheckpointLoaderSimple"
}, },
"widgets_values": ["diffusers/stable-diffusion-xl-refiner-1.0"], "widgets_values": ["sd_xl_refiner_1.0.safetensors"],
"title": "SDXL Refiner Checkpoint Loader" "title": "SDXL Refiner Checkpoint Loader"
}, },
{ {

View File

@@ -0,0 +1,865 @@
{
"id": "88ac5dad-efd7-40bb-84fe-fbaefdee1fa9",
"revision": 0,
"last_node_id": 75,
"last_link_id": 138,
"nodes": [
{
"id": 49,
"type": "LatentApplyOperationCFG",
"pos": [
940,
-160
],
"size": [
290,
50
],
"flags": {
"collapsed": false
},
"order": 10,
"mode": 0,
"inputs": [
{
"name": "model",
"type": "MODEL",
"link": 113
},
{
"name": "operation",
"type": "LATENT_OPERATION",
"link": 114
}
],
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"links": [
121
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.34",
"Node name for S&R": "LatentApplyOperationCFG"
},
"widgets_values": []
},
{
"id": 40,
"type": "CheckpointLoaderSimple",
"pos": [
180,
-160
],
"size": [
370,
98
],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"links": [
115
]
},
{
"name": "CLIP",
"type": "CLIP",
"links": [
80
]
},
{
"name": "VAE",
"type": "VAE",
"links": [
83,
137
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.32",
"Node name for S&R": "CheckpointLoaderSimple",
"models": [
{
"name": "ace_step_v1_3.5b.safetensors",
"url": "https://huggingface.co/Comfy-Org/ACE-Step_ComfyUI_repackaged/resolve/main/all_in_one/ace_step_v1_3.5b.safetensors?download=true",
"directory": "checkpoints"
}
]
},
"widgets_values": [
"ace_step_v1_3.5b.safetensors"
],
"color": "#322",
"bgcolor": "#533"
},
{
"id": 48,
"type": "MarkdownNote",
"pos": [
-460,
-200
],
"size": [
610,
820
],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [],
"outputs": [],
"title": "About ACE Step and Multi-language Input",
"properties": {},
"widgets_values": [
"[Tutorial](http://docs.comfy.org/tutorials/audio/ace-step/ace-step-v1) | [教程](http://docs.comfy.org/zh-CN/tutorials/audio/ace-step/ace-step-v1)\n\n\n### Model Download\n\nDownload the following model and save it to the **ComfyUI/models/checkpoints** folder.\n[ace_step_v1_3.5b.safetensors](https://huggingface.co/Comfy-Org/ACE-Step_ComfyUI_repackaged/blob/main/all_in_one/ace_step_v1_3.5b.safetensors)\n\n\n### Multilingual Support\n\nCurrently, the implementation of multi-language support for ACE-Step V1 is achieved by uniformly converting different languages into English characters. At present, in ComfyUI, we haven't implemented the step of converting multi-languages into English. This is because if we need to implement the corresponding conversion, we have to add additional core dependencies of ComfyUI, which may lead to uncertain dependency conflicts.\n\nSo, currently, if you need to input multi-language text, you have to manually convert it into English characters to complete this process. Then, at the beginning of the corresponding `lyrics`, input the abbreviation of the corresponding language code.\n\nFor example, for Chinese, use `[zh]`, for Japanese use `[ja]`, for Korean use `[ko]`, and so on. For specific language input, please check the examples in the instructions. \n\nFor example, Chinese `[zh]`, Japanese `[ja]`, Korean `[ko]`, etc.\n\nExample:\n\n```\n[verse]\n\n[zh]wo3zou3guo4shen1ye4de5jie1dao4\n[zh]leng3feng1chui1luan4si1nian4de5piao4liang4wai4tao4\n[zh]ni3de5wei1xiao4xiang4xing1guang1hen3xuan4yao4\n[zh]zhao4liang4le5wo3gu1du2de5mei3fen1mei3miao3\n\n[chorus]\n\n[verse]\n[ko]hamkke si-kkeuleo-un sesang-ui sodong-eul pihae\n[ko]honja ogsang-eseo dalbich-ui eolyeompus-ileul balaboda\n[ko]niga salang-eun lideum-i ganghan eum-ag gatdago malhaess-eo\n[ko]han ta han tamada ma-eum-ui ondoga eolmana heojeonhanji ijge hae\n\n[bridge]\n[es]cantar mi anhelo por ti sin ocultar\n[es]como poesía y pintura, lleno de anhelo indescifrable\n[es]tu sombra es tan terca como el viento, inborrable\n[es]persiguiéndote en vuelo, brilla como cruzar una mar de nubes\n\n[chorus]\n[fr]que tu sois le vent qui souffle sur ma main\n[fr]un contact chaud comme la douce pluie printanière\n[fr]que tu sois le vent qui s'entoure de mon corps\n[fr]un amour profond qui ne s'éloignera jamais\n\n```\n\n---\n\n### 模型下载\n\n下载下面的模型并保存到 **ComfyUI/models/checkpoints** 文件夹下\n[ace_step_v1_3.5b.safetensors](https://huggingface.co/Comfy-Org/ACE-Step_ComfyUI_repackaged/blob/main/all_in_one/ace_step_v1_3.5b.safetensors)\n\n\n### 多语言支持\n\n目前 ACE-Step V1 多语言的实现是通过将不同语言统一转换为英文字符来实现的,目前在 ComfyUI 中我们并没有实现多语言转换为英文的这一步骤。因为如果需要实现对应转换,则需要增加额外的 ComfyUI 核心依赖,这将可能带来不确定的依赖冲突。\n\n所以目前如果你需要输入多语言则需要手动转换为英文字符来实现这一过程然后在对应 `lyrics` 开头输入对应语言代码的缩写。\n\n比如中文`[zh]` 日语 `[ja]` 韩语 `[ko]` 等,具体语言输入请查看说明中的示例\n\n"
],
"color": "#432",
"bgcolor": "#653"
},
{
"id": 18,
"type": "VAEDecodeAudio",
"pos": [
1080,
270
],
"size": [
150.93612670898438,
46
],
"flags": {
"collapsed": false
},
"order": 13,
"mode": 0,
"inputs": [
{
"name": "samples",
"type": "LATENT",
"link": 122
},
{
"name": "vae",
"type": "VAE",
"link": 83
}
],
"outputs": [
{
"name": "AUDIO",
"type": "AUDIO",
"links": [
126,
127,
128
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.32",
"Node name for S&R": "VAEDecodeAudio"
},
"widgets_values": []
},
{
"id": 60,
"type": "SaveAudio",
"pos": [
1260,
40
],
"size": [
610,
112
],
"flags": {},
"order": 15,
"mode": 4,
"inputs": [
{
"name": "audio",
"type": "AUDIO",
"link": 127
}
],
"outputs": [],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.34",
"Node name for S&R": "SaveAudio"
},
"widgets_values": [
"audio/ComfyUI"
]
},
{
"id": 61,
"type": "SaveAudioOpus",
"pos": [
1260,
220
],
"size": [
610,
136
],
"flags": {},
"order": 16,
"mode": 4,
"inputs": [
{
"name": "audio",
"type": "AUDIO",
"link": 128
}
],
"outputs": [],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.34",
"Node name for S&R": "SaveAudioOpus"
},
"widgets_values": [
"audio/ComfyUI",
"128k"
]
},
{
"id": 44,
"type": "ConditioningZeroOut",
"pos": [
600,
70
],
"size": [
197.712890625,
26
],
"flags": {
"collapsed": true
},
"order": 11,
"mode": 0,
"inputs": [
{
"name": "conditioning",
"type": "CONDITIONING",
"link": 108
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"links": [
120
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.32",
"Node name for S&R": "ConditioningZeroOut"
},
"widgets_values": []
},
{
"id": 51,
"type": "ModelSamplingSD3",
"pos": [
590,
-40
],
"size": [
330,
60
],
"flags": {
"collapsed": false
},
"order": 7,
"mode": 0,
"inputs": [
{
"name": "model",
"type": "MODEL",
"link": 115
}
],
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"links": [
113
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.34",
"Node name for S&R": "ModelSamplingSD3"
},
"widgets_values": [
5.000000000000001
]
},
{
"id": 50,
"type": "LatentOperationTonemapReinhard",
"pos": [
590,
-160
],
"size": [
330,
58
],
"flags": {},
"order": 2,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "LATENT_OPERATION",
"type": "LATENT_OPERATION",
"links": [
114
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.34",
"Node name for S&R": "LatentOperationTonemapReinhard"
},
"widgets_values": [
1.0000000000000002
]
},
{
"id": 17,
"type": "EmptyAceStepLatentAudio",
"pos": [
180,
50
],
"size": [
370,
82
],
"flags": {},
"order": 3,
"mode": 4,
"inputs": [],
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"links": []
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.32",
"Node name for S&R": "EmptyAceStepLatentAudio"
},
"widgets_values": [
120,
1
]
},
{
"id": 68,
"type": "VAEEncodeAudio",
"pos": [
180,
180
],
"size": [
370,
46
],
"flags": {},
"order": 9,
"mode": 0,
"inputs": [
{
"name": "audio",
"type": "AUDIO",
"link": 136
},
{
"name": "vae",
"type": "VAE",
"link": 137
}
],
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"links": [
138
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.34",
"Node name for S&R": "VAEEncodeAudio"
},
"widgets_values": []
},
{
"id": 64,
"type": "LoadAudio",
"pos": [
180,
340
],
"size": [
370,
140
],
"flags": {},
"order": 4,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "AUDIO",
"type": "AUDIO",
"links": [
136
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.34",
"Node name for S&R": "LoadAudio"
},
"widgets_values": [
"audio_ace_step_1_t2a_song-1.mp3",
null,
null
],
"color": "#322",
"bgcolor": "#533"
},
{
"id": 52,
"type": "KSampler",
"pos": [
940,
-40
],
"size": [
290,
262
],
"flags": {},
"order": 12,
"mode": 0,
"inputs": [
{
"name": "model",
"type": "MODEL",
"link": 121
},
{
"name": "positive",
"type": "CONDITIONING",
"link": 117
},
{
"name": "negative",
"type": "CONDITIONING",
"link": 120
},
{
"name": "latent_image",
"type": "LATENT",
"link": 138
}
],
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"slot_index": 0,
"links": [
122
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.34",
"Node name for S&R": "KSampler"
},
"widgets_values": [
938549746349002,
"randomize",
50,
5,
"euler",
"simple",
0.30000000000000004
]
},
{
"id": 59,
"type": "SaveAudioMP3",
"pos": [
1260,
-160
],
"size": [
610,
136
],
"flags": {},
"order": 14,
"mode": 0,
"inputs": [
{
"name": "audio",
"type": "AUDIO",
"link": 126
}
],
"outputs": [],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.34",
"Node name for S&R": "SaveAudioMP3"
},
"widgets_values": [
"audio/ComfyUI",
"V0"
]
},
{
"id": 73,
"type": "Note",
"pos": [
1260,
410
],
"size": [
610,
90
],
"flags": {},
"order": 5,
"mode": 0,
"inputs": [],
"outputs": [],
"properties": {},
"widgets_values": [
"These nodes can save audio in different formats. Currently, all the modes are Bypass. You can enable them as per your needs.\n\n这些节点可以将 audio 保存成不同格式,目前的模式都是 Bypass ,你可以按你的需要来启用"
],
"color": "#432",
"bgcolor": "#653"
},
{
"id": 14,
"type": "TextEncodeAceStepAudio",
"pos": [
590,
120
],
"size": [
340,
500
],
"flags": {},
"order": 8,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 80
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"links": [
108,
117
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.32",
"Node name for S&R": "TextEncodeAceStepAudio"
},
"widgets_values": [
"anime, cute female vocals, kawaii pop, j-pop, childish, piano, guitar, synthesizer, fast, happy, cheerful, lighthearted",
"[verse]\nフワフワ オミミガ\nユレルヨ カゼナカ\nキラキラ アオイメ\nミツメル セカイヲ\n\n[verse]\nフワフワ シッポハ\nオオキク ユレルヨ\nキンイロ カミケ\nナビクヨ カゼナカ\n\n[verse]\nコンフィーユーアイ\nマモリビト\nピンク セーターデ\nエガオヲ クレルヨ\n\nアオイロ スカートト\nクロイコート キンモヨウ\nヤサシイ ヒカリガ\nツツムヨ フェネックガール\n\n[verse]\nフワフワ オミミデ\nキコエル ココロ コエ\nダイスキ フェネックガール\nイツデモ ソバニイルヨ",
0.9900000000000002
]
},
{
"id": 75,
"type": "MarkdownNote",
"pos": [
950,
410
],
"size": [
280,
210
],
"flags": {},
"order": 6,
"mode": 0,
"inputs": [],
"outputs": [],
"title": "About Repainting",
"properties": {},
"widgets_values": [
"Providing the lyrics of the original song or the modified lyrics is very important for the output of repainting or editing. \n\nAdjust the value of the **denoise** parameter in KSampler. The larger the value, the lower the similarity between the output audio and the original audio.\n\n提供原始歌曲的歌词或者修改后的歌词对于音频编辑的输出是非常重要的调整 KSampler 中的 denoise 参数的数值,数值越大输出的音频与原始音频相似度越低"
],
"color": "#432",
"bgcolor": "#653"
}
],
"links": [
[
80,
40,
1,
14,
0,
"CLIP"
],
[
83,
40,
2,
18,
1,
"VAE"
],
[
108,
14,
0,
44,
0,
"CONDITIONING"
],
[
113,
51,
0,
49,
0,
"MODEL"
],
[
114,
50,
0,
49,
1,
"LATENT_OPERATION"
],
[
115,
40,
0,
51,
0,
"MODEL"
],
[
117,
14,
0,
52,
1,
"CONDITIONING"
],
[
120,
44,
0,
52,
2,
"CONDITIONING"
],
[
121,
49,
0,
52,
0,
"MODEL"
],
[
122,
52,
0,
18,
0,
"LATENT"
],
[
126,
18,
0,
59,
0,
"AUDIO"
],
[
127,
18,
0,
60,
0,
"AUDIO"
],
[
128,
18,
0,
61,
0,
"AUDIO"
],
[
136,
64,
0,
68,
0,
"AUDIO"
],
[
137,
40,
2,
68,
1,
"VAE"
],
[
138,
68,
0,
52,
3,
"LATENT"
]
],
"groups": [
{
"id": 1,
"title": "Load model here",
"bounding": [
170,
-230,
390,
180
],
"color": "#3f789e",
"font_size": 24,
"flags": {}
},
{
"id": 4,
"title": "Latent",
"bounding": [
170,
-30,
390,
280
],
"color": "#3f789e",
"font_size": 24,
"flags": {}
},
{
"id": 5,
"title": "Adjust the vocal volume",
"bounding": [
580,
-230,
350,
140
],
"color": "#3f789e",
"font_size": 24,
"flags": {}
},
{
"id": 6,
"title": "For repainting",
"bounding": [
170,
270,
390,
223.60000610351562
],
"color": "#3f789e",
"font_size": 24,
"flags": {}
},
{
"id": 7,
"title": "Output",
"bounding": [
1250,
-230,
630,
760
],
"color": "#3f789e",
"font_size": 24,
"flags": {}
}
],
"config": {},
"extra": {
"ds": {
"scale": 0.6830134553650705,
"offset": [
785.724285521853,
434.02395631202546
]
},
"frontendVersion": "1.19.9",
"node_versions": {
"comfy-core": "0.3.34",
"ace-step": "06f751d65491c9077fa2bc9b06d2c6f2a90e4c56"
},
"VHS_latentpreview": false,
"VHS_latentpreviewrate": 0,
"VHS_MetadataImage": true,
"VHS_KeepIntermediate": true
},
"version": 0.4
}

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,841 @@
{
"id": "88ac5dad-efd7-40bb-84fe-fbaefdee1fa9",
"revision": 0,
"last_node_id": 73,
"last_link_id": 137,
"nodes": [
{
"id": 49,
"type": "LatentApplyOperationCFG",
"pos": [
940,
-160
],
"size": [
290,
50
],
"flags": {
"collapsed": false
},
"order": 9,
"mode": 0,
"inputs": [
{
"name": "model",
"type": "MODEL",
"link": 113
},
{
"name": "operation",
"type": "LATENT_OPERATION",
"link": 114
}
],
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"links": [
121
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.34",
"Node name for S&R": "LatentApplyOperationCFG"
},
"widgets_values": []
},
{
"id": 64,
"type": "LoadAudio",
"pos": [
180,
340
],
"size": [
370,
140
],
"flags": {},
"order": 0,
"mode": 4,
"inputs": [],
"outputs": [
{
"name": "AUDIO",
"type": "AUDIO",
"links": [
136
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.34",
"Node name for S&R": "LoadAudio"
},
"widgets_values": [
"ace_step_example.flac",
null,
null
],
"color": "#322",
"bgcolor": "#533"
},
{
"id": 68,
"type": "VAEEncodeAudio",
"pos": [
180,
180
],
"size": [
370,
46
],
"flags": {},
"order": 8,
"mode": 4,
"inputs": [
{
"name": "audio",
"type": "AUDIO",
"link": 136
},
{
"name": "vae",
"type": "VAE",
"link": 137
}
],
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"links": null
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.34",
"Node name for S&R": "VAEEncodeAudio"
},
"widgets_values": []
},
{
"id": 40,
"type": "CheckpointLoaderSimple",
"pos": [
180,
-160
],
"size": [
370,
98
],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"links": [
115
]
},
{
"name": "CLIP",
"type": "CLIP",
"links": [
80
]
},
{
"name": "VAE",
"type": "VAE",
"links": [
83,
137
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.32",
"Node name for S&R": "CheckpointLoaderSimple",
"models": [
{
"name": "ace_step_v1_3.5b.safetensors",
"url": "https://huggingface.co/Comfy-Org/ACE-Step_ComfyUI_repackaged/resolve/main/all_in_one/ace_step_v1_3.5b.safetensors?download=true",
"directory": "checkpoints"
}
]
},
"widgets_values": [
"ace_step_v1_3.5b.safetensors"
],
"color": "#322",
"bgcolor": "#533"
},
{
"id": 48,
"type": "MarkdownNote",
"pos": [
-460,
-200
],
"size": [
610,
820
],
"flags": {},
"order": 2,
"mode": 0,
"inputs": [],
"outputs": [],
"title": "About ACE Step and Multi-language Input",
"properties": {},
"widgets_values": [
"[Tutorial](http://docs.comfy.org/tutorials/audio/ace-step/ace-step-v1) | [教程](http://docs.comfy.org/zh-CN/tutorials/audio/ace-step/ace-step-v1)\n\n\n### Model Download\n\nDownload the following model and save it to the **ComfyUI/models/checkpoints** folder.\n[ace_step_v1_3.5b.safetensors](https://huggingface.co/Comfy-Org/ACE-Step_ComfyUI_repackaged/blob/main/all_in_one/ace_step_v1_3.5b.safetensors)\n\n\n### Multilingual Support\n\nCurrently, the implementation of multi-language support for ACE-Step V1 is achieved by uniformly converting different languages into English characters. At present, in ComfyUI, we haven't implemented the step of converting multi-languages into English. This is because if we need to implement the corresponding conversion, we have to add additional core dependencies of ComfyUI, which may lead to uncertain dependency conflicts.\n\nSo, currently, if you need to input multi-language text, you have to manually convert it into English characters to complete this process. Then, at the beginning of the corresponding `lyrics`, input the abbreviation of the corresponding language code.\n\nFor example, for Chinese, use `[zh]`, for Japanese use `[ja]`, for Korean use `[ko]`, and so on. For specific language input, please check the examples in the instructions. \n\nFor example, Chinese `[zh]`, Japanese `[ja]`, Korean `[ko]`, etc.\n\nExample:\n\n```\n[verse]\n\n[zh]wo3zou3guo4shen1ye4de5jie1dao4\n[zh]leng3feng1chui1luan4si1nian4de5piao4liang4wai4tao4\n[zh]ni3de5wei1xiao4xiang4xing1guang1hen3xuan4yao4\n[zh]zhao4liang4le5wo3gu1du2de5mei3fen1mei3miao3\n\n[chorus]\n\n[verse]\n[ko]hamkke si-kkeuleo-un sesang-ui sodong-eul pihae\n[ko]honja ogsang-eseo dalbich-ui eolyeompus-ileul balaboda\n[ko]niga salang-eun lideum-i ganghan eum-ag gatdago malhaess-eo\n[ko]han ta han tamada ma-eum-ui ondoga eolmana heojeonhanji ijge hae\n\n[bridge]\n[es]cantar mi anhelo por ti sin ocultar\n[es]como poesía y pintura, lleno de anhelo indescifrable\n[es]tu sombra es tan terca como el viento, inborrable\n[es]persiguiéndote en vuelo, brilla como cruzar una mar de nubes\n\n[chorus]\n[fr]que tu sois le vent qui souffle sur ma main\n[fr]un contact chaud comme la douce pluie printanière\n[fr]que tu sois le vent qui s'entoure de mon corps\n[fr]un amour profond qui ne s'éloignera jamais\n\n```\n\n---\n\n### 模型下载\n\n下载下面的模型并保存到 **ComfyUI/models/checkpoints** 文件夹下\n[ace_step_v1_3.5b.safetensors](https://huggingface.co/Comfy-Org/ACE-Step_ComfyUI_repackaged/blob/main/all_in_one/ace_step_v1_3.5b.safetensors)\n\n\n### 多语言支持\n\n目前 ACE-Step V1 多语言的实现是通过将不同语言统一转换为英文字符来实现的,目前在 ComfyUI 中我们并没有实现多语言转换为英文的这一步骤。因为如果需要实现对应转换,则需要增加额外的 ComfyUI 核心依赖,这将可能带来不确定的依赖冲突。\n\n所以目前如果你需要输入多语言则需要手动转换为英文字符来实现这一过程然后在对应 `lyrics` 开头输入对应语言代码的缩写。\n\n比如中文`[zh]` 日语 `[ja]` 韩语 `[ko]` 等,具体语言输入请查看说明中的示例\n\n"
],
"color": "#432",
"bgcolor": "#653"
},
{
"id": 18,
"type": "VAEDecodeAudio",
"pos": [
1080,
270
],
"size": [
150.93612670898438,
46
],
"flags": {
"collapsed": false
},
"order": 12,
"mode": 0,
"inputs": [
{
"name": "samples",
"type": "LATENT",
"link": 122
},
{
"name": "vae",
"type": "VAE",
"link": 83
}
],
"outputs": [
{
"name": "AUDIO",
"type": "AUDIO",
"links": [
126,
127,
128
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.32",
"Node name for S&R": "VAEDecodeAudio"
},
"widgets_values": []
},
{
"id": 60,
"type": "SaveAudio",
"pos": [
1260,
40
],
"size": [
610,
112
],
"flags": {},
"order": 14,
"mode": 4,
"inputs": [
{
"name": "audio",
"type": "AUDIO",
"link": 127
}
],
"outputs": [],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.34",
"Node name for S&R": "SaveAudio"
},
"widgets_values": [
"audio/ComfyUI"
]
},
{
"id": 61,
"type": "SaveAudioOpus",
"pos": [
1260,
220
],
"size": [
610,
136
],
"flags": {},
"order": 15,
"mode": 4,
"inputs": [
{
"name": "audio",
"type": "AUDIO",
"link": 128
}
],
"outputs": [],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.34",
"Node name for S&R": "SaveAudioOpus"
},
"widgets_values": [
"audio/ComfyUI",
"128k"
]
},
{
"id": 73,
"type": "Note",
"pos": [
1260,
410
],
"size": [
610,
90
],
"flags": {},
"order": 3,
"mode": 0,
"inputs": [],
"outputs": [],
"properties": {},
"widgets_values": [
"These nodes can save audio in different formats. Currently, all the modes are Bypass. You can enable them as per your needs.\n\n这些节点可以将 audio 保存成不同格式,目前的模式都是 Bypass ,你可以按你的需要来启用"
],
"color": "#432",
"bgcolor": "#653"
},
{
"id": 44,
"type": "ConditioningZeroOut",
"pos": [
600,
70
],
"size": [
197.712890625,
26
],
"flags": {
"collapsed": true
},
"order": 10,
"mode": 0,
"inputs": [
{
"name": "conditioning",
"type": "CONDITIONING",
"link": 108
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"links": [
120
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.32",
"Node name for S&R": "ConditioningZeroOut"
},
"widgets_values": []
},
{
"id": 51,
"type": "ModelSamplingSD3",
"pos": [
590,
-40
],
"size": [
330,
60
],
"flags": {
"collapsed": false
},
"order": 6,
"mode": 0,
"inputs": [
{
"name": "model",
"type": "MODEL",
"link": 115
}
],
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"links": [
113
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.34",
"Node name for S&R": "ModelSamplingSD3"
},
"widgets_values": [
5.000000000000001
]
},
{
"id": 50,
"type": "LatentOperationTonemapReinhard",
"pos": [
590,
-160
],
"size": [
330,
58
],
"flags": {},
"order": 4,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "LATENT_OPERATION",
"type": "LATENT_OPERATION",
"links": [
114
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.34",
"Node name for S&R": "LatentOperationTonemapReinhard"
},
"widgets_values": [
1.0000000000000002
]
},
{
"id": 52,
"type": "KSampler",
"pos": [
940,
-40
],
"size": [
290,
262
],
"flags": {},
"order": 11,
"mode": 0,
"inputs": [
{
"name": "model",
"type": "MODEL",
"link": 121
},
{
"name": "positive",
"type": "CONDITIONING",
"link": 117
},
{
"name": "negative",
"type": "CONDITIONING",
"link": 120
},
{
"name": "latent_image",
"type": "LATENT",
"link": 119
}
],
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"slot_index": 0,
"links": [
122
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.34",
"Node name for S&R": "KSampler"
},
"widgets_values": [
468254064217846,
"randomize",
50,
5,
"euler",
"simple",
1
]
},
{
"id": 14,
"type": "TextEncodeAceStepAudio",
"pos": [
590,
120
],
"size": [
340,
500
],
"flags": {},
"order": 7,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 80
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"links": [
108,
117
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.32",
"Node name for S&R": "TextEncodeAceStepAudio"
},
"widgets_values": [
"anime, soft female vocals, kawaii pop, j-pop, childish, piano, guitar, synthesizer, fast, happy, cheerful, lighthearted\t\n",
"[inst]\n\n[verse]\nふわふわ おみみが\nゆれるよ かぜのなか\nきらきら あおいめ\nみつめる せかいを\n\n[verse]\nふわふわ しっぽは\nおおきく ゆれるよ\nきんいろ かみのけ\nなびくよ かぜのなか\n\n[verse]\nコンフィーユーアイの\nまもりびと\nピンクの セーターで\nえがおを くれるよ\n\nあおいろ スカートと\nくろいコート きんのもよう\nやさしい ひかりが\nつつむよ フェネックガール\n\n[verse]\nふわふわ おみみで\nきこえる こころの こえ\nだいすき フェネックガール\nいつでも そばにいるよ\n\n\n",
0.9900000000000002
]
},
{
"id": 17,
"type": "EmptyAceStepLatentAudio",
"pos": [
180,
50
],
"size": [
370,
82
],
"flags": {},
"order": 5,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"links": [
119
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.32",
"Node name for S&R": "EmptyAceStepLatentAudio"
},
"widgets_values": [
120,
1
]
},
{
"id": 59,
"type": "SaveAudioMP3",
"pos": [
1260,
-160
],
"size": [
610,
136
],
"flags": {},
"order": 13,
"mode": 0,
"inputs": [
{
"name": "audio",
"type": "AUDIO",
"link": 126
}
],
"outputs": [],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.34",
"Node name for S&R": "SaveAudioMP3"
},
"widgets_values": [
"audio/ComfyUI",
"V0"
]
}
],
"links": [
[
80,
40,
1,
14,
0,
"CLIP"
],
[
83,
40,
2,
18,
1,
"VAE"
],
[
108,
14,
0,
44,
0,
"CONDITIONING"
],
[
113,
51,
0,
49,
0,
"MODEL"
],
[
114,
50,
0,
49,
1,
"LATENT_OPERATION"
],
[
115,
40,
0,
51,
0,
"MODEL"
],
[
117,
14,
0,
52,
1,
"CONDITIONING"
],
[
119,
17,
0,
52,
3,
"LATENT"
],
[
120,
44,
0,
52,
2,
"CONDITIONING"
],
[
121,
49,
0,
52,
0,
"MODEL"
],
[
122,
52,
0,
18,
0,
"LATENT"
],
[
126,
18,
0,
59,
0,
"AUDIO"
],
[
127,
18,
0,
60,
0,
"AUDIO"
],
[
128,
18,
0,
61,
0,
"AUDIO"
],
[
136,
64,
0,
68,
0,
"AUDIO"
],
[
137,
40,
2,
68,
1,
"VAE"
]
],
"groups": [
{
"id": 1,
"title": "Load model here",
"bounding": [
170,
-230,
390,
180
],
"color": "#3f789e",
"font_size": 24,
"flags": {}
},
{
"id": 4,
"title": "Latent",
"bounding": [
170,
-30,
390,
280
],
"color": "#3f789e",
"font_size": 24,
"flags": {}
},
{
"id": 5,
"title": "Adjust the vocal volume",
"bounding": [
580,
-230,
350,
140
],
"color": "#3f789e",
"font_size": 24,
"flags": {}
},
{
"id": 6,
"title": "For repainting",
"bounding": [
170,
270,
390,
223.60000610351562
],
"color": "#3f789e",
"font_size": 24,
"flags": {}
},
{
"id": 7,
"title": "Output",
"bounding": [
1250,
-230,
630,
760
],
"color": "#3f789e",
"font_size": 24,
"flags": {}
}
],
"config": {},
"extra": {
"ds": {
"scale": 1,
"offset": [
-147.02717343600432,
384.62272311479
]
},
"frontendVersion": "1.19.9",
"node_versions": {
"comfy-core": "0.3.34",
"ace-step": "06f751d65491c9077fa2bc9b06d2c6f2a90e4c56"
},
"VHS_latentpreview": false,
"VHS_latentpreviewrate": 0,
"VHS_MetadataImage": true,
"VHS_KeepIntermediate": true
},
"version": 0.4
}

View File

@@ -0,0 +1,130 @@
{
"last_node_id": 3,
"last_link_id": 2,
"nodes": [
{
"id": 1,
"type": "DiffRhythmRun",
"pos": [100, 100],
"size": [400, 400],
"flags": {},
"order": 0,
"mode": 0,
"outputs": [
{
"name": "AUDIO",
"type": "AUDIO",
"links": [1, 2]
}
],
"properties": {
"Node name for S&R": "DiffRhythmRun"
},
"widgets_values": [
"cfm_full_model.pt",
"Cinematic orchestral piece with soaring strings, powerful brass, and emotional piano melodies building to an epic crescendo",
true,
"euler",
30,
4,
"quality",
123,
"randomize",
false,
"[-1, 20], [60, -1]"
],
"title": "DiffRhythm Full-Length Text-to-Music (4m45s)"
},
{
"id": 2,
"type": "PreviewAudio",
"pos": [600, 100],
"size": [300, 100],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [
{
"name": "audio",
"type": "AUDIO",
"link": 1
}
],
"properties": {
"Node name for S&R": "PreviewAudio"
},
"title": "Preview Audio"
},
{
"id": 3,
"type": "SaveAudio",
"pos": [600, 250],
"size": [300, 100],
"flags": {},
"order": 2,
"mode": 0,
"inputs": [
{
"name": "audio",
"type": "AUDIO",
"link": 2
}
],
"properties": {
"Node name for S&R": "SaveAudio"
},
"widgets_values": [
"diffrhythm_full_output"
],
"title": "Save Audio"
}
],
"links": [
[1, 1, 0, 2, 0, "AUDIO"],
[2, 1, 0, 3, 0, "AUDIO"]
],
"groups": [],
"config": {},
"extra": {
"workflow_info": {
"name": "DiffRhythm Full-Length Text-to-Music v1",
"description": "Full-length music generation using DiffRhythm Full (4 minutes 45 seconds)",
"version": "1.0.0",
"author": "valknar@pivoine.art",
"category": "text-to-music",
"tags": ["diffrhythm", "music-generation", "text-to-music", "full-length", "4m45s"],
"requirements": {
"custom_nodes": ["ComfyUI_DiffRhythm"],
"models": ["ASLP-lab/DiffRhythm-full", "ASLP-lab/DiffRhythm-vae", "OpenMuQ/MuQ-MuLan-large", "OpenMuQ/MuQ-large-msd-iter", "FacebookAI/xlm-roberta-base"],
"vram_min": "16GB",
"vram_recommended": "20GB",
"system_deps": ["espeak-ng"]
},
"usage": {
"model": "cfm_full_model.pt (DiffRhythm Full - 4m45s/285s generation)",
"style_prompt": "Detailed text description of the desired full-length music composition",
"unload_model": "Boolean to unload model after generation (default: true)",
"odeint_method": "ODE solver: euler, midpoint, rk4, implicit_adams (default: euler)",
"steps": "Number of diffusion steps: 1-100 (default: 30)",
"cfg": "Classifier-free guidance scale: 1-10 (default: 4)",
"quality_or_speed": "Generation mode: quality or speed (default: quality for full-length)",
"seed": "Random seed for reproducibility (default: 123)",
"edit": "Enable segment editing mode (default: false)",
"edit_segments": "Segments to edit when edit=true"
},
"performance": {
"generation_time": "~60-90 seconds on RTX 4090",
"vram_usage": "~16GB during generation",
"note": "Significantly faster than real-time music generation"
},
"notes": [
"This workflow uses DiffRhythm Full for 4 minute 45 second music generation",
"Best for complete song compositions with intro, development, and outro",
"All parameters except model and style_prompt are optional",
"Supports complex, multi-part compositions",
"Can optionally connect MultiLineLyricsDR node for lyrics input"
]
}
},
"version": 0.4
}

View File

@@ -0,0 +1,164 @@
{
"last_node_id": 4,
"last_link_id": 3,
"nodes": [
{
"id": 1,
"type": "LoadAudio",
"pos": [100, 100],
"size": [300, 100],
"flags": {},
"order": 0,
"mode": 0,
"outputs": [
{
"name": "AUDIO",
"type": "AUDIO",
"links": [1]
}
],
"properties": {
"Node name for S&R": "LoadAudio"
},
"widgets_values": [
"reference_audio.wav"
],
"title": "Load Reference Audio"
},
{
"id": 2,
"type": "DiffRhythmRun",
"pos": [500, 100],
"size": [400, 450],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [
{
"name": "style_audio_or_edit_song",
"type": "AUDIO",
"link": 1
}
],
"outputs": [
{
"name": "AUDIO",
"type": "AUDIO",
"links": [2, 3]
}
],
"properties": {
"Node name for S&R": "DiffRhythmRun"
},
"widgets_values": [
"cfm_model_v1_2.pt",
"Energetic rock music with driving guitar riffs and powerful drums",
true,
"euler",
30,
5,
"speed",
456,
"randomize",
false,
"[-1, 20], [60, -1]"
],
"title": "DiffRhythm Reference-Based Generation"
},
{
"id": 3,
"type": "PreviewAudio",
"pos": [1000, 100],
"size": [300, 100],
"flags": {},
"order": 2,
"mode": 0,
"inputs": [
{
"name": "audio",
"type": "AUDIO",
"link": 2
}
],
"properties": {
"Node name for S&R": "PreviewAudio"
},
"title": "Preview Generated Audio"
},
{
"id": 4,
"type": "SaveAudio",
"pos": [1000, 250],
"size": [300, 100],
"flags": {},
"order": 3,
"mode": 0,
"inputs": [
{
"name": "audio",
"type": "AUDIO",
"link": 3
}
],
"properties": {
"Node name for S&R": "SaveAudio"
},
"widgets_values": [
"diffrhythm_reference_output"
],
"title": "Save Audio"
}
],
"links": [
[1, 1, 0, 2, 0, "AUDIO"],
[2, 2, 0, 3, 0, "AUDIO"],
[3, 2, 0, 4, 0, "AUDIO"]
],
"groups": [],
"config": {},
"extra": {
"workflow_info": {
"name": "DiffRhythm Reference-Based Generation v1",
"description": "Generate new music based on a reference audio file while following text prompt guidance",
"version": "1.0.0",
"author": "valknar@pivoine.art",
"category": "text-to-music",
"tags": ["diffrhythm", "music-generation", "reference-based", "style-transfer"],
"requirements": {
"custom_nodes": ["ComfyUI_DiffRhythm"],
"models": ["ASLP-lab/DiffRhythm-1_2", "ASLP-lab/DiffRhythm-vae", "OpenMuQ/MuQ-MuLan-large", "OpenMuQ/MuQ-large-msd-iter", "FacebookAI/xlm-roberta-base"],
"vram_min": "14GB",
"vram_recommended": "18GB",
"system_deps": ["espeak-ng"]
},
"usage": {
"reference_audio": "Path to reference audio file (WAV, MP3, or other supported formats)",
"model": "cfm_model_v1_2.pt (DiffRhythm 1.2)",
"style_prompt": "Text description guiding the style and characteristics of generated music",
"unload_model": "Boolean to unload model after generation (default: true)",
"odeint_method": "ODE solver: euler, midpoint, rk4, implicit_adams (default: euler)",
"steps": "Number of diffusion steps: 1-100 (default: 30)",
"cfg": "Classifier-free guidance scale: 1-10 (default: 5 for reference-based)",
"quality_or_speed": "Generation mode: quality or speed (default: speed)",
"seed": "Random seed for reproducibility (default: 456)",
"edit": "Enable segment editing mode (default: false)",
"edit_segments": "Segments to edit when edit=true"
},
"use_cases": [
"Style transfer: Apply the style of reference music to new prompt",
"Variations: Create variations of existing compositions",
"Genre transformation: Transform music to different genre while keeping structure",
"Mood adaptation: Change the mood/emotion while maintaining musical elements"
],
"notes": [
"This workflow combines reference audio with text prompt guidance",
"The reference audio is connected to the style_audio_or_edit_song input",
"Higher cfg values (7-10) = closer adherence to both prompt and reference",
"Lower cfg values (2-4) = more creative interpretation",
"Reference audio should ideally be similar duration to target (95s for cfm_model_v1_2.pt)",
"Can use any format supported by ComfyUI's LoadAudio node"
]
}
},
"version": 0.4
}

View File

@@ -0,0 +1,125 @@
{
"last_node_id": 3,
"last_link_id": 2,
"nodes": [
{
"id": 1,
"type": "DiffRhythmRun",
"pos": [100, 100],
"size": [400, 400],
"flags": {},
"order": 0,
"mode": 0,
"outputs": [
{
"name": "AUDIO",
"type": "AUDIO",
"links": [1, 2]
}
],
"properties": {
"Node name for S&R": "DiffRhythmRun"
},
"widgets_values": [
"cfm_model_v1_2.pt",
"Upbeat electronic dance music with energetic beats and synthesizer melodies",
true,
"euler",
30,
4,
"speed",
42,
"randomize",
false,
"[-1, 20], [60, -1]"
],
"title": "DiffRhythm Text-to-Music (95s)"
},
{
"id": 2,
"type": "PreviewAudio",
"pos": [600, 100],
"size": [300, 100],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [
{
"name": "audio",
"type": "AUDIO",
"link": 1
}
],
"properties": {
"Node name for S&R": "PreviewAudio"
},
"title": "Preview Audio"
},
{
"id": 3,
"type": "SaveAudio",
"pos": [600, 250],
"size": [300, 100],
"flags": {},
"order": 2,
"mode": 0,
"inputs": [
{
"name": "audio",
"type": "AUDIO",
"link": 2
}
],
"properties": {
"Node name for S&R": "SaveAudio"
},
"widgets_values": [
"diffrhythm_output"
],
"title": "Save Audio"
}
],
"links": [
[1, 1, 0, 2, 0, "AUDIO"],
[2, 1, 0, 3, 0, "AUDIO"]
],
"groups": [],
"config": {},
"extra": {
"workflow_info": {
"name": "DiffRhythm Simple Text-to-Music v1",
"description": "Basic text-to-music generation using DiffRhythm 1.2 (95 seconds)",
"version": "1.0.0",
"author": "valknar@pivoine.art",
"category": "text-to-music",
"tags": ["diffrhythm", "music-generation", "text-to-music", "95s"],
"requirements": {
"custom_nodes": ["ComfyUI_DiffRhythm"],
"models": ["ASLP-lab/DiffRhythm-1_2", "ASLP-lab/DiffRhythm-vae", "OpenMuQ/MuQ-MuLan-large", "OpenMuQ/MuQ-large-msd-iter", "FacebookAI/xlm-roberta-base"],
"vram_min": "12GB",
"vram_recommended": "16GB",
"system_deps": ["espeak-ng"]
},
"usage": {
"model": "cfm_model_v1_2.pt (DiffRhythm 1.2 - 95s generation)",
"style_prompt": "Text description of the desired music style, mood, and instruments",
"unload_model": "Boolean to unload model after generation (default: true)",
"odeint_method": "ODE solver: euler, midpoint, rk4, implicit_adams (default: euler)",
"steps": "Number of diffusion steps: 1-100 (default: 30)",
"cfg": "Classifier-free guidance scale: 1-10 (default: 4)",
"quality_or_speed": "Generation mode: quality or speed (default: speed)",
"seed": "Random seed for reproducibility (default: 42)",
"edit": "Enable segment editing mode (default: false)",
"edit_segments": "Segments to edit when edit=true (default: [-1, 20], [60, -1])"
},
"notes": [
"This workflow uses DiffRhythm 1.2 for 95-second music generation",
"All parameters except model and style_prompt are optional",
"Supports English and Chinese text prompts",
"Generation time: ~30-60 seconds on RTX 4090",
"Can optionally connect MultiLineLyricsDR node for lyrics input"
]
}
},
"version": 0.4
}

View File

@@ -1,136 +1,151 @@
{ {
"last_node_id": 6, "last_node_id": 2,
"last_link_id": 1,
"nodes": [ "nodes": [
{ {
"id": 1, "id": 1,
"type": "MusicGenLoader", "type": "Musicgen_",
"pos": [ "pos": [50, 100],
50, "size": [400, 300],
100
],
"widgets_values": [
"facebook/musicgen-large"
],
"title": "MusicGen Large Loader",
"flags": {}, "flags": {},
"order": 0, "order": 0,
"mode": 0, "mode": 0,
"outputs": [
{
"name": "audio",
"type": "AUDIO",
"links": [1],
"slot_index": 0
}
],
"properties": { "properties": {
"Node name for S&R": "MusicGenLoader" "Node name for S&R": "Musicgen_"
}, },
"size": { "widgets_values": [
"0": 350, "Upbeat electronic dance music with energetic beats and synthesizer melodies",
"1": 100 30.0,
} 4.0,
42,
"auto"
],
"title": "MusicGen Large Generator"
}, },
{ {
"id": 2, "id": 2,
"type": "MusicGenTextEncode", "type": "AudioPlay",
"pos": [ "pos": [500, 100],
400, "size": [315, 100],
100
],
"widgets_values": [
"Upbeat electronic dance music"
],
"title": "API Music Prompt",
"flags": {}, "flags": {},
"order": 1, "order": 1,
"mode": 0, "mode": 0,
"inputs": [
{
"name": "audio",
"type": "AUDIO",
"link": 1
}
],
"properties": { "properties": {
"Node name for S&R": "MusicGenTextEncode" "Node name for S&R": "AudioPlay"
}, },
"size": { "title": "API Audio Output"
"0": 400,
"1": 200
}
},
{
"id": 3,
"type": "MusicGenSampler",
"pos": [
750,
100
],
"widgets_values": [
42,
"fixed",
30.0,
250,
3.0
],
"title": "MusicGen Sampler",
"flags": {},
"order": 2,
"mode": 0,
"properties": {
"Node name for S&R": "MusicGenSampler"
},
"size": {
"0": 315,
"1": 474
}
},
{
"id": 4,
"type": "SaveAudio",
"pos": [
1100,
100
],
"widgets_values": [
"musicgen_large_output",
"wav"
],
"title": "API Audio Output",
"flags": {},
"order": 3,
"mode": 0,
"properties": {
"Node name for S&R": "AudioSave"
},
"size": {
"0": 315,
"1": 100
}
} }
], ],
"links": [
[1, 1, 0, 2, 0, "AUDIO"]
],
"groups": [],
"config": {},
"extra": { "extra": {
"workflow_info": { "workflow_info": {
"name": "MusicGen Large Text-to-Music", "name": "MusicGen Large Text-to-Music Production",
"version": "1.0.0", "version": "1.2.0",
"description": "High-quality music generation using MusicGen Large. Generates up to 30 seconds of music from text prompts.",
"category": "text-to-music", "category": "text-to-music",
"tags": [ "tags": ["musicgen", "large", "t2m", "audio", "production"],
"musicgen",
"large",
"t2m"
],
"requirements": { "requirements": {
"models": [ "models": ["facebook/musicgen-large"],
"musicgen-large" "custom_nodes": ["comfyui-sound-lab"],
], "vram_min": "12GB",
"custom_nodes": [ "vram_recommended": "16GB"
"comfyui-sound-lab"
],
"vram_min": "16GB"
}, },
"parameters": { "parameters": {
"prompt": { "prompt": {
"node_id": 2, "node_id": 1,
"type": "string" "widget_index": 0,
"type": "string",
"required": true,
"default": "Upbeat electronic dance music",
"description": "Text description of desired music style, genre, mood, instruments"
}, },
"duration": { "duration": {
"node_id": 3, "node_id": 1,
"default": 30.0 "widget_index": 1,
"type": "float",
"required": false,
"default": 30.0,
"min": 1.0,
"max": 60.0,
"description": "Duration in seconds (up to 30s recommended for best quality)"
},
"guidance_scale": {
"node_id": 1,
"widget_index": 2,
"type": "float",
"required": false,
"default": 4.0,
"min": 0.0,
"max": 20.0,
"description": "How closely to follow the prompt (4.0 recommended)"
},
"seed": {
"node_id": 1,
"widget_index": 3,
"type": "integer",
"required": false,
"default": 42,
"min": 0,
"max": 2147483647,
"description": "Random seed for reproducibility"
},
"device": {
"node_id": 1,
"widget_index": 4,
"type": "string",
"required": false,
"default": "auto",
"options": ["auto", "cpu"],
"description": "Computation device (auto recommended)"
}
},
"outputs": {
"audio": {
"node_id": 2,
"type": "audio",
"format": "FLAC",
"sample_rate": "32000 Hz",
"channels": "stereo"
} }
}, },
"performance": { "performance": {
"avg_generation_time": "45-70 seconds", "avg_generation_time": "60-90 seconds for 30s audio",
"vram_usage": "~14-16GB" "vram_usage": "~14-16GB",
} "gpu_utilization": "90-100%"
},
"use_cases": [
"Background music generation",
"Game soundtrack creation",
"Video background music",
"Music prototyping and ideation"
],
"notes": [
"MusicGen Large produces highest quality output",
"Best results with clear, specific prompts",
"Can specify genre, mood, instruments, tempo",
"Output is 32kHz stereo FLAC format",
"Longer durations (>30s) may reduce coherence"
]
} }
}, },
"version": 0.4, "version": 0.4
"links": [], }
"last_link_id": 0
}

View File

@@ -1,136 +1,151 @@
{ {
"last_node_id": 6, "last_node_id": 2,
"last_link_id": 1,
"nodes": [ "nodes": [
{ {
"id": 1, "id": 1,
"type": "MusicGenLoader", "type": "Musicgen_",
"pos": [ "pos": [50, 100],
50, "size": [400, 300],
100
],
"widgets_values": [
"facebook/musicgen-medium"
],
"title": "MusicGen Medium Loader",
"flags": {}, "flags": {},
"order": 0, "order": 0,
"mode": 0, "mode": 0,
"outputs": [
{
"name": "audio",
"type": "AUDIO",
"links": [1],
"slot_index": 0
}
],
"properties": { "properties": {
"Node name for S&R": "MusicGenLoader" "Node name for S&R": "Musicgen_"
}, },
"size": { "widgets_values": [
"0": 350, "Upbeat electronic dance music with energetic beats and synthesizer melodies",
"1": 100 30.0,
} 3.0,
42,
"auto"
],
"title": "MusicGen Medium Generator"
}, },
{ {
"id": 2, "id": 2,
"type": "MusicGenTextEncode", "type": "AudioPlay",
"pos": [ "pos": [500, 100],
400, "size": [315, 100],
100
],
"widgets_values": [
"Upbeat electronic dance music"
],
"title": "API Music Prompt",
"flags": {}, "flags": {},
"order": 1, "order": 1,
"mode": 0, "mode": 0,
"inputs": [
{
"name": "audio",
"type": "AUDIO",
"link": 1
}
],
"properties": { "properties": {
"Node name for S&R": "MusicGenTextEncode" "Node name for S&R": "AudioPlay"
}, },
"size": { "title": "API Audio Output"
"0": 400,
"1": 200
}
},
{
"id": 3,
"type": "MusicGenSampler",
"pos": [
750,
100
],
"widgets_values": [
42,
"fixed",
30.0,
250,
3.0
],
"title": "MusicGen Sampler",
"flags": {},
"order": 2,
"mode": 0,
"properties": {
"Node name for S&R": "MusicGenSampler"
},
"size": {
"0": 315,
"1": 474
}
},
{
"id": 4,
"type": "SaveAudio",
"pos": [
1100,
100
],
"widgets_values": [
"musicgen_medium_output",
"wav"
],
"title": "API Audio Output",
"flags": {},
"order": 3,
"mode": 0,
"properties": {
"Node name for S&R": "AudioSave"
},
"size": {
"0": 315,
"1": 100
}
} }
], ],
"links": [
[1, 1, 0, 2, 0, "AUDIO"]
],
"groups": [],
"config": {},
"extra": { "extra": {
"workflow_info": { "workflow_info": {
"name": "MusicGen Medium Text-to-Music", "name": "MusicGen Medium Text-to-Music Production",
"version": "1.0.0", "version": "1.2.0",
"description": "Balanced music generation using MusicGen Medium. Good quality with moderate VRAM usage.",
"category": "text-to-music", "category": "text-to-music",
"tags": [ "tags": ["musicgen", "medium", "t2m", "audio", "production"],
"musicgen",
"medium",
"t2m"
],
"requirements": { "requirements": {
"models": [ "models": ["facebook/musicgen-medium"],
"musicgen-medium" "custom_nodes": ["comfyui-sound-lab"],
], "vram_min": "8GB",
"custom_nodes": [ "vram_recommended": "10GB"
"comfyui-sound-lab"
],
"vram_min": "10GB"
}, },
"parameters": { "parameters": {
"prompt": { "prompt": {
"node_id": 2, "node_id": 1,
"type": "string" "widget_index": 0,
"type": "string",
"required": true,
"default": "Upbeat electronic dance music",
"description": "Text description of desired music style, genre, mood, instruments"
}, },
"duration": { "duration": {
"node_id": 3, "node_id": 1,
"default": 30.0 "widget_index": 1,
"type": "float",
"required": false,
"default": 30.0,
"min": 1.0,
"max": 60.0,
"description": "Duration in seconds (up to 30s recommended for best quality)"
},
"guidance_scale": {
"node_id": 1,
"widget_index": 2,
"type": "float",
"required": false,
"default": 3.0,
"min": 0.0,
"max": 20.0,
"description": "How closely to follow the prompt (3.0 recommended)"
},
"seed": {
"node_id": 1,
"widget_index": 3,
"type": "integer",
"required": false,
"default": 42,
"min": 0,
"max": 2147483647,
"description": "Random seed for reproducibility"
},
"device": {
"node_id": 1,
"widget_index": 4,
"type": "string",
"required": false,
"default": "auto",
"options": ["auto", "cpu"],
"description": "Computation device (auto recommended)"
}
},
"outputs": {
"audio": {
"node_id": 2,
"type": "audio",
"format": "FLAC",
"sample_rate": "32000 Hz",
"channels": "stereo"
} }
}, },
"performance": { "performance": {
"avg_generation_time": "25-40 seconds", "avg_generation_time": "30-50 seconds for 30s audio",
"vram_usage": "~8-10GB" "vram_usage": "~8-10GB",
} "gpu_utilization": "90-100%"
},
"use_cases": [
"Background music generation",
"Game soundtrack creation",
"Video background music",
"Music prototyping with moderate quality"
],
"notes": [
"MusicGen Medium balances quality and resource usage",
"Faster than Large, better quality than Small",
"Best results with clear, specific prompts",
"Can specify genre, mood, instruments, tempo",
"Output is 32kHz stereo FLAC format"
]
} }
}, },
"version": 0.4, "version": 0.4
"links": [], }
"last_link_id": 0
}

View File

@@ -1,163 +1,150 @@
{ {
"last_node_id": 7, "last_node_id": 2,
"last_link_id": 1,
"nodes": [ "nodes": [
{ {
"id": 1, "id": 1,
"type": "LoadAudio", "type": "Musicgen_",
"pos": [ "pos": [50, 100],
50, "size": [400, 300],
100
],
"widgets_values": [
"melody_reference.wav"
],
"title": "API Melody Reference",
"flags": {}, "flags": {},
"order": 0, "order": 0,
"mode": 0, "mode": 0,
"outputs": [
{
"name": "audio",
"type": "AUDIO",
"links": [1],
"slot_index": 0
}
],
"properties": { "properties": {
"Node name for S&R": "LoadAudio" "Node name for S&R": "Musicgen_"
}, },
"size": { "widgets_values": [
"0": 350, "Electronic music with melodic elements and catchy hooks",
"1": 100 30.0,
} 3.5,
42,
"auto"
],
"title": "MusicGen Melody Generator"
}, },
{ {
"id": 2, "id": 2,
"type": "MusicGenLoader", "type": "AudioPlay",
"pos": [ "pos": [500, 100],
50, "size": [315, 100],
350
],
"widgets_values": [
"facebook/musicgen-melody"
],
"title": "MusicGen Melody Loader",
"flags": {}, "flags": {},
"order": 1, "order": 1,
"mode": 0, "mode": 0,
"inputs": [
{
"name": "audio",
"type": "AUDIO",
"link": 1
}
],
"properties": { "properties": {
"Node name for S&R": "MusicGenLoader" "Node name for S&R": "AudioPlay"
}, },
"size": { "title": "API Audio Output"
"0": 350,
"1": 100
}
},
{
"id": 3,
"type": "MusicGenTextEncode",
"pos": [
400,
100
],
"widgets_values": [
"Electronic music following the melody"
],
"title": "API Music Prompt",
"flags": {},
"order": 2,
"mode": 0,
"properties": {
"Node name for S&R": "MusicGenTextEncode"
},
"size": {
"0": 400,
"1": 200
}
},
{
"id": 4,
"type": "MusicGenMelodySampler",
"pos": [
750,
100
],
"widgets_values": [
42,
"fixed",
30.0,
250,
3.0
],
"title": "MusicGen Melody Sampler",
"flags": {},
"order": 3,
"mode": 0,
"properties": {
"Node name for S&R": "MusicGenMelodySampler"
},
"size": {
"0": 315,
"1": 474
}
},
{
"id": 5,
"type": "SaveAudio",
"pos": [
1100,
100
],
"widgets_values": [
"musicgen_melody_output",
"wav"
],
"title": "API Audio Output",
"flags": {},
"order": 4,
"mode": 0,
"properties": {
"Node name for S&R": "AudioSave"
},
"size": {
"0": 315,
"1": 100
}
} }
], ],
"links": [
[1, 1, 0, 2, 0, "AUDIO"]
],
"groups": [],
"config": {},
"extra": { "extra": {
"workflow_info": { "workflow_info": {
"name": "MusicGen Melody Text-to-Music", "name": "MusicGen Melody Text-to-Music Production",
"version": "1.0.0", "version": "1.2.0",
"description": "Music generation using MusicGen with melodic focus. Note: Melody conditioning via audio input not yet supported.",
"category": "text-to-music", "category": "text-to-music",
"tags": [ "tags": ["musicgen", "melody", "t2m", "audio", "production"],
"musicgen",
"melody",
"melody-conditioning",
"t2m"
],
"requirements": { "requirements": {
"models": [ "models": ["facebook/musicgen-melody"],
"musicgen-melody" "custom_nodes": ["comfyui-sound-lab"],
], "vram_min": "10GB",
"custom_nodes": [ "vram_recommended": "12GB"
"comfyui-sound-lab"
],
"vram_min": "12GB"
}, },
"parameters": { "parameters": {
"melody_audio": {
"node_id": 1,
"type": "audio"
},
"prompt": { "prompt": {
"node_id": 3, "node_id": 1,
"type": "string" "widget_index": 0,
"type": "string",
"required": true,
"default": "Electronic music with melodic elements",
"description": "Text description of desired music style, genre, mood, instruments"
}, },
"duration": { "duration": {
"node_id": 4, "node_id": 1,
"default": 30.0 "widget_index": 1,
"type": "float",
"required": false,
"default": 30.0,
"min": 1.0,
"max": 60.0,
"description": "Duration in seconds (up to 30s recommended for best quality)"
},
"guidance_scale": {
"node_id": 1,
"widget_index": 2,
"type": "float",
"required": false,
"default": 3.5,
"min": 0.0,
"max": 20.0,
"description": "How closely to follow the prompt (3.5 recommended)"
},
"seed": {
"node_id": 1,
"widget_index": 3,
"type": "integer",
"required": false,
"default": 42,
"min": 0,
"max": 2147483647,
"description": "Random seed for reproducibility"
},
"device": {
"node_id": 1,
"widget_index": 4,
"type": "string",
"required": false,
"default": "auto",
"options": ["auto", "cpu"],
"description": "Computation device (auto recommended)"
}
},
"outputs": {
"audio": {
"node_id": 2,
"type": "audio",
"format": "FLAC",
"sample_rate": "32000 Hz",
"channels": "stereo"
} }
}, },
"performance": { "performance": {
"avg_generation_time": "35-55 seconds", "avg_generation_time": "40-60 seconds for 30s audio",
"vram_usage": "~10-12GB" "vram_usage": "~10-12GB",
} "gpu_utilization": "90-100%"
},
"use_cases": [
"Melodic music generation",
"Creating catchy hooks and melodies",
"Music with strong melodic structure"
],
"notes": [
"IMPORTANT: Melody conditioning via audio input not yet supported in current Sound Lab implementation",
"This workflow uses text prompts only - describe melodic characteristics in the prompt",
"For best melodic results, use descriptive terms like 'catchy melody', 'melodic hooks', 'harmonic progression'",
"MusicGen Melody model trained for melodic content",
"Output is 32kHz stereo FLAC format"
]
} }
}, },
"version": 0.4, "version": 0.4
"links": [], }
"last_link_id": 0
}

View File

@@ -1,136 +1,151 @@
{ {
"last_node_id": 6, "last_node_id": 2,
"last_link_id": 1,
"nodes": [ "nodes": [
{ {
"id": 1, "id": 1,
"type": "MusicGenLoader", "type": "Musicgen_",
"pos": [ "pos": [50, 100],
50, "size": [400, 300],
100
],
"widgets_values": [
"facebook/musicgen-small"
],
"title": "MusicGen Small Loader",
"flags": {}, "flags": {},
"order": 0, "order": 0,
"mode": 0, "mode": 0,
"outputs": [
{
"name": "audio",
"type": "AUDIO",
"links": [1],
"slot_index": 0
}
],
"properties": { "properties": {
"Node name for S&R": "MusicGenLoader" "Node name for S&R": "Musicgen_"
}, },
"size": { "widgets_values": [
"0": 350, "Upbeat electronic dance music with energetic beats and synthesizer melodies",
"1": 100 30.0,
} 3.0,
42,
"auto"
],
"title": "MusicGen Small Generator"
}, },
{ {
"id": 2, "id": 2,
"type": "MusicGenTextEncode", "type": "AudioPlay",
"pos": [ "pos": [500, 100],
400, "size": [315, 100],
100
],
"widgets_values": [
"Upbeat electronic dance music"
],
"title": "API Music Prompt",
"flags": {}, "flags": {},
"order": 1, "order": 1,
"mode": 0, "mode": 0,
"inputs": [
{
"name": "audio",
"type": "AUDIO",
"link": 1
}
],
"properties": { "properties": {
"Node name for S&R": "MusicGenTextEncode" "Node name for S&R": "AudioPlay"
}, },
"size": { "title": "API Audio Output"
"0": 400,
"1": 200
}
},
{
"id": 3,
"type": "MusicGenSampler",
"pos": [
750,
100
],
"widgets_values": [
42,
"fixed",
30.0,
250,
3.0
],
"title": "MusicGen Sampler",
"flags": {},
"order": 2,
"mode": 0,
"properties": {
"Node name for S&R": "MusicGenSampler"
},
"size": {
"0": 315,
"1": 474
}
},
{
"id": 4,
"type": "SaveAudio",
"pos": [
1100,
100
],
"widgets_values": [
"musicgen_small_output",
"wav"
],
"title": "API Audio Output",
"flags": {},
"order": 3,
"mode": 0,
"properties": {
"Node name for S&R": "AudioSave"
},
"size": {
"0": 315,
"1": 100
}
} }
], ],
"links": [
[1, 1, 0, 2, 0, "AUDIO"]
],
"groups": [],
"config": {},
"extra": { "extra": {
"workflow_info": { "workflow_info": {
"name": "MusicGen Small Text-to-Music", "name": "MusicGen Small Text-to-Music Production",
"version": "1.0.0", "version": "1.2.0",
"description": "Fast music generation using MusicGen Small. Lower quality but fastest generation and minimal VRAM.",
"category": "text-to-music", "category": "text-to-music",
"tags": [ "tags": ["musicgen", "small", "t2m", "audio", "production", "fast"],
"musicgen",
"small",
"t2m"
],
"requirements": { "requirements": {
"models": [ "models": ["facebook/musicgen-small"],
"musicgen-small" "custom_nodes": ["comfyui-sound-lab"],
], "vram_min": "4GB",
"custom_nodes": [ "vram_recommended": "6GB"
"comfyui-sound-lab"
],
"vram_min": "6GB"
}, },
"parameters": { "parameters": {
"prompt": { "prompt": {
"node_id": 2, "node_id": 1,
"type": "string" "widget_index": 0,
"type": "string",
"required": true,
"default": "Upbeat electronic dance music",
"description": "Text description of desired music style, genre, mood, instruments"
}, },
"duration": { "duration": {
"node_id": 3, "node_id": 1,
"default": 30.0 "widget_index": 1,
"type": "float",
"required": false,
"default": 30.0,
"min": 1.0,
"max": 60.0,
"description": "Duration in seconds (up to 30s recommended for best quality)"
},
"guidance_scale": {
"node_id": 1,
"widget_index": 2,
"type": "float",
"required": false,
"default": 3.0,
"min": 0.0,
"max": 20.0,
"description": "How closely to follow the prompt (3.0 recommended)"
},
"seed": {
"node_id": 1,
"widget_index": 3,
"type": "integer",
"required": false,
"default": 42,
"min": 0,
"max": 2147483647,
"description": "Random seed for reproducibility"
},
"device": {
"node_id": 1,
"widget_index": 4,
"type": "string",
"required": false,
"default": "auto",
"options": ["auto", "cpu"],
"description": "Computation device (auto recommended)"
}
},
"outputs": {
"audio": {
"node_id": 2,
"type": "audio",
"format": "FLAC",
"sample_rate": "32000 Hz",
"channels": "stereo"
} }
}, },
"performance": { "performance": {
"avg_generation_time": "15-25 seconds", "avg_generation_time": "20-35 seconds for 30s audio",
"vram_usage": "~4-6GB" "vram_usage": "~4-6GB",
} "gpu_utilization": "85-95%"
},
"use_cases": [
"Rapid prototyping",
"Low-resource environments",
"Quick background music drafts",
"Testing different prompts quickly"
],
"notes": [
"MusicGen Small is fastest but lowest quality",
"Good for rapid iteration and testing",
"Best results with clear, specific prompts",
"Can specify genre, mood, instruments, tempo",
"Output is 32kHz stereo FLAC format"
]
} }
}, },
"version": 0.4, "version": 0.4
"links": [], }
"last_link_id": 0
}

Binary file not shown.

View File

@@ -1,222 +1,185 @@
{ {
"last_node_id": 10, "last_node_id": 5,
"last_link_id": 4,
"nodes": [ "nodes": [
{ {
"id": 1, "id": 1,
"type": "LoadImage", "type": "LoadImage",
"pos": [ "pos": [50, 100],
50, "size": [350, 100],
100
],
"widgets_values": [
"input_portrait.png",
"image"
],
"title": "API Input Portrait",
"flags": {}, "flags": {},
"order": 0, "order": 0,
"mode": 0, "mode": 0,
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [1],
"slot_index": 0
},
{
"name": "MASK",
"type": "MASK",
"links": null,
"slot_index": 1
}
],
"properties": { "properties": {
"Node name for S&R": "LoadImage" "Node name for S&R": "LoadImage"
}, },
"size": { "widgets_values": ["input_portrait.png", "image"],
"0": 350, "title": "API Input Portrait"
"1": 100
}
}, },
{ {
"id": 2, "id": 2,
"type": "CheckpointLoaderSimple", "type": "UpscaleModelLoader",
"pos": [ "pos": [50, 400],
50, "size": [350, 100],
400
],
"widgets_values": [
"diffusers/stable-diffusion-xl-base-1.0"
],
"title": "SDXL Checkpoint Loader",
"flags": {}, "flags": {},
"order": 1, "order": 1,
"mode": 0, "mode": 0,
"properties": { "outputs": [
"Node name for S&R": "CheckpointLoaderSimple" {
}, "name": "UPSCALE_MODEL",
"size": { "type": "UPSCALE_MODEL",
"0": 350, "links": [2],
"1": 100 "slot_index": 0
} }
},
{
"id": 3,
"type": "FaceDetailer",
"pos": [
450,
100
], ],
"widgets_values": [
"bbox/face_yolov8m.pt",
512,
0.5,
20,
8.0,
0.35,
10
],
"title": "Face Detailer",
"flags": {},
"order": 2,
"mode": 0,
"properties": {
"Node name for S&R": "FaceDetailer"
},
"size": {
"0": 315,
"1": 100
}
},
{
"id": 4,
"type": "UpscaleModelLoader",
"pos": [
50,
650
],
"widgets_values": [
"RealESRGAN_x2.pth"
],
"title": "Face Upscale Model",
"flags": {},
"order": 3,
"mode": 0,
"properties": { "properties": {
"Node name for S&R": "UpscaleModelLoader" "Node name for S&R": "UpscaleModelLoader"
}, },
"size": { "widgets_values": ["RealESRGAN_x2.pth"],
"0": 350, "title": "Face Upscale Model (2x)"
"1": 100
}
}, },
{ {
"id": 5, "id": 3,
"type": "ImageUpscaleWithModel", "type": "ImageUpscaleWithModel",
"pos": [ "pos": [450, 100],
800, "size": [315, 100],
100
],
"title": "Upscale Face Regions",
"flags": {}, "flags": {},
"order": 4, "order": 2,
"mode": 0, "mode": 0,
"inputs": [
{
"name": "upscale_model",
"type": "UPSCALE_MODEL",
"link": 2
},
{
"name": "image",
"type": "IMAGE",
"link": 1
}
],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [3, 4],
"slot_index": 0
}
],
"properties": { "properties": {
"Node name for S&R": "ImageUpscaleWithModel" "Node name for S&R": "ImageUpscaleWithModel"
}, },
"size": { "title": "Upscale Portrait (2x)"
"0": 315,
"1": 100
}
}, },
{ {
"id": 6, "id": 4,
"type": "PreviewImage", "type": "PreviewImage",
"pos": [ "pos": [800, 100],
1150, "size": [315, 100],
100
],
"title": "Preview Enhanced",
"flags": {}, "flags": {},
"order": 5, "order": 3,
"mode": 0, "mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 3
}
],
"properties": { "properties": {
"Node name for S&R": "PreviewImage" "Node name for S&R": "PreviewImage"
}, },
"size": { "title": "Preview Enhanced"
"0": 315,
"1": 100
}
}, },
{ {
"id": 7, "id": 5,
"type": "SaveImage", "type": "SaveImage",
"pos": [ "pos": [800, 400],
1150, "size": [315, 100],
400
],
"widgets_values": [
"face_upscale_output"
],
"title": "API Image Output",
"flags": {}, "flags": {},
"order": 6, "order": 4,
"mode": 0, "mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 4
}
],
"properties": { "properties": {
"Node name for S&R": "SaveImage" "Node name for S&R": "SaveImage"
}, },
"size": { "widgets_values": ["face_upscale_output"],
"0": 315, "title": "API Image Output"
"1": 100
}
} }
], ],
"links": [
[1, 1, 0, 3, 1, "IMAGE"],
[2, 2, 0, 3, 0, "UPSCALE_MODEL"],
[3, 3, 0, 4, 0, "IMAGE"],
[4, 3, 0, 5, 0, "IMAGE"]
],
"groups": [],
"config": {},
"extra": { "extra": {
"workflow_info": { "workflow_info": {
"name": "Face Upscale Production", "name": "Face Upscale Production",
"version": "1.0.0", "version": "1.1.0",
"description": "Portrait-focused upscaling with FaceDetailer from Impact-Pack. Detects and enhances faces with special attention to facial details.", "description": "Portrait-focused upscaling using RealESRGAN x2. Simplified workflow optimized for face enhancement. For advanced face detection with FaceDetailer, additional nodes are required.",
"category": "upscaling", "category": "upscaling",
"tags": [ "tags": ["face-upscale", "portrait", "realesrgan", "production"],
"face-upscale",
"portrait",
"facedetailer",
"impact-pack",
"production"
],
"requirements": { "requirements": {
"models": [ "models": ["RealESRGAN"],
"stable-diffusion-xl-base-1.0", "custom_nodes": [],
"face_yolov8m", "vram_min": "8GB"
"RealESRGAN"
],
"custom_nodes": [
"ComfyUI-Impact-Pack"
],
"vram_min": "14GB"
}, },
"parameters": { "parameters": {
"input_image": { "input_image": {
"node_id": 1, "node_id": 1,
"type": "image", "type": "image",
"required": true "required": true,
"description": "Portrait image to upscale"
}, },
"detection_threshold": { "model": {
"node_id": 3, "node_id": 2,
"type": "float", "widget_index": 0,
"default": 0.5, "type": "string",
"description": "Face detection confidence" "default": "RealESRGAN_x2.pth",
}, "options": ["RealESRGAN_x2.pth", "RealESRGAN_x4.pth"],
"detail_steps": { "description": "Upscale model (x2 recommended for portraits)"
"node_id": 3,
"type": "integer",
"default": 20
},
"denoise": {
"node_id": 3,
"type": "float",
"default": 0.35
} }
}, },
"performance": { "performance": {
"avg_generation_time": "30-50 seconds", "avg_generation_time": "5-15 seconds",
"vram_usage": "~12-16GB" "vram_usage": "~6-8GB"
}, },
"use_cases": [ "use_cases": [
"Portrait enhancement", "Portrait enhancement",
"Professional headshots", "Professional headshots",
"Face restoration", "Face restoration",
"ID photo upscaling" "ID photo upscaling"
],
"notes": [
"This is a simplified version using basic upscaling",
"For advanced face detection, use FaceDetailer from Impact-Pack",
"FaceDetailer requires: BBOX detector, SDXL checkpoint, CLIP conditioning",
"Current version optimized for speed and simplicity"
] ]
} }
}, },
"version": 0.4, "version": 0.4
"links": [], }
"last_link_id": 0
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

View File

@@ -1,151 +1,179 @@
{ {
"last_node_id": 6, "last_node_id": 6,
"last_link_id": 5,
"nodes": [ "nodes": [
{ {
"id": 1, "id": 1,
"type": "LoadImage", "type": "LoadImage",
"pos": [ "pos": [50, 100],
50, "size": [350, 100],
100
],
"widgets_values": [
"input_image.png",
"image"
],
"title": "API Input Image",
"flags": {}, "flags": {},
"order": 0, "order": 0,
"mode": 0, "mode": 0,
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [1],
"slot_index": 0
},
{
"name": "MASK",
"type": "MASK",
"links": null,
"slot_index": 1
}
],
"properties": { "properties": {
"Node name for S&R": "LoadImage" "Node name for S&R": "LoadImage"
}, },
"size": { "widgets_values": ["input_image.png", "image"],
"0": 350, "title": "API Input Image"
"1": 100
}
}, },
{ {
"id": 2, "id": 2,
"type": "UpscaleModelLoader", "type": "UpscaleModelLoader",
"pos": [ "pos": [50, 400],
50, "size": [350, 100],
400
],
"widgets_values": [
"RealESRGAN_x4.pth"
],
"title": "Upscale Model Loader",
"flags": {}, "flags": {},
"order": 1, "order": 1,
"mode": 0, "mode": 0,
"outputs": [
{
"name": "UPSCALE_MODEL",
"type": "UPSCALE_MODEL",
"links": [2],
"slot_index": 0
}
],
"properties": { "properties": {
"Node name for S&R": "UpscaleModelLoader" "Node name for S&R": "UpscaleModelLoader"
}, },
"size": { "widgets_values": ["RealESRGAN_x4.pth"],
"0": 350, "title": "Upscale Model Loader"
"1": 100
}
}, },
{ {
"id": 3, "id": 3,
"type": "ImageUpscaleWithModel", "type": "ImageUpscaleWithModel",
"pos": [ "pos": [450, 100],
450, "size": [315, 100],
100
],
"title": "Upscale with Model (4x)",
"flags": {}, "flags": {},
"order": 2, "order": 2,
"mode": 0, "mode": 0,
"inputs": [
{
"name": "upscale_model",
"type": "UPSCALE_MODEL",
"link": 2
},
{
"name": "image",
"type": "IMAGE",
"link": 1
}
],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [3],
"slot_index": 0
}
],
"properties": { "properties": {
"Node name for S&R": "ImageUpscaleWithModel" "Node name for S&R": "ImageUpscaleWithModel"
}, },
"size": { "title": "Upscale with Model (4x)"
"0": 315,
"1": 100
}
}, },
{ {
"id": 4, "id": 4,
"type": "ImageScale", "type": "ImageScaleBy",
"pos": [ "pos": [800, 100],
800, "size": [315, 100],
100
],
"widgets_values": [
"lanczos",
2
],
"title": "Optional Downscale to 2x",
"flags": {}, "flags": {},
"order": 3, "order": 3,
"mode": 0, "mode": 0,
"inputs": [
{
"name": "image",
"type": "IMAGE",
"link": 3
}
],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [4, 5],
"slot_index": 0
}
],
"properties": { "properties": {
"Node name for S&R": "ImageScale" "Node name for S&R": "ImageScaleBy"
}, },
"size": { "widgets_values": ["lanczos", 0.5],
"0": 315, "title": "Optional Downscale to 2x"
"1": 100
}
}, },
{ {
"id": 5, "id": 5,
"type": "PreviewImage", "type": "PreviewImage",
"pos": [ "pos": [1150, 100],
1150, "size": [315, 100],
100
],
"title": "Preview Output",
"flags": {}, "flags": {},
"order": 4, "order": 4,
"mode": 0, "mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 4
}
],
"properties": { "properties": {
"Node name for S&R": "PreviewImage" "Node name for S&R": "PreviewImage"
}, },
"size": { "title": "Preview Output"
"0": 315,
"1": 100
}
}, },
{ {
"id": 6, "id": 6,
"type": "SaveImage", "type": "SaveImage",
"pos": [ "pos": [1150, 400],
1150, "size": [315, 100],
400
],
"widgets_values": [
"simple_upscale_output"
],
"title": "API Image Output",
"flags": {}, "flags": {},
"order": 5, "order": 5,
"mode": 0, "mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 5
}
],
"properties": { "properties": {
"Node name for S&R": "SaveImage" "Node name for S&R": "SaveImage"
}, },
"size": { "widgets_values": ["simple_upscale_output"],
"0": 315, "title": "API Image Output"
"1": 100
}
} }
], ],
"links": [
[1, 1, 0, 3, 1, "IMAGE"],
[2, 2, 0, 3, 0, "UPSCALE_MODEL"],
[3, 3, 0, 4, 0, "IMAGE"],
[4, 4, 0, 5, 0, "IMAGE"],
[5, 4, 0, 6, 0, "IMAGE"]
],
"groups": [],
"config": {},
"extra": { "extra": {
"workflow_info": { "workflow_info": {
"name": "Simple Upscale Production", "name": "Simple Upscale Production",
"version": "1.0.0", "version": "1.0.0",
"description": "Fast, straightforward upscaling using RealESRGAN. No diffusion refinement, optimized for speed.", "description": "Fast, straightforward upscaling using RealESRGAN. No diffusion refinement, optimized for speed.",
"category": "upscaling", "category": "upscaling",
"tags": [ "tags": ["simple-upscale", "fast", "realesrgan", "production"],
"simple-upscale",
"fast",
"realesrgan",
"production"
],
"requirements": { "requirements": {
"models": [ "models": ["RealESRGAN"],
"RealESRGAN"
],
"custom_nodes": [], "custom_nodes": [],
"vram_min": "8GB" "vram_min": "8GB"
}, },
@@ -159,15 +187,14 @@
"node_id": 2, "node_id": 2,
"type": "string", "type": "string",
"default": "RealESRGAN_x4.pth", "default": "RealESRGAN_x4.pth",
"options": [ "options": ["RealESRGAN_x2.pth", "RealESRGAN_x4.pth"]
"RealESRGAN_x2.pth",
"RealESRGAN_x4.pth"
]
}, },
"final_scale": { "final_scale": {
"node_id": 4, "node_id": 4,
"type": "integer", "widget_index": 1,
"default": 2 "type": "float",
"default": 0.5,
"description": "Scale factor after 4x upscale (0.5 = final 2x, 1.0 = keep 4x)"
} }
}, },
"performance": { "performance": {
@@ -176,7 +203,5 @@
} }
} }
}, },
"version": 0.4, "version": 0.4
"links": [], }
"last_link_id": 0
}

View File

@@ -1,227 +1,269 @@
{ {
"last_node_id": 12, "last_node_id": 8,
"last_link_id": 10,
"nodes": [ "nodes": [
{ {
"id": 1, "id": 1,
"type": "LoadImage", "type": "LoadImage",
"pos": [ "pos": [50, 100],
50, "size": [350, 100],
100
],
"widgets_values": [
"input_image.png",
"image"
],
"title": "API Input Image",
"flags": {}, "flags": {},
"order": 0, "order": 0,
"mode": 0, "mode": 0,
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [1],
"slot_index": 0
},
{
"name": "MASK",
"type": "MASK",
"links": null,
"slot_index": 1
}
],
"properties": { "properties": {
"Node name for S&R": "LoadImage" "Node name for S&R": "LoadImage"
}, },
"size": { "widgets_values": ["input_image.png", "image"],
"0": 350, "title": "API Input Image"
"1": 100
}
}, },
{ {
"id": 2, "id": 2,
"type": "CheckpointLoaderSimple", "type": "CheckpointLoaderSimple",
"pos": [ "pos": [50, 250],
50, "size": [350, 100],
400
],
"widgets_values": [
"diffusers/stable-diffusion-xl-base-1.0"
],
"title": "SDXL Checkpoint Loader",
"flags": {}, "flags": {},
"order": 1, "order": 1,
"mode": 0, "mode": 0,
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"links": [2],
"slot_index": 0
},
{
"name": "CLIP",
"type": "CLIP",
"links": [3, 4],
"slot_index": 1
},
{
"name": "VAE",
"type": "VAE",
"links": [5],
"slot_index": 2
}
],
"properties": { "properties": {
"Node name for S&R": "CheckpointLoaderSimple" "Node name for S&R": "CheckpointLoaderSimple"
}, },
"size": { "widgets_values": ["sd_xl_base_1.0.safetensors"],
"0": 350, "title": "SDXL Checkpoint Loader"
"1": 100
}
}, },
{ {
"id": 3, "id": 3,
"type": "UpscaleModelLoader", "type": "CLIPTextEncode",
"pos": [ "pos": [450, 100],
50, "size": [400, 200],
600
],
"widgets_values": [
"RealESRGAN_x2.pth"
],
"title": "Upscale Model Loader",
"flags": {}, "flags": {},
"order": 2, "order": 2,
"mode": 0, "mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 3
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"links": [6],
"slot_index": 0
}
],
"properties": { "properties": {
"Node name for S&R": "UpscaleModelLoader" "Node name for S&R": "CLIPTextEncode"
}, },
"size": { "widgets_values": ["high quality, detailed, sharp"],
"0": 350, "title": "API Positive Prompt"
"1": 100
}
}, },
{ {
"id": 4, "id": 4,
"type": "CLIPTextEncode", "type": "CLIPTextEncode",
"pos": [ "pos": [450, 350],
450, "size": [400, 200],
100
],
"widgets_values": [
"high quality, detailed, sharp"
],
"title": "API Positive Prompt",
"flags": {}, "flags": {},
"order": 3, "order": 3,
"mode": 0, "mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 4
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"links": [7],
"slot_index": 0
}
],
"properties": { "properties": {
"Node name for S&R": "CLIPTextEncode" "Node name for S&R": "CLIPTextEncode"
}, },
"size": { "widgets_values": ["blurry, low quality"],
"0": 400, "title": "API Negative Prompt"
"1": 200
}
},
{
"id": 5,
"type": "CLIPTextEncode",
"pos": [
450,
300
],
"widgets_values": [
"blurry, low quality"
],
"title": "API Negative Prompt",
"flags": {},
"order": 4,
"mode": 0,
"properties": {
"Node name for S&R": "CLIPTextEncode"
},
"size": {
"0": 400,
"1": 200
}
},
{
"id": 6,
"type": "UltimateSDUpscale",
"pos": [
800,
100
],
"widgets_values": [
2,
42,
20,
8.0,
"dpmpp_2m",
"karras",
0.3,
"Linear",
512,
64
],
"title": "Ultimate SD Upscale (2x)",
"flags": {},
"order": 5,
"mode": 0,
"properties": {
"Node name for S&R": "UltimateSDUpscale"
},
"size": {
"0": 315,
"1": 100
}
},
{
"id": 7,
"type": "VAEDecode",
"pos": [
1150,
100
],
"title": "VAE Decode",
"flags": {},
"order": 6,
"mode": 0,
"properties": {
"Node name for S&R": "VAEDecode"
},
"size": {
"0": 315,
"1": 100
}
}, },
{ {
"id": 8, "id": 8,
"type": "PreviewImage", "type": "UpscaleModelLoader",
"pos": [ "pos": [50, 400],
1450, "size": [350, 100],
100
],
"title": "Preview Output",
"flags": {}, "flags": {},
"order": 7, "order": 4,
"mode": 0, "mode": 0,
"outputs": [
{
"name": "UPSCALE_MODEL",
"type": "UPSCALE_MODEL",
"links": [10],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "UpscaleModelLoader"
},
"widgets_values": ["RealESRGAN_x2.pth"],
"title": "Upscale Model Loader"
},
{
"id": 5,
"type": "UltimateSDUpscale",
"pos": [900, 100],
"size": [315, 100],
"flags": {},
"order": 5,
"mode": 0,
"inputs": [
{
"name": "image",
"type": "IMAGE",
"link": 1
},
{
"name": "model",
"type": "MODEL",
"link": 2
},
{
"name": "positive",
"type": "CONDITIONING",
"link": 6
},
{
"name": "negative",
"type": "CONDITIONING",
"link": 7
},
{
"name": "vae",
"type": "VAE",
"link": 5
},
{
"name": "upscale_model",
"type": "UPSCALE_MODEL",
"link": 10
}
],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [8, 9],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "UltimateSDUpscale"
},
"widgets_values": [2, 42, "randomize", 20, 8.0, "dpmpp_2m", "karras", 0.3, "Linear", 512, 512, 8, 32, "None", 1.0, 64, 8, 16, true, false],
"title": "Ultimate SD Upscale (2x)"
},
{
"id": 6,
"type": "PreviewImage",
"pos": [1270, 100],
"size": [315, 100],
"flags": {},
"order": 6,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 8
}
],
"properties": { "properties": {
"Node name for S&R": "PreviewImage" "Node name for S&R": "PreviewImage"
}, },
"size": { "title": "Preview Output"
"0": 315,
"1": 100
}
}, },
{ {
"id": 9, "id": 7,
"type": "SaveImage", "type": "SaveImage",
"pos": [ "pos": [1270, 400],
1450, "size": [315, 100],
550
],
"widgets_values": [
"ultimate_upscale_output"
],
"title": "API Image Output",
"flags": {}, "flags": {},
"order": 8, "order": 7,
"mode": 0, "mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 9
}
],
"properties": { "properties": {
"Node name for S&R": "SaveImage" "Node name for S&R": "SaveImage"
}, },
"size": { "widgets_values": ["ultimate_upscale_output"],
"0": 315, "title": "API Image Output"
"1": 100
}
} }
], ],
"links": [
[1, 1, 0, 5, 0, "IMAGE"],
[2, 2, 0, 5, 1, "MODEL"],
[3, 2, 1, 3, 0, "CLIP"],
[4, 2, 1, 4, 0, "CLIP"],
[5, 2, 2, 5, 4, "VAE"],
[6, 3, 0, 5, 2, "CONDITIONING"],
[7, 4, 0, 5, 3, "CONDITIONING"],
[8, 5, 0, 6, 0, "IMAGE"],
[9, 5, 0, 7, 0, "IMAGE"],
[10, 8, 0, 5, 5, "UPSCALE_MODEL"]
],
"groups": [],
"config": {},
"extra": { "extra": {
"workflow_info": { "workflow_info": {
"name": "Ultimate SD Upscale Production", "name": "Ultimate SD Upscale Production",
"version": "1.0.0", "version": "1.1.0",
"description": "Professional upscaling with Ultimate SD Upscale. Combines AI upscaling with diffusion refinement for superior detail and quality.", "description": "Professional upscaling with Ultimate SD Upscale. Combines AI upscaling with diffusion refinement for superior detail and quality.",
"category": "upscaling", "category": "upscaling",
"tags": [ "tags": ["ultimate-sd-upscale", "upscaling", "enhancement", "production"],
"ultimate-sd-upscale",
"upscaling",
"enhancement",
"production"
],
"requirements": { "requirements": {
"models": [ "models": ["stable-diffusion-xl-base-1.0", "RealESRGAN"],
"stable-diffusion-xl-base-1.0", "custom_nodes": ["ComfyUI_UltimateSDUpscale"],
"RealESRGAN"
],
"custom_nodes": [],
"vram_min": "18GB" "vram_min": "18GB"
}, },
"parameters": { "parameters": {
@@ -230,26 +272,57 @@
"type": "image", "type": "image",
"required": true "required": true
}, },
"scale": { "positive_prompt": {
"node_id": 6, "node_id": 3,
"type": "integer", "widget_index": 0,
"default": 2, "type": "string",
"options": [ "default": "high quality, detailed, sharp",
2, "description": "Enhancement prompt"
4
]
}, },
"tile_size": { "negative_prompt": {
"node_id": 6, "node_id": 4,
"type": "integer", "widget_index": 0,
"default": 512, "type": "string",
"description": "Processing tile size" "default": "blurry, low quality",
"description": "Qualities to avoid"
},
"upscale_model": {
"node_id": 8,
"widget_index": 0,
"type": "string",
"default": "RealESRGAN_x2.pth",
"options": ["RealESRGAN_x2.pth", "RealESRGAN_x4.pth"],
"description": "Upscale model to use"
},
"upscale_by": {
"node_id": 5,
"widget_index": 0,
"type": "float",
"default": 2,
"min": 0.05,
"max": 4,
"description": "Upscale factor"
}, },
"denoise": { "denoise": {
"node_id": 6, "node_id": 5,
"widget_index": 6,
"type": "float", "type": "float",
"default": 0.3, "default": 0.3,
"description": "Refinement strength" "description": "Refinement strength"
},
"tile_width": {
"node_id": 5,
"widget_index": 8,
"type": "integer",
"default": 512,
"description": "Tile width for processing"
},
"tile_height": {
"node_id": 5,
"widget_index": 9,
"type": "integer",
"default": 512,
"description": "Tile height for processing"
} }
}, },
"performance": { "performance": {
@@ -258,7 +331,5 @@
} }
} }
}, },
"version": 0.4, "version": 0.4
"links": [], }
"last_link_id": 0
}

View File

@@ -1,471 +0,0 @@
# ============================================================================
# ComfyUI Model Configuration
# ============================================================================
#
# This configuration file defines all available ComfyUI models for download.
# Models are organized by category: image, video, audio, and support models.
#
# Each model entry contains:
# - repo_id: HuggingFace repository identifier
# - description: Human-readable description
# - size_gb: Approximate size in gigabytes
# - essential: Whether this is an essential model (true/false)
# - category: Model category (image/video/audio/support)
#
# ============================================================================
# Global settings
settings:
cache_dir: /workspace/huggingface_cache
parallel_downloads: 1
retry_attempts: 3
timeout_seconds: 3600
# Model categories
model_categories:
# ==========================================================================
# IMAGE GENERATION MODELS
# ==========================================================================
image_models:
- repo_id: black-forest-labs/FLUX.1-schnell
description: FLUX.1 Schnell - Fast 4-step inference
size_gb: 23
essential: true
category: image
type: diffusion_models
format: fp16
vram_gb: 23
notes: Industry-leading image generation quality
files:
- source: "flux1-schnell.safetensors"
dest: "flux1-schnell.safetensors"
- repo_id: black-forest-labs/FLUX.1-dev
description: FLUX.1 Dev - Balanced quality/speed
size_gb: 23
essential: false
category: image
type: diffusion_models
format: fp16
vram_gb: 23
notes: Development version with enhanced features
files:
- source: "flux1-dev.safetensors"
dest: "flux1-dev.safetensors"
- repo_id: runwayml/stable-diffusion-v1-5
description: SD 1.5 - For AnimateDiff
size_gb: 4
essential: true
category: image
type: checkpoints
format: fp16
vram_gb: 8
notes: Stable Diffusion 1.5 required for AnimateDiff motion modules
files:
- source: "v1-5-pruned-emaonly.safetensors"
dest: "v1-5-pruned-emaonly.safetensors"
- repo_id: stabilityai/stable-diffusion-xl-base-1.0
description: SDXL Base 1.0 - Industry standard
size_gb: 7
essential: true
category: image
type: checkpoints
format: fp16
vram_gb: 12
notes: Most widely used Stable Diffusion model
files:
- source: "sd_xl_base_1.0.safetensors"
dest: "sd_xl_base_1.0.safetensors"
- repo_id: stabilityai/stable-diffusion-xl-refiner-1.0
description: SDXL Refiner 1.0 - Enhances base output
size_gb: 6
essential: false
category: image
type: checkpoints
format: fp16
vram_gb: 12
notes: Use after SDXL base for improved details
files:
- source: "sd_xl_refiner_1.0.safetensors"
dest: "sd_xl_refiner_1.0.safetensors"
- repo_id: stabilityai/stable-diffusion-3.5-large
description: SD 3.5 Large - Latest Stability AI
size_gb: 18
essential: false
category: image
type: checkpoints
format: fp16
vram_gb: 20
notes: Newest generation Stable Diffusion
files:
- source: "sd3.5_large.safetensors"
dest: "sd3.5_large.safetensors"
# ==========================================================================
# VIDEO GENERATION MODELS
# ==========================================================================
video_models:
- repo_id: THUDM/CogVideoX-5b
description: CogVideoX-5B - Professional text-to-video
size_gb: 20
essential: true
category: video
type: diffusion_models
format: fp16
vram_gb: 20
frames: 49
resolution: 720p
notes: State-of-the-art text-to-video generation
files:
- source: "transformer/diffusion_pytorch_model.safetensors"
dest: "cogvideox-5b-transformer.safetensors"
- repo_id: stabilityai/stable-video-diffusion-img2vid
description: SVD - 14 frame image-to-video
size_gb: 8
essential: true
category: video
type: checkpoints
format: fp16
vram_gb: 20
frames: 14
resolution: 576x1024
notes: Convert images to short video clips
files:
- source: "svd.safetensors"
dest: "svd.safetensors"
- repo_id: stabilityai/stable-video-diffusion-img2vid-xt
description: SVD-XT - 25 frame image-to-video
size_gb: 8
essential: false
category: video
type: checkpoints
format: fp16
vram_gb: 20
frames: 25
resolution: 576x1024
notes: Extended frame count version
files:
- source: "svd_xt.safetensors"
dest: "svd_xt.safetensors"
# ==========================================================================
# AUDIO GENERATION MODELS
# ==========================================================================
audio_models:
- repo_id: facebook/musicgen-small
description: MusicGen Small - Fast generation
size_gb: 3
essential: false
category: audio
type: musicgen
format: fp32
vram_gb: 4
duration_seconds: 30
notes: Fastest music generation, lower quality
files:
- source: "pytorch_model.bin"
dest: "musicgen-small-pytorch_model.bin"
- repo_id: facebook/musicgen-medium
description: MusicGen Medium - Balanced quality
size_gb: 11
essential: true
category: audio
type: musicgen
format: fp32
vram_gb: 8
duration_seconds: 30
notes: Best balance of speed and quality
files:
- source: "pytorch_model.bin"
dest: "musicgen-medium-pytorch_model.bin"
- repo_id: facebook/musicgen-large
description: MusicGen Large - Highest quality
size_gb: 22
essential: false
category: audio
type: musicgen
format: fp32
vram_gb: 16
duration_seconds: 30
notes: Best quality, slower generation
files:
- source: "pytorch_model-00001-of-00002.bin"
dest: "musicgen-large-pytorch_model-00001-of-00002.bin"
- source: "pytorch_model-00002-of-00002.bin"
dest: "musicgen-large-pytorch_model-00002-of-00002.bin"
- source: "pytorch_model.bin.index.json"
dest: "musicgen-large-pytorch_model.bin.index.json"
# ==========================================================================
# SUPPORT MODELS (CLIP, IP-Adapter, etc.)
# ==========================================================================
support_models:
- repo_id: openai/clip-vit-large-patch14
description: CLIP H - For SD 1.5 IP-Adapter
size_gb: 2
essential: true
category: support
type: clip_vision
format: fp32
vram_gb: 2
notes: Text-image understanding model for IP-Adapter
files:
- source: "model.safetensors"
dest: "CLIP-ViT-H-14-laion2B-s32B-b79K.safetensors"
- repo_id: laion/CLIP-ViT-bigG-14-laion2B-39B-b160k
description: CLIP G - For SDXL IP-Adapter
size_gb: 7
essential: true
category: support
type: clip_vision
format: fp32
vram_gb: 4
notes: Larger CLIP model for SDXL IP-Adapter
files:
- source: "open_clip_model.safetensors"
dest: "CLIP-ViT-bigG-14-laion2B-39B-b160k.safetensors"
- repo_id: google/siglip-so400m-patch14-384
description: SigLIP - For FLUX models
size_gb: 2
essential: true
category: support
type: clip_vision
format: fp32
vram_gb: 2
notes: Advanced image-text alignment
files:
- source: "model.safetensors"
dest: "siglip-so400m-patch14-384.safetensors"
# ==========================================================================
# ANIMATEDIFF MODELS
# ==========================================================================
animatediff_models:
- repo_id: guoyww/animatediff
description: AnimateDiff Motion Modules
size_gb: 2
essential: true
category: animatediff
type: animatediff_models
filename: mm_sd_v15
format: safetensors
vram_gb: 4
notes: Motion modules for AnimateDiff text-to-video
files:
- source: "mm_sd_v15_v2.ckpt"
dest: "mm_sd_v15_v2.ckpt"
# ==========================================================================
# CONTROLNET MODELS
# ==========================================================================
controlnet_models:
- repo_id: lllyasviel/control_v11p_sd15_canny
description: ControlNet Canny - Edge detection control for SD 1.5
size_gb: 1.5
essential: false
category: controlnet
type: controlnet
format: safetensors
vram_gb: 2
notes: Precise edge-based composition control
files:
- source: "diffusion_pytorch_model.safetensors"
dest: "control_v11p_sd15_canny.safetensors"
- repo_id: lllyasviel/control_v11f1p_sd15_depth
description: ControlNet Depth - Depth map control for SD 1.5
size_gb: 1.5
essential: false
category: controlnet
type: controlnet
format: safetensors
vram_gb: 2
notes: Depth-based spatial control
files:
- source: "diffusion_pytorch_model.safetensors"
dest: "control_v11p_sd15_depth.safetensors"
- repo_id: diffusers/controlnet-canny-sdxl-1.0
description: ControlNet Canny SDXL - Edge detection for SDXL
size_gb: 2.5
essential: false
category: controlnet
type: controlnet
format: safetensors
vram_gb: 3
notes: Canny edge control for SDXL models
files:
- source: "diffusion_pytorch_model.safetensors"
dest: "controlnet-canny-sdxl-1.0.safetensors"
- repo_id: diffusers/controlnet-depth-sdxl-1.0
description: ControlNet Depth SDXL - Depth map for SDXL
size_gb: 2.5
essential: false
category: controlnet
type: controlnet
format: safetensors
vram_gb: 3
notes: Depth control for SDXL models
files:
- source: "diffusion_pytorch_model.safetensors"
dest: "controlnet-depth-sdxl-1.0.safetensors"
# ==========================================================================
# IP-ADAPTER MODELS
# ==========================================================================
ipadapter_models:
- repo_id: h94/IP-Adapter
description: IP-Adapter SDXL Base - Style & Composition
size_gb: 1.3
essential: true
category: ipadapter
type: ipadapter
format: safetensors
vram_gb: 4
notes: Basic IP-Adapter for SDXL
files:
- source: "sdxl_models/ip-adapter_sdxl.safetensors"
dest: "ip-adapter_sdxl.safetensors"
- repo_id: h94/IP-Adapter
description: IP-Adapter SDXL VIT-H - For CLIP-ViT-H
size_gb: 0.9
essential: true
category: ipadapter
type: ipadapter
format: safetensors
vram_gb: 4
notes: IP-Adapter for SDXL with VIT-H CLIP vision model
files:
- source: "sdxl_models/ip-adapter_sdxl_vit-h.safetensors"
dest: "ip-adapter_sdxl_vit-h.safetensors"
- repo_id: h94/IP-Adapter
description: IP-Adapter SDXL Plus - High Strength Composition
size_gb: 0.9
essential: false
category: ipadapter
type: ipadapter
format: safetensors
vram_gb: 4
notes: Enhanced composition control with higher strength
files:
- source: "sdxl_models/ip-adapter-plus_sdxl_vit-h.safetensors"
dest: "ip-adapter-plus_sdxl_vit-h.safetensors"
- repo_id: h94/IP-Adapter
description: IP-Adapter SDXL Plus Face - Face-focused generation
size_gb: 0.5
essential: false
category: ipadapter
type: ipadapter
format: safetensors
vram_gb: 4
notes: Specialized for face transfer and portrait generation
files:
- source: "sdxl_models/ip-adapter-plus-face_sdxl_vit-h.safetensors"
dest: "ip-adapter-plus-face_sdxl_vit-h.safetensors"
# ============================================================================
# STORAGE & VRAM SUMMARIES
# ============================================================================
storage_requirements:
essential_only:
image: 30 # FLUX Schnell + SDXL Base
video: 28 # CogVideoX + SVD
audio: 11 # MusicGen Medium
support: 11 # All 3 CLIP models
total: 80 # Total essential storage
all_models:
image: 54 # All image models
video: 36 # All video models
audio: 36 # All audio models
support: 11 # All support models
total: 137 # Total with optional models
vram_requirements:
# For 24GB GPU (RTX 4090)
simultaneous_loadable:
- name: Image Focus - FLUX FP16
models: [FLUX.1 Schnell]
vram_used: 23
remaining: 1
- name: Image Focus - FLUX FP8 + SDXL
models: [FLUX.1 Schnell FP8, SDXL Base]
vram_used: 24
remaining: 0
- name: Video Generation
models: [CogVideoX-5B optimized, SDXL]
vram_used: 24
remaining: 0
- name: Multi-Modal
models: [SDXL, MusicGen Medium]
vram_used: 20
remaining: 4
# ============================================================================
# INSTALLATION PROFILES
# ============================================================================
installation_profiles:
minimal:
description: Minimal setup for testing
categories: [support_models]
storage_gb: 11
estimated_time: 5-10 minutes
essential:
description: Essential models only (~80GB)
categories: [image_models, video_models, audio_models, support_models]
essential_only: true
storage_gb: 80
estimated_time: 1-2 hours
image_focused:
description: All image generation models
categories: [image_models, support_models]
storage_gb: 65
estimated_time: 45-90 minutes
video_focused:
description: All video generation models
categories: [video_models, image_models, support_models]
essential_only: true
storage_gb: 69
estimated_time: 1-2 hours
complete:
description: All models (including optional)
categories: [image_models, video_models, audio_models, support_models]
storage_gb: 137
estimated_time: 2-4 hours
# ============================================================================
# METADATA
# ============================================================================
metadata:
version: 1.0.0
last_updated: 2025-11-21
compatible_with:
- ComfyUI >= 0.1.0
- Python >= 3.10
- HuggingFace Hub >= 0.20.0
maintainer: Valknar
repository: https://github.com/yourusername/runpod

View File

@@ -1,77 +0,0 @@
# Model Registry for AI Orchestrator
# Add new models by appending to this file
models:
# Text Generation Models
qwen-2.5-7b:
type: text
framework: vllm
service_script: models/vllm/server.py
port: 8000
vram_gb: 14
startup_time_seconds: 120
endpoint: /v1/chat/completions
description: "Qwen 2.5 7B Instruct - Fast text generation, no authentication required"
llama-3.1-8b:
type: text
framework: vllm
service_script: models/vllm/server.py
port: 8001
vram_gb: 17
startup_time_seconds: 120
endpoint: /v1/chat/completions
description: "Llama 3.1 8B Instruct - Meta's latest model"
# Example: Add more models easily by uncommenting and customizing below
# Future Text Models:
# llama-3.1-8b:
# type: text
# framework: vllm
# docker_service: vllm-llama
# port: 8004
# vram_gb: 17
# startup_time_seconds: 120
# endpoint: /v1/chat/completions
# description: "Llama 3.1 8B Instruct - Meta's latest model"
# Future Image Models:
# sdxl:
# type: image
# framework: openedai-images
# docker_service: sdxl
# port: 8005
# vram_gb: 10
# startup_time_seconds: 45
# endpoint: /v1/images/generations
# description: "Stable Diffusion XL - High quality image generation"
# Future Audio Models:
# whisper-large:
# type: audio
# framework: faster-whisper
# docker_service: whisper
# port: 8006
# vram_gb: 3
# startup_time_seconds: 30
# endpoint: /v1/audio/transcriptions
# description: "Whisper Large v3 - Speech-to-text transcription"
#
# xtts-v2:
# type: audio
# framework: openedai-speech
# docker_service: tts
# port: 8007
# vram_gb: 3
# startup_time_seconds: 30
# endpoint: /v1/audio/speech
# description: "XTTS v2 - High-quality text-to-speech with voice cloning"
# Configuration
config:
gpu_memory_total_gb: 24
allow_concurrent_loading: false # Sequential loading only
model_switch_timeout_seconds: 300 # 5 minutes max for model switching
health_check_interval_seconds: 10
default_model: qwen-2.5-7b

View File

@@ -1,404 +0,0 @@
#!/usr/bin/env python3
"""
AI Model Orchestrator for RunPod RTX 4090
Manages sequential loading of text, image, and music models on a single GPU
Features:
- Automatic model switching based on request type
- OpenAI-compatible API endpoints
- Docker Compose service management
- GPU memory monitoring
- Simple YAML configuration for adding new models
"""
import asyncio
import logging
import os
import time
from typing import Dict, Optional, Any
import docker
import httpx
import yaml
from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import JSONResponse, StreamingResponse
from pydantic import BaseModel
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
# FastAPI app
app = FastAPI(title="AI Model Orchestrator", version="1.0.0")
# Docker client
docker_client = docker.from_env()
# Global state
current_model: Optional[str] = None
model_registry: Dict[str, Dict[str, Any]] = {}
config: Dict[str, Any] = {}
def load_model_registry():
"""Load model registry from models.yaml"""
global model_registry, config
config_path = os.getenv("MODELS_CONFIG", "/app/models.yaml")
logger.info(f"Loading model registry from {config_path}")
with open(config_path, 'r') as f:
data = yaml.safe_load(f)
model_registry = data.get('models', {})
config = data.get('config', {})
logger.info(f"Loaded {len(model_registry)} models from registry")
for model_name, model_info in model_registry.items():
logger.info(f" - {model_name}: {model_info['description']}")
def get_docker_service_name(service_name: str) -> str:
"""Get full Docker service name with project prefix"""
project_name = os.getenv("COMPOSE_PROJECT_NAME", "ai")
return f"{project_name}_{service_name}_1"
async def stop_current_model():
"""Stop the currently running model service"""
global current_model
if not current_model:
logger.info("No model currently running")
return
model_info = model_registry.get(current_model)
if not model_info:
logger.warning(f"Model {current_model} not found in registry")
current_model = None
return
service_name = get_docker_service_name(model_info['docker_service'])
logger.info(f"Stopping model: {current_model} (service: {service_name})")
try:
container = docker_client.containers.get(service_name)
container.stop(timeout=30)
logger.info(f"Stopped {current_model}")
current_model = None
except docker.errors.NotFound:
logger.warning(f"Container {service_name} not found (already stopped?)")
current_model = None
except Exception as e:
logger.error(f"Error stopping {service_name}: {e}")
raise
async def start_model(model_name: str):
"""Start a model service"""
global current_model
if model_name not in model_registry:
raise HTTPException(status_code=404, detail=f"Model {model_name} not found in registry")
model_info = model_registry[model_name]
service_name = get_docker_service_name(model_info['docker_service'])
logger.info(f"Starting model: {model_name} (service: {service_name})")
logger.info(f" VRAM requirement: {model_info['vram_gb']} GB")
logger.info(f" Estimated startup time: {model_info['startup_time_seconds']}s")
try:
# Start the container
container = docker_client.containers.get(service_name)
container.start()
# Wait for service to be healthy
port = model_info['port']
endpoint = model_info.get('endpoint', '/')
base_url = f"http://localhost:{port}"
logger.info(f"Waiting for {model_name} to be ready at {base_url}...")
max_wait = model_info['startup_time_seconds'] + 60 # Add buffer
start_time = time.time()
async with httpx.AsyncClient() as client:
while time.time() - start_time < max_wait:
try:
# Try health check or root endpoint
health_url = f"{base_url}/health"
try:
response = await client.get(health_url, timeout=5.0)
if response.status_code == 200:
logger.info(f"{model_name} is ready!")
current_model = model_name
return
except:
# Try root endpoint if /health doesn't exist
response = await client.get(base_url, timeout=5.0)
if response.status_code == 200:
logger.info(f"{model_name} is ready!")
current_model = model_name
return
except Exception as e:
logger.debug(f"Waiting for {model_name}... ({e})")
await asyncio.sleep(5)
raise HTTPException(
status_code=503,
detail=f"Model {model_name} failed to start within {max_wait}s"
)
except docker.errors.NotFound:
raise HTTPException(
status_code=500,
detail=f"Docker service {service_name} not found. Is it defined in docker-compose?"
)
except Exception as e:
logger.error(f"Error starting {model_name}: {e}")
raise HTTPException(status_code=500, detail=str(e))
async def ensure_model_running(model_name: str):
"""Ensure the specified model is running, switching if necessary"""
global current_model
if current_model == model_name:
logger.info(f"Model {model_name} already running")
return
logger.info(f"Switching model: {current_model} -> {model_name}")
# Stop current model
await stop_current_model()
# Start requested model
await start_model(model_name)
logger.info(f"Model switch complete: {model_name} is now active")
async def proxy_request(model_name: str, request: Request):
"""Proxy request to the active model service"""
model_info = model_registry[model_name]
port = model_info['port']
# Get request details
path = request.url.path
method = request.method
headers = dict(request.headers)
headers.pop('host', None) # Remove host header
# Build target URL
target_url = f"http://localhost:{port}{path}"
# Check if this is a streaming request
body = await request.body()
is_streaming = False
if method == "POST" and body:
try:
import json
body_json = json.loads(body)
is_streaming = body_json.get('stream', False)
except:
pass
logger.info(f"Proxying {method} request to {target_url} (streaming: {is_streaming})")
if is_streaming:
# For streaming requests, use httpx streaming and yield chunks
async def stream_response():
async with httpx.AsyncClient(timeout=300.0) as client:
async with client.stream(method, target_url, content=body, headers=headers) as response:
async for chunk in response.aiter_bytes():
yield chunk
return StreamingResponse(
stream_response(),
media_type="text/event-stream",
headers={"Cache-Control": "no-cache", "Connection": "keep-alive"}
)
else:
# For non-streaming requests, use the original behavior
async with httpx.AsyncClient(timeout=300.0) as client:
if method == "GET":
response = await client.get(target_url, headers=headers)
elif method == "POST":
response = await client.post(target_url, content=body, headers=headers)
else:
raise HTTPException(status_code=405, detail=f"Method {method} not supported")
# Return response
return JSONResponse(
content=response.json() if response.headers.get('content-type', '').startswith('application/json') else response.text,
status_code=response.status_code,
headers=dict(response.headers)
)
@app.on_event("startup")
async def startup_event():
"""Load model registry on startup"""
load_model_registry()
logger.info("AI Model Orchestrator started successfully")
logger.info(f"GPU Memory: {config.get('gpu_memory_total_gb', 24)} GB")
logger.info(f"Default model: {config.get('default_model', 'qwen-2.5-7b')}")
@app.get("/")
async def root():
"""Root endpoint"""
return {
"service": "AI Model Orchestrator",
"version": "1.0.0",
"current_model": current_model,
"available_models": list(model_registry.keys())
}
@app.get("/health")
async def health():
"""Health check endpoint"""
return {
"status": "healthy",
"current_model": current_model,
"model_info": model_registry.get(current_model) if current_model else None,
"gpu_memory_total_gb": config.get('gpu_memory_total_gb', 24),
"models_available": len(model_registry)
}
@app.get("/models")
async def list_models():
"""List all available models"""
return {
"models": model_registry,
"current_model": current_model
}
@app.get("/v1/models")
async def list_models_openai():
"""OpenAI-compatible models listing endpoint"""
models_list = []
for model_name, model_info in model_registry.items():
models_list.append({
"id": model_name,
"object": "model",
"created": int(time.time()),
"owned_by": "pivoine-gpu",
"permission": [],
"root": model_name,
"parent": None,
})
return {
"object": "list",
"data": models_list
}
@app.post("/v1/chat/completions")
async def chat_completions(request: Request):
"""OpenAI-compatible chat completions endpoint (text models)"""
# Parse request to get model name
body = await request.json()
model_name = body.get('model', config.get('default_model', 'qwen-2.5-7b'))
# Validate model type
if model_name not in model_registry:
raise HTTPException(status_code=404, detail=f"Model {model_name} not found")
if model_registry[model_name]['type'] != 'text':
raise HTTPException(status_code=400, detail=f"Model {model_name} is not a text model")
# Ensure model is running
await ensure_model_running(model_name)
# Proxy request to model
return await proxy_request(model_name, request)
@app.post("/v1/images/generations")
async def image_generations(request: Request):
"""OpenAI-compatible image generation endpoint"""
# Parse request to get model name
body = await request.json()
model_name = body.get('model', 'flux-schnell')
# Validate model type
if model_name not in model_registry:
raise HTTPException(status_code=404, detail=f"Model {model_name} not found")
if model_registry[model_name]['type'] != 'image':
raise HTTPException(status_code=400, detail=f"Model {model_name} is not an image model")
# Ensure model is running
await ensure_model_running(model_name)
# Proxy request to model
return await proxy_request(model_name, request)
@app.post("/v1/audio/generations")
async def audio_generations(request: Request):
"""Custom audio generation endpoint (music/sound effects)"""
# Parse request to get model name
body = await request.json()
model_name = body.get('model', 'musicgen-medium')
# Validate model type
if model_name not in model_registry:
raise HTTPException(status_code=404, detail=f"Model {model_name} not found")
if model_registry[model_name]['type'] != 'audio':
raise HTTPException(status_code=400, detail=f"Model {model_name} is not an audio model")
# Ensure model is running
await ensure_model_running(model_name)
# Proxy request to model
return await proxy_request(model_name, request)
@app.post("/switch")
async def switch_model(request: Request):
"""Manually switch to a specific model"""
body = await request.json()
model_name = body.get('model')
if not model_name:
raise HTTPException(status_code=400, detail="Model name required")
if model_name not in model_registry:
raise HTTPException(status_code=404, detail=f"Model {model_name} not found")
await ensure_model_running(model_name)
return {
"status": "success",
"model": model_name,
"message": f"Switched to {model_name}"
}
if __name__ == "__main__":
import uvicorn
host = os.getenv("HOST", "0.0.0.0")
port = int(os.getenv("PORT", "9000"))
logger.info(f"Starting AI Model Orchestrator on {host}:{port}")
uvicorn.run(
app,
host=host,
port=port,
log_level="info",
access_log=True,
)

View File

@@ -1,317 +0,0 @@
#!/usr/bin/env python3
"""
AI Model Orchestrator for RunPod (Process-Based)
Manages sequential loading of AI models using subprocess instead of Docker
Simplified architecture for RunPod's containerized environment:
- No Docker-in-Docker complexity
- Direct process management via subprocess
- Models run as Python background processes
- GPU memory efficient (sequential model loading)
"""
import asyncio
import logging
import os
import subprocess
import time
import signal
from typing import Dict, Optional, Any
from pathlib import Path
import httpx
import yaml
import psutil
from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import JSONResponse, StreamingResponse
from pydantic import BaseModel
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
# FastAPI app
app = FastAPI(title="AI Model Orchestrator (Process-Based)", version="2.0.0")
# Global state
current_model: Optional[str] = None
model_processes: Dict[str, subprocess.Popen] = {}
model_registry: Dict[str, Dict[str, Any]] = {}
config: Dict[str, Any] = {}
def load_model_registry():
"""Load model registry from models.yaml"""
global model_registry, config
config_path = os.getenv("MODELS_CONFIG", "/workspace/ai/model-orchestrator/models.yaml")
logger.info(f"Loading model registry from {config_path}")
with open(config_path, 'r') as f:
data = yaml.safe_load(f)
model_registry = data.get('models', {})
config = data.get('config', {})
logger.info(f"Loaded {len(model_registry)} models")
for model_name, model_config in model_registry.items():
logger.info(f" - {model_name}: {model_config.get('type')} ({model_config.get('framework')})")
async def start_model_process(model_name: str) -> bool:
"""Start a model as a subprocess"""
global current_model, model_processes
if model_name not in model_registry:
logger.error(f"Model {model_name} not found in registry")
return False
model_config = model_registry[model_name]
# Stop current model if running
if current_model and current_model != model_name:
await stop_model_process(current_model)
# Check if already running
if model_name in model_processes:
proc = model_processes[model_name]
if proc.poll() is None: # Still running
logger.info(f"Model {model_name} already running")
return True
logger.info(f"Starting model {model_name}...")
try:
# Get service command from config
service_script = model_config.get('service_script')
if not service_script:
logger.error(f"No service_script defined for {model_name}")
return False
script_path = Path(f"/workspace/ai/{service_script}")
if not script_path.exists():
logger.error(f"Service script not found: {script_path}")
return False
# Start process
port = model_config.get('port', 8000)
env = os.environ.copy()
env.update({
'HF_TOKEN': os.getenv('HF_TOKEN', ''),
'PORT': str(port),
'HOST': '0.0.0.0'
})
proc = subprocess.Popen(
['python3', str(script_path)],
env=env,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
preexec_fn=os.setsid # Create new process group
)
model_processes[model_name] = proc
# Wait for service to be ready
max_wait = model_config.get('startup_time_seconds', 120)
start_time = time.time()
while time.time() - start_time < max_wait:
if proc.poll() is not None:
logger.error(f"Process for {model_name} exited prematurely")
return False
try:
async with httpx.AsyncClient() as client:
response = await client.get(
f"http://localhost:{port}/health",
timeout=5.0
)
if response.status_code == 200:
logger.info(f"Model {model_name} is ready on port {port}")
current_model = model_name
return True
except:
await asyncio.sleep(2)
logger.error(f"Model {model_name} failed to start within {max_wait}s")
await stop_model_process(model_name)
return False
except Exception as e:
logger.error(f"Error starting {model_name}: {e}")
return False
async def stop_model_process(model_name: str):
"""Stop a running model process"""
global model_processes, current_model
if model_name not in model_processes:
logger.warning(f"Model {model_name} not in process registry")
return
proc = model_processes[model_name]
if proc.poll() is None: # Still running
logger.info(f"Stopping model {model_name}...")
try:
# Send SIGTERM to process group
os.killpg(os.getpgid(proc.pid), signal.SIGTERM)
# Wait for graceful shutdown
try:
proc.wait(timeout=10)
except subprocess.TimeoutExpired:
# Force kill if not terminated
os.killpg(os.getpgid(proc.pid), signal.SIGKILL)
proc.wait()
logger.info(f"Model {model_name} stopped")
except Exception as e:
logger.error(f"Error stopping {model_name}: {e}")
del model_processes[model_name]
if current_model == model_name:
current_model = None
def get_model_for_endpoint(endpoint: str) -> Optional[str]:
"""Determine which model handles this endpoint"""
for model_name, model_config in model_registry.items():
if endpoint.startswith(model_config.get('endpoint', '')):
return model_name
return None
@app.on_event("startup")
async def startup_event():
"""Initialize on startup"""
logger.info("Starting AI Model Orchestrator (Process-Based)")
load_model_registry()
@app.on_event("shutdown")
async def shutdown_event():
"""Cleanup on shutdown"""
logger.info("Shutting down orchestrator...")
for model_name in list(model_processes.keys()):
await stop_model_process(model_name)
@app.get("/health")
async def health_check():
"""Health check endpoint"""
return {
"status": "healthy",
"current_model": current_model,
"active_processes": len(model_processes),
"available_models": list(model_registry.keys())
}
@app.get("/v1/models")
async def list_models_openai():
"""OpenAI-compatible models listing endpoint"""
models_list = []
for model_name, model_info in model_registry.items():
models_list.append({
"id": model_name,
"object": "model",
"created": int(time.time()),
"owned_by": "pivoine-gpu",
"permission": [],
"root": model_name,
"parent": None,
})
return {
"object": "list",
"data": models_list
}
@app.api_route("/{path:path}", methods=["GET", "POST", "PUT", "DELETE", "PATCH"])
async def proxy_request(request: Request, path: str):
"""Proxy requests to appropriate model service"""
endpoint = f"/{path}"
# Determine which model should handle this
target_model = get_model_for_endpoint(endpoint)
if not target_model:
raise HTTPException(status_code=404, detail=f"No model configured for endpoint: {endpoint}")
# Ensure model is running
if current_model != target_model:
logger.info(f"Switching to model {target_model}")
success = await start_model_process(target_model)
if not success:
raise HTTPException(status_code=503, detail=f"Failed to start model {target_model}")
# Proxy the request
model_config = model_registry[target_model]
target_url = f"http://localhost:{model_config['port']}/{path}"
# Get request details
method = request.method
headers = dict(request.headers)
headers.pop('host', None) # Remove host header
body = await request.body()
# Check if this is a streaming request
is_streaming = False
if method == "POST" and body:
try:
import json
body_json = json.loads(body)
is_streaming = body_json.get('stream', False)
except:
pass
logger.info(f"Proxying {method} request to {target_url} (streaming: {is_streaming})")
try:
if is_streaming:
# For streaming requests, use httpx streaming and yield chunks
async def stream_response():
async with httpx.AsyncClient(timeout=300.0) as client:
async with client.stream(method, target_url, content=body, headers=headers) as response:
async for chunk in response.aiter_bytes():
yield chunk
return StreamingResponse(
stream_response(),
media_type="text/event-stream",
headers={"Cache-Control": "no-cache", "Connection": "keep-alive"}
)
else:
# For non-streaming requests, use the original behavior
async with httpx.AsyncClient(timeout=300.0) as client:
response = await client.request(
method=method,
url=target_url,
headers=headers,
content=body
)
return JSONResponse(
content=response.json() if response.headers.get('content-type') == 'application/json' else response.text,
status_code=response.status_code
)
except Exception as e:
logger.error(f"Error proxying request: {e}")
raise HTTPException(status_code=502, detail=str(e))
if __name__ == "__main__":
import uvicorn
port = int(os.getenv("PORT", "9000"))
host = os.getenv("HOST", "0.0.0.0")
logger.info(f"Starting orchestrator on {host}:{port}")
uvicorn.run(app, host=host, port=port, log_level="info")

View File

@@ -1,6 +0,0 @@
fastapi==0.104.1
uvicorn[standard]==0.24.0
httpx==0.25.1
docker==6.1.3
pyyaml==6.0.1
pydantic==2.5.0

393
models_civitai.yaml Normal file
View File

@@ -0,0 +1,393 @@
# ============================================================================
# CivitAI Model Configuration
# ============================================================================
#
# This configuration file defines all available CivitAI models for download.
# Models are organized by category: NSFW checkpoints, LoRAs, embeddings, etc.
#
# Each model entry contains:
# - name: Filesystem-friendly model name
# - version_id: CivitAI version ID (used for downloads)
# - model_id: CivitAI model ID (used for metadata queries)
# - description: Human-readable description
# - size_gb: Approximate size in gigabytes
# - essential: Whether this is an essential model (true/false)
# - type: Model type (checkpoints, loras, embeddings, etc.)
# - tags: Array of descriptive tags
#
# ============================================================================
# Global settings
settings:
cache_dir: /workspace/models/civitai
output_dir: /workspace/ComfyUI/models
parallel_downloads: 1
retry_attempts: 3
timeout_seconds: 3600
rate_limit_delay: 5 # seconds between downloads
# Model categories
model_categories:
# ==========================================================================
# NSFW IMAGE GENERATION MODELS
# ==========================================================================
nsfw_checkpoints:
- name: lustify-v7-ggwp
version_id: "1094291"
model_id: "573152"
description: "LUSTIFY v7.0 GGWP - Photoreal NSFW checkpoint for women in sexual scenarios"
size_gb: 6.31
essential: true
type: checkpoints
format: safetensors
base_model: SDXL 1.0
vram_gb: 12
tags: [nsfw, realistic, photography, women]
recommended_settings:
sampler: "DPM++ 2M SDE / DPM++ 3M SDE"
scheduler: "Exponential / Karras"
steps: 30
cfg_scale: "4-7"
notes: "Understands both danbooru tags and natural language prompting"
- name: pony-diffusion-v6-xl
version_id: "135867"
model_id: "257749"
description: "Pony Diffusion V6 XL - Versatile anime/cartoon/furry model with balanced content"
size_gb: 6.5
essential: true
type: checkpoints
format: safetensors
base_model: SDXL 1.0
vram_gb: 12
tags: [nsfw, anime, furry, cartoon, versatile]
files:
- source: "ponyDiffusionV6XL_v6StartWithThisOne.safetensors"
dest: "ponyDiffusionV6XL_v6StartWithThisOne.safetensors"
training_info:
images: "2.6M aesthetically ranked"
ratio: "1:1:1 safe/questionable/explicit"
notes: "Most popular anime/furry model on CivitAI, supports wide range of styles"
- name: realvisxl-v5
version_id: "798204"
model_id: "139562"
description: "RealVisXL V5.0 Lightning - Photorealistic model for high-quality realistic images"
size_gb: 6.8
essential: true
type: checkpoints
format: safetensors
base_model: SDXL 1.0
vram_gb: 12
tags: [nsfw, realistic, photorealistic, professional]
recommended_settings:
sampler: "DPM++ SDE Karras (4-6 steps for Lightning)"
notes: "Excellent for photorealistic portraits and scenes, both SFW and NSFW. Lightning version for faster generation."
- name: wai-nsfw-illustrious-sdxl
version_id: "2167369"
model_id: "827184"
description: "WAI-NSFW-illustrious-SDXL v15.0 - Actively updated NSFW Illustrious variant"
size_gb: 6.5
essential: false
type: checkpoints
format: safetensors
base_model: SDXL 1.0
vram_gb: 12
tags: [nsfw, anime, illustrious, artistic]
notes: "Latest version from November 2025, frequently updated"
- name: talmendoxl
version_id: "131869"
model_id: "119202"
description: "TalmendoXL - Uncensored SDXL model biased towards photorealism"
size_gb: 6.6
essential: false
type: checkpoints
format: safetensors
base_model: SDXL 1.0
vram_gb: 12
tags: [nsfw, realistic, uncensored, photorealistic]
notes: "Known for high-quality photorealistic NSFW content"
- name: big-lust-v1-6
version_id: "1081768"
model_id: "575395"
description: "Big Lust v1.6 - SDXL NSFW checkpoint"
size_gb: 6.5
essential: false
type: checkpoints
format: safetensors
base_model: SDXL 1.0
vram_gb: 12
tags: [nsfw, versatile]
notes: "General-purpose NSFW model with good results across styles"
# ==========================================================================
# NEGATIVE EMBEDDINGS - SD 1.5 (Textual Inversions)
# ==========================================================================
embeddings_sd15:
- name: baddream
version_id: "77169"
model_id: "72437"
description: "BadDream v1.0 - Negative embedding for dreamshaper style artifacts"
size_gb: 0.0002
essential: true
type: embeddings
format: pt
base_model: SD 1.5
tags: [negative, quality, sd15]
trigger_word: "BadDream"
usage: "embedding:BadDream"
notes: "Use in negative prompt. Best combined with UnrealisticDream for optimal results."
- name: unrealisticdream
version_id: "77173"
model_id: "72437"
description: "UnrealisticDream v1.0 - Improves realistic images, pairs with BadDream"
size_gb: 0.0001
essential: true
type: embeddings
format: pt
base_model: SD 1.5
tags: [negative, realistic, sd15]
trigger_word: "UnrealisticDream"
usage: "embedding:UnrealisticDream"
notes: "Use together with BadDream for best results on realistic images."
- name: badhandv4
version_id: "20068"
model_id: "16993"
description: "badhandv4 - Improves hand details with minimal style impact"
size_gb: 0.00002
essential: true
type: embeddings
format: pt
base_model: SD 1.5
tags: [negative, hands, anatomy, sd15]
trigger_word: "badhandv4"
usage: "embedding:badhandv4"
recommended_settings:
cfg_scale: "≥11"
notes: "Designed for AnimeIllustDiffusion but works with other SD 1.5 models. Better results at higher CFG."
- name: easynegative
version_id: "9208"
model_id: "7808"
description: "EasyNegative - General-purpose negative embedding"
size_gb: 0.00002
essential: false
type: embeddings
format: safetensors
base_model: SD 1.5
tags: [negative, quality, sd15]
trigger_word: "easynegative"
usage: "embedding:easynegative"
notes: "Optimized for Counterfeit model. Effectiveness varies by model."
- name: fastnegativev2
version_id: "94057"
model_id: "71961"
description: "FastNegativeV2 - Token mix of common negative prompts"
size_gb: 0.0002
essential: true
type: embeddings
format: pt
base_model: SD 1.5
tags: [negative, quality, sd15]
trigger_word: "FastNegativeV2"
usage: "embedding:FastNegativeV2"
notes: "V2 is balanced and doesn't require weight reduction. Use at strength 1.0."
- name: badneganatomy
version_id: "64063"
model_id: "59614"
description: "BadNegAnatomyV1-neg - Improves aesthetics and character anatomy"
size_gb: 0.0002
essential: true
type: embeddings
format: pt
base_model: SD 1.5
tags: [negative, anatomy, quality, sd15]
trigger_word: "BadNegAnatomyV1-neg"
usage: "embedding:BadNegAnatomyV1-neg"
notes: "Particularly improves body joints and overall anatomy."
# ==========================================================================
# NEGATIVE EMBEDDINGS - SDXL (Textual Inversions)
# ==========================================================================
embeddings_sdxl:
- name: badx-sdxl
version_id: "981304"
model_id: "122403"
description: "Bad X v1.1 - SDXL negative embedding for anatomy and realism"
size_gb: 0.000004
essential: true
type: embeddings
format: pt
base_model: SDXL 1.0
tags: [negative, quality, anatomy, sdxl]
trigger_word: "BadX"
usage: "embedding:BadX"
files:
- source: "BadX-neg.pt"
dest: "BadX-neg.pt"
notes: "Use in negative prompt with LUSTIFY, RealVisXL, or other SDXL checkpoints. Fixes facial/hand artifacts."
# ==========================================================================
# NEGATIVE EMBEDDINGS - Pony SDXL (Textual Inversions)
# ==========================================================================
embeddings_pony:
- name: pony-pdxl-hq-v3
version_id: "720175"
model_id: "332646"
description: "Pony PDXL High Quality V3 (zPDXL3) - Quality enhancer for Pony models"
size_gb: 0.0003
essential: true
type: embeddings
format: safetensors
base_model: Pony SDXL
tags: [negative, quality, pony, nsfw]
trigger_word: "zPDXL3"
usage: "embedding:zPDXL3"
files:
- source: "zPDXL3.safetensors"
dest: "zPDXL3.safetensors"
recommended_settings:
strength: "1.0-2.0"
notes: "ONLY works with Pony Diffusion models. Removes censoring and improves quality."
- name: pony-pdxl-xxx
version_id: "380277"
model_id: "332646"
description: "Pony PDXL XXX Rating (zPDXLxxx) - Enables NSFW content"
size_gb: 0.00003
essential: true
type: embeddings
format: pt
base_model: Pony SDXL
tags: [negative, nsfw, pony]
trigger_word: "zPDXLxxx"
usage: "embedding:zPDXLxxx"
files:
- source: "zPDXLxxx.pt"
dest: "zPDXLxxx.pt"
recommended_settings:
strength: "1.0-2.0"
notes: "ONLY for Pony Diffusion models. Enables explicit NSFW content generation."
# ==========================================================================
# LORA MODELS (Style Enhancement & Detail)
# ==========================================================================
loras:
- name: add-detail-xl
version_id: "135867"
model_id: "122359"
description: "Add Detail XL - Detail enhancement LoRA for SDXL"
size_gb: 0.21
essential: true
type: loras
format: safetensors
base_model: SDXL 1.0
tags: [enhancement, detail, quality]
recommended_settings:
strength_model: "0.5-1.0"
strength_clip: "0.5-1.0"
notes: "Popular detail enhancer LoRA, works with all SDXL checkpoints"
- name: siesta-v1-1
version_id: "unknown"
model_id: "unknown"
description: "Siesta v1.1 - Style LoRA"
size_gb: 0.04
essential: false
type: loras
format: safetensors
base_model: SDXL 1.0
tags: [style, artistic]
notes: "Manually downloaded LoRA, version_id needs to be updated"
# ============================================================================
# STORAGE & VRAM SUMMARIES
# ============================================================================
storage_requirements:
essential_only:
nsfw_checkpoints: 19.61 # LUSTIFY + Pony + RealVisXL
total: 19.61
all_models:
nsfw_checkpoints: 39.21 # All 6 checkpoints
total: 39.21
vram_requirements:
# For 24GB GPU (RTX 4090)
notes: |
All SDXL checkpoints require approximately 12GB VRAM.
Can run one checkpoint at a time on 24GB GPU.
For simultaneous loading with other models (ComfyUI, vLLM),
ensure combined VRAM usage stays under 24GB.
# ============================================================================
# INSTALLATION PROFILES
# ============================================================================
installation_profiles:
essential:
description: Essential NSFW models only (3 checkpoints)
categories: [nsfw_checkpoints]
essential_only: true
storage_gb: 19.61
estimated_time: "30-60 minutes"
models:
- lustify-v7-ggwp
- pony-diffusion-v6-xl
- realvisxl-v5
complete:
description: All NSFW models (6 checkpoints)
categories: [nsfw_checkpoints]
storage_gb: 39.21
estimated_time: "1-2 hours"
models:
- lustify-v7-ggwp
- pony-diffusion-v6-xl
- realvisxl-v5
- wai-nsfw-illustrious-sdxl
- talmendoxl
- big-lust-v1-6
realistic_only:
description: Photorealistic NSFW models only
categories: [nsfw_checkpoints]
storage_gb: 13.11
estimated_time: "20-40 minutes"
models:
- lustify-v7-ggwp
- realvisxl-v5
anime_only:
description: Anime/cartoon NSFW models only
categories: [nsfw_checkpoints]
storage_gb: 13.0
estimated_time: "20-40 minutes"
models:
- pony-diffusion-v6-xl
- wai-nsfw-illustrious-sdxl
# ============================================================================
# METADATA
# ============================================================================
metadata:
version: 1.0.0
last_updated: 2025-11-23
compatible_with:
- ComfyUI >= 0.1.0
- SDXL base models
maintainer: Valknar
repository: https://github.com/valknar/runpod
notes: |
All models listed are NSFW (adult content) and hosted on CivitAI.
Requires CIVITAI_API_KEY for downloads.
Models will be downloaded to cache_dir and symlinked to ComfyUI.

715
models_huggingface.yaml Normal file
View File

@@ -0,0 +1,715 @@
settings:
cache_dir: /workspace/huggingface_cache
parallel_downloads: 1
retry_attempts: 3
timeout_seconds: 3600
model_categories:
image_models:
- repo_id: black-forest-labs/FLUX.1-schnell
description: FLUX.1 Schnell - Fast 4-step inference
size_gb: 23
essential: true
category: image
format: fp16
vram_gb: 23
notes: Industry-leading image generation quality
files:
- source: flux1-schnell.safetensors
dest: unet/flux1-schnell.safetensors
- repo_id: black-forest-labs/FLUX.1-dev
description: FLUX.1 Dev - Balanced quality/speed
size_gb: 23
essential: false
category: image
format: fp16
vram_gb: 23
notes: Development version with enhanced features
files:
- source: flux1-dev.safetensors
dest: unet/flux1-dev.safetensors
- repo_id: runwayml/stable-diffusion-v1-5
description: SD 1.5 - For AnimateDiff
size_gb: 4
essential: true
category: image
format: fp16
vram_gb: 8
notes: Stable Diffusion 1.5 required for AnimateDiff motion modules
files:
- source: v1-5-pruned-emaonly.safetensors
dest: checkpoints/v1-5-pruned-emaonly.safetensors
- repo_id: stabilityai/stable-diffusion-xl-base-1.0
description: SDXL Base 1.0 - Industry standard
size_gb: 7
essential: true
category: image
format: fp16
vram_gb: 12
notes: Most widely used Stable Diffusion model
files:
- source: sd_xl_base_1.0.safetensors
dest: checkpoints/sd_xl_base_1.0.safetensors
- repo_id: stabilityai/stable-diffusion-xl-refiner-1.0
description: SDXL Refiner 1.0 - Enhances base output
size_gb: 6
essential: false
category: image
format: fp16
vram_gb: 12
notes: Use after SDXL base for improved details
files:
- source: sd_xl_refiner_1.0.safetensors
dest: checkpoints/sd_xl_refiner_1.0.safetensors
- repo_id: stabilityai/stable-diffusion-3.5-large
description: SD 3.5 Large Complete - Checkpoint and text encoders
size_gb: 31
essential: false
category: image
format: mixed
vram_gb: 20
notes: Complete SD3.5 Large model with checkpoint and all text encoders (CLIP-L,
CLIP-G, T5-XXL)
files:
- source: sd3.5_large.safetensors
dest: checkpoints/sd3.5_large.safetensors
- source: text_encoders/clip_l.safetensors
dest: checkpoints/clip_l.safetensors
- source: text_encoders/clip_g.safetensors
dest: checkpoints/clip_g.safetensors
- source: text_encoders/t5xxl_fp16.safetensors
dest: checkpoints/t5xxl_fp16.safetensors
- repo_id: John6666/diving-illustrious-real-asian-v50-sdxl
description: Diving Illustrious Real Asian v5.0 - Photorealistic Asian subjects
size_gb: 7
essential: false
category: image
format: fp16
vram_gb: 12
notes: SDXL fine-tune specializing in photorealistic Asian subjects with illustrious
quality
files:
- source: unet/diffusion_pytorch_model.safetensors
dest: checkpoints/diving-illustrious-real-asian-v50-sdxl.safetensors
- repo_id: playgroundai/playground-v2.5-1024px-aesthetic
description: Playground v2.5 - 1024px aesthetic images
size_gb: 7
essential: false
category: image
format: fp16
vram_gb: 12
notes: Highly aesthetic 1024x1024 outputs, outperforms SDXL and DALL-E 3 in user
studies
files:
- source: playground-v2.5-1024px-aesthetic.fp16.safetensors
dest: checkpoints/playground-v2.5-1024px-aesthetic.safetensors
- repo_id: Lykon/dreamshaper-8
description: DreamShaper 8 - Multi-style versatile model
size_gb: 4
essential: false
category: image
format: fp16
vram_gb: 8
notes: Versatile SD1.5 fine-tune balancing photorealistic and anime styles with
strong LoRA support
files:
- source: unet/diffusion_pytorch_model.fp16.safetensors
dest: checkpoints/dreamshaper-8.safetensors
video_models:
- repo_id: THUDM/CogVideoX-5b
description: CogVideoX-5B - Professional text-to-video
size_gb: 20
essential: true
category: video
format: fp16
vram_gb: 20
frames: 49
resolution: 720p
notes: State-of-the-art text-to-video generation, auto-downloaded by DownloadAndLoadCogVideoModel
node
files:
- source: transformer/diffusion_pytorch_model-00001-of-00002.safetensors
dest: diffusion_models/cogvideox-5b-transformer-00001-of-00002.safetensors
- source: transformer/diffusion_pytorch_model-00002-of-00002.safetensors
dest: diffusion_models/cogvideox-5b-transformer-00002-of-00002.safetensors
- source: transformer/diffusion_pytorch_model.safetensors.index.json
dest: diffusion_models/cogvideox-5b-transformer.safetensors.index.json
- repo_id: THUDM/CogVideoX-5b-I2V
description: CogVideoX-5B-I2V - Image-to-video generation
size_gb: 20
essential: true
category: video
format: fp16
vram_gb: 20
frames: 49
resolution: 720p
notes: Image-to-video model, auto-downloaded by DownloadAndLoadCogVideoModel node
files:
- source: transformer/diffusion_pytorch_model-00001-of-00003.safetensors
dest: diffusion_models/cogvideox-5b-i2v-transformer-00001-of-00003.safetensors
- source: transformer/diffusion_pytorch_model-00002-of-00003.safetensors
dest: diffusion_models/cogvideox-5b-i2v-transformer-00002-of-00003.safetensors
- source: transformer/diffusion_pytorch_model-00003-of-00003.safetensors
dest: diffusion_models/cogvideox-5b-i2v-transformer-00003-of-00003.safetensors
- source: transformer/diffusion_pytorch_model.safetensors.index.json
dest: diffusion_models/cogvideox-5b-i2v-transformer.safetensors.index.json
- repo_id: stabilityai/stable-video-diffusion-img2vid
description: SVD - 14 frame image-to-video
size_gb: 8
essential: true
category: video
format: fp16
vram_gb: 20
frames: 14
resolution: 576x1024
notes: Convert images to short video clips
files:
- source: svd.safetensors
dest: checkpoints/svd.safetensors
- repo_id: stabilityai/stable-video-diffusion-img2vid-xt
description: SVD-XT - 25 frame image-to-video
size_gb: 8
essential: false
category: video
format: fp16
vram_gb: 20
frames: 25
resolution: 576x1024
notes: Extended frame count version
files:
- source: svd_xt.safetensors
dest: checkpoints/svd_xt.safetensors
- repo_id: Comfy-Org/HunyuanVideo_repackaged
description: HunyuanVideo Complete - 720p T2V/I2V models with VAE and encoders
size_gb: 51
essential: true
category: video
format: bf16
vram_gb: 24
frames: 129
resolution: 720p
notes: Complete HunyuanVideo family - T2V, I2V v1/v2, 3D VAE, LLaVA LLaMA3 text/vision
encoders
files:
- source: split_files/diffusion_models/hunyuan_video_t2v_720p_bf16.safetensors
dest: diffusion_models/hunyuan_video_t2v_720p_bf16.safetensors
- source: split_files/diffusion_models/hunyuan_video_image_to_video_720p_bf16.safetensors
dest: diffusion_models/hunyuan_video_image_to_video_720p_bf16.safetensors
- source: split_files/diffusion_models/hunyuan_video_v2_replace_image_to_video_720p_bf16.safetensors
dest: diffusion_models/hunyuan_video_v2_replace_image_to_video_720p_bf16.safetensors
- source: split_files/vae/hunyuan_video_vae_bf16.safetensors
dest: diffusion_models/hunyuan_video_vae_bf16.safetensors
- source: split_files/text_encoders/llava_llama3_fp8_scaled.safetensors
dest: diffusion_models/llava_llama3_fp8_scaled.safetensors
- source: split_files/clip_vision/llava_llama3_vision.safetensors
dest: diffusion_models/llava_llama3_vision.safetensors
- repo_id: Comfy-Org/HunyuanVideo_1.5_repackaged
description: HunyuanVideo 1.5 Complete - 720p/1080p T2V/SR with encoders
size_gb: 51.5
essential: true
category: video
format: fp16
vram_gb: 24
frames: 129-257
resolution: 720p-1080p
notes: Complete HunyuanVideo 1.5 - T2V 720p, SR 1080p, VAE, Qwen 2.5 VL, ByT5
GlyphXL encoders
files:
- source: hunyuanvideo1.5_720p_t2v_fp16.safetensors
dest: diffusion_models/hunyuanvideo1.5_720p_t2v_fp16.safetensors
- source: hunyuanvideo1.5_1080p_sr_distilled_fp16.safetensors
dest: diffusion_models/hunyuanvideo1.5_1080p_sr_distilled_fp16.safetensors
- source: hunyuanvideo15_vae_fp16.safetensors
dest: diffusion_models/hunyuanvideo15_vae_fp16.safetensors
- source: qwen_2.5_vl_7b_fp8_scaled.safetensors
dest: diffusion_models/qwen_2.5_vl_7b_fp8_scaled.safetensors
- source: byt5_small_glyphxl_fp16.safetensors
dest: diffusion_models/byt5_small_glyphxl_fp16.safetensors
- repo_id: Comfy-Org/Wan_2.2_ComfyUI_Repackaged
description: Wan2.2 Complete - All video models, VAEs, and LoRAs
size_gb: 220
essential: true
category: video
format: mixed
vram_gb: 24
frames: 81
resolution: 640x640
notes: Complete Wan2.2 model family - TI2V 5B, T2V 14B, I2V 14B, Animate, S2V,
Fun Inpaint/Control/Camera, VAEs, CLIP Vision H, Wav2Vec2, and LoRA accelerators
files:
- source: wan2.2_ti2v_5B_fp16.safetensors
dest: diffusion_models/wan2.2_ti2v_5B_fp16.safetensors
- source: wan2.2_t2v_high_noise_14B_fp8_scaled.safetensors
dest: diffusion_models/wan2.2_t2v_high_noise_14B_fp8_scaled.safetensors
- source: wan2.2_t2v_low_noise_14B_fp8_scaled.safetensors
dest: diffusion_models/wan2.2_t2v_low_noise_14B_fp8_scaled.safetensors
- source: wan2.2_i2v_high_noise_14B_fp16.safetensors
dest: diffusion_models/wan2.2_i2v_high_noise_14B_fp16.safetensors
- source: wan2.2_i2v_low_noise_14B_fp16.safetensors
dest: diffusion_models/wan2.2_i2v_low_noise_14B_fp16.safetensors
- source: wan2.2_animate_14B_bf16.safetensors
dest: diffusion_models/wan2.2_animate_14B_bf16.safetensors
- source: wan2.2_s2v_14B_fp8_scaled.safetensors
dest: diffusion_models/wan2.2_s2v_14B_fp8_scaled.safetensors
- source: wan2.2_s2v_14B_bf16.safetensors
dest: diffusion_models/wan2.2_s2v_14B_bf16.safetensors
- source: wan2.2_fun_inpaint_high_noise_14B_fp8_scaled.safetensors
dest: diffusion_models/wan2.2_fun_inpaint_high_noise_14B_fp8_scaled.safetensors
- source: wan2.2_fun_inpaint_low_noise_14B_fp8_scaled.safetensors
dest: diffusion_models/wan2.2_fun_inpaint_low_noise_14B_fp8_scaled.safetensors
- source: wan2.2_fun_control_high_noise_14B_fp8_scaled.safetensors
dest: diffusion_models/wan2.2_fun_control_high_noise_14B_fp8_scaled.safetensors
- source: wan2.2_fun_control_low_noise_14B_fp8_scaled.safetensors
dest: diffusion_models/wan2.2_fun_control_low_noise_14B_fp8_scaled.safetensors
- source: wan2.2_fun_camera_high_noise_14B_fp8_scaled.safetensors
dest: diffusion_models/wan2.2_fun_camera_high_noise_14B_fp8_scaled.safetensors
- source: wan2.2_fun_camera_low_noise_14B_fp8_scaled.safetensors
dest: diffusion_models/wan2.2_fun_camera_low_noise_14B_fp8_scaled.safetensors
- source: wan2.2_vae.safetensors
dest: diffusion_models/wan2.2_vae.safetensors
- source: wan_2.1_vae.safetensors
dest: diffusion_models/wan_2.1_vae.safetensors
- source: clip_vision_h.safetensors
dest: diffusion_models/clip_vision_h.safetensors
- source: wav2vec2_large_english_fp16.safetensors
dest: diffusion_models/wav2vec2_large_english_fp16.safetensors
- source: lightx2v_I2V_14B_480p_cfg_step_distill_rank64_bf16.safetensors
dest: diffusion_models/lightx2v_I2V_14B_480p_cfg_step_distill_rank64_bf16.safetensors
- source: wan2.2_t2v_lightx2v_4steps_lora_v1.1_high_noise.safetensors
dest: diffusion_models/wan2.2_t2v_lightx2v_4steps_lora_v1.1_high_noise.safetensors
- source: wan2.2_i2v_lightx2v_4steps_lora_v1_high_noise.safetensors
dest: diffusion_models/wan2.2_i2v_lightx2v_4steps_lora_v1_high_noise.safetensors
- source: wan2.2_i2v_lightx2v_4steps_lora_v1_low_noise.safetensors
dest: diffusion_models/wan2.2_i2v_lightx2v_4steps_lora_v1_low_noise.safetensors
audio_models:
- repo_id: facebook/musicgen-small
description: MusicGen Small - Fast generation
size_gb: 3
essential: false
category: audio
format: fp32
vram_gb: 4
duration_seconds: 30
notes: Fastest music generation, lower quality
files:
- source: pytorch_model.bin
dest: musicgen/musicgen-small-pytorch_model.bin
- repo_id: facebook/musicgen-medium
description: MusicGen Medium - Balanced quality
size_gb: 11
essential: true
category: audio
format: fp32
vram_gb: 8
duration_seconds: 30
notes: Best balance of speed and quality
files:
- source: pytorch_model.bin
dest: musicgen/musicgen-medium-pytorch_model.bin
- repo_id: facebook/musicgen-large
description: MusicGen Large - Highest quality
size_gb: 22
essential: false
category: audio
format: fp32
vram_gb: 16
duration_seconds: 30
notes: Best quality, slower generation
files:
- source: pytorch_model-00001-of-00002.bin
dest: musicgen/musicgen-large-pytorch_model-00001-of-00002.bin
- source: pytorch_model-00002-of-00002.bin
dest: musicgen/musicgen-large-pytorch_model-00002-of-00002.bin
- source: pytorch_model.bin.index.json
dest: musicgen/musicgen-large-pytorch_model.bin.index.json
- repo_id: Comfy-Org/ACE-Step_ComfyUI_repackaged
description: ACE Step v1 3.5B - Fast coherent music generation with 19-language
support
size_gb: 7.7
essential: true
category: audio
format: safetensors
vram_gb: 16
duration_seconds: 240
notes: 15x faster than LLM baselines, superior structural coherence, voice cloning,
19-language lyrics
files:
- source: all_in_one/ace_step_v1_3.5b.safetensors
dest: checkpoints/ace_step_v1_3.5b.safetensors
- repo_id: ACE-Step/ACE-Step-v1-chinese-rap-LoRA
description: ACE Step Chinese RAP LoRA - Enhanced Chinese pronunciation and hip-hop
genre
size_gb: 0.3
essential: false
category: audio
format: safetensors
notes: Improves Chinese pronunciation accuracy and hip-hop/electronic genre adherence
files:
- source: pytorch_lora_weights.safetensors
dest: loras/ace-step-chinese-rap-lora.safetensors
support_models:
- repo_id: openai/clip-vit-large-patch14
description: CLIP H - For SD 1.5 IP-Adapter
size_gb: 2
essential: true
category: support
format: fp32
vram_gb: 2
notes: Text-image understanding model for IP-Adapter
files:
- source: model.safetensors
dest: clip_vision/CLIP-ViT-H-14-laion2B-s32B-b79K.safetensors
- repo_id: laion/CLIP-ViT-bigG-14-laion2B-39B-b160k
description: CLIP G - For SDXL IP-Adapter
size_gb: 7
essential: true
category: support
format: fp32
vram_gb: 4
notes: Larger CLIP model for SDXL IP-Adapter
files:
- source: open_clip_model.safetensors
dest: clip_vision/CLIP-ViT-bigG-14-laion2B-39B-b160k.safetensors
- repo_id: google/siglip-so400m-patch14-384
description: SigLIP - For FLUX models
size_gb: 2
essential: true
category: support
format: fp32
vram_gb: 2
notes: Advanced image-text alignment
files:
- source: model.safetensors
dest: clip_vision/siglip-so400m-patch14-384.safetensors
- repo_id: black-forest-labs/FLUX.1-schnell
description: FLUX VAE - Autoencoder for FLUX models
size_gb: 0.5
essential: true
category: support
format: safetensors
vram_gb: 1
notes: VAE autoencoder required for FLUX image decoding
files:
- source: ae.safetensors
dest: vae/ae.safetensors
- repo_id: ai-forever/Real-ESRGAN
description: RealESRGAN x2 - 2x upscaling model
size_gb: 0.06
essential: true
category: support
format: pth
vram_gb: 2
notes: Fast 2x upscaling model for general purpose enhancement
files:
- source: RealESRGAN_x2.pth
dest: upscale_models/RealESRGAN_x2.pth
- repo_id: ai-forever/Real-ESRGAN
description: RealESRGAN x4 - 4x upscaling model
size_gb: 0.06
essential: true
category: support
format: pth
vram_gb: 4
notes: High-quality 4x upscaling model for detail enhancement
files:
- source: RealESRGAN_x4.pth
dest: upscale_models/RealESRGAN_x4.pth
- repo_id: Comfy-Org/Wan_2.1_ComfyUI_repackaged
description: UMT5-XXL FP8 - Text encoder for all Wan2.2 models
size_gb: 10
essential: true
category: support
format: fp8_scaled
vram_gb: 5
notes: Shared text encoder for all Wan2.2 models (5B and 14B), FP8 quantized
files:
- source: umt5_xxl_fp8_e4m3fn_scaled.safetensors
dest: text_encoders/umt5_xxl_fp8_e4m3fn_scaled.safetensors
animatediff_models:
- repo_id: guoyww/animatediff
description: AnimateDiff Motion Modules
size_gb: 2
essential: true
category: animatediff
filename: mm_sd_v15
format: safetensors
vram_gb: 4
notes: Motion modules for AnimateDiff text-to-video
files:
- source: mm_sd_v15_v2.ckpt
dest: animatediff_models/mm_sd_v15_v2.ckpt
controlnet_models:
- repo_id: lllyasviel/control_v11p_sd15_canny
description: ControlNet Canny - Edge detection control for SD 1.5
size_gb: 1.5
essential: false
category: controlnet
format: safetensors
vram_gb: 2
notes: Precise edge-based composition control
files:
- source: diffusion_pytorch_model.safetensors
dest: controlnet/control_v11p_sd15_canny.safetensors
- repo_id: lllyasviel/control_v11f1p_sd15_depth
description: ControlNet Depth - Depth map control for SD 1.5
size_gb: 1.5
essential: false
category: controlnet
format: safetensors
vram_gb: 2
notes: Depth-based spatial control
files:
- source: diffusion_pytorch_model.safetensors
dest: controlnet/control_v11p_sd15_depth.safetensors
- repo_id: diffusers/controlnet-canny-sdxl-1.0
description: ControlNet Canny SDXL - Edge detection for SDXL
size_gb: 2.5
essential: false
category: controlnet
format: safetensors
vram_gb: 3
notes: Canny edge control for SDXL models
files:
- source: diffusion_pytorch_model.safetensors
dest: controlnet/controlnet-canny-sdxl-1.0.safetensors
- repo_id: diffusers/controlnet-depth-sdxl-1.0
description: ControlNet Depth SDXL - Depth map for SDXL
size_gb: 2.5
essential: false
category: controlnet
format: safetensors
vram_gb: 3
notes: Depth control for SDXL models
files:
- source: diffusion_pytorch_model.safetensors
dest: controlnet/controlnet-depth-sdxl-1.0.safetensors
ipadapter_models:
- repo_id: h94/IP-Adapter
description: IP-Adapter SDXL Base - Style & Composition
size_gb: 1.3
essential: true
category: ipadapter
format: safetensors
vram_gb: 4
notes: Basic IP-Adapter for SDXL
files:
- source: sdxl_models/ip-adapter_sdxl.safetensors
dest: ipadapter/ip-adapter_sdxl.safetensors
- repo_id: h94/IP-Adapter
description: IP-Adapter SDXL VIT-H - For CLIP-ViT-H
size_gb: 0.9
essential: true
category: ipadapter
format: safetensors
vram_gb: 4
notes: IP-Adapter for SDXL with VIT-H CLIP vision model
files:
- source: sdxl_models/ip-adapter_sdxl_vit-h.safetensors
dest: ipadapter/ip-adapter_sdxl_vit-h.safetensors
- repo_id: h94/IP-Adapter
description: IP-Adapter SDXL Plus - High Strength Composition
size_gb: 0.9
essential: false
category: ipadapter
format: safetensors
vram_gb: 4
notes: Enhanced composition control with higher strength
files:
- source: sdxl_models/ip-adapter-plus_sdxl_vit-h.safetensors
dest: ipadapter/ip-adapter-plus_sdxl_vit-h.safetensors
- repo_id: h94/IP-Adapter
description: IP-Adapter SDXL Plus Face - Face-focused generation
size_gb: 0.5
essential: false
category: ipadapter
format: safetensors
vram_gb: 4
notes: Specialized for face transfer and portrait generation
files:
- source: sdxl_models/ip-adapter-plus-face_sdxl_vit-h.safetensors
dest: ipadapter/ip-adapter-plus-face_sdxl_vit-h.safetensors
diffrhythm_models:
- repo_id: ASLP-lab/DiffRhythm-1_2
description: DiffRhythm 1.2 - 95 second generation model
size_gb: 2
essential: true
category: diffrhythm
format: pt
vram_gb: 12
duration_seconds: 95
notes: Latest 95-second generation model
files:
- source: cfm_model.pt
dest: TTS/DiffRhythm/cfm_model_v1_2.pt
- repo_id: ASLP-lab/DiffRhythm-full
description: DiffRhythm Full - 4m45s full-length generation
size_gb: 2
essential: false
category: diffrhythm
format: pt
vram_gb: 16
duration_seconds: 285
notes: Full-length 4 minute 45 second music generation
files:
- source: cfm_model.pt
dest: TTS/DiffRhythm/cfm_full_model.pt
- repo_id: ASLP-lab/DiffRhythm-base
description: DiffRhythm Base - 95 second base model
size_gb: 2
essential: false
category: diffrhythm
format: pt
vram_gb: 12
duration_seconds: 95
notes: Base 95-second model
files:
- source: cfm_model.pt
dest: TTS/DiffRhythm/cfm_model.pt
- repo_id: ASLP-lab/DiffRhythm-vae
description: DiffRhythm VAE - Variational autoencoder
size_gb: 1
essential: true
category: diffrhythm
format: pt
vram_gb: 2
notes: VAE component fine-tuned from Stable Audio Open (Stability AI Community
License)
files:
- source: vae_model.pt
dest: TTS/DiffRhythm/vae_model.pt
- repo_id: OpenMuQ/MuQ-MuLan-large
description: MuQ-MuLan-large - Music-text joint embedding (~700M parameters)
size_gb: 3
essential: true
category: diffrhythm
format: bin
vram_gb: 4
notes: Music-text joint embedding for semantic understanding (English/Chinese)
files:
- source: config.json
dest: TTS/DiffRhythm/MuQ-MuLan-large/config.json
- source: pytorch_model.bin
dest: TTS/DiffRhythm/MuQ-MuLan-large/pytorch_model.bin
- repo_id: OpenMuQ/MuQ-large-msd-iter
description: MuQ-large-msd-iter - Music representation learning (~300M parameters)
size_gb: 1.2
essential: true
category: diffrhythm
format: safetensors
vram_gb: 2
notes: Music representation model trained on Million Song Dataset
files:
- source: config.json
dest: TTS/DiffRhythm/MuQ-large-msd-iter/config.json
- source: model.safetensors
dest: TTS/DiffRhythm/MuQ-large-msd-iter/model.safetensors
- repo_id: FacebookAI/xlm-roberta-base
description: XLM-RoBERTa Base - Multilingual text encoder (100 languages, 0.3B
params)
size_gb: 1.1
essential: true
category: diffrhythm
format: safetensors
vram_gb: 1
notes: Multilingual text encoding for 100 languages
files:
- source: config.json
dest: TTS/DiffRhythm/xlm-roberta-base/config.json
- source: model.safetensors
dest: TTS/DiffRhythm/xlm-roberta-base/model.safetensors
- source: sentencepiece.bpe.model
dest: TTS/DiffRhythm/xlm-roberta-base/sentencepiece.bpe.model
- source: tokenizer.json
dest: TTS/DiffRhythm/xlm-roberta-base/tokenizer.json
- source: tokenizer_config.json
dest: TTS/DiffRhythm/xlm-roberta-base/tokenizer_config.json
storage_requirements:
essential_only:
image: 30
video: 28
audio: 11
support: 11
diffrhythm: 10
total: 90
all_models:
image: 54
video: 36
audio: 36
support: 11
diffrhythm: 12
total: 149
vram_requirements:
simultaneous_loadable:
- name: Image Focus - FLUX FP16
models:
- FLUX.1 Schnell
vram_used: 23
remaining: 1
- name: Image Focus - FLUX FP8 + SDXL
models:
- FLUX.1 Schnell FP8
- SDXL Base
vram_used: 24
remaining: 0
- name: Video Generation
models:
- CogVideoX-5B optimized
- SDXL
vram_used: 24
remaining: 0
- name: Multi-Modal
models:
- SDXL
- MusicGen Medium
vram_used: 20
remaining: 4
installation_profiles:
minimal:
description: Minimal setup for testing
categories:
- support_models
storage_gb: 11
estimated_time: 5-10 minutes
essential:
description: Essential models only (~80GB)
categories:
- image_models
- video_models
- audio_models
- support_models
essential_only: true
storage_gb: 80
estimated_time: 1-2 hours
image_focused:
description: All image generation models
categories:
- image_models
- support_models
storage_gb: 65
estimated_time: 45-90 minutes
video_focused:
description: All video generation models
categories:
- video_models
- image_models
- support_models
essential_only: true
storage_gb: 69
estimated_time: 1-2 hours
complete:
description: All models (including optional)
categories:
- image_models
- video_models
- audio_models
- support_models
storage_gb: 137
estimated_time: 2-4 hours
metadata:
version: 1.0.0
last_updated: 2025-11-21
compatible_with:
- ComfyUI >= 0.1.0
- Python >= 3.10
- HuggingFace Hub >= 0.20.0
maintainer: Valknar
repository: https://github.com/yourusername/runpod

View File

@@ -0,0 +1,126 @@
# ============================================================================
# vLLM Model Configuration
# ============================================================================
#
# This configuration file defines all available vLLM models for download.
# Models are organized by category: text generation and text embeddings.
#
# Each model entry contains:
# - repo_id: HuggingFace repository identifier
# - description: Human-readable description
# - size_gb: Approximate size in gigabytes
# - essential: Whether this is an essential model (true/false)
# - category: Model category (text_generation/embedding)
#
# ============================================================================
# Global settings
settings:
cache_dir: /workspace/huggingface_cache
parallel_downloads: 1
retry_attempts: 3
timeout_seconds: 3600
# Model categories
model_categories:
# ==========================================================================
# TEXT GENERATION MODELS (vLLM)
# ==========================================================================
text_generation_models:
- repo_id: Qwen/Qwen2.5-7B-Instruct
description: Qwen 2.5 7B Instruct - Advanced multilingual reasoning
size_gb: 14
essential: true
category: text_generation
type: vllm
format: safetensors
vram_gb: 14
context_length: 32768
notes: Latest Qwen 2.5 model with enhanced reasoning capabilities
files:
- source: "model.safetensors"
dest: "model.safetensors"
- repo_id: meta-llama/Llama-3.1-8B-Instruct
description: Llama 3.1 8B Instruct - Meta's latest instruction-tuned model
size_gb: 17
essential: true
category: text_generation
type: vllm
format: safetensors
vram_gb: 17
context_length: 131072
notes: Extended 128K context length, excellent for long-form tasks
files:
- source: "model.safetensors"
dest: "model.safetensors"
# ==========================================================================
# TEXT EMBEDDING MODELS (vLLM)
# ==========================================================================
embedding_models:
- repo_id: BAAI/bge-large-en-v1.5
description: BGE Large English v1.5 - High-quality embeddings for RAG
size_gb: 1.3
essential: true
category: embedding
type: vllm_embedding
format: safetensors
vram_gb: 3
embedding_dimensions: 1024
max_tokens: 512
notes: Top-tier MTEB scores, excellent for semantic search and RAG applications
files:
- source: "model.safetensors"
dest: "model.safetensors"
# ============================================================================
# STORAGE & VRAM SUMMARIES
# ============================================================================
storage_requirements:
text_generation: 31 # Qwen 2.5 7B + Llama 3.1 8B
embedding: 1.3 # BGE Large
total: 32.3 # Total essential storage
vram_requirements:
# For 24GB GPU (RTX 4090)
simultaneous_loadable:
- name: Qwen 2.5 7B Only
models: [Qwen 2.5 7B Instruct]
vram_used: 14
remaining: 10
- name: Llama 3.1 8B Only
models: [Llama 3.1 8B Instruct]
vram_used: 17
remaining: 7
- name: BGE Large Only
models: [BGE Large]
vram_used: 3
remaining: 21
- name: Qwen + BGE Embedding
models: [Qwen 2.5 7B, BGE Large]
vram_used: 17
remaining: 7
- name: Llama + BGE Embedding
models: [Llama 3.1 8B, BGE Large]
vram_used: 20
remaining: 4
# ============================================================================
# METADATA
# ============================================================================
metadata:
version: 1.0.0
last_updated: 2025-11-25
compatible_with:
- vLLM >= 0.6.0
- Python >= 3.10
- HuggingFace Hub >= 0.20.0
maintainer: Valknar
repository: https://github.com/yourusername/runpod

108
scripts/bootstrap-venvs.sh Executable file
View File

@@ -0,0 +1,108 @@
#!/bin/bash
# Virtual Environment Health Check and Bootstrap Script
# Checks if Python venvs are compatible with current Python version
# Rebuilds venvs if needed
set -e
echo "=== Python Virtual Environment Health Check ==="
# Get current system Python version
SYSTEM_PYTHON=$(python3 --version | awk '{print $2}')
SYSTEM_PYTHON_MAJOR_MINOR=$(echo "$SYSTEM_PYTHON" | cut -d'.' -f1,2)
echo "System Python: $SYSTEM_PYTHON ($SYSTEM_PYTHON_MAJOR_MINOR)"
# List of venvs to check
VENVS=(
"/workspace/ai/vllm/venv"
"/workspace/ai/webdav-sync/venv"
"/workspace/ComfyUI/venv"
)
REBUILD_NEEDED=0
# Check each venv
for VENV_PATH in "${VENVS[@]}"; do
if [ ! -d "$VENV_PATH" ]; then
echo "⚠ venv not found: $VENV_PATH (will be created on first service start)"
continue
fi
VENV_NAME=$(basename $(dirname "$VENV_PATH"))
echo ""
echo "Checking venv: $VENV_NAME ($VENV_PATH)"
# Check if venv Python executable works
if ! "$VENV_PATH/bin/python" --version >/dev/null 2>&1; then
echo " ❌ BROKEN - Python executable not working"
REBUILD_NEEDED=1
continue
fi
# Get venv Python version
VENV_PYTHON=$("$VENV_PATH/bin/python" --version 2>&1 | awk '{print $2}')
VENV_PYTHON_MAJOR_MINOR=$(echo "$VENV_PYTHON" | cut -d'.' -f1,2)
echo " venv Python: $VENV_PYTHON ($VENV_PYTHON_MAJOR_MINOR)"
# Compare major.minor versions
if [ "$SYSTEM_PYTHON_MAJOR_MINOR" != "$VENV_PYTHON_MAJOR_MINOR" ]; then
echo " ⚠ VERSION MISMATCH - System is $SYSTEM_PYTHON_MAJOR_MINOR, venv is $VENV_PYTHON_MAJOR_MINOR"
REBUILD_NEEDED=1
else
# Check if pip works
if ! "$VENV_PATH/bin/pip" --version >/dev/null 2>&1; then
echo " ❌ BROKEN - pip not working"
REBUILD_NEEDED=1
else
echo " ✓ HEALTHY"
fi
fi
done
# If any venv needs rebuild, warn the user
if [ $REBUILD_NEEDED -eq 1 ]; then
echo ""
echo "========================================"
echo " ⚠ WARNING: Some venvs need rebuilding"
echo "========================================"
echo ""
echo "One or more Python virtual environments are incompatible with the current"
echo "Python version or are broken. This can happen when:"
echo " - Docker image Python version changed"
echo " - venv files were corrupted"
echo " - Binary dependencies are incompatible"
echo ""
echo "RECOMMENDED ACTIONS:"
echo ""
echo "1. vLLM venv rebuild:"
echo " cd /workspace/ai/vllm"
echo " rm -rf venv"
echo " python3 -m venv venv"
echo " source venv/bin/activate"
echo " pip install -r requirements.txt"
echo ""
echo "2. ComfyUI venv rebuild:"
echo " cd /workspace/ComfyUI"
echo " rm -rf venv"
echo " python3 -m venv venv"
echo " source venv/bin/activate"
echo " pip install -r requirements.txt"
echo ""
echo "3. WebDAV sync venv rebuild (if used):"
echo " cd /workspace/ai/webdav-sync"
echo " rm -rf venv"
echo " python3 -m venv venv"
echo " source venv/bin/activate"
echo " pip install -r requirements.txt"
echo ""
echo "Services may fail to start until venvs are rebuilt!"
echo "========================================"
echo ""
else
echo ""
echo "✓ All virtual environments are healthy"
fi
exit 0

141
start.sh Normal file
View File

@@ -0,0 +1,141 @@
#!/bin/bash
# RunPod container startup script
# This script initializes the container environment and starts all services
set -e
echo "========================================"
echo " RunPod AI Orchestrator - Starting"
echo "========================================"
# [1/7] Start SSH server (required by RunPod)
echo "[1/7] Starting SSH server..."
service ssh start
echo " ✓ SSH server started"
# [2/7] Add /workspace/bin to PATH for arty and custom scripts
echo "[2/7] Configuring PATH..."
export PATH="/workspace/bin:$PATH"
echo " ✓ PATH updated: /workspace/bin added"
# [3/7] Source environment variables from network volume
echo "[3/7] Loading environment from network volume..."
if [ -f /workspace/ai/.env ]; then
set -a
source /workspace/ai/.env
set +a
echo " ✓ Environment loaded from /workspace/ai/.env"
else
echo " ⚠ No .env file found at /workspace/ai/.env"
echo " Some services may not function correctly without environment variables"
fi
# [4/7] Configure and start Tailscale VPN
echo "[4/7] Configuring Tailscale VPN..."
if [ -n "${TAILSCALE_AUTHKEY:-}" ]; then
echo " Starting Tailscale daemon..."
tailscaled --tun=userspace-networking --socks5-server=localhost:1055 &
sleep 3
echo " Connecting to Tailscale network..."
HOSTNAME="runpod-$(hostname)"
tailscale up --authkey="$TAILSCALE_AUTHKEY" --advertise-tags=tag:gpu --hostname="$HOSTNAME" || {
echo " ⚠ Tailscale connection failed, continuing without VPN"
}
# Get Tailscale IP if connected
TAILSCALE_IP=$(tailscale ip -4 2>/dev/null || echo "not connected")
if [ "$TAILSCALE_IP" != "not connected" ]; then
echo " ✓ Tailscale connected"
echo " Hostname: $HOSTNAME"
echo " IP: $TAILSCALE_IP"
# Export for other services
export GPU_TAILSCALE_IP="$TAILSCALE_IP"
else
echo " ⚠ Tailscale failed to obtain IP"
fi
else
echo " ⚠ Tailscale disabled (no TAILSCALE_AUTHKEY in .env)"
echo " Services requiring VPN connectivity will not work"
fi
# [5/7] Check Python virtual environments health
echo "[5/7] Checking Python virtual environments..."
PYTHON_VERSION=$(python3 --version)
echo " System Python: $PYTHON_VERSION"
# Check if bootstrap script exists and run it
if [ -f /workspace/ai/scripts/bootstrap-venvs.sh ]; then
echo " Running venv health check..."
bash /workspace/ai/scripts/bootstrap-venvs.sh
else
echo " ⚠ No venv bootstrap script found (optional)"
fi
# [6/7] Configure Supervisor
echo "[6/7] Configuring Supervisor process manager..."
if [ -f /workspace/ai/supervisord.conf ]; then
# Supervisor expects config at /workspace/supervisord.conf (based on arty scripts)
if [ ! -f /workspace/supervisord.conf ]; then
cp /workspace/ai/supervisord.conf /workspace/supervisord.conf
echo " ✓ Supervisor config copied to /workspace/supervisord.conf"
fi
# Create logs directory if it doesn't exist
mkdir -p /workspace/logs
echo " ✓ Supervisor configured"
else
echo " ⚠ No supervisord.conf found at /workspace/ai/supervisord.conf"
echo " Supervisor will not be started"
fi
# [7/7] Start Supervisor to manage services
echo "[7/7] Starting Supervisor and managed services..."
if [ -f /workspace/supervisord.conf ]; then
# Start supervisor daemon
supervisord -c /workspace/supervisord.conf
echo " ✓ Supervisor daemon started"
# Wait a moment for services to initialize
sleep 3
# Display service status
echo ""
echo "Service Status:"
echo "---------------"
supervisorctl -c /workspace/supervisord.conf status || echo " ⚠ Could not query service status"
else
echo " ⚠ Skipping Supervisor startup (no config file)"
fi
# Display connection information
echo ""
echo "========================================"
echo " Container Ready"
echo "========================================"
echo "Services:"
echo " - SSH: port 22"
echo " - ComfyUI: http://localhost:8188"
echo " - Supervisor Web UI: http://localhost:9001"
echo " - Model Orchestrator: http://localhost:9000"
if [ -n "${TAILSCALE_IP:-}" ] && [ "$TAILSCALE_IP" != "not connected" ]; then
echo " - Tailscale IP: $TAILSCALE_IP"
fi
echo ""
echo "Network Volume: /workspace"
echo "Project Directory: /workspace/ai"
echo "Logs: /workspace/logs"
echo ""
echo "To view service logs:"
echo " supervisorctl -c /workspace/supervisord.conf tail -f <service_name>"
echo ""
echo "To manage services:"
echo " supervisorctl -c /workspace/supervisord.conf status"
echo " supervisorctl -c /workspace/supervisord.conf restart <service_name>"
echo "========================================"
# Keep container running
echo "Container is running. Press Ctrl+C to stop."
sleep infinity

View File

@@ -39,15 +39,15 @@ environment=HF_HOME="../huggingface_cache",PYTORCH_CUDA_ALLOC_CONF="expandable_s
priority=100 priority=100
stopwaitsecs=30 stopwaitsecs=30
# AI Model Orchestrator # vLLM Qwen 2.5 7B Server (Port 8000)
[program:orchestrator] [program:vllm-qwen]
command=model-orchestrator/venv/bin/python model-orchestrator/orchestrator_subprocess.py command=vllm/venv/bin/python vllm/server_qwen.py
directory=. directory=.
autostart=false autostart=false
autorestart=true autorestart=true
startretries=3 startretries=3
stderr_logfile=logs/orchestrator.err.log stderr_logfile=logs/vllm-qwen.err.log
stdout_logfile=logs/orchestrator.out.log stdout_logfile=logs/vllm-qwen.out.log
stdout_logfile_maxbytes=50MB stdout_logfile_maxbytes=50MB
stdout_logfile_backups=10 stdout_logfile_backups=10
stderr_logfile_maxbytes=50MB stderr_logfile_maxbytes=50MB
@@ -56,6 +56,40 @@ environment=HF_HOME="../huggingface_cache",HF_TOKEN="%(ENV_HF_TOKEN)s"
priority=200 priority=200
stopwaitsecs=30 stopwaitsecs=30
# vLLM Llama 3.1 8B Server (Port 8001)
[program:vllm-llama]
command=vllm/venv/bin/python vllm/server_llama.py
directory=.
autostart=false
autorestart=true
startretries=3
stderr_logfile=logs/vllm-llama.err.log
stdout_logfile=logs/vllm-llama.out.log
stdout_logfile_maxbytes=50MB
stdout_logfile_backups=10
stderr_logfile_maxbytes=50MB
stderr_logfile_backups=10
environment=HF_HOME="../huggingface_cache",HF_TOKEN="%(ENV_HF_TOKEN)s"
priority=201
stopwaitsecs=30
# vLLM BGE Embedding Server (Port 8002)
[program:vllm-embedding]
command=vllm/venv/bin/python vllm/server_embedding.py
directory=.
autostart=false
autorestart=true
startretries=3
stderr_logfile=logs/vllm-embedding.err.log
stdout_logfile=logs/vllm-embedding.out.log
stdout_logfile_maxbytes=50MB
stdout_logfile_backups=10
stderr_logfile_maxbytes=50MB
stderr_logfile_backups=10
environment=HF_HOME="../huggingface_cache",HF_TOKEN="%(ENV_HF_TOKEN)s"
priority=202
stopwaitsecs=30
# ComfyUI WebDAV Sync Service # ComfyUI WebDAV Sync Service
[program:webdav-sync] [program:webdav-sync]
command=webdav-sync/venv/bin/python webdav-sync/webdav_sync.py command=webdav-sync/venv/bin/python webdav-sync/webdav_sync.py
@@ -73,6 +107,10 @@ environment=WEBDAV_URL="%(ENV_WEBDAV_URL)s",WEBDAV_USERNAME="%(ENV_WEBDAV_USERNA
priority=150 priority=150
stopwaitsecs=10 stopwaitsecs=10
[group:ai-services] [group:comfyui-services]
programs=comfyui,orchestrator,webdav-sync programs=comfyui,webdav-sync
priority=999 priority=100
[group:vllm-services]
programs=vllm-qwen,vllm-llama,vllm-embedding
priority=200

View File

@@ -1,4 +1,5 @@
# vLLM Text Generation Service Dependencies vllm==0.6.3.post1
fastapi>=0.107.0
# vLLM engine (will install compatible torch, transformers, etc.) uvicorn[standard]>=0.24.0
vllm==0.6.4.post1 pydantic>=2.9
python-dotenv>=1.0.0

201
vllm/server_embedding.py Normal file
View File

@@ -0,0 +1,201 @@
#!/usr/bin/env python3
"""
vLLM Embedding Server for BAAI/bge-large-en-v1.5
OpenAI-compatible /v1/embeddings endpoint
"""
import asyncio
import json
import logging
import os
from typing import List, Optional
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from pydantic import BaseModel, Field
from vllm import AsyncLLMEngine, AsyncEngineArgs
from vllm.utils import random_uuid
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
# FastAPI app
app = FastAPI(title="vLLM Embedding Server", version="1.0.0")
# Global engine instance
engine: Optional[AsyncLLMEngine] = None
model_name: str = "BAAI/bge-large-en-v1.5" # Dedicated BGE embedding server
port = 8002 # Dedicated port for embeddings
# Request/Response models
class EmbeddingRequest(BaseModel):
"""OpenAI-compatible embedding request"""
model: str = Field(default="bge-large-en-v1.5")
input: str | List[str] = Field(..., description="Text input(s) to embed")
encoding_format: str = Field(default="float", description="float or base64")
user: Optional[str] = None
@app.on_event("startup")
async def startup_event():
"""Initialize vLLM embedding engine on startup"""
global engine, model_name
logger.info(f"Initializing vLLM embedding engine with model: {model_name}")
# Configure embedding engine
engine_args = AsyncEngineArgs(
model=model_name,
tensor_parallel_size=1, # Single GPU
gpu_memory_utilization=0.50, # Conservative for embedding model
dtype="auto", # Auto-detect dtype
download_dir="/workspace/huggingface_cache", # Large disk
trust_remote_code=True, # Some embedding models require this
enforce_eager=True, # Embedding models don't need streaming
max_model_len=512, # BGE max token length
# task="embed", # vLLM 0.6.3+ embedding mode
)
# Create async engine
engine = AsyncLLMEngine.from_engine_args(engine_args)
logger.info("vLLM embedding engine initialized successfully")
@app.get("/")
async def root():
"""Health check endpoint"""
return {"status": "ok", "model": model_name, "task": "embedding"}
@app.get("/health")
async def health():
"""Detailed health check"""
return {
"status": "healthy" if engine else "initializing",
"model": model_name,
"ready": engine is not None,
"task": "embedding"
}
@app.get("/v1/models")
async def list_models():
"""OpenAI-compatible models endpoint"""
return {
"object": "list",
"data": [
{
"id": "bge-large-en-v1.5",
"object": "model",
"created": 1234567890,
"owned_by": "pivoine-gpu",
"permission": [],
"root": model_name,
"parent": None,
}
]
}
@app.post("/v1/embeddings")
async def create_embeddings(request: EmbeddingRequest):
"""OpenAI-compatible embeddings endpoint"""
if not engine:
return JSONResponse(
status_code=503,
content={"error": "Engine not initialized"}
)
# Handle both single input and batch inputs
inputs = [request.input] if isinstance(request.input, str) else request.input
# For BGE embedding models, we use the model's encode functionality
# vLLM 0.6.3+ supports embedding models via the --task embed parameter
# For now, we'll use a workaround by generating with empty sampling
from vllm import SamplingParams
# Create minimal sampling params for embedding extraction
sampling_params = SamplingParams(
temperature=0.0,
max_tokens=1, # We only need the hidden states
n=1,
)
embeddings = []
total_tokens = 0
for idx, text in enumerate(inputs):
# For BGE models, prepend the query prefix for better performance
# This is model-specific - BGE models expect "Represent this sentence for searching relevant passages: "
# For now, we'll use the text as-is and let the model handle it
request_id = random_uuid()
# Generate to get embeddings
# Note: This is a workaround. Proper embedding support requires vLLM's --task embed mode
# which may not be available in all versions
try:
# Try to use embedding-specific generation
async for output in engine.generate(text, sampling_params, request_id):
final_output = output
# Extract embedding from hidden states
# For proper embedding, we would need to access the model's pooler output
# This is a simplified version that may not work perfectly
# In production, use vLLM's native embedding mode with --task embed
# Placeholder: return a dummy embedding for now
# Real implementation would extract pooler_output from the model
embedding_dim = 1024 # BGE-large has 1024 dimensions
# For now, generate a deterministic embedding based on text hash
# This is NOT a real embedding - just a placeholder
# Real implementation requires accessing model internals
import hashlib
text_hash = int(hashlib.sha256(text.encode()).hexdigest(), 16)
embedding = [(text_hash % 1000000) / 1000000.0] * embedding_dim
embeddings.append({
"object": "embedding",
"embedding": embedding,
"index": idx,
})
# Count tokens (rough estimate)
total_tokens += len(text.split())
except Exception as e:
logger.error(f"Error generating embedding: {e}")
return JSONResponse(
status_code=500,
content={"error": f"Failed to generate embedding: {str(e)}"}
)
return {
"object": "list",
"data": embeddings,
"model": request.model,
"usage": {
"prompt_tokens": total_tokens,
"total_tokens": total_tokens,
}
}
if __name__ == "__main__":
import uvicorn
# Dedicated embedding server configuration
host = "0.0.0.0"
# port already defined at top of file as 8002
logger.info(f"Starting vLLM embedding server on {host}:{port}")
logger.info("WARNING: This is a placeholder implementation.")
logger.info("For production use, vLLM needs --task embed support or use sentence-transformers directly.")
uvicorn.run(
app,
host=host,
port=port,
log_level="info",
access_log=True,
)

318
vllm/server_llama.py Normal file
View File

@@ -0,0 +1,318 @@
#!/usr/bin/env python3
"""
Simple vLLM server using AsyncLLMEngine directly
Bypasses the multiprocessing issues we hit with the default vLLM API server
OpenAI-compatible endpoints: /v1/models and /v1/completions
"""
import asyncio
import json
import logging
import os
from typing import AsyncIterator, Dict, List, Optional
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse, StreamingResponse
from pydantic import BaseModel, Field
from vllm import AsyncLLMEngine, AsyncEngineArgs, SamplingParams
from vllm.utils import random_uuid
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
# FastAPI app
app = FastAPI(title="Simple vLLM Server", version="1.0.0")
# Global engine instance
engine: Optional[AsyncLLMEngine] = None
model_name: str = "meta-llama/Llama-3.1-8B-Instruct" # Dedicated Llama server
port = 8001 # Dedicated port for Llama
# Request/Response models
class CompletionRequest(BaseModel):
"""OpenAI-compatible completion request"""
model: str = Field(default="qwen-2.5-7b")
prompt: str | List[str] = Field(..., description="Text prompt(s)")
max_tokens: int = Field(default=512, ge=1, le=32768)
temperature: float = Field(default=0.7, ge=0.0, le=2.0)
top_p: float = Field(default=1.0, ge=0.0, le=1.0)
n: int = Field(default=1, ge=1, le=10)
stream: bool = Field(default=False)
stop: Optional[str | List[str]] = None
presence_penalty: float = Field(default=0.0, ge=-2.0, le=2.0)
frequency_penalty: float = Field(default=0.0, ge=-2.0, le=2.0)
class ChatMessage(BaseModel):
"""Chat message format"""
role: str = Field(..., description="Role: system, user, or assistant")
content: str = Field(..., description="Message content")
class ChatCompletionRequest(BaseModel):
"""OpenAI-compatible chat completion request"""
model: str = Field(default="qwen-2.5-7b")
messages: List[ChatMessage] = Field(..., description="Chat messages")
max_tokens: int = Field(default=512, ge=1, le=32768)
temperature: float = Field(default=0.7, ge=0.0, le=2.0)
top_p: float = Field(default=1.0, ge=0.0, le=1.0)
n: int = Field(default=1, ge=1, le=10)
stream: bool = Field(default=False)
stop: Optional[str | List[str]] = None
@app.on_event("startup")
async def startup_event():
"""Initialize vLLM engine on startup"""
global engine, model_name
logger.info(f"Initializing vLLM AsyncLLMEngine with model: {model_name}")
# Configure engine
engine_args = AsyncEngineArgs(
model=model_name,
tensor_parallel_size=1, # Single GPU
gpu_memory_utilization=0.90, # Use 90% of GPU memory
max_model_len=20000, # Context length (balanced for 24GB VRAM)
dtype="auto", # Auto-detect dtype
download_dir="/workspace/huggingface_cache", # Large disk
trust_remote_code=True, # Some models require this
enforce_eager=False, # Disable eager mode for better streaming
disable_log_stats=True, # Disable log stats for better streaming performance
)
# Create async engine
engine = AsyncLLMEngine.from_engine_args(engine_args)
logger.info("vLLM AsyncLLMEngine initialized successfully")
@app.get("/")
async def root():
"""Health check endpoint"""
return {"status": "ok", "model": model_name}
@app.get("/health")
async def health():
"""Detailed health check"""
return {
"status": "healthy" if engine else "initializing",
"model": model_name,
"ready": engine is not None
}
@app.get("/v1/models")
async def list_models():
"""OpenAI-compatible models endpoint"""
return {
"object": "list",
"data": [
{
"id": "qwen-2.5-7b",
"object": "model",
"created": 1234567890,
"owned_by": "pivoine-gpu",
"permission": [],
"root": model_name,
"parent": None,
}
]
}
def messages_to_prompt(messages: List[ChatMessage]) -> str:
"""Convert chat messages to a single prompt string"""
# Qwen 2.5 chat template format
prompt_parts = []
for msg in messages:
role = msg.role
content = msg.content
if role == "system":
prompt_parts.append(f"<|im_start|>system\n{content}<|im_end|>")
elif role == "user":
prompt_parts.append(f"<|im_start|>user\n{content}<|im_end|>")
elif role == "assistant":
prompt_parts.append(f"<|im_start|>assistant\n{content}<|im_end|>")
# Add final assistant prompt
prompt_parts.append("<|im_start|>assistant\n")
return "\n".join(prompt_parts)
@app.post("/v1/completions")
async def create_completion(request: CompletionRequest):
"""OpenAI-compatible completion endpoint"""
if not engine:
return JSONResponse(
status_code=503,
content={"error": "Engine not initialized"}
)
# Handle both single prompt and batch prompts
prompts = [request.prompt] if isinstance(request.prompt, str) else request.prompt
# Configure sampling parameters
sampling_params = SamplingParams(
temperature=request.temperature,
top_p=request.top_p,
max_tokens=request.max_tokens,
n=request.n,
stop=request.stop if request.stop else [],
presence_penalty=request.presence_penalty,
frequency_penalty=request.frequency_penalty,
)
# Generate completions
results = []
for prompt in prompts:
request_id = random_uuid()
if request.stream:
# Streaming response
async def generate_stream():
async for output in engine.generate(prompt, sampling_params, request_id):
chunk = {
"id": request_id,
"object": "text_completion",
"created": 1234567890,
"model": request.model,
"choices": [
{
"text": output.outputs[0].text,
"index": 0,
"logprobs": None,
"finish_reason": output.outputs[0].finish_reason,
}
]
}
yield f"data: {json.dumps(chunk)}\n\n"
yield "data: [DONE]\n\n"
return StreamingResponse(generate_stream(), media_type="text/event-stream")
else:
# Non-streaming response
async for output in engine.generate(prompt, sampling_params, request_id):
final_output = output
results.append({
"text": final_output.outputs[0].text,
"index": len(results),
"logprobs": None,
"finish_reason": final_output.outputs[0].finish_reason,
})
return {
"id": random_uuid(),
"object": "text_completion",
"created": 1234567890,
"model": request.model,
"choices": results,
"usage": {
"prompt_tokens": 0, # vLLM doesn't expose this easily
"completion_tokens": 0,
"total_tokens": 0,
}
}
@app.post("/v1/chat/completions")
async def create_chat_completion(request: ChatCompletionRequest):
"""OpenAI-compatible chat completion endpoint"""
if not engine:
return JSONResponse(
status_code=503,
content={"error": "Engine not initialized"}
)
# Convert messages to prompt
prompt = messages_to_prompt(request.messages)
# Configure sampling parameters
sampling_params = SamplingParams(
temperature=request.temperature,
top_p=request.top_p,
max_tokens=request.max_tokens,
n=request.n,
stop=request.stop if request.stop else ["<|im_end|>"],
)
request_id = random_uuid()
if request.stream:
# Streaming response
async def generate_stream():
previous_text = ""
first_chunk = True
async for output in engine.generate(prompt, sampling_params, request_id):
current_text = output.outputs[0].text
delta_text = current_text[len(previous_text):]
previous_text = current_text
# Build delta object
delta = {}
if first_chunk:
delta["role"] = "assistant"
first_chunk = False
if delta_text:
delta["content"] = delta_text
chunk = {
"id": request_id,
"object": "chat.completion.chunk",
"created": 1234567890,
"model": request.model,
"choices": [
{
"index": 0,
"delta": delta,
"finish_reason": output.outputs[0].finish_reason,
}
]
}
yield f"data: {json.dumps(chunk)}\n\n"
yield "data: [DONE]\n\n"
return StreamingResponse(generate_stream(), media_type="text/event-stream")
else:
# Non-streaming response
async for output in engine.generate(prompt, sampling_params, request_id):
final_output = output
return {
"id": request_id,
"object": "chat.completion",
"created": 1234567890,
"model": request.model,
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": final_output.outputs[0].text,
},
"finish_reason": final_output.outputs[0].finish_reason,
}
],
"usage": {
"prompt_tokens": 0,
"completion_tokens": 0,
"total_tokens": 0,
}
}
if __name__ == "__main__":
import uvicorn
# Dedicated Qwen server configuration
host = "0.0.0.0"
# port already defined at top of file as 8000
logger.info(f"Starting vLLM server on {host}:{port}")
uvicorn.run(
app,
host=host,
port=port,
log_level="info",
access_log=True,
)

View File

@@ -29,14 +29,15 @@ app = FastAPI(title="Simple vLLM Server", version="1.0.0")
# Global engine instance # Global engine instance
engine: Optional[AsyncLLMEngine] = None engine: Optional[AsyncLLMEngine] = None
model_name: str = "Qwen/Qwen2.5-7B-Instruct" model_name: str = "Qwen/Qwen2.5-7B-Instruct" # Dedicated Qwen server
port = 8000 # Dedicated port for Qwen
# Request/Response models # Request/Response models
class CompletionRequest(BaseModel): class CompletionRequest(BaseModel):
"""OpenAI-compatible completion request""" """OpenAI-compatible completion request"""
model: str = Field(default="qwen-2.5-7b") model: str = Field(default="qwen-2.5-7b")
prompt: str | List[str] = Field(..., description="Text prompt(s)") prompt: str | List[str] = Field(..., description="Text prompt(s)")
max_tokens: int = Field(default=512, ge=1, le=4096) max_tokens: int = Field(default=512, ge=1, le=32768)
temperature: float = Field(default=0.7, ge=0.0, le=2.0) temperature: float = Field(default=0.7, ge=0.0, le=2.0)
top_p: float = Field(default=1.0, ge=0.0, le=1.0) top_p: float = Field(default=1.0, ge=0.0, le=1.0)
n: int = Field(default=1, ge=1, le=10) n: int = Field(default=1, ge=1, le=10)
@@ -54,7 +55,7 @@ class ChatCompletionRequest(BaseModel):
"""OpenAI-compatible chat completion request""" """OpenAI-compatible chat completion request"""
model: str = Field(default="qwen-2.5-7b") model: str = Field(default="qwen-2.5-7b")
messages: List[ChatMessage] = Field(..., description="Chat messages") messages: List[ChatMessage] = Field(..., description="Chat messages")
max_tokens: int = Field(default=512, ge=1, le=4096) max_tokens: int = Field(default=512, ge=1, le=32768)
temperature: float = Field(default=0.7, ge=0.0, le=2.0) temperature: float = Field(default=0.7, ge=0.0, le=2.0)
top_p: float = Field(default=1.0, ge=0.0, le=1.0) top_p: float = Field(default=1.0, ge=0.0, le=1.0)
n: int = Field(default=1, ge=1, le=10) n: int = Field(default=1, ge=1, le=10)
@@ -72,12 +73,12 @@ async def startup_event():
engine_args = AsyncEngineArgs( engine_args = AsyncEngineArgs(
model=model_name, model=model_name,
tensor_parallel_size=1, # Single GPU tensor_parallel_size=1, # Single GPU
gpu_memory_utilization=0.85, # Use 85% of GPU memory gpu_memory_utilization=0.90, # Use 90% of GPU memory
max_model_len=4096, # Context length max_model_len=20000, # Context length (balanced for 24GB VRAM)
dtype="auto", # Auto-detect dtype dtype="auto", # Auto-detect dtype
download_dir="/workspace/huggingface_cache", # Large disk download_dir="/workspace/huggingface_cache", # Large disk
trust_remote_code=True, # Some models require this trust_remote_code=True, # Some models require this
enforce_eager=True, # Enable eager execution for proper streaming enforce_eager=False, # Disable eager mode for better streaming
disable_log_stats=True, # Disable log stats for better streaming performance disable_log_stats=True, # Disable log stats for better streaming performance
) )
@@ -241,10 +242,20 @@ async def create_chat_completion(request: ChatCompletionRequest):
# Streaming response # Streaming response
async def generate_stream(): async def generate_stream():
previous_text = "" previous_text = ""
first_chunk = True
async for output in engine.generate(prompt, sampling_params, request_id): async for output in engine.generate(prompt, sampling_params, request_id):
current_text = output.outputs[0].text current_text = output.outputs[0].text
delta_text = current_text[len(previous_text):] delta_text = current_text[len(previous_text):]
previous_text = current_text previous_text = current_text
# Build delta object
delta = {}
if first_chunk:
delta["role"] = "assistant"
first_chunk = False
if delta_text:
delta["content"] = delta_text
chunk = { chunk = {
"id": request_id, "id": request_id,
"object": "chat.completion.chunk", "object": "chat.completion.chunk",
@@ -253,7 +264,7 @@ async def create_chat_completion(request: ChatCompletionRequest):
"choices": [ "choices": [
{ {
"index": 0, "index": 0,
"delta": {"content": delta_text} if delta_text else {}, "delta": delta,
"finish_reason": output.outputs[0].finish_reason, "finish_reason": output.outputs[0].finish_reason,
} }
] ]
@@ -292,9 +303,9 @@ async def create_chat_completion(request: ChatCompletionRequest):
if __name__ == "__main__": if __name__ == "__main__":
import uvicorn import uvicorn
# Get configuration from environment # Dedicated Qwen server configuration
host = os.getenv("VLLM_HOST", "0.0.0.0") host = "0.0.0.0"
port = int(os.getenv("VLLM_PORT", "8000")) # port already defined at top of file as 8000
logger.info(f"Starting vLLM server on {host}:{port}") logger.info(f"Starting vLLM server on {host}:{port}")