sd: support changing preloaded LoRA multipliers (#2041)

* sd: remove C++ support for enforcing fixed LoRA multipliers

The logic at the Python level is enough.

* sd: support changing preloaded LoRA multipliers

We keep the same rules as before:
- Any LoRA with multiplier 0 can be changed
- If all LoRAs have multiplier != 0, they are fixed and optimized

but tweak the corner case of LoRAs specified more than once to
allow adjusting the multiplier if the same LoRA is also specified
with a zero multiplier, as if they were two different LoRAs.

So the following keeps working as before:
- --sdlora /loras/lcm.gguf --sdloramult 1 : fixed as 1
- --sdlora /loras/lcm.gguf --sdloramult 0 : dynamic, default 0
- --sdlora /loras/ : dynamic, default 0
- --sdlora /loras/lcm.gguf /loras/lcm.gguf --sdloramult 1 1 : fixed as 2

But now we have:
- --sdlora /loras/lcm.gguf /loras/lcm.gguf --sdloramult 1 0 : dynamic, default 1
- --sdlora /loras/lcm.gguf /loras/ --sdloramult 1 : dynamic, default 1
This commit is contained in:
Wagner Bruna
2026-03-16 23:09:55 -03:00
committed by GitHub
parent 0c66ed863d
commit 51187d5362
3 changed files with 35 additions and 41 deletions
+13 -15
View File
@@ -59,7 +59,7 @@ def mk_lora_info(imgloras, multipliers):
fake filesystem access
fake filesystem access
>>> pre
[{'fullpath': '/x/lora1.safetensors', 'name': 'lora1', 'path': 'lora1.safetensors', 'multiplier': 1.0, 'preloaded': True}, {'fullpath': '/y/lora2.gguf', 'name': 'lora2', 'path': 'lora2.gguf', 'multiplier': 1.0, 'preloaded': True}]
[{'fullpath': '/x/lora1.safetensors', 'name': 'lora1', 'path': 'lora1.safetensors', 'multiplier': 1.0, 'preloaded': True, 'fixed': True}, {'fullpath': '/y/lora2.gguf', 'name': 'lora2', 'path': 'lora2.gguf', 'multiplier': 1.0, 'preloaded': True, 'fixed': True}]
>>> path
{}
>>> name
@@ -79,7 +79,7 @@ def mk_lora_info(imgloras, multipliers):
fake filesystem access
fake filesystem access
>>> pre
[{'fullpath': '/x/lora1.safetensors', 'name': 'lora1', 'path': 'lora1.safetensors', 'multiplier': 0.3, 'preloaded': True}, {'fullpath': '/y/lora1.safetensors', 'name': 'lora1_2', 'path': 'lora1_2.safetensors', 'multiplier': 0.3, 'preloaded': True}]
[{'fullpath': '/x/lora1.safetensors', 'name': 'lora1', 'path': 'lora1.safetensors', 'multiplier': 0.3, 'preloaded': True, 'fixed': True}, {'fullpath': '/y/lora1.safetensors', 'name': 'lora1_2', 'path': 'lora1_2.safetensors', 'multiplier': 0.3, 'preloaded': True, 'fixed': True}]
>>> path
{}
@@ -95,14 +95,12 @@ def mk_lora_info(imgloras, multipliers):
... 'fullpath': '/lora/dir/lora1_makebelieve.gguf',
... 'name': 'lora1_makebelieve',
... 'path': 'lora1_makebelieve.gguf',
... 'multiplier': 0.0,
... 'preloaded': False},
... 'multiplier': 0.0},
... 'lora2/makebelieve.gguf': {
... 'fullpath': '/lora/dir/lora2/makebelieve.gguf',
... 'name': 'lora2/makebelieve',
... 'path': 'lora2/makebelieve.gguf',
... 'multiplier': 0.0,
... 'preloaded': False}}
... 'multiplier': 0.0}}
>>> path == expected
True
>>> name
@@ -185,21 +183,21 @@ def mk_sdapi_lora_list(imglora_bypath):
... 'lora_a.safetensors': {'name': 'lora_a', 'path': 'lora_a.safetensors', 'multiplier': 0.0},
... 'lora_b.gguf' : {'name': 'lora_b', 'path': 'lora_b.gguf', 'multiplier': 0.0},
... 'lora_c.safetensors': {'name': 'lora_c', 'path': 'lora_c.safetensors', 'multiplier': 1.0},
... 'lora_d.safetensors': {'name': 'lora_d', 'path': 'lora_d.safetensors', 'multiplier': 1.0, 'fixed': True},
... 'chars/waifu.gguf' : {'name': 'chars/waifu', 'path': 'chars/waifu.gguf', 'multiplier': 0.0}
... }
>>> mk_sdapi_lora_list(imglora_bypath)
[{'name': 'lora_a', 'path': 'lora_a.safetensors'}, {'name': 'lora_b', 'path': 'lora_b.gguf'}, {'name': 'chars/waifu', 'path': 'chars/waifu.gguf'}]
>>> expected = [
... {'name': 'lora_a', 'path': 'lora_a.safetensors'},
... {'name': 'lora_b', 'path': 'lora_b.gguf'},
... {'name': 'lora_c', 'path': 'lora_c.safetensors'},
... {'name': 'chars/waifu', 'path': 'chars/waifu.gguf'}
... ]
>>> mk_sdapi_lora_list(imglora_bypath) == expected
True
>>> empty_data = {}
>>> mk_sdapi_lora_list(empty_data)
[]
>>> mixed_data = {
... 'k1': {'name': 'X', 'path': 'p1', 'multiplier': 0.5},
... 'k2': {'name': 'Y', 'path': 'p2', 'multiplier': 0.0}
... }
>>> mk_sdapi_lora_list(mixed_data)
[{'name': 'Y', 'path': 'p2'}]
'''
return koboldcpp.mk_sdapi_lora_list(imglora_bypath)