feat(enhance): LoRA strength scale alongside the on/off switch (#218)
So the app builds against the final shape: each [[template.lora]] gains `strength` (the scale when on, default 1.0) and `min` / `max` (the slider's range, default 0.0-1.5). - POST /enhance `loras` takes true / false or a scale: true = strength, false or <= 0 = off, a scale is clamped to min..max. - The scale multiplies each node's exported strength_model / strength_clip, so 1.0 = as exported and a high/low pair keeps its ratio. - Jobs and the job view store the resolved scale per id (0 = off); GET /enhance/templates lists strength, min and max. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
31da21e061
commit
cc96873f86
7 files changed
+298
-110
No files matched your search
@@ -183,6 +183,9 @@ fn animate_with_style() -> Template {
|
||||
id: "style".into(),
|
||||
label: "Style".into(),
|
||||
default: false,
|
||||
strength: 0.8,
|
||||
min: 0.0,
|
||||
max: 1.5,
|
||||
}];
|
||||
Template::from_value(cfg, serde_json::from_str(ANIMATE_LORAS).unwrap()).unwrap()
|
||||
}
|
||||
@@ -1127,12 +1130,12 @@ async fn lora_switches_are_listed_sent_and_stored_on_the_job() {
|
||||
let animate = templates.iter().find(|t| t["name"] == "animate").unwrap();
|
||||
assert_eq!(
|
||||
animate["loras"],
|
||||
json!([{"id": "style", "label": "Style", "default": false}])
|
||||
json!([{"id": "style", "label": "Style", "default": false, "strength": 0.8, "min": 0.0, "max": 1.5}])
|
||||
);
|
||||
let restore = templates.iter().find(|t| t["name"] == "restore").unwrap();
|
||||
assert_eq!(restore["loras"], json!([]));
|
||||
|
||||
// On: the pair keeps its strength, and the job remembers the choice.
|
||||
// On: the configured strength, and the job remembers it.
|
||||
let (st, job, _) = call(
|
||||
&fx,
|
||||
"POST",
|
||||
@@ -1141,7 +1144,7 @@ async fn lora_switches_are_listed_sent_and_stored_on_the_job() {
|
||||
)
|
||||
.await;
|
||||
assert_eq!(st, 200, "{job}");
|
||||
assert_eq!(job["loras"], json!({"style": true}));
|
||||
assert_eq!(job["loras"], json!({"style": 0.8}));
|
||||
let (_, again, _) = call(
|
||||
&fx,
|
||||
"GET",
|
||||
@@ -1149,7 +1152,7 @@ async fn lora_switches_are_listed_sent_and_stored_on_the_job() {
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
assert_eq!(again["loras"], json!({"style": true}));
|
||||
assert_eq!(again["loras"], json!({"style": 0.8}));
|
||||
|
||||
// Omitted: the default (off) zeroes both nodes.
|
||||
let (st, off, _) = call(
|
||||
@@ -1160,12 +1163,27 @@ async fn lora_switches_are_listed_sent_and_stored_on_the_job() {
|
||||
)
|
||||
.await;
|
||||
assert_eq!(st, 200, "{off}");
|
||||
assert_eq!(off["loras"], json!({"style": false}));
|
||||
assert_eq!(off["loras"], json!({"style": 0.0}));
|
||||
|
||||
// A slider value scales the exported strength.
|
||||
let (st, half, _) = call(
|
||||
&fx,
|
||||
"POST",
|
||||
"/enhance",
|
||||
Some(json!({"path": PHOTO, "template": "animate", "loras": {"style": 0.5}})),
|
||||
)
|
||||
.await;
|
||||
assert_eq!(st, 200, "{half}");
|
||||
assert_eq!(half["loras"], json!({"style": 0.5}));
|
||||
{
|
||||
let sent = fx.mock.submitted.lock().unwrap();
|
||||
assert_eq!(
|
||||
sent[0]["prompt"]["50"]["inputs"]["strength_model"],
|
||||
json!(1.0)
|
||||
json!(0.8)
|
||||
);
|
||||
assert_eq!(
|
||||
sent[2]["prompt"]["51"]["inputs"]["strength_model"],
|
||||
json!(0.5)
|
||||
);
|
||||
assert_eq!(
|
||||
sent[1]["prompt"]["50"]["inputs"]["strength_model"],
|
||||
|
||||
Reference in new issue
Block a user