feat(enhance): pick LoRAs from ComfyUI per job (#220)
Templates with `imageapi:lora-slot:<n>:high|low` nodes take LoRAs picked
per job from a catalog built live from ComfyUI.
- Catalog: ComfyUI's LoraLoaderModelOnly `lora_name` choices (cached
60 s, re-read when a submit names an unknown id), paired by High/Low
name tokens (StyleHigh/StyleLow, x-HIGH/x-LOW, x_high_noise/...). Files
the workflow already loads outside the slots (lightx2v, switches) and
`[template.catalog] exclude` substrings never show; ids derive from the
names so they stay stable.
- POST /enhance `slots: [{lora, scale?}]` fills the slots in order: each
pick sets the slot nodes' lora_name and scales their exported strength;
unused slots run at 0, so the graph is never rewired. More picks than
slots, duplicates or unknown ids are 400s.
- GET /enhance/templates gains `slots` and `catalog: {loras, strength,
min, max}`; jobs store and return the picks (new enhance_jobs.lora_slots
JSON column).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
6fffca9989
commit
e2cf18678f
15 files changed
+1454
-33
No files matched your search
+404
@@ -0,0 +1,404 @@
|
||||
{
|
||||
"1": {
|
||||
"class_type": "ImageApiLoadImageFromPath",
|
||||
"_meta": {
|
||||
"title": "imageapi:source"
|
||||
},
|
||||
"inputs": {
|
||||
"path": ""
|
||||
}
|
||||
},
|
||||
"2": {
|
||||
"class_type": "ImageApiTargetSize",
|
||||
"_meta": {
|
||||
"title": "Target Size (~0.92 MP, keeps aspect)"
|
||||
},
|
||||
"inputs": {
|
||||
"image": [
|
||||
"1",
|
||||
0
|
||||
],
|
||||
"max_megapixels": 0.92,
|
||||
"min_megapixels": 0.92,
|
||||
"multiple_of": 16
|
||||
}
|
||||
},
|
||||
"10": {
|
||||
"class_type": "UNETLoader",
|
||||
"_meta": {
|
||||
"title": "Wan 2.2 i2v high noise"
|
||||
},
|
||||
"inputs": {
|
||||
"unet_name": "wan2.2_i2v_high_noise_14B_fp8_scaled.safetensors",
|
||||
"weight_dtype": "default"
|
||||
}
|
||||
},
|
||||
"11": {
|
||||
"class_type": "UNETLoader",
|
||||
"_meta": {
|
||||
"title": "Wan 2.2 i2v low noise"
|
||||
},
|
||||
"inputs": {
|
||||
"unet_name": "wan2.2_i2v_low_noise_14B_fp8_scaled.safetensors",
|
||||
"weight_dtype": "default"
|
||||
}
|
||||
},
|
||||
"12": {
|
||||
"class_type": "LoraLoaderModelOnly",
|
||||
"_meta": {
|
||||
"title": "lightx2v 4-step (high)"
|
||||
},
|
||||
"inputs": {
|
||||
"model": [
|
||||
"10",
|
||||
0
|
||||
],
|
||||
"lora_name": "wan2.2_i2v_lightx2v_4steps_lora_v1_high_noise.safetensors",
|
||||
"strength_model": 1.0
|
||||
}
|
||||
},
|
||||
"13": {
|
||||
"class_type": "LoraLoaderModelOnly",
|
||||
"_meta": {
|
||||
"title": "lightx2v 4-step (low)"
|
||||
},
|
||||
"inputs": {
|
||||
"model": [
|
||||
"11",
|
||||
0
|
||||
],
|
||||
"lora_name": "wan2.2_i2v_lightx2v_4steps_lora_v1_low_noise.safetensors",
|
||||
"strength_model": 1.0
|
||||
}
|
||||
},
|
||||
"14": {
|
||||
"class_type": "ModelSamplingSD3",
|
||||
"_meta": {
|
||||
"title": "Shift (high)"
|
||||
},
|
||||
"inputs": {
|
||||
"model": [
|
||||
"62",
|
||||
0
|
||||
],
|
||||
"shift": 5.0
|
||||
}
|
||||
},
|
||||
"15": {
|
||||
"class_type": "ModelSamplingSD3",
|
||||
"_meta": {
|
||||
"title": "Shift (low)"
|
||||
},
|
||||
"inputs": {
|
||||
"model": [
|
||||
"63",
|
||||
0
|
||||
],
|
||||
"shift": 5.0
|
||||
}
|
||||
},
|
||||
"40": {
|
||||
"class_type": "PathchSageAttentionKJ",
|
||||
"_meta": {
|
||||
"title": "Sage attention (high)"
|
||||
},
|
||||
"inputs": {
|
||||
"model": [
|
||||
"14",
|
||||
0
|
||||
],
|
||||
"sage_attention": "auto"
|
||||
}
|
||||
},
|
||||
"41": {
|
||||
"class_type": "PathchSageAttentionKJ",
|
||||
"_meta": {
|
||||
"title": "Sage attention (low)"
|
||||
},
|
||||
"inputs": {
|
||||
"model": [
|
||||
"15",
|
||||
0
|
||||
],
|
||||
"sage_attention": "auto"
|
||||
}
|
||||
},
|
||||
"16": {
|
||||
"class_type": "CLIPLoader",
|
||||
"_meta": {
|
||||
"title": "Load CLIP"
|
||||
},
|
||||
"inputs": {
|
||||
"clip_name": "umt5_xxl_fp8_e4m3fn_scaled.safetensors",
|
||||
"type": "wan",
|
||||
"device": "default"
|
||||
}
|
||||
},
|
||||
"17": {
|
||||
"class_type": "CLIPTextEncode",
|
||||
"_meta": {
|
||||
"title": "imageapi:prompt"
|
||||
},
|
||||
"inputs": {
|
||||
"clip": [
|
||||
"16",
|
||||
0
|
||||
],
|
||||
"text": "natural, lifelike motion with a slow, gentle camera movement, realistic, cinematic"
|
||||
}
|
||||
},
|
||||
"18": {
|
||||
"class_type": "CLIPTextEncode",
|
||||
"_meta": {
|
||||
"title": "Negative"
|
||||
},
|
||||
"inputs": {
|
||||
"clip": [
|
||||
"16",
|
||||
0
|
||||
],
|
||||
"text": "static, frozen, blurry, low quality, distorted, warped faces, morphing, flicker, watermark, text"
|
||||
}
|
||||
},
|
||||
"19": {
|
||||
"class_type": "VAELoader",
|
||||
"_meta": {
|
||||
"title": "Load VAE"
|
||||
},
|
||||
"inputs": {
|
||||
"vae_name": "wan_2.1_vae.safetensors"
|
||||
}
|
||||
},
|
||||
"21": {
|
||||
"class_type": "WanImageToVideo",
|
||||
"_meta": {
|
||||
"title": "Wan Image To Video (81 frames)"
|
||||
},
|
||||
"inputs": {
|
||||
"positive": [
|
||||
"17",
|
||||
0
|
||||
],
|
||||
"negative": [
|
||||
"18",
|
||||
0
|
||||
],
|
||||
"vae": [
|
||||
"19",
|
||||
0
|
||||
],
|
||||
"start_image": [
|
||||
"1",
|
||||
0
|
||||
],
|
||||
"width": [
|
||||
"2",
|
||||
0
|
||||
],
|
||||
"height": [
|
||||
"2",
|
||||
1
|
||||
],
|
||||
"length": 81,
|
||||
"batch_size": 1
|
||||
}
|
||||
},
|
||||
"22": {
|
||||
"class_type": "KSamplerAdvanced",
|
||||
"_meta": {
|
||||
"title": "Sampler (high, steps 0-2)"
|
||||
},
|
||||
"inputs": {
|
||||
"model": [
|
||||
"40",
|
||||
0
|
||||
],
|
||||
"positive": [
|
||||
"21",
|
||||
0
|
||||
],
|
||||
"negative": [
|
||||
"21",
|
||||
1
|
||||
],
|
||||
"latent_image": [
|
||||
"21",
|
||||
2
|
||||
],
|
||||
"add_noise": "enable",
|
||||
"noise_seed": 1,
|
||||
"steps": 4,
|
||||
"cfg": 1.0,
|
||||
"sampler_name": "euler",
|
||||
"scheduler": "simple",
|
||||
"start_at_step": 0,
|
||||
"end_at_step": 2,
|
||||
"return_with_leftover_noise": "enable"
|
||||
}
|
||||
},
|
||||
"23": {
|
||||
"class_type": "KSamplerAdvanced",
|
||||
"_meta": {
|
||||
"title": "Sampler (low, steps 2-4)"
|
||||
},
|
||||
"inputs": {
|
||||
"model": [
|
||||
"41",
|
||||
0
|
||||
],
|
||||
"positive": [
|
||||
"21",
|
||||
0
|
||||
],
|
||||
"negative": [
|
||||
"21",
|
||||
1
|
||||
],
|
||||
"latent_image": [
|
||||
"22",
|
||||
0
|
||||
],
|
||||
"add_noise": "disable",
|
||||
"noise_seed": 0,
|
||||
"steps": 4,
|
||||
"cfg": 1.0,
|
||||
"sampler_name": "euler",
|
||||
"scheduler": "simple",
|
||||
"start_at_step": 2,
|
||||
"end_at_step": 10000,
|
||||
"return_with_leftover_noise": "disable"
|
||||
}
|
||||
},
|
||||
"24": {
|
||||
"class_type": "VAEDecode",
|
||||
"_meta": {
|
||||
"title": "VAE Decode"
|
||||
},
|
||||
"inputs": {
|
||||
"samples": [
|
||||
"23",
|
||||
0
|
||||
],
|
||||
"vae": [
|
||||
"19",
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
"25": {
|
||||
"class_type": "CreateVideo",
|
||||
"_meta": {
|
||||
"title": "Create Video (16 fps)"
|
||||
},
|
||||
"inputs": {
|
||||
"images": [
|
||||
"24",
|
||||
0
|
||||
],
|
||||
"fps": 16.0
|
||||
}
|
||||
},
|
||||
"36": {
|
||||
"class_type": "ImageApiSaveVideoVersion",
|
||||
"_meta": {
|
||||
"title": "imageapi:save"
|
||||
},
|
||||
"inputs": {
|
||||
"video": [
|
||||
"25",
|
||||
0
|
||||
],
|
||||
"source": [
|
||||
"1",
|
||||
1
|
||||
],
|
||||
"kind": "animated",
|
||||
"subfolder": "aiedits",
|
||||
"require_approval": true
|
||||
}
|
||||
},
|
||||
"50": {
|
||||
"inputs": {
|
||||
"lora_name": "example_style_high.safetensors",
|
||||
"strength_model": 1.0,
|
||||
"model": [
|
||||
"12",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "LoraLoaderModelOnly",
|
||||
"_meta": {
|
||||
"title": "imageapi:lora:style"
|
||||
}
|
||||
},
|
||||
"51": {
|
||||
"inputs": {
|
||||
"lora_name": "example_style_low.safetensors",
|
||||
"strength_model": 1.0,
|
||||
"model": [
|
||||
"13",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "LoraLoaderModelOnly",
|
||||
"_meta": {
|
||||
"title": "imageapi:lora:style"
|
||||
}
|
||||
},
|
||||
"60": {
|
||||
"inputs": {
|
||||
"lora_name": "example_slot_high.safetensors",
|
||||
"strength_model": 1.0,
|
||||
"model": [
|
||||
"50",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "LoraLoaderModelOnly",
|
||||
"_meta": {
|
||||
"title": "imageapi:lora-slot:1:high"
|
||||
}
|
||||
},
|
||||
"61": {
|
||||
"inputs": {
|
||||
"lora_name": "example_slot_low.safetensors",
|
||||
"strength_model": 1.0,
|
||||
"model": [
|
||||
"51",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "LoraLoaderModelOnly",
|
||||
"_meta": {
|
||||
"title": "imageapi:lora-slot:1:low"
|
||||
}
|
||||
},
|
||||
"62": {
|
||||
"inputs": {
|
||||
"lora_name": "example_slot_high.safetensors",
|
||||
"strength_model": 1.0,
|
||||
"model": [
|
||||
"60",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "LoraLoaderModelOnly",
|
||||
"_meta": {
|
||||
"title": "imageapi:lora-slot:2:high"
|
||||
}
|
||||
},
|
||||
"63": {
|
||||
"inputs": {
|
||||
"lora_name": "example_slot_low.safetensors",
|
||||
"strength_model": 1.0,
|
||||
"model": [
|
||||
"61",
|
||||
0
|
||||
]
|
||||
},
|
||||
"class_type": "LoraLoaderModelOnly",
|
||||
"_meta": {
|
||||
"title": "imageapi:lora-slot:2:low"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user