mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-02-11 05:52:33 +08:00
feat: Add RunPod Hub configuration and storage access test
- Add .runpod/hub.json with serverless configuration - Add .runpod/tests.json with comprehensive test cases - Add storage access test to Dockerfile build process - Add RunPod badge to README.md - Include model download script for build-time optimization - Test storage accessibility during Docker build phase
This commit is contained in:
parent
cd8bb55239
commit
80848f3c54
66
.runpod/hub.json
Normal file
66
.runpod/hub.json
Normal file
@ -0,0 +1,66 @@
|
||||
{
|
||||
"title": "ComfyUI - AI Image Generation",
|
||||
"description": "ComfyUI serverless deployment with network storage support for models. Generate high-quality images using Stable Diffusion XL with custom workflows.",
|
||||
"type": "serverless",
|
||||
"category": "image",
|
||||
"iconUrl": "https://raw.githubusercontent.com/comfyanonymous/ComfyUI/master/web/favicon.ico",
|
||||
"config": {
|
||||
"runsOn": "GPU",
|
||||
"containerDiskInGb": 20,
|
||||
"presets": [
|
||||
{
|
||||
"name": "SDXL Base",
|
||||
"defaults": {
|
||||
"MODEL_NAME": "sd_xl_base_1.0.safetensors",
|
||||
"STEPS": "25",
|
||||
"CFG": "8.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "High Quality",
|
||||
"defaults": {
|
||||
"MODEL_NAME": "sd_xl_base_1.0.safetensors",
|
||||
"STEPS": "50",
|
||||
"CFG": "7.0"
|
||||
}
|
||||
}
|
||||
],
|
||||
"env": [
|
||||
{
|
||||
"key": "HF_HUB_DISABLE_TELEMETRY",
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"key": "DO_NOT_TRACK",
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"key": "MODEL_NAME",
|
||||
"input": {
|
||||
"name": "Model Name",
|
||||
"type": "string",
|
||||
"description": "Checkpoint model file name to use",
|
||||
"default": "sd_xl_base_1.0.safetensors"
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "STEPS",
|
||||
"input": {
|
||||
"name": "Generation Steps",
|
||||
"type": "string",
|
||||
"description": "Number of denoising steps",
|
||||
"default": "25"
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "CFG",
|
||||
"input": {
|
||||
"name": "CFG Scale",
|
||||
"type": "string",
|
||||
"description": "Classifier-free guidance scale",
|
||||
"default": "8.0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
94
.runpod/tests.json
Normal file
94
.runpod/tests.json
Normal file
@ -0,0 +1,94 @@
|
||||
{
|
||||
"tests": [
|
||||
{
|
||||
"name": "basic_text_to_image",
|
||||
"input": {
|
||||
"workflow": {
|
||||
"3": {
|
||||
"inputs": {
|
||||
"seed": 42,
|
||||
"steps": 20,
|
||||
"cfg": 8.0,
|
||||
"sampler_name": "euler",
|
||||
"scheduler": "normal",
|
||||
"denoise": 1.0,
|
||||
"model": ["4", 0],
|
||||
"positive": ["6", 0],
|
||||
"negative": ["7", 0],
|
||||
"latent_image": ["5", 0]
|
||||
},
|
||||
"class_type": "KSampler"
|
||||
},
|
||||
"4": {
|
||||
"inputs": {
|
||||
"ckpt_name": "sd_xl_base_1.0.safetensors"
|
||||
},
|
||||
"class_type": "CheckpointLoaderSimple"
|
||||
},
|
||||
"5": {
|
||||
"inputs": {
|
||||
"width": 1024,
|
||||
"height": 1024,
|
||||
"batch_size": 1
|
||||
},
|
||||
"class_type": "EmptyLatentImage"
|
||||
},
|
||||
"6": {
|
||||
"inputs": {
|
||||
"text": "a beautiful landscape, high quality, detailed",
|
||||
"clip": ["4", 1]
|
||||
},
|
||||
"class_type": "CLIPTextEncode"
|
||||
},
|
||||
"7": {
|
||||
"inputs": {
|
||||
"text": "blurry, low quality, distorted",
|
||||
"clip": ["4", 1]
|
||||
},
|
||||
"class_type": "CLIPTextEncode"
|
||||
},
|
||||
"8": {
|
||||
"inputs": {
|
||||
"samples": ["3", 0],
|
||||
"vae": ["4", 2]
|
||||
},
|
||||
"class_type": "VAEDecode"
|
||||
},
|
||||
"9": {
|
||||
"inputs": {
|
||||
"filename_prefix": "test_output",
|
||||
"images": ["8", 0]
|
||||
},
|
||||
"class_type": "SaveImage"
|
||||
}
|
||||
}
|
||||
},
|
||||
"timeout": 120000
|
||||
},
|
||||
{
|
||||
"name": "simple_prompt_test",
|
||||
"input": {
|
||||
"prompt": "modern software interface, clean design"
|
||||
},
|
||||
"timeout": 60000
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"gpuTypeId": "NVIDIA RTX A4000",
|
||||
"gpuCount": 1,
|
||||
"env": [
|
||||
{
|
||||
"key": "HF_HUB_DISABLE_TELEMETRY",
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"key": "DO_NOT_TRACK",
|
||||
"value": "1"
|
||||
}
|
||||
],
|
||||
"allowedCudaVersions": [
|
||||
"12.1",
|
||||
"11.8"
|
||||
]
|
||||
}
|
||||
}
|
||||
23
Dockerfile
23
Dockerfile
@ -13,6 +13,29 @@ RUN apt-get update && apt-get install -y \
|
||||
# Tüm dosyaları kopyala
|
||||
COPY . /app
|
||||
|
||||
# Model klasörlerini oluştur
|
||||
RUN mkdir -p /app/models/checkpoints /app/models/loras /app/models/vae \
|
||||
/app/models/controlnet /app/models/upscale_models \
|
||||
/app/models/text_encoders /app/models/clip \
|
||||
/app/models/diffusion_models /app/models/unet \
|
||||
/app/models/embeddings /app/models/clip_vision
|
||||
|
||||
# Storage erişim testi - Build sırasında storage erişimi kontrol et
|
||||
RUN echo "🔍 RunPod Build Storage Access Test" && \
|
||||
echo "=================================" && \
|
||||
echo "📁 Testing storage paths:" && \
|
||||
(ls -la /runpod-volume 2>/dev/null && echo "✅ /runpod-volume accessible" || echo "❌ /runpod-volume not accessible") && \
|
||||
(ls -la /workspace 2>/dev/null && echo "✅ /workspace accessible" || echo "❌ /workspace not accessible") && \
|
||||
(ls -la /content 2>/dev/null && echo "✅ /content accessible" || echo "❌ /content not accessible") && \
|
||||
echo "🌐 Network test:" && \
|
||||
(ping -c 1 google.com >/dev/null 2>&1 && echo "✅ Internet access available" || echo "❌ No internet access") && \
|
||||
echo "================================="
|
||||
|
||||
# Temel modelleri Docker build sırasında indir
|
||||
RUN pip install huggingface-hub && \
|
||||
python download_models.py && \
|
||||
rm -rf /tmp/hf_cache
|
||||
|
||||
# PyTorch CPU versiyonu ve bağımlılıklar
|
||||
RUN pip install --no-cache-dir \
|
||||
torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu && \
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
[![Dynamic JSON Badge][discord-shield]][discord-url]
|
||||
[![Twitter][twitter-shield]][twitter-url]
|
||||
[![Matrix][matrix-shield]][matrix-url]
|
||||
[![Runpod][runpod-shield]][runpod-url]
|
||||
<br>
|
||||
[![][github-release-shield]][github-release-link]
|
||||
[![][github-release-date-shield]][github-release-link]
|
||||
@ -18,6 +19,8 @@
|
||||
[matrix-url]: https://app.element.io/#/room/%23comfyui_space%3Amatrix.org
|
||||
[website-shield]: https://img.shields.io/badge/ComfyOrg-4285F4?style=flat
|
||||
[website-url]: https://www.comfy.org/
|
||||
[runpod-shield]: https://api.runpod.io/badge/bahadirciloglu/ComfyUI
|
||||
[runpod-url]: https://console.runpod.io/hub/bahadirciloglu/ComfyUI
|
||||
<!-- Workaround to display total user from https://github.com/badges/shields/issues/4500#issuecomment-2060079995 -->
|
||||
[discord-shield]: https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fdiscord.com%2Fapi%2Finvites%2Fcomfyorg%3Fwith_counts%3Dtrue&query=%24.approximate_member_count&logo=discord&logoColor=white&label=Discord&color=green&suffix=%20total
|
||||
[discord-url]: https://www.comfy.org/discord
|
||||
|
||||
17
debug_runpod.sh
Executable file
17
debug_runpod.sh
Executable file
@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
# Debug RunPod API call
|
||||
|
||||
ENDPOINT_ID="sfkzjudvrj50yq"
|
||||
API_KEY="${RUNPOD_API_KEY:-YOUR_API_KEY}"
|
||||
BASE_URL="https://api.runpod.ai/v2"
|
||||
|
||||
echo "🔍 Debugging RunPod API..."
|
||||
echo "📍 Endpoint: $ENDPOINT_ID"
|
||||
echo "🔑 API Key: ${API_KEY:0:10}..." # Show only first 10 chars for security
|
||||
|
||||
# Simple test with minimal payload
|
||||
echo "📤 Testing with simple payload..."
|
||||
curl -v -X POST "$BASE_URL/$ENDPOINT_ID/run" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer $API_KEY" \
|
||||
-d '{"input":{"prompt":"test prompt"}}'
|
||||
90
download_models.py
Normal file
90
download_models.py
Normal file
@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Docker build sırasında temel modelleri indir
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from huggingface_hub import hf_hub_download
|
||||
|
||||
def download_model(repo_id, filename, target_dir):
|
||||
"""Model indir ve hedef dizine kopyala"""
|
||||
try:
|
||||
print(f"📥 İndiriliyor: {repo_id}/{filename}")
|
||||
|
||||
# Model'i indir
|
||||
model_path = hf_hub_download(
|
||||
repo_id=repo_id,
|
||||
filename=filename,
|
||||
cache_dir="/tmp/hf_cache"
|
||||
)
|
||||
|
||||
# Hedef dizini oluştur
|
||||
os.makedirs(target_dir, exist_ok=True)
|
||||
|
||||
# Dosyayı kopyala
|
||||
target_path = os.path.join(target_dir, filename)
|
||||
os.system(f"cp '{model_path}' '{target_path}'")
|
||||
|
||||
print(f"✅ Kaydedildi: {target_path}")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Hata: {repo_id}/{filename} - {e}")
|
||||
return False
|
||||
|
||||
def main():
|
||||
"""Temel modelleri indir"""
|
||||
print("🚀 Docker build - Model indirme başlatılıyor...")
|
||||
|
||||
models_base = "/app/models"
|
||||
|
||||
# İndirilecek modeller
|
||||
models_to_download = [
|
||||
# SDXL Base Model
|
||||
{
|
||||
"repo_id": "stabilityai/stable-diffusion-xl-base-1.0",
|
||||
"filename": "sd_xl_base_1.0.safetensors",
|
||||
"target_dir": f"{models_base}/checkpoints"
|
||||
},
|
||||
# SDXL VAE
|
||||
{
|
||||
"repo_id": "stabilityai/sdxl-vae",
|
||||
"filename": "sdxl_vae.safetensors",
|
||||
"target_dir": f"{models_base}/vae"
|
||||
},
|
||||
# CLIP Text Encoder
|
||||
{
|
||||
"repo_id": "openai/clip-vit-large-patch14",
|
||||
"filename": "pytorch_model.bin",
|
||||
"target_dir": f"{models_base}/clip"
|
||||
}
|
||||
]
|
||||
|
||||
success_count = 0
|
||||
|
||||
for model in models_to_download:
|
||||
if download_model(
|
||||
model["repo_id"],
|
||||
model["filename"],
|
||||
model["target_dir"]
|
||||
):
|
||||
success_count += 1
|
||||
|
||||
print(f"\n🎉 Model indirme tamamlandı: {success_count}/{len(models_to_download)}")
|
||||
|
||||
# Model klasörlerini listele
|
||||
print("\n📁 Model klasörleri:")
|
||||
for root, dirs, files in os.walk(models_base):
|
||||
level = root.replace(models_base, '').count(os.sep)
|
||||
indent = ' ' * 2 * level
|
||||
print(f"{indent}{os.path.basename(root)}/")
|
||||
subindent = ' ' * 2 * (level + 1)
|
||||
for file in files:
|
||||
file_size = os.path.getsize(os.path.join(root, file))
|
||||
size_mb = file_size / (1024 * 1024)
|
||||
print(f"{subindent}{file} ({size_mb:.1f} MB)")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
0
runpod_template_config.md
Normal file
0
runpod_template_config.md
Normal file
91
runpod_test_commands.md
Normal file
91
runpod_test_commands.md
Normal file
@ -0,0 +1,91 @@
|
||||
# RunPod Container Test Komutları
|
||||
|
||||
## 1. Container'a Bağlan
|
||||
RunPod dashboard'da "Connect" → "Start Web Terminal"
|
||||
|
||||
## 2. Test Scriptini Çalıştır
|
||||
```bash
|
||||
# Container içinde:
|
||||
cd /app
|
||||
python test_image_generation.py
|
||||
```
|
||||
|
||||
## 3. Manuel Test (Alternatif)
|
||||
```bash
|
||||
# ComfyUI durumunu kontrol et
|
||||
curl http://127.0.0.1:8188/system_stats
|
||||
|
||||
# Model listesini al
|
||||
curl http://127.0.0.1:8188/object_info | jq '.CheckpointLoaderSimple.input.required.ckpt_name'
|
||||
|
||||
# Basit workflow gönder
|
||||
curl -X POST http://127.0.0.1:8188/prompt \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @test_simple_workflow.json
|
||||
```
|
||||
|
||||
## 4. Network Storage Kontrolü
|
||||
```bash
|
||||
# Models klasörünü kontrol et
|
||||
ls -la /app/models/
|
||||
ls -la /runpod-volume/models/
|
||||
|
||||
# Symlink kontrolü
|
||||
readlink /app/models
|
||||
```
|
||||
|
||||
## 5. Model Yükleme (Gerekirse)
|
||||
```bash
|
||||
# Network storage'a model yükle
|
||||
cd /runpod-volume/models/checkpoints
|
||||
wget https://huggingface.co/stabilityai/stable-diffusion-xl-base-1.0/resolve/main/sd_xl_base_1.0.safetensors
|
||||
|
||||
# ComfyUI'yi yeniden başlat
|
||||
pkill -f main.py
|
||||
python main.py --listen 0.0.0.0 --port 8188 --cpu
|
||||
```
|
||||
|
||||
## 6. Beklenen Çıktılar
|
||||
|
||||
### Başarılı Durum:
|
||||
```
|
||||
✅ ComfyUI server çalışıyor
|
||||
✅ Yüklü modeller (1 adet):
|
||||
- sd_xl_base_1.0.safetensors
|
||||
🎨 Resim üretiliyor...
|
||||
Model: sd_xl_base_1.0.safetensors
|
||||
Prompt: a modern user interface design...
|
||||
📝 Prompt ID: abc123
|
||||
⏳ Bekleniyor... (15s)
|
||||
✅ Resim kaydedildi: test_output/test_ui_design_00001_.png
|
||||
🎉 Test tamamlandı!
|
||||
```
|
||||
|
||||
### Hata Durumu:
|
||||
```
|
||||
❌ ComfyUI server'a bağlanılamıyor
|
||||
❌ Hiç model bulunamadı
|
||||
❌ Network storage mount edilmedi
|
||||
```
|
||||
|
||||
## 7. Troubleshooting
|
||||
|
||||
### ComfyUI Başlamazsa:
|
||||
```bash
|
||||
# Logları kontrol et
|
||||
tail -f /var/log/comfyui.log
|
||||
|
||||
# Manuel başlat
|
||||
cd /app
|
||||
python main.py --listen 0.0.0.0 --port 8188 --cpu
|
||||
```
|
||||
|
||||
### Network Storage Sorunları:
|
||||
```bash
|
||||
# Mount durumunu kontrol et
|
||||
mount | grep runpod-volume
|
||||
|
||||
# Manuel mount
|
||||
mkdir -p /runpod-volume/models
|
||||
ln -sf /runpod-volume/models /app/models
|
||||
```
|
||||
@ -161,11 +161,12 @@ def main():
|
||||
# Environment setup
|
||||
setup_environment()
|
||||
|
||||
# Network storage'ı bekle
|
||||
wait_for_storage()
|
||||
|
||||
# Network storage mount
|
||||
mount_runpod_storage()
|
||||
# Hızlı başlatma için network storage mount'u atla
|
||||
# Modeller zaten Docker image'da mevcut
|
||||
logger.info("Hızlı başlatma modu - modeller image'da mevcut")
|
||||
|
||||
# Model klasörlerini kontrol et
|
||||
ensure_local_model_folders()
|
||||
|
||||
# Temel modelleri indir (opsiyonel)
|
||||
download_essential_models()
|
||||
|
||||
40
test-storage-access.Dockerfile
Normal file
40
test-storage-access.Dockerfile
Normal file
@ -0,0 +1,40 @@
|
||||
FROM python:3.10-slim
|
||||
|
||||
# RunPod build sırasında storage erişimi test et
|
||||
RUN echo "🔍 RunPod Build Storage Access Test" && \
|
||||
echo "=================================" && \
|
||||
echo "" && \
|
||||
echo "📁 Testing common RunPod storage paths:" && \
|
||||
echo "" && \
|
||||
echo "1. /workspace:" && \
|
||||
(ls -la /workspace 2>/dev/null || echo "❌ /workspace not accessible") && \
|
||||
echo "" && \
|
||||
echo "2. /runpod-volume:" && \
|
||||
(ls -la /runpod-volume 2>/dev/null || echo "❌ /runpod-volume not accessible") && \
|
||||
echo "" && \
|
||||
echo "3. /content:" && \
|
||||
(ls -la /content 2>/dev/null || echo "❌ /content not accessible") && \
|
||||
echo "" && \
|
||||
echo "4. /storage:" && \
|
||||
(ls -la /storage 2>/dev/null || echo "❌ /storage not accessible") && \
|
||||
echo "" && \
|
||||
echo "5. Environment variables:" && \
|
||||
env | grep -i runpod || echo "❌ No RUNPOD env vars found" && \
|
||||
echo "" && \
|
||||
echo "6. Mount points:" && \
|
||||
mount | grep -E "(workspace|runpod|storage)" || echo "❌ No storage mounts found" && \
|
||||
echo "" && \
|
||||
echo "7. Available disk space:" && \
|
||||
df -h && \
|
||||
echo "" && \
|
||||
echo "8. Network connectivity test:" && \
|
||||
(ping -c 1 google.com >/dev/null 2>&1 && echo "✅ Internet access available" || echo "❌ No internet access") && \
|
||||
echo "" && \
|
||||
echo "=================================" && \
|
||||
echo "🏁 Test completed"
|
||||
|
||||
# Basit bir uygulama
|
||||
WORKDIR /app
|
||||
RUN echo 'print("Hello from RunPod build test!")' > app.py
|
||||
|
||||
CMD ["python", "app.py"]
|
||||
21
test_build.sh
Executable file
21
test_build.sh
Executable file
@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
# RunPod Build Test Script
|
||||
|
||||
echo "🔍 RunPod Storage Access Test"
|
||||
echo "============================="
|
||||
|
||||
# Docker build ile test et (local)
|
||||
echo "📦 Local Docker build test..."
|
||||
docker build -f test-storage-access.Dockerfile -t runpod-storage-test . 2>&1 | grep -E "(Storage Access Test|accessible|not accessible)"
|
||||
|
||||
echo ""
|
||||
echo "🚀 Gerçek test için RunPod Dashboard'da bu Dockerfile'ı kullan:"
|
||||
echo " 1. RunPod Dashboard → Templates → Create Template"
|
||||
echo " 2. Container Image → Build from Dockerfile"
|
||||
echo " 3. test-storage-access.Dockerfile içeriğini yapıştır"
|
||||
echo " 4. Build loglarında storage erişim sonuçlarını kontrol et"
|
||||
|
||||
echo ""
|
||||
echo "📋 Test sonuçlarına göre:"
|
||||
echo " ✅ Storage erişimi VARSA → Build sırasında model kopyalama"
|
||||
echo " ❌ Storage erişimi YOKSA → HuggingFace'den model indirme"
|
||||
155
test_curl_runpod.sh
Executable file
155
test_curl_runpod.sh
Executable file
@ -0,0 +1,155 @@
|
||||
#!/bin/bash
|
||||
# RunPod Serverless API Test with curl
|
||||
# Usage: ./test_curl_runpod.sh "your prompt here"
|
||||
|
||||
# Configuration
|
||||
ENDPOINT_ID="sfkzjudvrj50yq"
|
||||
API_KEY="${RUNPOD_API_KEY:-YOUR_API_KEY}" # Set RUNPOD_API_KEY environment variable
|
||||
BASE_URL="https://api.runpod.ai/v2"
|
||||
|
||||
# Check if API key is set
|
||||
if [ "$API_KEY" = "YOUR_API_KEY" ]; then
|
||||
echo "❌ API key not set!"
|
||||
echo "💡 Set your API key: export RUNPOD_API_KEY='your_key_here'"
|
||||
echo " Or edit this script and replace YOUR_API_KEY with your actual key"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get prompt from command line or use default
|
||||
PROMPT="${1:-modern software interface, clean dashboard design, professional UI layout, high quality, detailed}"
|
||||
|
||||
echo "🚀 Testing RunPod Serverless API..."
|
||||
echo "📍 Endpoint: $ENDPOINT_ID"
|
||||
echo "💬 Prompt: $PROMPT"
|
||||
|
||||
# Create the JSON payload
|
||||
JSON_PAYLOAD=$(cat <<EOF
|
||||
{
|
||||
"input": {
|
||||
"workflow": {
|
||||
"3": {
|
||||
"inputs": {
|
||||
"seed": 42,
|
||||
"steps": 25,
|
||||
"cfg": 8.0,
|
||||
"sampler_name": "euler",
|
||||
"scheduler": "normal",
|
||||
"denoise": 1.0,
|
||||
"model": ["4", 0],
|
||||
"positive": ["6", 0],
|
||||
"negative": ["7", 0],
|
||||
"latent_image": ["5", 0]
|
||||
},
|
||||
"class_type": "KSampler"
|
||||
},
|
||||
"4": {
|
||||
"inputs": {
|
||||
"ckpt_name": "sd_xl_base_1.0.safetensors"
|
||||
},
|
||||
"class_type": "CheckpointLoaderSimple"
|
||||
},
|
||||
"5": {
|
||||
"inputs": {
|
||||
"width": 1024,
|
||||
"height": 1024,
|
||||
"batch_size": 1
|
||||
},
|
||||
"class_type": "EmptyLatentImage"
|
||||
},
|
||||
"6": {
|
||||
"inputs": {
|
||||
"text": "$PROMPT",
|
||||
"clip": ["4", 1]
|
||||
},
|
||||
"class_type": "CLIPTextEncode"
|
||||
},
|
||||
"7": {
|
||||
"inputs": {
|
||||
"text": "blurry, low quality, distorted, ugly, bad anatomy, worst quality",
|
||||
"clip": ["4", 1]
|
||||
},
|
||||
"class_type": "CLIPTextEncode"
|
||||
},
|
||||
"8": {
|
||||
"inputs": {
|
||||
"samples": ["3", 0],
|
||||
"vae": ["4", 2]
|
||||
},
|
||||
"class_type": "VAEDecode"
|
||||
},
|
||||
"9": {
|
||||
"inputs": {
|
||||
"filename_prefix": "curl_test",
|
||||
"images": ["8", 0]
|
||||
},
|
||||
"class_type": "SaveImage"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
)
|
||||
|
||||
# Submit the job
|
||||
echo "📤 Submitting job..."
|
||||
RESPONSE=$(curl -s -X POST "$BASE_URL/$ENDPOINT_ID/run" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer $API_KEY" \
|
||||
-d "$JSON_PAYLOAD")
|
||||
|
||||
# Check if curl succeeded
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "❌ Curl command failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Parse job ID
|
||||
JOB_ID=$(echo "$RESPONSE" | grep -o '"id":"[^"]*"' | cut -d'"' -f4)
|
||||
|
||||
if [ -z "$JOB_ID" ]; then
|
||||
echo "❌ Failed to get job ID"
|
||||
echo "Response: $RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ Job submitted: $JOB_ID"
|
||||
|
||||
# Monitor job status
|
||||
echo "⏳ Monitoring job status..."
|
||||
MAX_WAIT=300 # 5 minutes
|
||||
WAIT_TIME=0
|
||||
|
||||
while [ $WAIT_TIME -lt $MAX_WAIT ]; do
|
||||
STATUS_RESPONSE=$(curl -s -X GET "$BASE_URL/$ENDPOINT_ID/status/$JOB_ID" \
|
||||
-H "Authorization: Bearer $API_KEY")
|
||||
|
||||
STATUS=$(echo "$STATUS_RESPONSE" | grep -o '"status":"[^"]*"' | cut -d'"' -f4)
|
||||
|
||||
case "$STATUS" in
|
||||
"COMPLETED")
|
||||
echo "✅ Job completed!"
|
||||
echo "📄 Full response:"
|
||||
echo "$STATUS_RESPONSE" | jq '.' 2>/dev/null || echo "$STATUS_RESPONSE"
|
||||
exit 0
|
||||
;;
|
||||
"FAILED")
|
||||
echo "❌ Job failed!"
|
||||
echo "📄 Error response:"
|
||||
echo "$STATUS_RESPONSE" | jq '.' 2>/dev/null || echo "$STATUS_RESPONSE"
|
||||
exit 1
|
||||
;;
|
||||
"IN_QUEUE"|"IN_PROGRESS")
|
||||
echo "⏳ Job status: $STATUS (${WAIT_TIME}s elapsed)"
|
||||
;;
|
||||
*)
|
||||
echo "❓ Unknown status: $STATUS"
|
||||
;;
|
||||
esac
|
||||
|
||||
sleep 5
|
||||
WAIT_TIME=$((WAIT_TIME + 5))
|
||||
done
|
||||
|
||||
echo "⏰ Timeout after ${MAX_WAIT} seconds"
|
||||
echo "📄 Last status response:"
|
||||
echo "$STATUS_RESPONSE" | jq '.' 2>/dev/null || echo "$STATUS_RESPONSE"
|
||||
274
test_image_generation.py
Normal file
274
test_image_generation.py
Normal file
@ -0,0 +1,274 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
ComfyUI Test Script - pars klasöründeki resimlere benzer resim üretimi
|
||||
"""
|
||||
|
||||
import os
|
||||
import json
|
||||
import base64
|
||||
import requests
|
||||
from pathlib import Path
|
||||
import time
|
||||
|
||||
class ComfyUITester:
|
||||
def __init__(self, comfyui_url="http://127.0.0.1:8188"):
|
||||
self.comfyui_url = comfyui_url
|
||||
self.client_id = "test_client"
|
||||
|
||||
def check_server(self):
|
||||
"""ComfyUI server'ın çalışıp çalışmadığını kontrol et"""
|
||||
try:
|
||||
response = requests.get(f"{self.comfyui_url}/system_stats", timeout=5)
|
||||
if response.status_code == 200:
|
||||
print("✅ ComfyUI server çalışıyor")
|
||||
return True
|
||||
else:
|
||||
print(f"❌ ComfyUI server yanıt vermiyor: {response.status_code}")
|
||||
return False
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"❌ ComfyUI server'a bağlanılamıyor: {e}")
|
||||
return False
|
||||
|
||||
def get_models(self):
|
||||
"""Yüklü modelleri listele"""
|
||||
try:
|
||||
response = requests.get(f"{self.comfyui_url}/object_info")
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
checkpoints = data.get("CheckpointLoaderSimple", {}).get("input", {}).get("required", {}).get("ckpt_name", [])
|
||||
if isinstance(checkpoints, list) and len(checkpoints) > 1:
|
||||
models = checkpoints[0] # İlk element model listesi
|
||||
print(f"✅ Yüklü modeller ({len(models)} adet):")
|
||||
for model in models[:5]: # İlk 5 modeli göster
|
||||
print(f" - {model}")
|
||||
return models
|
||||
else:
|
||||
print("❌ Model listesi alınamadı")
|
||||
return []
|
||||
except Exception as e:
|
||||
print(f"❌ Model listesi alınamadı: {e}")
|
||||
return []
|
||||
|
||||
def create_basic_workflow(self, model_name="sd_xl_base_1.0.safetensors", prompt="a beautiful landscape"):
|
||||
"""Temel SDXL workflow oluştur"""
|
||||
workflow = {
|
||||
"3": {
|
||||
"inputs": {
|
||||
"seed": 42,
|
||||
"steps": 20,
|
||||
"cfg": 8.0,
|
||||
"sampler_name": "euler",
|
||||
"scheduler": "normal",
|
||||
"denoise": 1.0,
|
||||
"model": ["4", 0],
|
||||
"positive": ["6", 0],
|
||||
"negative": ["7", 0],
|
||||
"latent_image": ["5", 0]
|
||||
},
|
||||
"class_type": "KSampler"
|
||||
},
|
||||
"4": {
|
||||
"inputs": {
|
||||
"ckpt_name": model_name
|
||||
},
|
||||
"class_type": "CheckpointLoaderSimple"
|
||||
},
|
||||
"5": {
|
||||
"inputs": {
|
||||
"width": 1024,
|
||||
"height": 1024,
|
||||
"batch_size": 1
|
||||
},
|
||||
"class_type": "EmptyLatentImage"
|
||||
},
|
||||
"6": {
|
||||
"inputs": {
|
||||
"text": prompt,
|
||||
"clip": ["4", 1]
|
||||
},
|
||||
"class_type": "CLIPTextEncode"
|
||||
},
|
||||
"7": {
|
||||
"inputs": {
|
||||
"text": "blurry, low quality, distorted",
|
||||
"clip": ["4", 1]
|
||||
},
|
||||
"class_type": "CLIPTextEncode"
|
||||
},
|
||||
"8": {
|
||||
"inputs": {
|
||||
"samples": ["3", 0],
|
||||
"vae": ["4", 2]
|
||||
},
|
||||
"class_type": "VAEDecode"
|
||||
},
|
||||
"9": {
|
||||
"inputs": {
|
||||
"filename_prefix": "test_output",
|
||||
"images": ["8", 0]
|
||||
},
|
||||
"class_type": "SaveImage"
|
||||
}
|
||||
}
|
||||
return workflow
|
||||
|
||||
def generate_image(self, prompt, model_name=None):
|
||||
"""Resim üret"""
|
||||
try:
|
||||
# Model seç
|
||||
if not model_name:
|
||||
models = self.get_models()
|
||||
if not models:
|
||||
print("❌ Hiç model bulunamadı")
|
||||
return None
|
||||
model_name = models[0] # İlk modeli kullan
|
||||
|
||||
print(f"🎨 Resim üretiliyor...")
|
||||
print(f" Model: {model_name}")
|
||||
print(f" Prompt: {prompt}")
|
||||
|
||||
# Workflow oluştur
|
||||
workflow = self.create_basic_workflow(model_name, prompt)
|
||||
|
||||
# İsteği gönder
|
||||
response = requests.post(
|
||||
f"{self.comfyui_url}/prompt",
|
||||
json={
|
||||
"prompt": workflow,
|
||||
"client_id": self.client_id
|
||||
},
|
||||
timeout=30
|
||||
)
|
||||
response.raise_for_status()
|
||||
|
||||
prompt_id = response.json()["prompt_id"]
|
||||
print(f"📝 Prompt ID: {prompt_id}")
|
||||
|
||||
# Tamamlanmasını bekle
|
||||
return self.wait_for_completion(prompt_id)
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Resim üretimi başarısız: {e}")
|
||||
return None
|
||||
|
||||
def wait_for_completion(self, prompt_id, timeout=300):
|
||||
"""İşlemin tamamlanmasını bekle"""
|
||||
start_time = time.time()
|
||||
|
||||
while time.time() - start_time < timeout:
|
||||
try:
|
||||
# Queue durumunu kontrol et
|
||||
queue_response = requests.get(f"{self.comfyui_url}/queue")
|
||||
queue_data = queue_response.json()
|
||||
|
||||
# İşlem hala çalışıyor mu?
|
||||
running = any(item[1]["prompt_id"] == prompt_id for item in queue_data.get("queue_running", []))
|
||||
pending = any(item[1]["prompt_id"] == prompt_id for item in queue_data.get("queue_pending", []))
|
||||
|
||||
if not running and not pending:
|
||||
# İşlem tamamlandı, sonuçları al
|
||||
history_response = requests.get(f"{self.comfyui_url}/history/{prompt_id}")
|
||||
if history_response.status_code == 200:
|
||||
history_data = history_response.json()
|
||||
if prompt_id in history_data:
|
||||
return self.download_results(history_data[prompt_id])
|
||||
|
||||
print(f"⏳ Bekleniyor... ({int(time.time() - start_time)}s)")
|
||||
time.sleep(3)
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Durum kontrolü hatası: {e}")
|
||||
time.sleep(5)
|
||||
|
||||
print(f"⏰ Timeout: {timeout} saniye")
|
||||
return None
|
||||
|
||||
def download_results(self, history_data):
|
||||
"""Sonuçları indir"""
|
||||
results = []
|
||||
|
||||
if "outputs" in history_data:
|
||||
for node_id, node_output in history_data["outputs"].items():
|
||||
if "images" in node_output:
|
||||
for image_info in node_output["images"]:
|
||||
try:
|
||||
# Resmi indir
|
||||
image_url = f"{self.comfyui_url}/view"
|
||||
params = {
|
||||
"filename": image_info["filename"],
|
||||
"subfolder": image_info.get("subfolder", ""),
|
||||
"type": image_info.get("type", "output")
|
||||
}
|
||||
|
||||
image_response = requests.get(image_url, params=params)
|
||||
image_response.raise_for_status()
|
||||
|
||||
# Test output klasörüne kaydet
|
||||
os.makedirs("test_output", exist_ok=True)
|
||||
output_path = f"test_output/{image_info['filename']}"
|
||||
|
||||
with open(output_path, "wb") as f:
|
||||
f.write(image_response.content)
|
||||
|
||||
results.append({
|
||||
"filename": image_info["filename"],
|
||||
"path": output_path,
|
||||
"node_id": node_id
|
||||
})
|
||||
|
||||
print(f"✅ Resim kaydedildi: {output_path}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Resim indirme hatası: {e}")
|
||||
|
||||
return results
|
||||
|
||||
def main():
|
||||
"""Ana test fonksiyonu"""
|
||||
print("🚀 ComfyUI Test Başlatılıyor...")
|
||||
|
||||
tester = ComfyUITester()
|
||||
|
||||
# Server kontrolü
|
||||
if not tester.check_server():
|
||||
print("\n💡 ComfyUI'yi başlatmak için:")
|
||||
print(" python main.py --listen 0.0.0.0 --port 8188")
|
||||
return
|
||||
|
||||
# Model kontrolü
|
||||
models = tester.get_models()
|
||||
if not models:
|
||||
print("\n💡 Model yüklemek için:")
|
||||
print(" 1. models/checkpoints/ klasörüne .safetensors dosyası ekleyin")
|
||||
print(" 2. ComfyUI'yi yeniden başlatın")
|
||||
return
|
||||
|
||||
# Test prompt'ları (pars klasöründeki screenshot'lara benzer)
|
||||
test_prompts = [
|
||||
"a modern user interface design, clean layout, professional software interface",
|
||||
"screenshot of a web application, dashboard design, modern UI elements",
|
||||
"software interface mockup, clean design, professional layout",
|
||||
"application screenshot, user interface design, modern web app",
|
||||
"dashboard interface, clean UI design, professional software layout"
|
||||
]
|
||||
|
||||
print(f"\n🎨 {len(test_prompts)} adet test resmi üretiliyor...")
|
||||
|
||||
# Her prompt için resim üret
|
||||
for i, prompt in enumerate(test_prompts, 1):
|
||||
print(f"\n--- Test {i}/{len(test_prompts)} ---")
|
||||
result = tester.generate_image(prompt, models[0])
|
||||
|
||||
if result:
|
||||
print(f"✅ Test {i} başarılı: {len(result)} resim üretildi")
|
||||
else:
|
||||
print(f"❌ Test {i} başarısız")
|
||||
|
||||
# Kısa bekleme
|
||||
time.sleep(2)
|
||||
|
||||
print("\n🎉 Test tamamlandı!")
|
||||
print("📁 Üretilen resimler: test_output/ klasöründe")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
257
test_runpod_api.py
Normal file
257
test_runpod_api.py
Normal file
@ -0,0 +1,257 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
RunPod Serverless API Test - pars klasöründeki resimlere benzer resim üretimi
|
||||
"""
|
||||
|
||||
import os
|
||||
import json
|
||||
import base64
|
||||
import requests
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
class RunPodTester:
|
||||
def __init__(self):
|
||||
# RunPod API bilgileri (.env.example'dan alın)
|
||||
self.api_key = os.getenv("RUNPOD_API_KEY", "YOUR_RUNPOD_API_KEY") # .env dosyasından alın
|
||||
self.endpoint_id = "sfkzjudvrj50yq" # Dashboard'dan aldığınız ID
|
||||
self.base_url = "https://api.runpod.ai/v2"
|
||||
|
||||
def create_test_workflow(self, prompt):
|
||||
"""Test workflow'u oluştur"""
|
||||
return {
|
||||
"input": {
|
||||
"workflow": {
|
||||
"3": {
|
||||
"inputs": {
|
||||
"seed": 42,
|
||||
"steps": 25,
|
||||
"cfg": 8.0,
|
||||
"sampler_name": "euler",
|
||||
"scheduler": "normal",
|
||||
"denoise": 1.0,
|
||||
"model": ["4", 0],
|
||||
"positive": ["6", 0],
|
||||
"negative": ["7", 0],
|
||||
"latent_image": ["5", 0]
|
||||
},
|
||||
"class_type": "KSampler"
|
||||
},
|
||||
"4": {
|
||||
"inputs": {
|
||||
"ckpt_name": "sd_xl_base_1.0.safetensors"
|
||||
},
|
||||
"class_type": "CheckpointLoaderSimple"
|
||||
},
|
||||
"5": {
|
||||
"inputs": {
|
||||
"width": 1024,
|
||||
"height": 1024,
|
||||
"batch_size": 1
|
||||
},
|
||||
"class_type": "EmptyLatentImage"
|
||||
},
|
||||
"6": {
|
||||
"inputs": {
|
||||
"text": prompt,
|
||||
"clip": ["4", 1]
|
||||
},
|
||||
"class_type": "CLIPTextEncode"
|
||||
},
|
||||
"7": {
|
||||
"inputs": {
|
||||
"text": "blurry, low quality, distorted, ugly, bad anatomy, worst quality",
|
||||
"clip": ["4", 1]
|
||||
},
|
||||
"class_type": "CLIPTextEncode"
|
||||
},
|
||||
"8": {
|
||||
"inputs": {
|
||||
"samples": ["3", 0],
|
||||
"vae": ["4", 2]
|
||||
},
|
||||
"class_type": "VAEDecode"
|
||||
},
|
||||
"9": {
|
||||
"inputs": {
|
||||
"filename_prefix": "runpod_test",
|
||||
"images": ["8", 0]
|
||||
},
|
||||
"class_type": "SaveImage"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def submit_job(self, prompt):
|
||||
"""RunPod'a job gönder"""
|
||||
try:
|
||||
workflow_data = self.create_test_workflow(prompt)
|
||||
|
||||
headers = {
|
||||
"Authorization": f"Bearer {self.api_key}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
url = f"{self.base_url}/{self.endpoint_id}/run"
|
||||
|
||||
print(f"🚀 Job gönderiliyor...")
|
||||
print(f" Endpoint: {self.endpoint_id}")
|
||||
print(f" Prompt: {prompt[:50]}...")
|
||||
|
||||
response = requests.post(url, json=workflow_data, headers=headers, timeout=30)
|
||||
response.raise_for_status()
|
||||
|
||||
job_data = response.json()
|
||||
job_id = job_data.get("id")
|
||||
|
||||
print(f"✅ Job gönderildi: {job_id}")
|
||||
return job_id
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Job gönderme hatası: {e}")
|
||||
return None
|
||||
|
||||
def check_job_status(self, job_id):
|
||||
"""Job durumunu kontrol et"""
|
||||
try:
|
||||
headers = {
|
||||
"Authorization": f"Bearer {self.api_key}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
url = f"{self.base_url}/{self.endpoint_id}/status/{job_id}"
|
||||
response = requests.get(url, headers=headers, timeout=10)
|
||||
response.raise_for_status()
|
||||
|
||||
return response.json()
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Durum kontrolü hatası: {e}")
|
||||
return None
|
||||
|
||||
def wait_for_completion(self, job_id, timeout=300):
|
||||
"""Job'ın tamamlanmasını bekle"""
|
||||
start_time = time.time()
|
||||
|
||||
while time.time() - start_time < timeout:
|
||||
status_data = self.check_job_status(job_id)
|
||||
|
||||
if not status_data:
|
||||
time.sleep(5)
|
||||
continue
|
||||
|
||||
status = status_data.get("status")
|
||||
|
||||
if status == "COMPLETED":
|
||||
print("✅ Job tamamlandı!")
|
||||
return status_data.get("output")
|
||||
elif status == "FAILED":
|
||||
print("❌ Job başarısız!")
|
||||
print(f" Hata: {status_data.get('error', 'Bilinmeyen hata')}")
|
||||
return None
|
||||
elif status in ["IN_QUEUE", "IN_PROGRESS"]:
|
||||
elapsed = int(time.time() - start_time)
|
||||
print(f"⏳ Job çalışıyor... ({status}) - {elapsed}s")
|
||||
|
||||
time.sleep(5)
|
||||
|
||||
print(f"⏰ Timeout: {timeout} saniye")
|
||||
return None
|
||||
|
||||
def save_results(self, output_data, test_name):
|
||||
"""Sonuçları kaydet"""
|
||||
if not output_data:
|
||||
return []
|
||||
|
||||
os.makedirs("test_output", exist_ok=True)
|
||||
saved_files = []
|
||||
|
||||
outputs = output_data.get("outputs", [])
|
||||
for i, output in enumerate(outputs):
|
||||
if "data" in output:
|
||||
try:
|
||||
# Base64 decode
|
||||
image_data = base64.b64decode(output["data"])
|
||||
|
||||
# Dosya adı
|
||||
filename = f"{test_name}_{i+1:02d}.png"
|
||||
filepath = f"test_output/{filename}"
|
||||
|
||||
# Kaydet
|
||||
with open(filepath, "wb") as f:
|
||||
f.write(image_data)
|
||||
|
||||
saved_files.append(filepath)
|
||||
print(f"💾 Resim kaydedildi: {filepath}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Resim kaydetme hatası: {e}")
|
||||
|
||||
return saved_files
|
||||
|
||||
def main():
|
||||
"""Ana test fonksiyonu"""
|
||||
print("🚀 RunPod Serverless Test Başlatılıyor...")
|
||||
|
||||
tester = RunPodTester()
|
||||
|
||||
# API key kontrolü
|
||||
if tester.api_key == "YOUR_RUNPOD_API_KEY":
|
||||
print("❌ API key ayarlanmamış!")
|
||||
print("💡 test_runpod_api.py dosyasında API key'inizi güncelleyin")
|
||||
print(" API key'i RunPod dashboard → Settings → API Keys'den alabilirsiniz")
|
||||
return
|
||||
|
||||
# pars klasöründeki screenshot'lara benzer prompt'lar
|
||||
test_prompts = [
|
||||
"modern software interface, clean dashboard design, professional UI layout, high quality, detailed",
|
||||
"web application screenshot, user interface mockup, modern design system, clean layout",
|
||||
"software dashboard, data visualization interface, professional web app design, modern UI",
|
||||
"application interface design, clean user experience, professional software layout, modern style",
|
||||
"digital interface mockup, clean web design, professional dashboard layout, modern UI elements"
|
||||
]
|
||||
|
||||
print(f"\n🎨 {len(test_prompts)} adet test resmi üretiliyor...")
|
||||
print(f"📍 Endpoint: {tester.endpoint_id}")
|
||||
|
||||
all_results = []
|
||||
|
||||
# Her prompt için test
|
||||
for i, prompt in enumerate(test_prompts, 1):
|
||||
print(f"\n--- Test {i}/{len(test_prompts)} ---")
|
||||
|
||||
# Job gönder
|
||||
job_id = tester.submit_job(prompt)
|
||||
if not job_id:
|
||||
continue
|
||||
|
||||
# Tamamlanmasını bekle
|
||||
output = tester.wait_for_completion(job_id)
|
||||
|
||||
# Sonuçları kaydet
|
||||
if output:
|
||||
saved_files = tester.save_results(output, f"ui_design_test_{i}")
|
||||
all_results.extend(saved_files)
|
||||
print(f"✅ Test {i} başarılı: {len(saved_files)} resim")
|
||||
else:
|
||||
print(f"❌ Test {i} başarısız")
|
||||
|
||||
# Rate limiting için bekleme
|
||||
if i < len(test_prompts):
|
||||
print("⏸️ Rate limiting için 10 saniye bekleniyor...")
|
||||
time.sleep(10)
|
||||
|
||||
# Özet
|
||||
print(f"\n🎉 Test tamamlandı!")
|
||||
print(f"📊 Toplam üretilen resim: {len(all_results)}")
|
||||
print(f"📁 Kaydedilen dosyalar:")
|
||||
for file in all_results:
|
||||
print(f" - {file}")
|
||||
|
||||
if all_results:
|
||||
print(f"\n💡 Resimleri görüntülemek için:")
|
||||
print(f" open test_output/")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
59
test_simple_workflow.json
Normal file
59
test_simple_workflow.json
Normal file
@ -0,0 +1,59 @@
|
||||
{
|
||||
"3": {
|
||||
"inputs": {
|
||||
"seed": 42,
|
||||
"steps": 20,
|
||||
"cfg": 8.0,
|
||||
"sampler_name": "euler",
|
||||
"scheduler": "normal",
|
||||
"denoise": 1.0,
|
||||
"model": ["4", 0],
|
||||
"positive": ["6", 0],
|
||||
"negative": ["7", 0],
|
||||
"latent_image": ["5", 0]
|
||||
},
|
||||
"class_type": "KSampler"
|
||||
},
|
||||
"4": {
|
||||
"inputs": {
|
||||
"ckpt_name": "sd_xl_base_1.0.safetensors"
|
||||
},
|
||||
"class_type": "CheckpointLoaderSimple"
|
||||
},
|
||||
"5": {
|
||||
"inputs": {
|
||||
"width": 1024,
|
||||
"height": 1024,
|
||||
"batch_size": 1
|
||||
},
|
||||
"class_type": "EmptyLatentImage"
|
||||
},
|
||||
"6": {
|
||||
"inputs": {
|
||||
"text": "a modern user interface design, clean layout, professional software interface, high quality, detailed",
|
||||
"clip": ["4", 1]
|
||||
},
|
||||
"class_type": "CLIPTextEncode"
|
||||
},
|
||||
"7": {
|
||||
"inputs": {
|
||||
"text": "blurry, low quality, distorted, ugly, bad anatomy",
|
||||
"clip": ["4", 1]
|
||||
},
|
||||
"class_type": "CLIPTextEncode"
|
||||
},
|
||||
"8": {
|
||||
"inputs": {
|
||||
"samples": ["3", 0],
|
||||
"vae": ["4", 2]
|
||||
},
|
||||
"class_type": "VAEDecode"
|
||||
},
|
||||
"9": {
|
||||
"inputs": {
|
||||
"filename_prefix": "test_ui_design",
|
||||
"images": ["8", 0]
|
||||
},
|
||||
"class_type": "SaveImage"
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user