lycoris-lora 3.0.1.dev4__tar.gz → 3.0.1.dev6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. {lycoris_lora-3.0.1.dev4/lycoris_lora.egg-info → lycoris_lora-3.0.1.dev6}/PKG-INFO +1 -1
  2. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris/kohya.py +31 -5
  3. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris/modules/norms.py +2 -2
  4. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris/utils/bnb.py +3 -1
  5. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris/wrapper.py +121 -18
  6. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6/lycoris_lora.egg-info}/PKG-INFO +1 -1
  7. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/setup.py +1 -1
  8. lycoris_lora-3.0.1.dev6/test/wrapper.py +777 -0
  9. lycoris_lora-3.0.1.dev4/test/wrapper.py +0 -128
  10. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/LICENSE.md +0 -0
  11. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/README.md +0 -0
  12. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris/__init__.py +0 -0
  13. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris/config.py +0 -0
  14. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris/functional/__init__.py +0 -0
  15. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris/functional/boft.py +0 -0
  16. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris/functional/diag_oft.py +0 -0
  17. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris/functional/general.py +0 -0
  18. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris/functional/locon.py +0 -0
  19. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris/functional/loha.py +0 -0
  20. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris/functional/lokr.py +0 -0
  21. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris/logging.py +0 -0
  22. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris/modules/__init__.py +0 -0
  23. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris/modules/base.py +0 -0
  24. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris/modules/boft.py +0 -0
  25. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris/modules/diag_oft.py +0 -0
  26. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris/modules/dylora.py +0 -0
  27. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris/modules/full.py +0 -0
  28. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris/modules/glora.py +0 -0
  29. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris/modules/ia3.py +0 -0
  30. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris/modules/locon.py +0 -0
  31. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris/modules/loha.py +0 -0
  32. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris/modules/lokr.py +0 -0
  33. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris/utils/__init__.py +0 -0
  34. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris/utils/general.py +0 -0
  35. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris/utils/logger.py +0 -0
  36. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris/utils/preset.py +0 -0
  37. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris/utils/xformers_utils.py +0 -0
  38. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris_lora.egg-info/SOURCES.txt +0 -0
  39. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris_lora.egg-info/dependency_links.txt +0 -0
  40. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris_lora.egg-info/not-zip-safe +0 -0
  41. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris_lora.egg-info/requires.txt +0 -0
  42. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/lycoris_lora.egg-info/top_level.txt +0 -0
  43. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/setup.cfg +0 -0
  44. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/test/__init__.py +0 -0
  45. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/test/functional.py +0 -0
  46. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/test/kohya.py +0 -0
  47. {lycoris_lora-3.0.1.dev4 → lycoris_lora-3.0.1.dev6}/test/module.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lycoris_lora
3
- Version: 3.0.1.dev4
3
+ Version: 3.0.1.dev6
4
4
  Summary: Lora beYond Conventional methods, Other Rank adaptation Implementations for Stable diffusion
5
5
  Home-page: https://github.com/KohakuBlueleaf/LyCORIS
6
6
  Author: Shih-Ying Yeh(KohakuBlueLeaf), Yu-Guan Hsieh, Zhidong Gao
@@ -1,7 +1,9 @@
1
1
  import os
2
+ import fnmatch
2
3
  import re
3
4
  import logging
4
- from typing import List
5
+
6
+ from typing import Any, List
5
7
 
6
8
  import torch
7
9
 
@@ -234,6 +236,7 @@ class LycorisNetworkKohya(LycorisNetwork):
234
236
  LORA_PREFIX_TEXT_ENCODER = "lora_te"
235
237
  MODULE_ALGO_MAP = {}
236
238
  NAME_ALGO_MAP = {}
239
+ USE_FNMATCH = False
237
240
 
238
241
  @classmethod
239
242
  def apply_preset(cls, preset):
