1
1
"""Utility functions for extracting metadata from LoRA model files."""
2
2
3
3
import json
4
- from pathlib import Path
5
- from typing import Dict , Any , Optional , Set , Tuple
6
4
import logging
5
+ from pathlib import Path
6
+ from typing import Any , Dict , Optional , Set , Tuple
7
7
8
8
from PIL import Image
9
9
10
- from invokeai .backend .model_manager .config import AnyModelConfig , ModelType
11
10
from invokeai .app .util .thumbnails import make_thumbnail
11
+ from invokeai .backend .model_manager .config import AnyModelConfig , ModelType
12
12
13
13
logger = logging .getLogger (__name__ )
14
14
15
15
16
- def extract_lora_metadata (model_path : Path , model_key : str , model_images_path : Path ) -> Tuple [Optional [str ], Optional [Set [str ]]]:
16
+ def extract_lora_metadata (
17
+ model_path : Path , model_key : str , model_images_path : Path
18
+ ) -> Tuple [Optional [str ], Optional [Set [str ]]]:
17
19
"""
18
20
Extract metadata for a LoRA model from associated JSON and image files.
19
-
21
+
20
22
Args:
21
23
model_path: Path to the LoRA model file
22
24
model_key: Unique key for the model
23
25
model_images_path: Path to the model images directory
24
-
26
+
25
27
Returns:
26
28
Tuple of (description, trigger_phrases)
27
29
"""
28
30
model_stem = model_path .stem
29
31
model_dir = model_path .parent
30
-
32
+
31
33
# Find and process preview image
32
34
_process_preview_image (model_stem , model_dir , model_key , model_images_path )
33
-
35
+
34
36
# Extract metadata from JSON
35
37
description , trigger_phrases = _extract_json_metadata (model_stem , model_dir )
36
-
38
+
37
39
return description , trigger_phrases
38
40
39
41
40
42
def _process_preview_image (model_stem : str , model_dir : Path , model_key : str , model_images_path : Path ) -> bool :
41
43
"""Find and process a preview image for the model, saving it to the model images store."""
42
- image_extensions = [' .png' , ' .jpg' , ' .jpeg' , ' .webp' ]
43
-
44
+ image_extensions = [" .png" , " .jpg" , " .jpeg" , " .webp" ]
45
+
44
46
for ext in image_extensions :
45
47
image_path = model_dir / f"{ model_stem } { ext } "
46
48
if image_path .exists ():
@@ -51,39 +53,39 @@ def _process_preview_image(model_stem: str, model_dir: Path, model_key: str, mod
51
53
thumbnail = make_thumbnail (img , 256 )
52
54
thumbnail_path = model_images_path / f"{ model_key } .webp"
53
55
thumbnail .save (thumbnail_path , format = "webp" )
54
-
56
+
55
57
logger .info (f"Processed preview image { image_path .name } for model { model_key } " )
56
58
return True
57
-
59
+
58
60
except Exception as e :
59
61
logger .warning (f"Failed to process preview image { image_path .name } : { e } " )
60
62
return False
61
-
63
+
62
64
return False
63
65
64
66
65
67
def _extract_json_metadata (model_stem : str , model_dir : Path ) -> Tuple [Optional [str ], Optional [Set [str ]]]:
66
68
"""Extract metadata from a JSON file with the same name as the model."""
67
69
json_path = model_dir / f"{ model_stem } .json"
68
-
70
+
69
71
if not json_path .exists ():
70
72
return None , None
71
-
73
+
72
74
try :
73
- with open (json_path , 'r' , encoding = ' utf-8' ) as f :
75
+ with open (json_path , "r" , encoding = " utf-8" ) as f :
74
76
metadata = json .load (f )
75
-
77
+
76
78
# Extract description
77
79
description = _build_description (metadata )
78
-
80
+
79
81
# Extract trigger phrases
80
82
trigger_phrases = _extract_trigger_phrases (metadata )
81
-
83
+
82
84
if description or trigger_phrases :
83
85
logger .info (f"Applied metadata from { json_path .name } " )
84
-
86
+
85
87
return description , trigger_phrases
86
-
88
+
87
89
except (json .JSONDecodeError , IOError , Exception ) as e :
88
90
logger .warning (f"Failed to read metadata from { json_path } : { e } " )
89
91
return None , None
@@ -92,35 +94,35 @@ def _extract_json_metadata(model_stem: str, model_dir: Path) -> Tuple[Optional[s
92
94
def _build_description (metadata : Dict [str , Any ]) -> Optional [str ]:
93
95
"""Build a description from metadata fields."""
94
96
description_parts = []
95
-
97
+
96
98
if description := metadata .get ("description" ):
97
99
description_parts .append (str (description ).strip ())
98
-
100
+
99
101
if notes := metadata .get ("notes" ):
100
102
description_parts .append (str (notes ).strip ())
101
-
103
+
102
104
return " | " .join (description_parts ) if description_parts else None
103
105
104
106
105
107
def _extract_trigger_phrases (metadata : Dict [str , Any ]) -> Optional [Set [str ]]:
106
108
"""Extract trigger phrases from metadata."""
107
109
if not (activation_text := metadata .get ("activation text" )):
108
110
return None
109
-
111
+
110
112
activation_text = str (activation_text ).strip ()
111
113
if not activation_text :
112
114
return None
113
-
115
+
114
116
# Split on commas and clean up each phrase
115
- phrases = [phrase .strip () for phrase in activation_text .split (',' ) if phrase .strip ()]
116
-
117
+ phrases = [phrase .strip () for phrase in activation_text .split ("," ) if phrase .strip ()]
118
+
117
119
return set (phrases ) if phrases else None
118
120
119
121
120
122
def apply_lora_metadata (info : AnyModelConfig , model_path : Path , model_images_path : Path ) -> None :
121
123
"""
122
124
Apply extracted metadata to a LoRA model configuration.
123
-
125
+
124
126
Args:
125
127
info: The model configuration to update
126
128
model_path: Path to the LoRA model file
@@ -129,17 +131,15 @@ def apply_lora_metadata(info: AnyModelConfig, model_path: Path, model_images_pat
129
131
# Only process LoRA models
130
132
if info .type != ModelType .LoRA :
131
133
return
132
-
134
+
133
135
# Extract and apply metadata
134
- description , trigger_phrases = extract_lora_metadata (
135
- model_path , info .key , model_images_path
136
- )
137
-
136
+ description , trigger_phrases = extract_lora_metadata (model_path , info .key , model_images_path )
137
+
138
138
# We don't set cover_image path in the config anymore since images are stored
139
139
# separately in the model images store by model key
140
-
140
+
141
141
if description :
142
142
info .description = description
143
-
143
+
144
144
if trigger_phrases :
145
- info .trigger_phrases = trigger_phrases
145
+ info .trigger_phrases = trigger_phrases
0 commit comments