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
@@ -460,7 +460,8 @@ auth and stays LAN-only, so ImageApi relays previews too.
|
||||
`unreachable_grace_secs`, `default_template`, `warn_above_megapixels`,
|
||||
`[[path_map]]` (`from`, `to`), `[[template]]` (`name`, `label`, `description`,
|
||||
`file`, `prompt_mode`, `prompt_join`, `output_megapixels`, `[[template.lora]]`
|
||||
(`id`, `label`, `default`, `strength`, `min`, `max`)).
|
||||
(`id`, `label`, `default`, `strength`, `min`, `max`), `[template.catalog]` (`strength`,
|
||||
`min`, `max`, `exclude`)).
|
||||
- **Templates** are API-format workflow exports, read-only (never edit them from
|
||||
here). Nodes are found by `_meta.title`: `imageapi:source` (required, gets the
|
||||
photo path), `imageapi:save` (required, forced to `require_approval = true`; a
|
||||
@@ -472,7 +473,12 @@ auth and stays LAN-only, so ImageApi relays previews too.
|
||||
low pair; the resolved scale multiplies each node's exported `strength_model` /
|
||||
`strength_clip` (1.0 = as exported, 0 = off, a pair keeps its ratio), never rewired; a
|
||||
node with no declaration keeps its strength, a declaration with no node isn't offered;
|
||||
both log a startup warning). `prompt_mode = "append"`: the user's text is joined
|
||||
both log a startup warning), `imageapi:lora-slot:<n>:high|low` (pickable LoRAs, #220:
|
||||
each slot needs a high and a low node, numbered 1.. without gaps; picks fill them in order,
|
||||
setting `lora_name` and scaling the exported strength, unused slots run at 0; the catalog is
|
||||
ComfyUI's `/object_info/LoraLoaderModelOnly` list (cached 60 s, re-read when a submit names
|
||||
an unknown id) paired by High/Low name tokens (`src/enhance/lora_catalog.rs`), minus every
|
||||
`lora_name` the workflow loads outside the slots and `catalog.exclude` substrings). `prompt_mode = "append"`: the user's text is joined
|
||||
after the template's own prompt with `prompt_join` (default one space); empty text
|
||||
leaves the prompt as is. `"replace"`: the text *is* the prompt and is required (empty
|
||||
= 400); it needs a prompt node. With no `reference_path` the reference node **and
|
||||
@@ -519,8 +525,12 @@ GET /enhance/templates
|
||||
"prompt_mode": "append"|"replace", "prompt_required",
|
||||
"accepts_reference","default","output_megapixels",
|
||||
"warn_above_megapixels", "output": "image"|"video",
|
||||
"loras": [{"id","label","default","strength","min","max"}]}]}
|
||||
POST /enhance {"path","template","prompt"?,"reference_path"?,"loras"?: {id: bool|scale},"library"?} -> job
|
||||
"loras": [{"id","label","default","strength","min","max"}],
|
||||
"slots": n, "catalog"?: {"loras": [{"id","label"}],"strength","min","max"}}]}
|
||||
POST /enhance {"path","template","prompt"?,"reference_path"?,"loras"?: {id: bool|scale},
|
||||
"slots"?: [{"lora": catalog id, "scale"?}],"library"?} -> job
|
||||
(slots: at most the template's slot count, no duplicates, unknown id = 400; no scale =
|
||||
catalog.strength, <= 0 = slot unused)
|
||||
(true = the switch's strength, false or scale <= 0 = off, a scale is clamped to min..max;
|
||||
a missing switch uses its default; an id the template doesn't offer = 400)
|
||||
GET /enhance/jobs/{id} -> job
|
||||
@@ -540,6 +550,7 @@ POST /enhance/jobs/{id}/discard -> job (hidden from the list; ComfyUI untou
|
||||
|
||||
job = {"id","status","queue_position"?,"error"?,"path","library_id","template",
|
||||
"prompt"?,"reference_path"?,"loras"?: {id: scale} (resolved, 0 = off; absent without switches),
|
||||
"slots"?: [{"lora","label","scale"}] (picked LoRAs; absent when none),
|
||||
"created_at","updated_at",
|
||||
"run_ms": <ms ComfyUI ran it, or null until finished / when ComfyUI gave no timings>,
|
||||
"pending": [{"n","preview": "/enhance/jobs/{id}/preview/{n}","approved"}],
|
||||
|
||||
Reference in new issue
Block a user