@@ -253,6 +256,8 @@ class LycorisNetworkKohya(LycorisNetwork):
253
256
  cls.MODULE_ALGO_MAP = preset["module_algo_map"]
254
257
  if "name_algo_map" in preset:
255
258
  cls.NAME_ALGO_MAP = preset["name_algo_map"]
259
+ if "use_fnmatch" in preset:
260
+ cls.USE_FNMATCH = preset["use_fnmatch"]
256
261
  return cls
257
262
 
258
263
  def __init__(
@@ -404,7 +409,9 @@ class LycorisNetworkKohya(LycorisNetwork):
404
409
  next_config = {}
405
410
  for name, module in root_module.named_modules():
406
411
  module_name = module.__class__.__name__
407
- if module_name in target_replace_modules:
412
+ if module_name in target_replace_modules and not any(
413
+ self.match_fn(t, name) for t in target_replace_names
414
+ ):
408
415
  if module_name in self.MODULE_ALGO_MAP:
409
416
  next_config = self.MODULE_ALGO_MAP[module_name]
410
417
  algo = next_config.get("algo", network_module)
@@ -417,10 +424,11 @@ class LycorisNetworkKohya(LycorisNetwork):
417
424
  )
418
425
  next_config = {}
419
426
  elif name in target_replace_names or any(
420
- re.match(t, name) for t in target_replace_names
427
+ self.match_fn(t, name) for t in target_replace_names
421
428
  ):
422
- if name in self.NAME_ALGO_MAP:
423
- next_config = self.NAME_ALGO_MAP[name]
429
+ conf_from_name = self.find_conf_for_name(name)
430
+ if conf_from_name is not None:
431
+ next_config = conf_from_name
424
432
  algo = next_config.get("algo", network_module)
425
433
  elif module_name in self.MODULE_ALGO_MAP:
426
434
  next_config = self.MODULE_ALGO_MAP[module_name]
@@ -492,6 +500,24 @@ class LycorisNetworkKohya(LycorisNetwork):
492
500
  ), f"duplicated lora name: {lora.lora_name}"
493
501
  names.add(lora.lora_name)
494
502
 
503
+ def match_fn(self, pattern: str, name: str) -> bool:
504
+ if self.USE_FNMATCH:
505
+ return fnmatch.fnmatch(name, pattern)
506
+ return re.match(pattern, name)
507
+
508
+ def find_conf_for_name(
509
+ self,
510
+ name: str,
511
+ ) -> dict[str, Any]:
512
+ if name in self.NAME_ALGO_MAP.keys():
513
+ return self.NAME_ALGO_MAP[name]
514
+
515
+ for key, value in self.NAME_ALGO_MAP.items():
516
+ if self.match_fn(key, name):
517
+ return value
518
+
519
+ return None
520
+
495
521
  def load_weights(self, file):
496
522
  if os.path.splitext(file)[1] == ".safetensors":
497
523
  from safetensors.torch import load_file, safe_open
@@ -37,14 +37,14 @@ class NormModule(LycorisBaseModule):
37
37
  if self.module_type == "unknown":
38
38
  if not hasattr(org_module, "weight") or not hasattr(org_module, "_norm"):
39
39
  warning_once(f"{type(org_module)} is not supported in Norm algo.")
40
- self.not_supported=True
40
+ self.not_supported = True
41
41
  return
42
42
  else:
43
43
  self.dim = org_module.weight.numel()
44
44
  self.not_supported = False
45
45
  elif self.module_type not in self.support_module:
46
46
  warning_once(f"{self.module_type} is not supported in Norm algo.")
47
- self.not_supported=True
47
+ self.not_supported = True
48
48
  return
49
49
 
50
50
  self.w_norm = nn.Parameter(torch.zeros(self.dim))
