soyailabs / app /services /workflow_manager.py
SOY NV AI
Initial commit after feature updates
16db560
import json
import os
import logging
import random
logger = logging.getLogger(__name__)
class WorkflowManager:
def __init__(self, workflows_dir="templates/workflows"):
self.workflows_dir = workflows_dir
def load_workflow(self, workflow_filename):
"""
templates/workflows/ 폴더 λ‚΄μ˜ JSON νŒŒμΌμ„ λ‘œλ“œν•˜λŠ” ν•¨μˆ˜.
"""
file_path = os.path.join(self.workflows_dir, workflow_filename)
if not file_path.endswith('.json'):
file_path += '.json'
try:
with open(file_path, 'r', encoding='utf-8') as f:
return json.load(f)
except Exception as e:
logger.error(f"Error loading workflow {workflow_filename}: {e}")
return None
def build_workflow(self, workflow_json, prompt_text=None, negative_prompt=None, seed=None,
image_path=None, checkpoint_name=None, width=None, height=None):
"""
μ›Œν¬ν”Œλ‘œμš° λ‚΄μ˜ νŠΉμ • λ…Έλ“œλ“€μ„ μ°Ύμ•„ 값을 μΉ˜ν™˜ν•˜λŠ” ν•¨μˆ˜.
1. CLIP Text Encode (Positive/Negative)
2. KSampler (Seed)
3. Load Image (Image path)
4. Checkpoint Loader (Model name)
5. Empty Latent Image (Width/Height)
"""
# μ›Œν¬ν”Œλ‘œμš° 볡사본 생성 (원본 μœ μ§€)
wf = json.loads(json.dumps(workflow_json))
for node_id, node in wf.items():
class_type = node.get("class_type")
inputs = node.get("inputs", {})
# 1. CLIP Text Encode (ν”„λ‘¬ν”„νŠΈ μΉ˜ν™˜)
if class_type == "CLIPTextEncode":
if prompt_text and "text" in inputs and "positive" in str(node.get("_meta", {}).get("title", "")).lower():
inputs["text"] = prompt_text
elif negative_prompt and "text" in inputs and "negative" in str(node.get("_meta", {}).get("title", "")).lower():
inputs["text"] = negative_prompt
# 타이틀이 μ—†λŠ” 경우 일반적인 ν…μŠ€νŠΈ λ…Έλ“œ 처리
elif prompt_text and "text" in inputs:
inputs["text"] = prompt_text
# 2. KSampler (μ‹œλ“œ μΉ˜ν™˜)
elif class_type == "KSampler":
if seed is not None:
inputs["seed"] = seed
else:
# μ‹œλ“œκ°€ μ§€μ •λ˜μ§€ μ•Šμ€ 경우 랜덀 생성
inputs["seed"] = random.randint(0, 0xffffffffffffffff)
# 3. Load Image (μ°Έμ‘° 이미지 경둜 μΉ˜ν™˜)
elif class_type == "LoadImage":
if image_path:
inputs["image"] = image_path
# 4. Checkpoint Loader (λͺ¨λΈ 경둜 μΉ˜ν™˜ - λ‚˜λ…Έλ°”λ‚˜λ‚˜, Z-image λ“±)
elif class_type in ["CheckpointLoaderSimple", "CheckpointLoader"]:
if checkpoint_name:
inputs["ckpt_name"] = checkpoint_name
# 5. Empty Latent Image (크기 μΉ˜ν™˜)
elif class_type == "EmptyLatentImage":
if width:
inputs["width"] = width
if height:
inputs["height"] = height
return wf
def get_available_workflows(self):
"""
μ‚¬μš© κ°€λŠ₯ν•œ μ›Œν¬ν”Œλ‘œμš° λͺ©λ‘μ„ λ°˜ν™˜ν•©λ‹ˆλ‹€.
"""
try:
return [f for f in os.listdir(self.workflows_dir) if f.endswith('.json')]
except Exception as e:
logger.error(f"Error listing workflows: {e}")
return []