@@ -74,4 +74,6 @@ QuantLinears = (
74
74
 
75
75
  @cache
76
76
  def log_bypass():
77
- return logger.warning("Using bnb/quanto/optimum-quanto with LyCORIS will enable force-bypass mode.")
77
+ return logger.warning(
78
+ "Using bnb/quanto/optimum-quanto with LyCORIS will enable force-bypass mode."
79
+ )
@@ -1,9 +1,10 @@
1
1
  # General LyCORIS wrapper based on kohya-ss/sd-scripts' style
2
2
  import os
3
- import regex as re
3
+ import fnmatch
4
+ import re
4
5
  import logging
5
6
 
6
- from typing import List
7
+ from typing import Any, List
7
8
 
8
9
  import torch
9
10
  import torch.nn as nn
@@ -25,6 +26,22 @@ from .utils import str_bool
25
26
  from .logging import logger
26
27
 
27
28
 
29
+ VALID_PRESET_KEYS = [
30
+ "enable_conv",
31
+ "target_module",
32
+ "target_name",
33
+ "module_algo_map",
34
+ "name_algo_map",
35
+ "lora_prefix",
36
+ "use_fnmatch",
37
+ "unet_target_module",
38
+ "unet_target_name",
39
+ "text_encoder_target_module",
40
+ "text_encoder_target_name",
41
+ "exclude_name",
42
+ ]
43
+
44
+
28
45
  network_module_dict = {
29
46
  "lora": LoConModule,
30
47
  "locon": LoConModule,
@@ -189,9 +206,17 @@ class LycorisNetwork(torch.nn.Module):
189
206
  LORA_PREFIX = "lycoris"
190
207
  MODULE_ALGO_MAP = {}
191
208
  NAME_ALGO_MAP = {}
209
+ USE_FNMATCH = False
210
+ TARGET_EXCLUDE_NAME = []
192
211
 
193
212
  @classmethod
194
213
  def apply_preset(cls, preset):
214
+ for preset_key in preset.keys():
215
+ if preset_key not in VALID_PRESET_KEYS:
216
+ raise KeyError(
217
+ f'Unknown preset key "{preset_key}". Valid keys: {VALID_PRESET_KEYS}'
218
+ )
219
+
195
220
  if "enable_conv" in preset:
196
221
  cls.ENABLE_CONV = preset["enable_conv"]
197
222
  if "target_module" in preset:
@@ -202,6 +227,12 @@ class LycorisNetwork(torch.nn.Module):
202
227
  cls.MODULE_ALGO_MAP = preset["module_algo_map"]
203
228
  if "name_algo_map" in preset:
204
229
  cls.NAME_ALGO_MAP = preset["name_algo_map"]
230
+ if "lora_prefix" in preset:
231
+ cls.LORA_PREFIX = preset["lora_prefix"]
232
+ if "use_fnmatch" in preset:
233
+ cls.USE_FNMATCH = preset["use_fnmatch"]
234
+ if "exclude_name" in preset:
235
+ cls.TARGET_EXCLUDE_NAME = preset["exclude_name"]
205
236
  return cls
206
237
 
207
238
  def __init__(
@@ -324,27 +355,42 @@ class LycorisNetwork(torch.nn.Module):
324
355
  prefix: str,
325
356
  root_module: torch.nn.Module,
326
357
  algo,
358
+ current_lora_map: dict[str, Any],
327
359
  configs={},
328
360
  ):
329
- loras = {}
361
+ assert current_lora_map is not None, "No mapping supplied"
362
+ loras = current_lora_map
330
363
  lora_names = []
331
364
  for name, module in root_module.named_modules():
332
365
  module_name = module.__class__.__name__
333
366
  if module_name in self.MODULE_ALGO_MAP and module is not root_module:
334
367
  next_config = self.MODULE_ALGO_MAP[module_name]
335
368
  next_algo = next_config.get("algo", algo)
336
- new_loras, new_lora_names = create_modules_(
337
- f"{prefix}_{name}" if name else prefix, module, next_algo, next_config
369
+ new_loras, new_lora_names, new_lora_map = create_modules_(
370
+ f"{prefix}_{name}" if name else prefix,
371
+ module,
372
+ next_algo,
373
+ loras,
374
+ configs=next_config,
338
375
  )
376
+ loras = {**loras, **new_lora_map}
339
377
  for lora_name, lora in zip(new_lora_names, new_loras):
340
- if lora_name not in loras:
378
+ if lora_name not in loras and lora_name not in current_lora_map:
341
379
  loras[lora_name] = lora
342
380
  lora_names.append(lora_name)
343
381
  continue
382
+
344
383
  if name:
345
384
  lora_name = prefix + "." + name
346
385
  else:
347
386
  lora_name = prefix
387
+
388
+ if f"{self.LORA_PREFIX}_." in lora_name:
389
+ lora_name = lora_name.replace(
390
+ f"{self.LORA_PREFIX}_.",
391
+ f"{self.LORA_PREFIX}.",
392
+ )
393
+
348
394
  lora_name = lora_name.replace(".", "_")
349
395
  if lora_name in loras:
350
396
  continue
@@ -353,7 +399,7 @@ class LycorisNetwork(torch.nn.Module):
353
399
  if lora is not None:
354
400
  loras[lora_name] = lora
355
401
  lora_names.append(lora_name)
356
- return [loras[lora_name] for lora_name in lora_names], lora_names
402
+ return [loras[lora_name] for lora_name in lora_names], lora_names, loras
357
403
 
358
404
  # create module instances
359
405
  def create_modules(
@@ -361,29 +407,44 @@ class LycorisNetwork(torch.nn.Module):
361
407
  root_module: torch.nn.Module,
362
408
  target_replace_modules,
363
409
  target_replace_names=[],
410
+ target_exclude_names=[],
364
411
  ) -> List:
365
412
  logger.info("Create LyCORIS Module")
366
413
  loras = []
414
+ lora_map = {}
367
415
  next_config = {}
368
416
  for name, module in root_module.named_modules():
417
+ if name in target_exclude_names or any(
418
+ self.match_fn(t, name) for t in target_exclude_names
419
+ ):
420
+ continue
421
+
369
422
  module_name = module.__class__.__name__
370
- if module_name in target_replace_modules:
423
+ if module_name in target_replace_modules and not any(
424
+ self.match_fn(t, name) for t in target_replace_names
425
+ ):
371
426
  if module_name in self.MODULE_ALGO_MAP:
372
427
  next_config = self.MODULE_ALGO_MAP[module_name]
373
428
  algo = next_config.get("algo", network_module)
374
429
  else:
375
430
  algo = network_module
376
- loras.extend(
377
- create_modules_(f"{prefix}_{name}", module, algo, next_config)[
378
- 0
379
- ]
431
+
432
+ lora_lst, _, _lora_map = create_modules_(
433
+ f"{prefix}_{name}",
434
+ module,
435
+ algo,
436
+ lora_map,
437
+ configs=next_config,
380
438
  )
439
+ lora_map = {**lora_map, **_lora_map}
440
+ loras.extend(lora_lst)
381
441
  next_config = {}
382
442
  elif name in target_replace_names or any(
383
- re.match(t, name) for t in target_replace_names
443
+ self.match_fn(t, name) for t in target_replace_names
384
444
  ):
385
- if name in self.NAME_ALGO_MAP:
386
- next_config = self.NAME_ALGO_MAP[name]
445
+ conf_from_name = self.find_conf_for_name(name)
446
+ if conf_from_name is not None:
447
+ next_config = conf_from_name
387
448
  algo = next_config.get("algo", network_module)
388
449
  elif module_name in self.MODULE_ALGO_MAP:
389
450
  next_config = self.MODULE_ALGO_MAP[module_name]
@@ -392,17 +453,37 @@ class LycorisNetwork(torch.nn.Module):
392
453
  algo = network_module
393
454
  lora_name = prefix + "." + name
394
455
  lora_name = lora_name.replace(".", "_")
456
+
457
+ if lora_name in lora_map:
458
+ continue
459
+
395
460
  lora = create_single_module(lora_name, module, algo, **next_config)
396
461
  next_config = {}
397
462
  if lora is not None:
463
+ lora_map[lora.lora_name] = lora
398
464
  loras.append(lora)
399
465
  return loras
400
466
 
401
467
  self.loras = create_modules(
402
468
  LycorisNetwork.LORA_PREFIX,
403
469
  module,
404
- LycorisNetwork.TARGET_REPLACE_MODULE,
405
- LycorisNetwork.TARGET_REPLACE_NAME,
470
+ list(
471
+ set(
472
+ [
473
+ *LycorisNetwork.TARGET_REPLACE_MODULE,
474
+ *LycorisNetwork.MODULE_ALGO_MAP.keys(),
475
+ ]
476
+ )
477
+ ),
478
+ list(
479
+ set(
480
+ [
481
+ *LycorisNetwork.TARGET_REPLACE_NAME,
482
+ *LycorisNetwork.NAME_ALGO_MAP.keys(),
483
+ ]
484
+ )
485
+ ),
486
+ target_exclude_names=LycorisNetwork.TARGET_EXCLUDE_NAME,
406
487
  )
407
488
  logger.info(f"create LyCORIS: {len(self.loras)} modules.")
408
489
 
@@ -413,7 +494,8 @@ class LycorisNetwork(torch.nn.Module):
413
494
  )
414
495
  logger.info(f"module type table: {algo_table}")
415
496
 
416
- # assertion
497
+ # Assertion to ensure we have not accidentally wrapped some layers
498
+ # multiple times.
417
499
  names = set()
418
500
  for lora in self.loras:
419
501
  assert (
@@ -421,6 +503,24 @@ class LycorisNetwork(torch.nn.Module):
421
503
  ), f"duplicated lora name: {lora.lora_name}"
422
504
  names.add(lora.lora_name)
423
505
 
506
+ def match_fn(self, pattern: str, name: str) -> bool:
507
+ if self.USE_FNMATCH:
508
+ return fnmatch.fnmatch(name, pattern)
509
+ return bool(re.match(pattern, name))
510
+
511
+ def find_conf_for_name(
512
+ self,
513
+ name: str,
514
+ ) -> dict[str, Any]:
515
+ if name in self.NAME_ALGO_MAP.keys():
516
+ return self.NAME_ALGO_MAP[name]
517
+
518
+ for key, value in self.NAME_ALGO_MAP.items():
519
+ if self.match_fn(key, name):
520
+ return value
521
+
522
+ return None
523
+
424
524
  def set_multiplier(self, multiplier):
425
525
  self.multiplier = multiplier
426
526
  for lora in self.loras:
@@ -442,6 +542,9 @@ class LycorisNetwork(torch.nn.Module):
442
542
  return state
443
543
 
444
544
  def apply_to(self):
545
+ """
546
+ Register to modules to the subclass so that torch sees them.
547
+ """
445
548
  for lora in self.loras:
446
549
  lora.apply_to()
447
550
  self.add_module(lora.lora_name, lora)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lycoris_lora
3
- Version: 3.0.1.dev4
3
+ Version: 3.0.1.dev6
4
4
  Summary: Lora beYond Conventional methods, Other Rank adaptation Implementations for Stable diffusion
5
5
  Home-page: https://github.com/KohakuBlueleaf/LyCORIS
6
6
  Author: Shih-Ying Yeh(KohakuBlueLeaf), Yu-Guan Hsieh, Zhidong Gao
@@ -4,7 +4,7 @@ from setuptools import setup, find_packages
4
4
  setup(
5
5
  name="lycoris_lora",
6
6
  packages=find_packages(),
7
- version="3.0.1.dev4",
7
+ version="3.0.1.dev6",
8
8
  url="https://github.com/KohakuBlueleaf/LyCORIS",
9
9
  description="Lora beYond Conventional methods, Other Rank adaptation Implementations for Stable diffusion",
10
10
  author="Shih-Ying Yeh(KohakuBlueLeaf), Yu-Guan Hsieh, Zhidong Gao",