T

Diffusers
Safetensors
chenzeyang1 commited on
Commit
ec755f8
·
verified ·
1 Parent(s): 9b6f8e5

Add files using upload-large-folder tool

Browse files
Files changed (50) hide show
  1. LICENSE +21 -0
  2. LaVi-Bridge/modules/__init__.py +1 -0
  3. LaVi-Bridge/modules/adapters.py +62 -0
  4. LaVi-Bridge/modules/lora.py +1106 -0
  5. README.md +509 -1
  6. __pycache__/thera_llava.cpython-310.pyc +0 -0
  7. __pycache__/thera_paths.cpython-310.pyc +0 -0
  8. infer_custom.py +526 -0
  9. infer_example_guided.py +432 -0
  10. infer_palette.sh +30 -0
  11. lavi_ip2p/__init__.py +8 -0
  12. lavi_ip2p/llava_adapter.py +135 -0
  13. lavi_ip2p/unet_8ch.py +161 -0
  14. llava/__init__.py +1 -0
  15. llava/constants.py +16 -0
  16. llava/conversation.py +396 -0
  17. llava/eval/table/results/test_sqa_llava_13b_v0.json +0 -0
  18. llava/mm_utils.py +247 -0
  19. llava/rgbt_dataset.py +328 -0
  20. llava/train/llama_flash_attn_monkey_patch.py +115 -0
  21. llava/train/llama_xformers_attn_monkey_patch.py +129 -0
  22. llava/train/llava_trainer.py +273 -0
  23. llava/train/train_vlm_ip2p_256.py +109 -0
  24. llava/utils.py +126 -0
  25. requirements.txt +23 -0
  26. thera_llava.py +21 -0
  27. thera_paths.py +26 -0
  28. weights/.gitattributes +35 -0
  29. weights/README.md +3 -0
  30. weights/TherA_VLM/adapter_config.json +34 -0
  31. weights/TherA_VLM/config.json +49 -0
  32. weights/TherA_VLM/trainer_state.json +0 -0
  33. weights/llava-1.5-7b-hf/.gitattributes +35 -0
  34. weights/llava-1.5-7b-hf/README.md +155 -0
  35. weights/llava-1.5-7b-hf/added_tokens.json +4 -0
  36. weights/llava-1.5-7b-hf/chat_template.jinja +2 -0
  37. weights/llava-1.5-7b-hf/chat_template.json +3 -0
  38. weights/llava-1.5-7b-hf/config.json +38 -0
  39. weights/llava-1.5-7b-hf/generation_config.json +7 -0
  40. weights/llava-1.5-7b-hf/model.safetensors.index.json +693 -0
  41. weights/llava-1.5-7b-hf/preprocessor_config.json +28 -0
  42. weights/llava-1.5-7b-hf/processor_config.json +7 -0
  43. weights/llava-1.5-7b-hf/special_tokens_map.json +30 -0
  44. weights/llava-1.5-7b-hf/tokenizer.json +0 -0
  45. weights/llava-1.5-7b-hf/tokenizer_config.json +64 -0
  46. weights/merged_models/adapter/config.json +8 -0
  47. weights/merged_models/unet/config.json +68 -0
  48. weights/stable-diffusion/scheduler/.ipynb_checkpoints/scheduler_config-checkpoint.json +9 -0
  49. weights/stable-diffusion/scheduler/scheduler_config.json +13 -0
  50. weights/stable-diffusion/vae/config.json +29 -0
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2025 donkeymouse
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
LaVi-Bridge/modules/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ """LaVi-Bridge modules used by TherA inference."""
LaVi-Bridge/modules/adapters.py ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from dataclasses import dataclass
2
+ from inspect import isfunction
3
+
4
+ import torch
5
+ import torch.nn as nn
6
+ import torch.nn.functional as F
7
+
8
+ from diffusers.utils import BaseOutput
9
+ from diffusers.models.modeling_utils import ModelMixin
10
+ from diffusers.configuration_utils import ConfigMixin, register_to_config
11
+
12
+
13
+ def default(val, d):
14
+ if val is not None: return val
15
+ return d() if isfunction(d) else d
16
+
17
+
18
+ class GEGLU(nn.Module):
19
+ def __init__(self, dim_in, dim_out):
20
+ super().__init__()
21
+ self.proj = nn.Linear(dim_in, dim_out * 2)
22
+
23
+ def forward(self, x):
24
+ x, gate = self.proj(x).chunk(2, dim=-1)
25
+ return x * F.gelu(gate)
26
+
27
+
28
+ class FeedForward(nn.Module):
29
+ def __init__(self, dim, dim_out, mult=4, dropout=0.1):
30
+ super().__init__()
31
+ inner_dim = int(dim * mult)
32
+ dim_out = default(dim_out, dim)
33
+ project_in = GEGLU(dim, inner_dim)
34
+ self.net = nn.Sequential(
35
+ project_in,
36
+ nn.Dropout(dropout),
37
+ nn.Linear(inner_dim, dim_out)
38
+ )
39
+
40
+ def forward(self, x):
41
+ return self.net(x)
42
+
43
+
44
+ @dataclass
45
+ class TextAdapterOutput(BaseOutput):
46
+ sample: torch.FloatTensor
47
+
48
+
49
+ class TextAdapter(ModelMixin, ConfigMixin):
50
+ @register_to_config
51
+ def __init__(self, in_dim, int_dim, out_dim):
52
+ super().__init__()
53
+ self.in_dim = in_dim
54
+ self.ff1 = FeedForward(in_dim, int_dim)
55
+ self.ff2 = FeedForward(int_dim, out_dim)
56
+ self.norm1 = nn.LayerNorm(in_dim)
57
+ self.norm2 = nn.LayerNorm(int_dim)
58
+
59
+ def forward(self, x):
60
+ x = self.ff1(self.norm1(x))
61
+ x = self.ff2(self.norm2(x))
62
+ return TextAdapterOutput(x)
LaVi-Bridge/modules/lora.py ADDED
@@ -0,0 +1,1106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ from itertools import groupby
3
+ from typing import Dict, List, Optional, Set, Tuple, Type, Union
4
+
5
+ import torch
6
+ import torch.nn as nn
7
+
8
+ try:
9
+ from safetensors.torch import safe_open
10
+ from safetensors.torch import save_file as safe_save
11
+
12
+ safetensors_available = True
13
+ except ImportError:
14
+ from .safe_open import safe_open
15
+
16
+ def safe_save(
17
+ tensors: Dict[str, torch.Tensor],
18
+ filename: str,
19
+ metadata: Optional[Dict[str, str]] = None,
20
+ ) -> None:
21
+ raise EnvironmentError(
22
+ "Saving safetensors requires the safetensors library. Please install with pip or similar."
23
+ )
24
+
25
+ safetensors_available = False
26
+
27
+
28
+ class LoraInjectedLinear(nn.Module):
29
+ def __init__(
30
+ self, in_features, out_features, bias=False, r=4, dropout_p=0.1, scale=1.0
31
+ ):
32
+ super().__init__()
33
+
34
+ if r > min(in_features, out_features):
35
+ raise ValueError(
36
+ f"LoRA rank {r} must be less or equal than {min(in_features, out_features)}"
37
+ )
38
+ self.r = r
39
+ self.linear = nn.Linear(in_features, out_features, bias)
40
+ self.lora_down = nn.Linear(in_features, r, bias=False)
41
+ self.dropout = nn.Dropout(dropout_p)
42
+ self.lora_up = nn.Linear(r, out_features, bias=False)
43
+ self.scale = scale
44
+ self.selector = nn.Identity()
45
+
46
+ nn.init.normal_(self.lora_down.weight, std=1 / r)
47
+ nn.init.zeros_(self.lora_up.weight)
48
+
49
+ def forward(self, input):
50
+ return (
51
+ self.linear(input)
52
+ + self.dropout(self.lora_up(self.selector(self.lora_down(input))))
53
+ * self.scale
54
+ )
55
+
56
+ def realize_as_lora(self):
57
+ return self.lora_up.weight.data * self.scale, self.lora_down.weight.data
58
+
59
+ def set_selector_from_diag(self, diag: torch.Tensor):
60
+ # diag is a 1D tensor of size (r,)
61
+ assert diag.shape == (self.r,)
62
+ self.selector = nn.Linear(self.r, self.r, bias=False)
63
+ self.selector.weight.data = torch.diag(diag)
64
+ self.selector.weight.data = self.selector.weight.data.to(
65
+ self.lora_up.weight.device
66
+ ).to(self.lora_up.weight.dtype)
67
+
68
+
69
+ class LoraInjectedConv2d(nn.Module):
70
+ def __init__(
71
+ self,
72
+ in_channels: int,
73
+ out_channels: int,
74
+ kernel_size,
75
+ stride=1,
76
+ padding=0,
77
+ dilation=1,
78
+ groups: int = 1,
79
+ bias: bool = True,
80
+ r: int = 4,
81
+ dropout_p: float = 0.1,
82
+ scale: float = 1.0,
83
+ ):
84
+ super().__init__()
85
+ if r > min(in_channels, out_channels):
86
+ raise ValueError(
87
+ f"LoRA rank {r} must be less or equal than {min(in_channels, out_channels)}"
88
+ )
89
+ self.r = r
90
+ self.conv = nn.Conv2d(
91
+ in_channels=in_channels,
92
+ out_channels=out_channels,
93
+ kernel_size=kernel_size,
94
+ stride=stride,
95
+ padding=padding,
96
+ dilation=dilation,
97
+ groups=groups,
98
+ bias=bias,
99
+ )
100
+
101
+ self.lora_down = nn.Conv2d(
102
+ in_channels=in_channels,
103
+ out_channels=r,
104
+ kernel_size=kernel_size,
105
+ stride=stride,
106
+ padding=padding,
107
+ dilation=dilation,
108
+ groups=groups,
109
+ bias=False,
110
+ )
111
+ self.dropout = nn.Dropout(dropout_p)
112
+ self.lora_up = nn.Conv2d(
113
+ in_channels=r,
114
+ out_channels=out_channels,
115
+ kernel_size=1,
116
+ stride=1,
117
+ padding=0,
118
+ bias=False,
119
+ )
120
+ self.selector = nn.Identity()
121
+ self.scale = scale
122
+
123
+ nn.init.normal_(self.lora_down.weight, std=1 / r)
124
+ nn.init.zeros_(self.lora_up.weight)
125
+
126
+ def forward(self, input):
127
+ return (
128
+ self.conv(input)
129
+ + self.dropout(self.lora_up(self.selector(self.lora_down(input))))
130
+ * self.scale
131
+ )
132
+
133
+ def realize_as_lora(self):
134
+ return self.lora_up.weight.data * self.scale, self.lora_down.weight.data
135
+
136
+ def set_selector_from_diag(self, diag: torch.Tensor):
137
+ # diag is a 1D tensor of size (r,)
138
+ assert diag.shape == (self.r,)
139
+ self.selector = nn.Conv2d(
140
+ in_channels=self.r,
141
+ out_channels=self.r,
142
+ kernel_size=1,
143
+ stride=1,
144
+ padding=0,
145
+ bias=False,
146
+ )
147
+ self.selector.weight.data = torch.diag(diag)
148
+
149
+ # same device + dtype as lora_up
150
+ self.selector.weight.data = self.selector.weight.data.to(
151
+ self.lora_up.weight.device
152
+ ).to(self.lora_up.weight.dtype)
153
+
154
+
155
+ UNET_DEFAULT_TARGET_REPLACE = {"CrossAttention", "Attention", "GEGLU"}
156
+
157
+ UNET_EXTENDED_TARGET_REPLACE = {"ResnetBlock2D", "CrossAttention", "Attention", "GEGLU"}
158
+
159
+ TEXT_ENCODER_DEFAULT_TARGET_REPLACE = {"CLIPAttention"}
160
+
161
+ TEXT_ENCODER_EXTENDED_TARGET_REPLACE = {"CLIPAttention"}
162
+
163
+ DEFAULT_TARGET_REPLACE = UNET_DEFAULT_TARGET_REPLACE
164
+
165
+ EMBED_FLAG = "<embed>"
166
+
167
+
168
+ def _find_children(
169
+ model,
170
+ search_class: List[Type[nn.Module]] = [nn.Linear],
171
+ ):
172
+ """
173
+ Find all modules of a certain class (or union of classes).
174
+
175
+ Returns all matching modules, along with the parent of those moduless and the
176
+ names they are referenced by.
177
+ """
178
+ # For each target find every linear_class module that isn't a child of a LoraInjectedLinear
179
+ for parent in model.modules():
180
+ for name, module in parent.named_children():
181
+ if any([isinstance(module, _class) for _class in search_class]):
182
+ yield parent, name, module
183
+
184
+
185
+ def _find_modules_v2(
186
+ model,
187
+ ancestor_class: Optional[Set[str]] = None,
188
+ search_class: List[Type[nn.Module]] = [nn.Linear],
189
+ exclude_children_of: Optional[List[Type[nn.Module]]] = [
190
+ LoraInjectedLinear,
191
+ LoraInjectedConv2d,
192
+ ],
193
+ ):
194
+ """
195
+ Find all modules of a certain class (or union of classes) that are direct or
196
+ indirect descendants of other modules of a certain class (or union of classes).
197
+
198
+ Returns all matching modules, along with the parent of those moduless and the
199
+ names they are referenced by.
200
+ """
201
+
202
+ # Get the targets we should replace all linears under
203
+ if ancestor_class is not None:
204
+ ancestors = (
205
+ module
206
+ for module in model.modules()
207
+ if module.__class__.__name__ in ancestor_class
208
+ )
209
+ else:
210
+ # this, incase you want to naively iterate over all modules.
211
+ ancestors = [module for module in model.modules()]
212
+
213
+ # For each target find every linear_class module that isn't a child of a LoraInjectedLinear
214
+ for ancestor in ancestors:
215
+ for fullname, module in ancestor.named_modules():
216
+ if any([isinstance(module, _class) for _class in search_class]):
217
+ # Find the direct parent if this is a descendant, not a child, of target
218
+ *path, name = fullname.split(".")
219
+ parent = ancestor
220
+ while path:
221
+ parent = parent.get_submodule(path.pop(0))
222
+ # Skip this linear if it's a child of a LoraInjectedLinear
223
+ if exclude_children_of and any(
224
+ [isinstance(parent, _class) for _class in exclude_children_of]
225
+ ):
226
+ continue
227
+ # Otherwise, yield it
228
+ yield parent, name, module
229
+
230
+
231
+ def _find_modules_old(
232
+ model,
233
+ ancestor_class: Set[str] = DEFAULT_TARGET_REPLACE,
234
+ search_class: List[Type[nn.Module]] = [nn.Linear],
235
+ exclude_children_of: Optional[List[Type[nn.Module]]] = [LoraInjectedLinear],
236
+ ):
237
+ ret = []
238
+ for _module in model.modules():
239
+ if _module.__class__.__name__ in ancestor_class:
240
+
241
+ for name, _child_module in _module.named_modules():
242
+ if _child_module.__class__ in search_class:
243
+ ret.append((_module, name, _child_module))
244
+ print(ret)
245
+ return ret
246
+
247
+
248
+ _find_modules = _find_modules_v2
249
+
250
+
251
+ def inject_trainable_lora(
252
+ model: nn.Module,
253
+ target_replace_module: Set[str] = DEFAULT_TARGET_REPLACE,
254
+ r: int = 4,
255
+ loras=None, # path to lora .pt
256
+ verbose: bool = False,
257
+ dropout_p: float = 0.0,
258
+ scale: float = 1.0,
259
+ ):
260
+ """
261
+ inject lora into model, and returns lora parameter groups.
262
+ """
263
+
264
+ require_grad_params = []
265
+ names = []
266
+
267
+ if loras != None:
268
+ loras = torch.load(loras)
269
+
270
+ for _module, name, _child_module in _find_modules(
271
+ model, target_replace_module, search_class=[nn.Linear]
272
+ ):
273
+ weight = _child_module.weight
274
+ bias = _child_module.bias
275
+ if verbose:
276
+ print("LoRA Injection : injecting lora into ", name)
277
+ print("LoRA Injection : weight shape", weight.shape)
278
+ _tmp = LoraInjectedLinear(
279
+ _child_module.in_features,
280
+ _child_module.out_features,
281
+ _child_module.bias is not None,
282
+ r=r,
283
+ dropout_p=dropout_p,
284
+ scale=scale,
285
+ )
286
+ _tmp.linear.weight = weight
287
+ if bias is not None:
288
+ _tmp.linear.bias = bias
289
+
290
+ # switch the module
291
+ _tmp.to(_child_module.weight.device).to(_child_module.weight.dtype)
292
+ _module._modules[name] = _tmp
293
+
294
+ require_grad_params.append(_module._modules[name].lora_up.parameters())
295
+ require_grad_params.append(_module._modules[name].lora_down.parameters())
296
+
297
+ if loras != None:
298
+ _module._modules[name].lora_up.weight = loras.pop(0)
299
+ _module._modules[name].lora_down.weight = loras.pop(0)
300
+
301
+ _module._modules[name].lora_up.weight.requires_grad = True
302
+ _module._modules[name].lora_down.weight.requires_grad = True
303
+ names.append(name)
304
+
305
+ return require_grad_params, names
306
+
307
+
308
+ def inject_trainable_lora_extended(
309
+ model: nn.Module,
310
+ target_replace_module: Set[str] = UNET_EXTENDED_TARGET_REPLACE,
311
+ r: int = 4,
312
+ loras=None, # path to lora .pt
313
+ ):
314
+ """
315
+ inject lora into model, and returns lora parameter groups.
316
+ """
317
+
318
+ require_grad_params = []
319
+ names = []
320
+
321
+ if loras != None:
322
+ loras = torch.load(loras)
323
+
324
+ for _module, name, _child_module in _find_modules(
325
+ model, target_replace_module, search_class=[nn.Linear, nn.Conv2d]
326
+ ):
327
+ if _child_module.__class__ == nn.Linear:
328
+ weight = _child_module.weight
329
+ bias = _child_module.bias
330
+ _tmp = LoraInjectedLinear(
331
+ _child_module.in_features,
332
+ _child_module.out_features,
333
+ _child_module.bias is not None,
334
+ r=r,
335
+ )
336
+ _tmp.linear.weight = weight
337
+ if bias is not None:
338
+ _tmp.linear.bias = bias
339
+ elif _child_module.__class__ == nn.Conv2d:
340
+ weight = _child_module.weight
341
+ bias = _child_module.bias
342
+ _tmp = LoraInjectedConv2d(
343
+ _child_module.in_channels,
344
+ _child_module.out_channels,
345
+ _child_module.kernel_size,
346
+ _child_module.stride,
347
+ _child_module.padding,
348
+ _child_module.dilation,
349
+ _child_module.groups,
350
+ _child_module.bias is not None,
351
+ r=r,
352
+ )
353
+
354
+ _tmp.conv.weight = weight
355
+ if bias is not None:
356
+ _tmp.conv.bias = bias
357
+
358
+ # switch the module
359
+ _tmp.to(_child_module.weight.device).to(_child_module.weight.dtype)
360
+ if bias is not None:
361
+ _tmp.to(_child_module.bias.device).to(_child_module.bias.dtype)
362
+
363
+ _module._modules[name] = _tmp
364
+
365
+ require_grad_params.append(_module._modules[name].lora_up.parameters())
366
+ require_grad_params.append(_module._modules[name].lora_down.parameters())
367
+
368
+ if loras != None:
369
+ _module._modules[name].lora_up.weight = loras.pop(0)
370
+ _module._modules[name].lora_down.weight = loras.pop(0)
371
+
372
+ _module._modules[name].lora_up.weight.requires_grad = True
373
+ _module._modules[name].lora_down.weight.requires_grad = True
374
+ names.append(name)
375
+
376
+ return require_grad_params, names
377
+
378
+
379
+ def extract_lora_ups_down(model, target_replace_module=DEFAULT_TARGET_REPLACE):
380
+
381
+ loras = []
382
+
383
+ for _m, _n, _child_module in _find_modules(
384
+ model,
385
+ target_replace_module,
386
+ search_class=[LoraInjectedLinear, LoraInjectedConv2d],
387
+ ):
388
+ loras.append((_child_module.lora_up, _child_module.lora_down))
389
+
390
+ if len(loras) == 0:
391
+ raise ValueError("No lora injected.")
392
+
393
+ return loras
394
+
395
+
396
+ def extract_lora_as_tensor(
397
+ model, target_replace_module=DEFAULT_TARGET_REPLACE, as_fp16=True
398
+ ):
399
+
400
+ loras = []
401
+
402
+ for _m, _n, _child_module in _find_modules(
403
+ model,
404
+ target_replace_module,
405
+ search_class=[LoraInjectedLinear, LoraInjectedConv2d],
406
+ ):
407
+ up, down = _child_module.realize_as_lora()
408
+ if as_fp16:
409
+ up = up.to(torch.float16)
410
+ down = down.to(torch.float16)
411
+
412
+ loras.append((up, down))
413
+
414
+ if len(loras) == 0:
415
+ raise ValueError("No lora injected.")
416
+
417
+ return loras
418
+
419
+
420
+ def save_lora_weight(
421
+ model,
422
+ path="./lora.pt",
423
+ target_replace_module=DEFAULT_TARGET_REPLACE,
424
+ ):
425
+ weights = []
426
+ for _up, _down in extract_lora_ups_down(
427
+ model, target_replace_module=target_replace_module
428
+ ):
429
+ weights.append(_up.weight.to("cpu").to(torch.float16))
430
+ weights.append(_down.weight.to("cpu").to(torch.float16))
431
+
432
+ torch.save(weights, path)
433
+
434
+
435
+ def save_lora_as_json(model, path="./lora.json"):
436
+ weights = []
437
+ for _up, _down in extract_lora_ups_down(model):
438
+ weights.append(_up.weight.detach().cpu().numpy().tolist())
439
+ weights.append(_down.weight.detach().cpu().numpy().tolist())
440
+
441
+ import json
442
+
443
+ with open(path, "w") as f:
444
+ json.dump(weights, f)
445
+
446
+
447
+ def save_safeloras_with_embeds(
448
+ modelmap: Dict[str, Tuple[nn.Module, Set[str]]] = {},
449
+ embeds: Dict[str, torch.Tensor] = {},
450
+ outpath="./lora.safetensors",
451
+ ):
452
+ """
453
+ Saves the Lora from multiple modules in a single safetensor file.
454
+
455
+ modelmap is a dictionary of {
456
+ "module name": (module, target_replace_module)
457
+ }
458
+ """
459
+ weights = {}
460
+ metadata = {}
461
+
462
+ for name, (model, target_replace_module) in modelmap.items():
463
+ metadata[name] = json.dumps(list(target_replace_module))
464
+
465
+ for i, (_up, _down) in enumerate(
466
+ extract_lora_as_tensor(model, target_replace_module)
467
+ ):
468
+ rank = _down.shape[0]
469
+
470
+ metadata[f"{name}:{i}:rank"] = str(rank)
471
+ weights[f"{name}:{i}:up"] = _up
472
+ weights[f"{name}:{i}:down"] = _down
473
+
474
+ for token, tensor in embeds.items():
475
+ metadata[token] = EMBED_FLAG
476
+ weights[token] = tensor
477
+
478
+ print(f"Saving weights to {outpath}")
479
+ safe_save(weights, outpath, metadata)
480
+
481
+
482
+ def save_safeloras(
483
+ modelmap: Dict[str, Tuple[nn.Module, Set[str]]] = {},
484
+ outpath="./lora.safetensors",
485
+ ):
486
+ return save_safeloras_with_embeds(modelmap=modelmap, outpath=outpath)
487
+
488
+
489
+ def convert_loras_to_safeloras_with_embeds(
490
+ modelmap: Dict[str, Tuple[str, Set[str], int]] = {},
491
+ embeds: Dict[str, torch.Tensor] = {},
492
+ outpath="./lora.safetensors",
493
+ ):
494
+ """
495
+ Converts the Lora from multiple pytorch .pt files into a single safetensor file.
496
+
497
+ modelmap is a dictionary of {
498
+ "module name": (pytorch_model_path, target_replace_module, rank)
499
+ }
500
+ """
501
+
502
+ weights = {}
503
+ metadata = {}
504
+
505
+ for name, (path, target_replace_module, r) in modelmap.items():
506
+ metadata[name] = json.dumps(list(target_replace_module))
507
+
508
+ lora = torch.load(path)
509
+ for i, weight in enumerate(lora):
510
+ is_up = i % 2 == 0
511
+ i = i // 2
512
+
513
+ if is_up:
514
+ metadata[f"{name}:{i}:rank"] = str(r)
515
+ weights[f"{name}:{i}:up"] = weight
516
+ else:
517
+ weights[f"{name}:{i}:down"] = weight
518
+
519
+ for token, tensor in embeds.items():
520
+ metadata[token] = EMBED_FLAG
521
+ weights[token] = tensor
522
+
523
+ print(f"Saving weights to {outpath}")
524
+ safe_save(weights, outpath, metadata)
525
+
526
+
527
+ def convert_loras_to_safeloras(
528
+ modelmap: Dict[str, Tuple[str, Set[str], int]] = {},
529
+ outpath="./lora.safetensors",
530
+ ):
531
+ convert_loras_to_safeloras_with_embeds(modelmap=modelmap, outpath=outpath)
532
+
533
+
534
+ def parse_safeloras(
535
+ safeloras,
536
+ ) -> Dict[str, Tuple[List[nn.parameter.Parameter], List[int], List[str]]]:
537
+ """
538
+ Converts a loaded safetensor file that contains a set of module Loras
539
+ into Parameters and other information
540
+
541
+ Output is a dictionary of {
542
+ "module name": (
543
+ [list of weights],
544
+ [list of ranks],
545
+ target_replacement_modules
546
+ )
547
+ }
548
+ """
549
+ loras = {}
550
+ metadata = safeloras.metadata()
551
+
552
+ get_name = lambda k: k.split(":")[0]
553
+
554
+ keys = list(safeloras.keys())
555
+ keys.sort(key=get_name)
556
+
557
+ for name, module_keys in groupby(keys, get_name):
558
+ info = metadata.get(name)
559
+
560
+ if not info:
561
+ raise ValueError(
562
+ f"Tensor {name} has no metadata - is this a Lora safetensor?"
563
+ )
564
+
565
+ # Skip Textual Inversion embeds
566
+ if info == EMBED_FLAG:
567
+ continue
568
+
569
+ # Handle Loras
570
+ # Extract the targets
571
+ target = json.loads(info)
572
+
573
+ # Build the result lists - Python needs us to preallocate lists to insert into them
574
+ module_keys = list(module_keys)
575
+ ranks = [4] * (len(module_keys) // 2)
576
+ weights = [None] * len(module_keys)
577
+
578
+ for key in module_keys:
579
+ # Split the model name and index out of the key
580
+ _, idx, direction = key.split(":")
581
+ idx = int(idx)
582
+
583
+ # Add the rank
584
+ ranks[idx] = int(metadata[f"{name}:{idx}:rank"])
585
+
586
+ # Insert the weight into the list
587
+ idx = idx * 2 + (1 if direction == "down" else 0)
588
+ weights[idx] = nn.parameter.Parameter(safeloras.get_tensor(key))
589
+
590
+ loras[name] = (weights, ranks, target)
591
+
592
+ return loras
593
+
594
+
595
+ def parse_safeloras_embeds(
596
+ safeloras,
597
+ ) -> Dict[str, torch.Tensor]:
598
+ """
599
+ Converts a loaded safetensor file that contains Textual Inversion embeds into
600
+ a dictionary of embed_token: Tensor
601
+ """
602
+ embeds = {}
603
+ metadata = safeloras.metadata()
604
+
605
+ for key in safeloras.keys():
606
+ # Only handle Textual Inversion embeds
607
+ meta = metadata.get(key)
608
+ if not meta or meta != EMBED_FLAG:
609
+ continue
610
+
611
+ embeds[key] = safeloras.get_tensor(key)
612
+
613
+ return embeds
614
+
615
+
616
+ def load_safeloras(path, device="cpu"):
617
+ safeloras = safe_open(path, framework="pt", device=device)
618
+ return parse_safeloras(safeloras)
619
+
620
+
621
+ def load_safeloras_embeds(path, device="cpu"):
622
+ safeloras = safe_open(path, framework="pt", device=device)
623
+ return parse_safeloras_embeds(safeloras)
624
+
625
+
626
+ def load_safeloras_both(path, device="cpu"):
627
+ safeloras = safe_open(path, framework="pt", device=device)
628
+ return parse_safeloras(safeloras), parse_safeloras_embeds(safeloras)
629
+
630
+
631
+ def collapse_lora(model, alpha=1.0):
632
+
633
+ for _module, name, _child_module in _find_modules(
634
+ model,
635
+ UNET_EXTENDED_TARGET_REPLACE | TEXT_ENCODER_EXTENDED_TARGET_REPLACE,
636
+ search_class=[LoraInjectedLinear, LoraInjectedConv2d],
637
+ ):
638
+
639
+ if isinstance(_child_module, LoraInjectedLinear):
640
+ print("Collapsing Lin Lora in", name)
641
+
642
+ _child_module.linear.weight = nn.Parameter(
643
+ _child_module.linear.weight.data
644
+ + alpha
645
+ * (
646
+ _child_module.lora_up.weight.data
647
+ @ _child_module.lora_down.weight.data
648
+ )
649
+ .type(_child_module.linear.weight.dtype)
650
+ .to(_child_module.linear.weight.device)
651
+ )
652
+
653
+ else:
654
+ print("Collapsing Conv Lora in", name)
655
+ _child_module.conv.weight = nn.Parameter(
656
+ _child_module.conv.weight.data
657
+ + alpha
658
+ * (
659
+ _child_module.lora_up.weight.data.flatten(start_dim=1)
660
+ @ _child_module.lora_down.weight.data.flatten(start_dim=1)
661
+ )
662
+ .reshape(_child_module.conv.weight.data.shape)
663
+ .type(_child_module.conv.weight.dtype)
664
+ .to(_child_module.conv.weight.device)
665
+ )
666
+
667
+
668
+ def monkeypatch_or_replace_lora(
669
+ model,
670
+ loras,
671
+ target_replace_module=DEFAULT_TARGET_REPLACE,
672
+ r: Union[int, List[int]] = 4,
673
+ ):
674
+ for _module, name, _child_module in _find_modules(
675
+ model, target_replace_module, search_class=[nn.Linear, LoraInjectedLinear]
676
+ ):
677
+ _source = (
678
+ _child_module.linear
679
+ if isinstance(_child_module, LoraInjectedLinear)
680
+ else _child_module
681
+ )
682
+
683
+ weight = _source.weight
684
+ bias = _source.bias
685
+ _tmp = LoraInjectedLinear(
686
+ _source.in_features,
687
+ _source.out_features,
688
+ _source.bias is not None,
689
+ r=r.pop(0) if isinstance(r, list) else r,
690
+ )
691
+ _tmp.linear.weight = weight
692
+
693
+ if bias is not None:
694
+ _tmp.linear.bias = bias
695
+
696
+ # switch the module
697
+ _module._modules[name] = _tmp
698
+
699
+ up_weight = loras.pop(0)
700
+ down_weight = loras.pop(0)
701
+
702
+ _module._modules[name].lora_up.weight = nn.Parameter(
703
+ up_weight.type(weight.dtype)
704
+ )
705
+ _module._modules[name].lora_down.weight = nn.Parameter(
706
+ down_weight.type(weight.dtype)
707
+ )
708
+
709
+ _module._modules[name].to(weight.device)
710
+
711
+
712
+ def monkeypatch_or_replace_lora_extended(
713
+ model,
714
+ loras,
715
+ target_replace_module=DEFAULT_TARGET_REPLACE,
716
+ r: Union[int, List[int]] = 4,
717
+ ):
718
+ for _module, name, _child_module in _find_modules(
719
+ model,
720
+ target_replace_module,
721
+ search_class=[nn.Linear, LoraInjectedLinear, nn.Conv2d, LoraInjectedConv2d],
722
+ ):
723
+
724
+ if (_child_module.__class__ == nn.Linear) or (
725
+ _child_module.__class__ == LoraInjectedLinear
726
+ ):
727
+ if len(loras[0].shape) != 2:
728
+ continue
729
+
730
+ _source = (
731
+ _child_module.linear
732
+ if isinstance(_child_module, LoraInjectedLinear)
733
+ else _child_module
734
+ )
735
+
736
+ weight = _source.weight
737
+ bias = _source.bias
738
+ _tmp = LoraInjectedLinear(
739
+ _source.in_features,
740
+ _source.out_features,
741
+ _source.bias is not None,
742
+ r=r.pop(0) if isinstance(r, list) else r,
743
+ )
744
+ _tmp.linear.weight = weight
745
+
746
+ if bias is not None:
747
+ _tmp.linear.bias = bias
748
+
749
+ elif (_child_module.__class__ == nn.Conv2d) or (
750
+ _child_module.__class__ == LoraInjectedConv2d
751
+ ):
752
+ if len(loras[0].shape) != 4:
753
+ continue
754
+ _source = (
755
+ _child_module.conv
756
+ if isinstance(_child_module, LoraInjectedConv2d)
757
+ else _child_module
758
+ )
759
+
760
+ weight = _source.weight
761
+ bias = _source.bias
762
+ _tmp = LoraInjectedConv2d(
763
+ _source.in_channels,
764
+ _source.out_channels,
765
+ _source.kernel_size,
766
+ _source.stride,
767
+ _source.padding,
768
+ _source.dilation,
769
+ _source.groups,
770
+ _source.bias is not None,
771
+ r=r.pop(0) if isinstance(r, list) else r,
772
+ )
773
+
774
+ _tmp.conv.weight = weight
775
+
776
+ if bias is not None:
777
+ _tmp.conv.bias = bias
778
+
779
+ # switch the module
780
+ _module._modules[name] = _tmp
781
+
782
+ up_weight = loras.pop(0)
783
+ down_weight = loras.pop(0)
784
+
785
+ _module._modules[name].lora_up.weight = nn.Parameter(
786
+ up_weight.type(weight.dtype)
787
+ )
788
+ _module._modules[name].lora_down.weight = nn.Parameter(
789
+ down_weight.type(weight.dtype)
790
+ )
791
+
792
+ _module._modules[name].to(weight.device)
793
+
794
+
795
+ def monkeypatch_or_replace_safeloras(models, safeloras):
796
+ loras = parse_safeloras(safeloras)
797
+
798
+ for name, (lora, ranks, target) in loras.items():
799
+ model = getattr(models, name, None)
800
+
801
+ if not model:
802
+ print(f"No model provided for {name}, contained in Lora")
803
+ continue
804
+
805
+ monkeypatch_or_replace_lora_extended(model, lora, target, ranks)
806
+
807
+
808
+ def monkeypatch_remove_lora(model):
809
+ for _module, name, _child_module in _find_modules(
810
+ model, search_class=[LoraInjectedLinear, LoraInjectedConv2d]
811
+ ):
812
+ if isinstance(_child_module, LoraInjectedLinear):
813
+ _source = _child_module.linear
814
+ weight, bias = _source.weight, _source.bias
815
+
816
+ _tmp = nn.Linear(
817
+ _source.in_features, _source.out_features, bias is not None
818
+ )
819
+
820
+ _tmp.weight = weight
821
+ if bias is not None:
822
+ _tmp.bias = bias
823
+
824
+ else:
825
+ _source = _child_module.conv
826
+ weight, bias = _source.weight, _source.bias
827
+
828
+ _tmp = nn.Conv2d(
829
+ in_channels=_source.in_channels,
830
+ out_channels=_source.out_channels,
831
+ kernel_size=_source.kernel_size,
832
+ stride=_source.stride,
833
+ padding=_source.padding,
834
+ dilation=_source.dilation,
835
+ groups=_source.groups,
836
+ bias=bias is not None,
837
+ )
838
+
839
+ _tmp.weight = weight
840
+ if bias is not None:
841
+ _tmp.bias = bias
842
+
843
+ _module._modules[name] = _tmp
844
+
845
+
846
+ def monkeypatch_add_lora(
847
+ model,
848
+ loras,
849
+ target_replace_module=DEFAULT_TARGET_REPLACE,
850
+ alpha: float = 1.0,
851
+ beta: float = 1.0,
852
+ ):
853
+ for _module, name, _child_module in _find_modules(
854
+ model, target_replace_module, search_class=[LoraInjectedLinear]
855
+ ):
856
+ weight = _child_module.linear.weight
857
+
858
+ up_weight = loras.pop(0)
859
+ down_weight = loras.pop(0)
860
+
861
+ _module._modules[name].lora_up.weight = nn.Parameter(
862
+ up_weight.type(weight.dtype).to(weight.device) * alpha
863
+ + _module._modules[name].lora_up.weight.to(weight.device) * beta
864
+ )
865
+ _module._modules[name].lora_down.weight = nn.Parameter(
866
+ down_weight.type(weight.dtype).to(weight.device) * alpha
867
+ + _module._modules[name].lora_down.weight.to(weight.device) * beta
868
+ )
869
+
870
+ _module._modules[name].to(weight.device)
871
+
872
+
873
+ def tune_lora_scale(model, alpha: float = 1.0):
874
+ for _module in model.modules():
875
+ if _module.__class__.__name__ in ["LoraInjectedLinear", "LoraInjectedConv2d"]:
876
+ _module.scale = alpha
877
+
878
+
879
+ def set_lora_diag(model, diag: torch.Tensor):
880
+ for _module in model.modules():
881
+ if _module.__class__.__name__ in ["LoraInjectedLinear", "LoraInjectedConv2d"]:
882
+ _module.set_selector_from_diag(diag)
883
+
884
+
885
+ def _text_lora_path(path: str) -> str:
886
+ assert path.endswith(".pt"), "Only .pt files are supported"
887
+ return ".".join(path.split(".")[:-1] + ["text_encoder", "pt"])
888
+
889
+
890
+ def _ti_lora_path(path: str) -> str:
891
+ assert path.endswith(".pt"), "Only .pt files are supported"
892
+ return ".".join(path.split(".")[:-1] + ["ti", "pt"])
893
+
894
+
895
+ def apply_learned_embed_in_clip(
896
+ learned_embeds,
897
+ text_encoder,
898
+ tokenizer,
899
+ token: Optional[Union[str, List[str]]] = None,
900
+ idempotent=False,
901
+ ):
902
+ if isinstance(token, str):
903
+ trained_tokens = [token]
904
+ elif isinstance(token, list):
905
+ assert len(learned_embeds.keys()) == len(
906
+ token
907
+ ), "The number of tokens and the number of embeds should be the same"
908
+ trained_tokens = token
909
+ else:
910
+ trained_tokens = list(learned_embeds.keys())
911
+
912
+ for token in trained_tokens:
913
+ print(token)
914
+ embeds = learned_embeds[token]
915
+
916
+ # cast to dtype of text_encoder
917
+ dtype = text_encoder.get_input_embeddings().weight.dtype
918
+ num_added_tokens = tokenizer.add_tokens(token)
919
+
920
+ i = 1
921
+ if not idempotent:
922
+ while num_added_tokens == 0:
923
+ print(f"The tokenizer already contains the token {token}.")
924
+ token = f"{token[:-1]}-{i}>"
925
+ print(f"Attempting to add the token {token}.")
926
+ num_added_tokens = tokenizer.add_tokens(token)
927
+ i += 1
928
+ elif num_added_tokens == 0 and idempotent:
929
+ print(f"The tokenizer already contains the token {token}.")
930
+ print(f"Replacing {token} embedding.")
931
+
932
+ # resize the token embeddings
933
+ text_encoder.resize_token_embeddings(len(tokenizer))
934
+
935
+ # get the id for the token and assign the embeds
936
+ token_id = tokenizer.convert_tokens_to_ids(token)
937
+ text_encoder.get_input_embeddings().weight.data[token_id] = embeds
938
+ return token
939
+
940
+
941
+ def load_learned_embed_in_clip(
942
+ learned_embeds_path,
943
+ text_encoder,
944
+ tokenizer,
945
+ token: Optional[Union[str, List[str]]] = None,
946
+ idempotent=False,
947
+ ):
948
+ learned_embeds = torch.load(learned_embeds_path)
949
+ apply_learned_embed_in_clip(
950
+ learned_embeds, text_encoder, tokenizer, token, idempotent
951
+ )
952
+
953
+
954
+ def patch_pipe(
955
+ pipe,
956
+ maybe_unet_path,
957
+ token: Optional[str] = None,
958
+ r: int = 4,
959
+ patch_unet=True,
960
+ patch_text=True,
961
+ patch_ti=True,
962
+ idempotent_token=True,
963
+ unet_target_replace_module=DEFAULT_TARGET_REPLACE,
964
+ text_target_replace_module=TEXT_ENCODER_DEFAULT_TARGET_REPLACE,
965
+ ):
966
+ if maybe_unet_path.endswith(".pt"):
967
+ # torch format
968
+
969
+ if maybe_unet_path.endswith(".ti.pt"):
970
+ unet_path = maybe_unet_path[:-6] + ".pt"
971
+ elif maybe_unet_path.endswith(".text_encoder.pt"):
972
+ unet_path = maybe_unet_path[:-16] + ".pt"
973
+ else:
974
+ unet_path = maybe_unet_path
975
+
976
+ ti_path = _ti_lora_path(unet_path)
977
+ text_path = _text_lora_path(unet_path)
978
+
979
+ if patch_unet:
980
+ print("LoRA : Patching Unet")
981
+ monkeypatch_or_replace_lora(
982
+ pipe.unet,
983
+ torch.load(unet_path),
984
+ r=r,
985
+ target_replace_module=unet_target_replace_module,
986
+ )
987
+
988
+ if patch_text:
989
+ print("LoRA : Patching text encoder")
990
+ monkeypatch_or_replace_lora(
991
+ pipe.text_encoder,
992
+ torch.load(text_path),
993
+ target_replace_module=text_target_replace_module,
994
+ r=r,
995
+ )
996
+ if patch_ti:
997
+ print("LoRA : Patching token input")
998
+ token = load_learned_embed_in_clip(
999
+ ti_path,
1000
+ pipe.text_encoder,
1001
+ pipe.tokenizer,
1002
+ token=token,
1003
+ idempotent=idempotent_token,
1004
+ )
1005
+
1006
+ elif maybe_unet_path.endswith(".safetensors"):
1007
+ safeloras = safe_open(maybe_unet_path, framework="pt", device="cpu")
1008
+ monkeypatch_or_replace_safeloras(pipe, safeloras)
1009
+ tok_dict = parse_safeloras_embeds(safeloras)
1010
+ if patch_ti:
1011
+ apply_learned_embed_in_clip(
1012
+ tok_dict,
1013
+ pipe.text_encoder,
1014
+ pipe.tokenizer,
1015
+ token=token,
1016
+ idempotent=idempotent_token,
1017
+ )
1018
+ return tok_dict
1019
+
1020
+
1021
+ @torch.no_grad()
1022
+ def inspect_lora(model):
1023
+ moved = {}
1024
+
1025
+ for name, _module in model.named_modules():
1026
+ if _module.__class__.__name__ in ["LoraInjectedLinear", "LoraInjectedConv2d"]:
1027
+ ups = _module.lora_up.weight.data.clone()
1028
+ downs = _module.lora_down.weight.data.clone()
1029
+
1030
+ wght: torch.Tensor = ups.flatten(1) @ downs.flatten(1)
1031
+
1032
+ dist = wght.flatten().abs().mean().item()
1033
+ if name in moved:
1034
+ moved[name].append(dist)
1035
+ else:
1036
+ moved[name] = [dist]
1037
+
1038
+ return moved
1039
+
1040
+
1041
+ def save_all(
1042
+ unet,
1043
+ text_encoder,
1044
+ save_path,
1045
+ placeholder_token_ids=None,
1046
+ placeholder_tokens=None,
1047
+ save_lora=True,
1048
+ save_ti=True,
1049
+ target_replace_module_text=TEXT_ENCODER_DEFAULT_TARGET_REPLACE,
1050
+ target_replace_module_unet=DEFAULT_TARGET_REPLACE,
1051
+ safe_form=True,
1052
+ ):
1053
+ if not safe_form:
1054
+ # save ti
1055
+ if save_ti:
1056
+ ti_path = _ti_lora_path(save_path)
1057
+ learned_embeds_dict = {}
1058
+ for tok, tok_id in zip(placeholder_tokens, placeholder_token_ids):
1059
+ learned_embeds = text_encoder.get_input_embeddings().weight[tok_id]
1060
+ print(
1061
+ f"Current Learned Embeddings for {tok}:, id {tok_id} ",
1062
+ learned_embeds[:4],
1063
+ )
1064
+ learned_embeds_dict[tok] = learned_embeds.detach().cpu()
1065
+
1066
+ torch.save(learned_embeds_dict, ti_path)
1067
+ print("Ti saved to ", ti_path)
1068
+
1069
+ # save text encoder
1070
+ if save_lora:
1071
+
1072
+ save_lora_weight(
1073
+ unet, save_path, target_replace_module=target_replace_module_unet
1074
+ )
1075
+ print("Unet saved to ", save_path)
1076
+
1077
+ save_lora_weight(
1078
+ text_encoder,
1079
+ _text_lora_path(save_path),
1080
+ target_replace_module=target_replace_module_text,
1081
+ )
1082
+ print("Text Encoder saved to ", _text_lora_path(save_path))
1083
+
1084
+ else:
1085
+ assert save_path.endswith(
1086
+ ".safetensors"
1087
+ ), f"Save path : {save_path} should end with .safetensors"
1088
+
1089
+ loras = {}
1090
+ embeds = {}
1091
+
1092
+ if save_lora:
1093
+
1094
+ loras["unet"] = (unet, target_replace_module_unet)
1095
+ loras["text_encoder"] = (text_encoder, target_replace_module_text)
1096
+
1097
+ if save_ti:
1098
+ for tok, tok_id in zip(placeholder_tokens, placeholder_token_ids):
1099
+ learned_embeds = text_encoder.get_input_embeddings().weight[tok_id]
1100
+ print(
1101
+ f"Current Learned Embeddings for {tok}:, id {tok_id} ",
1102
+ learned_embeds[:4],
1103
+ )
1104
+ embeds[tok] = learned_embeds.detach().cpu()
1105
+
1106
+ save_safeloras_with_embeds(loras, embeds, save_path)
README.md CHANGED
@@ -1,3 +1,511 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
- license: mit
 
 
 
 
 
3
  ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div align="center">
2
+
3
+ # TherA: Thermal-Aware Visual-Language Prompting for<br>Controllable RGB-to-Thermal Infrared Translation
4
+
5
+ [**Dong-Guw Lee**](https://scholar.google.com/citations?user=u6VDnlgAAAAJ&hl=ko)<sup>1*</sup>&emsp;
6
+ [**Tai Hyoung Rhee**](https://scholar.google.com/citations?user=PF8EfdYAAAAJ&hl=en&oi=ao)<sup>1*</sup>&emsp;
7
+ [**Hyunsoo Jang**](https://rpm.snu.ac.kr)<sup>1</sup><br>
8
+ [**Young-Sik Shin**](https://scholar.google.com/citations?user=gGfBRawAAAAJ&hl=en&oi=ao)<sup>2</sup>&emsp;
9
+ [**Ukcheol Shin**](https://scholar.google.com/citations?user=ZvxI80EAAAAJ&hl=ko&oi=ao)<sup>3</sup>&emsp;
10
+ [**Ayoung Kim**](https://ayoungk.github.io/)<sup>1&dagger;</sup>
11
+
12
+ <sup>1</sup>Seoul National University&emsp;
13
+ <sup>2</sup>Kyungpook National University&emsp;
14
+ <sup>3</sup>KENTECH
15
+ <sup>*</sup> Equal Contribution&emsp;
16
+ <sup>&dagger;</sup> Corresponding Author
17
+
18
+ **CVPR 2026**
19
+
20
+ [![Project Page](https://img.shields.io/badge/Project_Page-TherA-blue)](https://donkeymouse.github.io/thera_cvpr26/)
21
+ [![arXiv](https://img.shields.io/badge/arXiv-2602.19430-b31b1b.svg)](https://arxiv.org/abs/2602.19430)
22
+ [![GitHub](https://img.shields.io/badge/GitHub-donkeymouse%2FTherA-black)](https://github.com/donkeymouse/TherA)
23
+ [![Weights](https://img.shields.io/badge/HuggingFace-Weights-yellow)](https://huggingface.co/donkeymouse/TherA/tree/main)
24
+ [![Dataset](https://img.shields.io/badge/HuggingFace-R2T2-orange)](https://huggingface.co/datasets/donkeymouse/TherA-R2T2)
25
+ [![Docker](https://img.shields.io/badge/Docker-donkeymouse%2Fthera-2496ED)](https://hub.docker.com/r/donkeymouse/thera)
26
+
27
+ </div>
28
+
29
+ <p align="center">
30
+ <img src="assets/method.png" width="90%" alt="TherA method overview">
31
+ </p>
32
+
33
+
34
  ---
35
+
36
+ ## News
37
+
38
+ - **2026-04-03**: TherA github repo opening
39
+ - **2026-05-22**: TherA inference code and R2T2 dataset release.
40
+
41
  ---
42
+
43
+ ## Overview
44
+
45
+ **TherA** is a controllable RGB-to-thermal infrared translation framework. Given an RGB image, TherA synthesizes a long-wave thermal infrared image using a latent-diffusion translator conditioned on thermal-aware visual-language features.
46
+
47
+ TherA is designed for:
48
+
49
+ - **RGB → TIR translation** for thermal perception research.
50
+ - **Thermal-aware VLM conditioning** using LLaVA hidden-state features.
51
+ - **Scene- and object-level controllability** across weather, time of day, and object state.
52
+ - **Reference-cache inference**, allowing deployment without loading LLaVA at runtime.
53
+
54
+
55
+ <div align="center">
56
+ <a href="https://www.youtube.com/watch?v=X60UxjGKQkg">
57
+ <img src="https://img.youtube.com/vi/X60UxjGKQkg/0.jpg" alt="TherA demo video" width="720">
58
+ </a>
59
+ </div>
60
+
61
+
62
+ ---
63
+
64
+ ## Key Idea
65
+
66
+ TherA does **not** condition directly on raw text during diffusion inference. Instead, it uses a **4096-dimensional LLaVA hidden state**, either:
67
+
68
+ 1. loaded from a precomputed `.pt` reference cache, or
69
+ 2. extracted on the fly using LLaVA.
70
+
71
+
72
+
73
+ For resource limited environments, we recommend **reference-cache mode**. This mode uses precomputed LLaVA features such as `SUNNY.pt`, `CLOUDY.pt`, `RAINY.pt`, or `NIGHT.pt`, and therefore does **not** require loading LLaVA weights at runtime. An alternative would be to compute pre-computed LLaVA feature first followed by inferencing with reference-cache mode (upcoming feature).
74
+
75
+ ---
76
+ ## Repository Layout
77
+
78
+ ```text
79
+ TherA/
80
+ ├── infer_custom.py # Batch RGB → TIR inference on a folder
81
+ ├── infer_example_guided.py # Single-image / example-guided inference
82
+ ├── infer_palette.sh # Run multiple weather/style palettes
83
+ ├── lavi_ip2p/ # UNet 8-channel + adapter wrapper
84
+ ├── LaVi-Bridge/modules/ # TextAdapter architecture
85
+ ├── llava/ # LLaVA code, only needed for on-the-fly mode
86
+ ├── thera_paths.py # Default local weight paths
87
+ ├── thera_llava.py # Lazy LLaVA loader
88
+ └── weights/ # Download weights here; not tracked by git
89
+ ├── model.pt # TherA Model
90
+ ├── merged_models/ # Initialization model
91
+ │ ├── unet/
92
+ │ └── adapter/
93
+ ├── stable-diffusion/
94
+ │ ├── vae/
95
+ │ └── scheduler/
96
+ ├── reference_caches/
97
+ │ ├── SUNNY.pt
98
+ │ ├── CLOUDY.pt
99
+ │ ├── RAINY.pt
100
+ │ └── NIGHT.pt
101
+ ├── reference_caches/
102
+ │ │ ├── SUNNY.pt
103
+ │ │ ├── CLOUDY.pt
104
+ │ │ ├── RAINY.pt
105
+ │ │ └── NIGHT.pt
106
+ └── TherA-VLM/ # Optional; only for on-the-fly mode
107
+ ├── adaptor_config.json/
108
+ └── adapter_model.safetensors
109
+ └── config.json
110
+ └── non_lora_trainables.bin
111
+ └── trainer_state.json
112
+ ```
113
+
114
+ ---
115
+
116
+ ## Installation
117
+
118
+ ### Option 1: Local Python Environment
119
+
120
+ ```bash
121
+ git clone https://github.com/donkeymouse/TherA.git
122
+ cd TherA
123
+
124
+ python -m venv .venv
125
+ source .venv/bin/activate
126
+
127
+ pip install --upgrade pip
128
+ pip install -r requirements.txt
129
+ ```
130
+
131
+ **Recommended environment**
132
+
133
+ - Python 3.10+
134
+ - CUDA-capable GPU
135
+ - 16 GB+ VRAM recommended for comfortable inference
136
+
137
+ ---
138
+
139
+ ### Option 2: Docker
140
+
141
+ A prebuilt Docker image is available at:
142
+
143
+ ```bash
144
+ docker pull donkeymouse/thera:latest
145
+ ```
146
+
147
+ Example interactive run:
148
+
149
+ ```bash
150
+ docker run --gpus all --rm -it \
151
+ -v "$(pwd)":/workspace/TherA \
152
+ -w /workspace/TherA \
153
+ donkeymouse/thera:latest \
154
+ bash
155
+ ```
156
+
157
+ Then run inference commands from inside the container.
158
+
159
+ ---
160
+
161
+ ## Download Weights
162
+
163
+ TherA weights are hosted on Hugging Face:
164
+
165
+ ```bash
166
+ pip install -U huggingface_hub
167
+
168
+ huggingface-cli download donkeymouse/TherA \
169
+ --local-dir weights
170
+ ```
171
+
172
+ After downloading, your `weights/` directory should contain:
173
+
174
+ | Path | Description | Required? |
175
+ |---|---|---|
176
+ | `weights/model.pt` | TherA trained UNet and adapter checkpoint | Yes |
177
+ | `weights/merged_models/unet/` | UNet architecture/config files | Yes |
178
+ | `weights/merged_models/adapter/` | TextAdapter architecture/config files | Yes |
179
+ | `weights/stable-diffusion/vae/` | Stable Diffusion VAE | Yes |
180
+ | `weights/stable-diffusion/scheduler/` | DDIM scheduler config | Yes |
181
+ | `weights/reference_caches/*.pt` | Precomputed LLaVA hidden states for inference palettes | Recommended |
182
+ | `weights/TherA-VLM/` | LLaVA weights for on-the-fly feature extraction | Optional |
183
+
184
+ ---
185
+
186
+ ## Optional: Download LLaVA Weights
187
+
188
+ LLaVA is only required for **on-the-fly feature extraction** or **two-image guided mode**. It is not required for reference-cache inference.
189
+
190
+ ```bash
191
+ huggingface-cli download llava-hf/llava-1.5-7b-hf \
192
+ --local-dir weights/llava-1.5-7b-hf
193
+ ```
194
+
195
+
196
+ ---
197
+
198
+ ## Quick Start
199
+
200
+ ---
201
+
202
+ ## Full RGB-TIR translation using TherA-VLM
203
+
204
+ Use this mode if you want to extract hidden states from TherA directly at runtime from an RGB image and prompt.
205
+
206
+ ```bash
207
+ python infer_custom.py \
208
+ --rgb-dir examples/rgb \
209
+ --output-dir preds \
210
+ --llava-base-path weights/llava-1.5-7b-hf \
211
+ --llava-lora-path weights/TherA-VLM \
212
+ --llava-prompt "How would this RGB scene appear in long-wave thermal infrared spectrum."
213
+ ```
214
+
215
+ This mode is more expensive because it loads LLaVA during inference.
216
+
217
+
218
+
219
+ ### Reference-Guided Image Translation Mode
220
+
221
+ This mode extracts LLaVA features from a reference RGB image and applies them to a target RGB image.
222
+
223
+ ```bash
224
+ python infer_example_guided.py \
225
+ --mode two-image \
226
+ --reference-image examples/ref/rgb.jpg \
227
+ --input-image examples/rgb/scene.jpg \
228
+ --output preds/scene_tir.png \
229
+ --llava-base-path weights/llava-1.5-7b-hf \
230
+ --llava-lora-path weights/TherA-VLM
231
+ ```
232
+
233
+ ---
234
+
235
+ ### Recursive Folder Inference
236
+
237
+ ```bash
238
+ python infer_custom.py \
239
+ --rgb-dir /path/to/dataset/RGB \
240
+ --output-dir preds \
241
+ --reference-cache weights/reference_caches/SUNNY.pt \
242
+ --recursive
243
+ ```
244
+
245
+ When `--recursive` is used, the output folder preserves the input directory structure.
246
+
247
+ ---
248
+ ---
249
+
250
+ ## Reference-cache Mode
251
+ Reference-cache mode is the recommended if you are lacking GPU memory. It does not load LLaVA at runtime.
252
+
253
+ ```bash
254
+ python infer_custom.py \
255
+ --rgb-dir examples/rgb \
256
+ --output-dir preds/sunny \
257
+ --reference-cache weights/reference_caches/SUNNY.pt
258
+ ```
259
+
260
+ The script reads all images in `examples/rgb` and writes translated TIR images to `preds/sunny`.
261
+
262
+ A lighter version of the text-guided image translation module.
263
+
264
+ Example palette caches:
265
+
266
+ ```text
267
+ weights/reference_caches/SUNNY.pt
268
+ weights/reference_caches/CLOUDY.pt
269
+ weights/reference_caches/RAINY.pt
270
+ weights/reference_caches/NIGHT.pt
271
+ ```
272
+
273
+ You can use different pallete cache to achieve different translation effects.
274
+
275
+ ---
276
+
277
+ ## Inference Modes
278
+
279
+ | Mode | Main flag / script | LLaVA weights needed? | Recommended use |
280
+ |---|---|---:|---|
281
+ | Reference cache | `--reference-cache path.pt` | No | Default deployment and fast inference |
282
+ | Per-image cache directory | `--cache-dir dir/` | No | Precomputed feature per image |
283
+ | Full RGB-TIR translation| `--llava-base-path ...` | Yes | Runtime prompt/image conditioning |
284
+ | Reference image-guided translation| `infer_example_guided.py --mode two-image` | Yes | Apply reference-image conditioning |
285
+
286
+ ---
287
+
288
+ ## Reference Cache Format
289
+
290
+ Reference caches are precomputed LLaVA hidden states saved as `.pt` files.
291
+
292
+ Supported tensor shapes:
293
+
294
+ ```text
295
+ [1, L, 4096]
296
+ [L, 4096]
297
+ ```
298
+
299
+ A single reference cache can be applied to all input images as a global thermal/weather/style condition.
300
+
301
+ ---
302
+
303
+ ## Important Arguments
304
+
305
+ | Argument | Default | Description |
306
+ |---|---:|---|
307
+ | `--checkpoint` | `weights/checkpoint` | Directory containing `model.pt` |
308
+ | `--merged-model-path` | `weights/merged_models` | Directory containing UNet and adapter configs |
309
+ | `--pretrained-sd` | `weights/stable-diffusion` | Directory containing VAE and scheduler |
310
+ | `--rgb-dir` | Required | Folder of RGB images for batch inference |
311
+ | `--output-dir` | `custom_predictions` | Output folder for predictions |
312
+ | `--reference-cache` | `None` | Single `.pt` cache used for all images |
313
+ | `--cache-dir` | `None` | Folder of per-image `.pt` caches matched by filename stem |
314
+ | `--llava-base-path` | `None` | Base LLaVA model path for on-the-fly mode |
315
+ | `--llava-lora-path` | `None` | Optional LLaVA LoRA path |
316
+ | `--llava-prompt` | thermal prompt | Prompt used for default inference/text-guided translation|
317
+ | `--num-steps` | `100` | DDIM sampling steps |
318
+ | `--cfg-text` | `3.5` | Text/VLM guidance strength |
319
+ | `--cfg-image` | `1.5` | Image guidance strength |
320
+ | `--target-size` | Auto | Resize image to this square size; otherwise dimensions are rounded to multiples of 32 |
321
+ | `--recursive` | Off | Recursively process subdirectories |
322
+ | `--device` | `cuda` | Device for inference |
323
+
324
+ ---
325
+
326
+ ## Architecture
327
+
328
+ ```text
329
+ RGB image
330
+ │
331
+ ▼
332
+ VAE encoder ──► RGB latents ───────────────────┐
333
+ │
334
+ ├──► 8-channel diffusion UNet ──► VAE decoder ──► TIR image
335
+ │
336
+ LLaVA hidden state, 4096-d ──► TextAdapter ─────┘
337
+ 768-d cross-attention tokens
338
+ ```
339
+
340
+ TherA uses dual classifier-free guidance at inference by combining:
341
+
342
+ - full conditioning,
343
+ - image-only conditioning,
344
+ - text/VLM-only conditioning.
345
+
346
+ ---
347
+
348
+ ## R2T2 Dataset
349
+
350
+ TherA is trained with **R2T2**, a large-scale RGB–TIR–Text dataset.
351
+
352
+ R2T2 includes:
353
+
354
+ - **112,970 aligned triplets**: RGB image, TIR image, and canonical thermal schema.
355
+ - Scene diversity across driving, CCTV, aerial, and ego-view settings.
356
+ - Temporal diversity across day/night and diurnal transitions.
357
+ - Environmental diversity across weather, season, and illumination.
358
+ - Material- and object-level annotations with structured canonicalization.
359
+ - Data compiled from multiple aligned RGB–TIR datasets with additional pseudo-aligned pairs.
360
+
361
+ Dataset page:
362
+
363
+ ```text
364
+ https://huggingface.co/datasets/donkeymouse/TherA-R2T2
365
+ ```
366
+
367
+ Example structure:
368
+
369
+ ```text
370
+ R2T2/
371
+ ├── ${DATASET_NAME}/
372
+ │ └── ${SEQUENCE_NAME}/
373
+ │ ├── RGB/
374
+ │ │ ├── 1.jpg
375
+ │ │ └── ...
376
+ │ └── TIR/
377
+ │ ├── 1.jpg
378
+ │ └── ...
379
+ ├── ViVID/
380
+ │ ├── img_campus_day1/
381
+ │ │ ├── RGB/
382
+ │ │ │ ├── 000001.png
383
+ │ │ │ └── ...
384
+ │ │ └── TIR/
385
+ │ │ ├── 000001.png
386
+ │ │ └── ...
387
+ │ └── ...
388
+ └── ...
389
+ ```
390
+
391
+ ---
392
+
393
+ ## Troubleshooting
394
+
395
+ ### `Checkpoint not found: weights/model.pt`
396
+
397
+ Download the TherA weights and make sure `model.pt` is located at:
398
+
399
+ ```text
400
+ weights/model.pt
401
+ ```
402
+
403
+ ---
404
+
405
+ ### `OSError: ... stable-diffusion/vae`
406
+
407
+ Make sure the Stable Diffusion VAE and scheduler folders are present:
408
+
409
+ ```text
410
+ weights/stable-diffusion/vae/
411
+ weights/stable-diffusion/scheduler/
412
+ ```
413
+
414
+ ---
415
+
416
+ ### Outputs look identical across palettes
417
+
418
+ Try increasing text/VLM guidance:
419
+
420
+ ```bash
421
+ --cfg-text 7.5
422
+ ```
423
+
424
+ Also verify that your reference cache files are distinct:
425
+
426
+ ```text
427
+ SUNNY.pt
428
+ CLOUDY.pt
429
+ RAINY.pt
430
+ NIGHT.pt
431
+ ```
432
+
433
+ ---
434
+
435
+ ### CUDA out of memory
436
+
437
+ Try reducing the image size:
438
+
439
+ ```bash
440
+ --target-size 512
441
+ ```
442
+
443
+ You can also run one image at a time with:
444
+
445
+ ```bash
446
+ python infer_example_guided.py
447
+ ```
448
+
449
+ ---
450
+
451
+ ### LLaVA import or loading errors
452
+
453
+ Use reference-cache mode if you do not need runtime LLaVA extraction:
454
+
455
+ ```bash
456
+ --reference-cache weights/reference_caches/SUNNY.pt
457
+ ```
458
+
459
+ For on-the-fly mode, make sure the LLaVA base model and TherA weights are correctly loaded`.
460
+
461
+ ---
462
+
463
+ ## TODOs
464
+ - [x] inference code and R2T2 dataset
465
+ - [] Upload cache extraction code
466
+ - [] Improve text-guidance
467
+
468
+
469
+ ## Citation
470
+
471
+ If you find TherA useful for your research, please cite:
472
+
473
+ ```bibtex
474
+ @inproceedings{lee2026thera,
475
+ title = {TherA: Thermal-Aware Visual-Language Prompting for Controllable RGB-to-Thermal Infrared Translation},
476
+ author = {Lee, Dong-Guw and Rhee, Tai Hyoung and Jang, Hyunsoo and Shin, Young-Sik and Shin, Ukcheol and Kim, Ayoung},
477
+ booktitle = {Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition},
478
+ year = {2026}
479
+ }
480
+ ```
481
+
482
+ You may also cite the arXiv version:
483
+
484
+ ```bibtex
485
+ @article{lee2026thera_arxiv,
486
+ title = {TherA: Thermal-Aware Visual-Language Prompting for Controllable RGB-to-Thermal Infrared Translation},
487
+ author = {Lee, Dong-Guw and Rhee, Tai Hyoung and Jang, Hyunsoo and Shin, Young-Sik and Shin, Ukcheol and Kim, Ayoung},
488
+ journal = {arXiv preprint arXiv:2602.19430},
489
+ year = {2026}
490
+ }
491
+ ```
492
+
493
+ ---
494
+
495
+ ## Acknowledgements
496
+
497
+ TherA builds on open-source components from the vision-language and diffusion communities, including LLaVA, Stable Diffusion, Diffusers, and LaVi-Bridge-style adapter architectures.
498
+
499
+ ---
500
+
501
+ ## License
502
+
503
+ See `LICENSE` for details.
504
+
505
+ Third-party models, datasets, and libraries retain their own licenses. Please review the licenses for LLaVA, Stable Diffusion, Hugging Face model files, and any external datasets before use.
506
+
507
+ ## Contact
508
+ If you have any questions, contact here please
509
+ ```
510
+ donkeymouse@snu.ac.kr
511
+ ```
__pycache__/thera_llava.cpython-310.pyc ADDED
Binary file (865 Bytes). View file
 
__pycache__/thera_paths.cpython-310.pyc ADDED
Binary file (967 Bytes). View file
 
infer_custom.py ADDED
@@ -0,0 +1,526 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Batch RGB → TIR inference for TherA.
4
+
5
+ Recommended (no LLaVA weights needed): use a reference .pt cache
6
+ python infer_custom.py --rgb-dir ./examples/rgb --output-dir ./preds \\
7
+ --reference-cache weights/reference_caches/SUNNY.pt
8
+
9
+ On-the-fly LLaVA (optional): requires separate LLaVA checkpoints
10
+ python infer_custom.py --rgb-dir ./examples/rgb --output-dir ./preds \\
11
+ --llava-base-path weights/llava/llava-1.5-7b-hf \\
12
+ --llava-lora-path weights/llava/llava-miragehd-lora
13
+
14
+ Single-image example-guided mode: see infer_example_guided.py
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ import argparse
20
+ from pathlib import Path
21
+ from typing import List
22
+
23
+ import torch
24
+ from PIL import Image
25
+ from tqdm import tqdm
26
+ from contextlib import nullcontext
27
+
28
+ from thera_paths import (
29
+ DEFAULT_CHECKPOINT,
30
+ DEFAULT_MERGED_MODEL,
31
+ DEFAULT_PRETRAINED_SD,
32
+ setup_project_path,
33
+ )
34
+ from thera_llava import create_frozen_llava_extractor
35
+
36
+ setup_project_path()
37
+
38
+ from diffusers import AutoencoderKL, DDIMScheduler, UNet2DConditionModel
39
+ from torchvision import transforms
40
+ from torchvision.utils import save_image
41
+
42
+ from lavi_ip2p.llava_adapter import create_llava_adapter
43
+ from lavi_ip2p.unet_8ch import convert_unet_to_8ch
44
+
45
+ IMAGE_EXTENSIONS = {".jpg", ".jpeg", ".png", ".bmp", ".tif", ".tiff"}
46
+
47
+
48
+ def parse_args():
49
+ parser = argparse.ArgumentParser(description="Generate TIR predictions from custom RGB images")
50
+
51
+ # Model paths (defaults under weights/ — see README.md)
52
+ parser.add_argument(
53
+ "--checkpoint",
54
+ type=str,
55
+ default=str(DEFAULT_CHECKPOINT),
56
+ help="Directory containing model.pt (TherA UNet + adapter weights)",
57
+ )
58
+ parser.add_argument(
59
+ "--merged-model-path",
60
+ type=str,
61
+ default=str(DEFAULT_MERGED_MODEL),
62
+ help="Directory with unet/ and adapter/ architecture configs",
63
+ )
64
+ parser.add_argument(
65
+ "--pretrained-sd",
66
+ type=str,
67
+ default=str(DEFAULT_PRETRAINED_SD),
68
+ help="Stable Diffusion folder with vae/ and scheduler/ subfolders",
69
+ )
70
+
71
+ # LLaVA paths (only for on-the-fly feature extraction)
72
+ parser.add_argument(
73
+ "--llava-base-path",
74
+ type=str,
75
+ default=None,
76
+ help="Base LLaVA model. Required unless --reference-cache or --cache-dir is set.",
77
+ )
78
+ parser.add_argument(
79
+ "--llava-lora-path",
80
+ type=str,
81
+ default=None,
82
+ help="Optional LLaVA LoRA weights (on-the-fly mode only)",
83
+ )
84
+ parser.add_argument("--llava-prompt", type=str,
85
+ default="How would this RGB scene appear in long-wave thermal infrared spectrum",
86
+ help="Prompt for LLaVA feature extraction")
87
+
88
+ # Reference cache mode (alternative to on-the-fly extraction)
89
+ parser.add_argument("--reference-cache", type=str, default=None,
90
+ help="Path to a reference .pt cache file. If provided, uses this fixed feature for all images instead of extracting per-image.")
91
+ parser.add_argument("--cache-dir", type=str, default=None,
92
+ help="Directory with per-image .pt cache files (matched by filename stem). Alternative to --reference-cache.")
93
+
94
+ # Data
95
+ parser.add_argument("--rgb-dir", type=str, required=True,
96
+ help="Directory containing RGB images")
97
+ parser.add_argument("--output-dir", type=str, default="custom_predictions",
98
+ help="Output directory for predictions")
99
+ parser.add_argument("--recursive", action="store_true",
100
+ help="Search for images recursively in subdirectories")
101
+
102
+ # Sampling
103
+ parser.add_argument("--num-steps", type=int, default=100, help="DDIM sampling steps")
104
+ parser.add_argument("--cfg-text", type=float, default=3.5, help="CFG scale for text")
105
+ parser.add_argument("--cfg-image", type=float, default=1.5, help="CFG scale for image")
106
+ parser.add_argument("--seed", type=int, default=42, help="Random seed")
107
+
108
+ # Processing
109
+ parser.add_argument("--target-size", type=int, default=None,
110
+ help="Resize images to this size (default: keep original, round to 32)")
111
+ parser.add_argument("--batch-size", type=int, default=1,
112
+ help="Batch size (>1 for faster processing if you have enough VRAM)")
113
+
114
+ # Device
115
+ parser.add_argument("--device", type=str, default="cuda", help="Device (cuda/cpu)")
116
+
117
+ return parser.parse_args()
118
+
119
+
120
+ def load_models(args):
121
+ """Load VAE, UNet, Adapter, Scheduler, and optionally LLaVA Extractor"""
122
+ print("\n" + "="*80)
123
+ print(f"Loading models on device {args.device}...")
124
+ print("="*80)
125
+
126
+ device = torch.device(args.device)
127
+
128
+ # Determine if we need LLaVA extractor
129
+ use_cache = args.reference_cache is not None or args.cache_dir is not None
130
+
131
+ # 1. VAE
132
+ print("\n[1/5] Loading VAE...")
133
+ vae = AutoencoderKL.from_pretrained(args.pretrained_sd, subfolder="vae")
134
+ vae.requires_grad_(False)
135
+ vae.eval()
136
+ vae.to(device)
137
+ print("✓ VAE loaded")
138
+
139
+ # 2. Scheduler
140
+ print("\n[2/5] Loading scheduler...")
141
+ scheduler = DDIMScheduler.from_pretrained(args.pretrained_sd, subfolder="scheduler")
142
+ print("✓ Scheduler loaded")
143
+
144
+ # 3. UNet (load from checkpoint)
145
+ checkpoint_dir = Path(args.checkpoint)
146
+ print(f"\n[3/5] Loading UNet from checkpoint: {checkpoint_dir}")
147
+ checkpoint_path = checkpoint_dir / "model.pt"
148
+ if not checkpoint_path.exists():
149
+ raise FileNotFoundError(f"Checkpoint not found: {checkpoint_path}")
150
+
151
+ checkpoint = torch.load(checkpoint_path, map_location="cpu")
152
+
153
+ # Load base UNet architecture from merged model
154
+ merged_unet_path = Path(args.merged_model_path) / "unet"
155
+ unet = UNet2DConditionModel.from_pretrained(str(merged_unet_path))
156
+
157
+ # Convert to 8-channel for image-to-image task
158
+ print(" Converting UNet to 8-channel input...")
159
+ unet = convert_unet_to_8ch(unet)
160
+
161
+ # Load trained weights
162
+ unet.load_state_dict(checkpoint['unet'])
163
+ unet.requires_grad_(False)
164
+ unet.eval()
165
+ unet.to(device)
166
+
167
+ global_step = checkpoint.get('global_step', 'unknown')
168
+ epoch = checkpoint.get('epoch', 'unknown')
169
+ print(f"✓ UNet loaded (step={global_step}, epoch={epoch})")
170
+
171
+ # 4. Adapter
172
+ print("\n[4/5] Loading LLaVA Adapter...")
173
+ merged_adapter_path = Path(args.merged_model_path) / "adapter"
174
+ adapter = create_llava_adapter(
175
+ adapter_path=str(merged_adapter_path),
176
+ use_rms_norm=False,
177
+ learnable_scale=False,
178
+ init_scale=1.0,
179
+ freeze_adapter=True,
180
+ )
181
+
182
+ # Load trained adapter weights if available in checkpoint
183
+ if 'llava_adapter' in checkpoint:
184
+ adapter.load_state_dict(checkpoint['llava_adapter'])
185
+ print("✓ Adapter loaded from checkpoint")
186
+ else:
187
+ print("✓ Adapter loaded (using base weights)")
188
+
189
+ adapter.requires_grad_(False)
190
+ adapter.eval()
191
+ adapter.to(device)
192
+
193
+ # 5. LLaVA Extractor (optional - only if not using cache)
194
+ llava_extractor = None
195
+ if use_cache:
196
+ print("\n[5/5] Skipping LLaVA extractor (using cached features)")
197
+ else:
198
+ print("\n[5/5] Loading LLaVA Feature Extractor...")
199
+ if not args.llava_base_path:
200
+ raise ValueError("--llava-base-path is required when not using --reference-cache or --cache-dir")
201
+ llava_extractor = create_frozen_llava_extractor(
202
+ llava_base_path=args.llava_base_path,
203
+ llava_lora_path=args.llava_lora_path,
204
+ device=args.device,
205
+ load_8bit=False,
206
+ load_4bit=False,
207
+ merge_lora=True,
208
+ )
209
+ print("✓ LLaVA extractor loaded")
210
+
211
+ return vae, unet, adapter, scheduler, llava_extractor, device
212
+
213
+
214
+ def find_images(rgb_dir: Path, recursive: bool = False) -> List[Path]:
215
+ """Find all image files in directory"""
216
+ if recursive:
217
+ images = []
218
+ for ext in IMAGE_EXTENSIONS:
219
+ images.extend(rgb_dir.rglob(f"*{ext}"))
220
+ images.extend(rgb_dir.rglob(f"*{ext.upper()}"))
221
+ return sorted(set(images))
222
+ else:
223
+ images = []
224
+ for ext in IMAGE_EXTENSIONS:
225
+ images.extend(rgb_dir.glob(f"*{ext}"))
226
+ images.extend(rgb_dir.glob(f"*{ext.upper()}"))
227
+ return sorted(set(images))
228
+
229
+
230
+ def load_and_prepare_image(image_path: Path, target_size: int = None, device: torch.device = None):
231
+ """Load RGB image and prepare for processing"""
232
+ rgb_img = Image.open(image_path).convert('RGB')
233
+ rgb_w, rgb_h = rgb_img.size
234
+
235
+ # Determine target dimensions
236
+ if target_size is not None:
237
+ target_w = target_h = target_size
238
+ else:
239
+ # Ensure dimensions divisible by 32 (required for VAE)
240
+ target_w = ((rgb_w + 31) // 32) * 32
241
+ target_h = ((rgb_h + 31) // 32) * 32
242
+
243
+ # Resize if needed
244
+ if target_w != rgb_w or target_h != rgb_h:
245
+ rgb_img = rgb_img.resize((target_w, target_h), Image.Resampling.LANCZOS)
246
+
247
+ # Convert to tensor for diffusion model
248
+ transform = transforms.Compose([
249
+ transforms.ToTensor(),
250
+ transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5]), # [-1, 1]
251
+ ])
252
+
253
+ rgb_tensor = transform(rgb_img).unsqueeze(0)
254
+ if device is not None:
255
+ rgb_tensor = rgb_tensor.to(device)
256
+
257
+ return rgb_tensor, rgb_img # Return both tensor and PIL image
258
+
259
+
260
+ def load_llava_cache(cache_path: Path, device: torch.device):
261
+ """Load a cached LLaVA hidden state from .pt file"""
262
+ try:
263
+ llava_hidden = torch.load(cache_path, map_location="cpu", weights_only=True)
264
+ except TypeError:
265
+ # For older torch versions without weights_only
266
+ llava_hidden = torch.load(cache_path, map_location="cpu")
267
+
268
+ if not isinstance(llava_hidden, torch.Tensor):
269
+ llava_hidden = torch.tensor(llava_hidden)
270
+
271
+ # Add batch dimension if needed
272
+ if llava_hidden.ndim == 2:
273
+ llava_hidden = llava_hidden.unsqueeze(0)
274
+
275
+ return llava_hidden.to(device)
276
+
277
+
278
+ def find_cache_for_image(image_path: Path, cache_dir: Path) -> Path:
279
+ """Find matching cache file for an image based on filename stem"""
280
+ stem = image_path.stem
281
+ for ext in ['.pt', '.pth']:
282
+ cache_path = cache_dir / f"{stem}{ext}"
283
+ if cache_path.exists():
284
+ return cache_path
285
+ raise FileNotFoundError(f"No cache file found for {image_path.name} in {cache_dir}")
286
+
287
+
288
+ def create_null_text(llava_tokens):
289
+ """Create null tokens for unconditional generation"""
290
+ return torch.zeros_like(llava_tokens)
291
+
292
+
293
+ @torch.no_grad()
294
+ def translate_image(
295
+ vae,
296
+ unet,
297
+ adapter,
298
+ scheduler,
299
+ rgb_tensor,
300
+ llava_hidden,
301
+ num_steps=100,
302
+ cfg_text=3.5,
303
+ cfg_image=1.5,
304
+ device=torch.device("cuda"),
305
+ ):
306
+ """Translate RGB to TIR using LLaVA features + conditional generation with CFG"""
307
+
308
+ # Encode RGB
309
+ rgb_latents = vae.encode(rgb_tensor).latent_dist.mode() * vae.config.scaling_factor
310
+
311
+ # Process LLaVA features through adapter
312
+ use_autocast = device.type == "cuda"
313
+ llava_input = llava_hidden.to(device)
314
+ if use_autocast:
315
+ llava_input = llava_input.to(dtype=torch.bfloat16)
316
+
317
+ autocast_ctx = (
318
+ torch.autocast(device_type=device.type, dtype=torch.bfloat16)
319
+ if use_autocast else nullcontext()
320
+ )
321
+ with autocast_ctx:
322
+ llava_tokens = adapter(llava_input)
323
+ llava_tokens = llava_tokens.to(device=device, dtype=next(unet.parameters()).dtype)
324
+
325
+ # Create null tokens for CFG
326
+ null_tokens = create_null_text(llava_tokens)
327
+
328
+ # Initialize random noise
329
+ latent_shape = (1, 4, rgb_latents.shape[2], rgb_latents.shape[3])
330
+ latents = torch.randn(latent_shape, device=device, dtype=rgb_latents.dtype)
331
+
332
+ # Setup scheduler
333
+ scheduler.set_timesteps(num_steps, device=device)
334
+
335
+ zeros_rgb = torch.zeros_like(rgb_latents)
336
+
337
+ for t in scheduler.timesteps:
338
+ t_batch = torch.full((1,), int(t), device=device, dtype=torch.long)
339
+
340
+ # 3 forward passes for dual-CFG
341
+ x8_full = torch.cat([latents, rgb_latents], dim=1)
342
+ x8_no_img = torch.cat([latents, zeros_rgb], dim=1)
343
+
344
+ # Full conditioning
345
+ eps_full = unet(x8_full, t_batch, encoder_hidden_states=llava_tokens).sample
346
+
347
+ # No text (image only)
348
+ eps_no_text = unet(x8_full, t_batch, encoder_hidden_states=null_tokens).sample
349
+
350
+ # No image (text only)
351
+ eps_no_img = unet(x8_no_img, t_batch, encoder_hidden_states=llava_tokens).sample
352
+
353
+ # Combine with dual-CFG
354
+ eps = eps_full + cfg_text * (eps_full - eps_no_text) + cfg_image * (eps_full - eps_no_img)
355
+ eps = torch.clamp(eps, -5.0, 5.0) # Safety guard
356
+
357
+ latents = scheduler.step(eps, t, latents, eta=0.0).prev_sample
358
+
359
+ # Decode
360
+ pred_tir = vae.decode(latents / vae.config.scaling_factor).sample
361
+ pred_tir = (pred_tir / 2 + 0.5).clamp(0, 1)
362
+
363
+ return pred_tir
364
+
365
+
366
+ def main():
367
+ args = parse_args()
368
+
369
+ # Set seed
370
+ torch.manual_seed(args.seed)
371
+ if torch.cuda.is_available():
372
+ torch.cuda.manual_seed_all(args.seed)
373
+
374
+ # Determine processing mode
375
+ use_reference = args.reference_cache is not None
376
+ use_cache_dir = args.cache_dir is not None
377
+
378
+ if use_reference and use_cache_dir:
379
+ raise ValueError("Cannot use both --reference-cache and --cache-dir. Choose one.")
380
+
381
+ print("\n" + "="*80)
382
+ if use_reference:
383
+ print("Custom Dataset Inference (Reference Cache Mode)")
384
+ elif use_cache_dir:
385
+ print("Custom Dataset Inference (Per-Image Cache Mode)")
386
+ else:
387
+ print("Custom Dataset Inference (On-the-fly LLaVA Features)")
388
+ print("="*80)
389
+ print(f"RGB directory: {args.rgb_dir}")
390
+ print(f"Checkpoint: {args.checkpoint}")
391
+
392
+ if use_reference:
393
+ print(f"Reference cache: {args.reference_cache}")
394
+ elif use_cache_dir:
395
+ print(f"Cache directory: {args.cache_dir}")
396
+ else:
397
+ print(f"LLaVA base: {args.llava_base_path}")
398
+ if args.llava_lora_path:
399
+ print(f"LLaVA LoRA: {args.llava_lora_path}")
400
+ print(f"Prompt: {args.llava_prompt}")
401
+
402
+ print(f"Output directory: {args.output_dir}")
403
+ print(f"DDIM steps: {args.num_steps}")
404
+ print(f"CFG scales: text={args.cfg_text}, image={args.cfg_image}")
405
+ print("="*80)
406
+
407
+ # Create output directory
408
+ output_dir = Path(args.output_dir)
409
+ output_dir.mkdir(parents=True, exist_ok=True)
410
+
411
+ # Load models
412
+ vae, unet, adapter, scheduler, llava_extractor, device = load_models(args)
413
+
414
+ # Load reference cache if provided
415
+ reference_hidden = None
416
+ if use_reference:
417
+ print(f"\nLoading reference cache from: {args.reference_cache}")
418
+ reference_hidden = load_llava_cache(Path(args.reference_cache), device)
419
+ print(f"✓ Reference cache loaded: {reference_hidden.shape}")
420
+
421
+ # Validate cache directory if provided
422
+ cache_dir = None
423
+ if use_cache_dir:
424
+ cache_dir = Path(args.cache_dir)
425
+ if not cache_dir.exists():
426
+ raise FileNotFoundError(f"Cache directory not found: {cache_dir}")
427
+ print(f"\nUsing cache directory: {cache_dir}")
428
+
429
+ # Find all RGB images
430
+ rgb_dir = Path(args.rgb_dir)
431
+ if not rgb_dir.exists():
432
+ raise FileNotFoundError(f"RGB directory not found: {rgb_dir}")
433
+
434
+ image_files = find_images(rgb_dir, recursive=args.recursive)
435
+ print(f"\nFound {len(image_files)} images")
436
+
437
+ if len(image_files) == 0:
438
+ print("No images found. Exiting.")
439
+ return
440
+
441
+ # Process each image
442
+ print("\n" + "="*80)
443
+ print("Generating predictions...")
444
+ print("="*80)
445
+
446
+ successful = 0
447
+ failed = 0
448
+ skipped = 0
449
+
450
+ for img_path in tqdm(image_files, desc="Processing images"):
451
+ try:
452
+ # Load and prepare RGB image
453
+ rgb_tensor, rgb_pil = load_and_prepare_image(
454
+ img_path,
455
+ target_size=args.target_size,
456
+ device=device
457
+ )
458
+
459
+ # Get LLaVA hidden states based on mode
460
+ if use_reference:
461
+ # Use the same reference cache for all images
462
+ llava_hidden = reference_hidden
463
+ elif use_cache_dir:
464
+ # Find matching cache file for this image
465
+ try:
466
+ cache_path = find_cache_for_image(img_path, cache_dir)
467
+ llava_hidden = load_llava_cache(cache_path, device)
468
+ except FileNotFoundError as e:
469
+ print(f"\nWarning: {e}")
470
+ skipped += 1
471
+ continue
472
+ else:
473
+ # Extract features on-the-fly using LLaVA
474
+ llava_hidden = llava_extractor.extract_hidden_states([rgb_pil], [args.llava_prompt])
475
+
476
+ # Translate RGB to TIR
477
+ pred_tir = translate_image(
478
+ vae,
479
+ unet,
480
+ adapter,
481
+ scheduler,
482
+ rgb_tensor,
483
+ llava_hidden,
484
+ num_steps=args.num_steps,
485
+ cfg_text=args.cfg_text,
486
+ cfg_image=args.cfg_image,
487
+ device=device,
488
+ )
489
+
490
+ # Save prediction
491
+ # Preserve relative path structure if recursive
492
+ if args.recursive:
493
+ rel_path = img_path.relative_to(rgb_dir)
494
+ save_path = output_dir / rel_path
495
+ else:
496
+ save_path = output_dir / img_path.name
497
+
498
+ save_path.parent.mkdir(parents=True, exist_ok=True)
499
+ save_image(pred_tir.cpu(), str(save_path))
500
+
501
+ successful += 1
502
+
503
+ except Exception as e:
504
+ print(f"\nError processing {img_path}: {e}")
505
+ import traceback
506
+ traceback.print_exc()
507
+ failed += 1
508
+ continue
509
+
510
+ # Print final results
511
+ print("\n" + "="*80)
512
+ print("INFERENCE COMPLETE")
513
+ print("="*80)
514
+ print(f"Total images: {len(image_files)}")
515
+ print(f"Successful: {successful}")
516
+ if skipped > 0:
517
+ print(f"Skipped (no cache): {skipped}")
518
+ print(f"Failed: {failed}")
519
+ if len(image_files) > 0:
520
+ print(f"Success rate: {successful/len(image_files)*100:.1f}%")
521
+ print(f"Predictions saved to: {args.output_dir}")
522
+ print("="*80)
523
+
524
+
525
+ if __name__ == "__main__":
526
+ main()
infer_example_guided.py ADDED
@@ -0,0 +1,432 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Single-image example-guided RGB → TIR translation.
4
+
5
+ Mode: cached (recommended — no LLaVA weights needed)
6
+ python infer_example_guided.py --mode cached \\
7
+ --reference-cache weights/reference_caches/SUNNY.pt \\
8
+ --input-image examples/rgb/scene.jpg \\
9
+ --output preds/scene_tir.png
10
+
11
+ Mode: two-image (extract features from a reference RGB on-the-fly)
12
+ python infer_example_guided.py --mode two-image \\
13
+ --reference-image examples/ref/rgb.jpg \\
14
+ --input-image examples/rgb/scene.jpg \\
15
+ --output preds/scene_tir.png \\
16
+ --llava-base-path weights/llava/llava-1.5-7b-hf \\
17
+ --llava-lora-path weights/llava/llava-miragehd-lora
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ import argparse
23
+ from pathlib import Path
24
+ import sys
25
+ from contextlib import nullcontext
26
+
27
+ import torch
28
+ from PIL import Image
29
+
30
+ from thera_paths import (
31
+ DEFAULT_CHECKPOINT,
32
+ DEFAULT_MERGED_MODEL,
33
+ DEFAULT_PRETRAINED_SD,
34
+ setup_project_path,
35
+ )
36
+ from thera_llava import create_frozen_llava_extractor
37
+
38
+ setup_project_path()
39
+
40
+ from diffusers import AutoencoderKL, DDIMScheduler, UNet2DConditionModel
41
+ from torchvision import transforms
42
+ from torchvision.utils import save_image
43
+
44
+ from lavi_ip2p.llava_adapter import create_llava_adapter
45
+ from lavi_ip2p.unet_8ch import convert_unet_to_8ch
46
+
47
+
48
+ def parse_args():
49
+ parser = argparse.ArgumentParser(
50
+ description="Example-guided translation with two modes",
51
+ formatter_class=argparse.RawDescriptionHelpFormatter,
52
+ epilog=__doc__
53
+ )
54
+
55
+ # Mode selection
56
+ parser.add_argument("--mode", type=str, required=True, choices=["two-image", "cached"],
57
+ help="Translation mode: 'two-image' (extract from reference image) or 'cached' (use .pt file)")
58
+
59
+ # Input/Output
60
+ parser.add_argument("--input-image", type=str, required=True,
61
+ help="Path to input RGB image (Image B) to be translated")
62
+ parser.add_argument("--output", type=str, required=True,
63
+ help="Path to save output TIR image")
64
+
65
+ # Reference (mode-dependent)
66
+ parser.add_argument("--reference-image", type=str, default=None,
67
+ help="Path to reference RGB image (Image A). Required for 'two-image' mode.")
68
+ parser.add_argument("--reference-cache", type=str, default=None,
69
+ help="Path to reference .pt cache file. Required for 'cached' mode.")
70
+
71
+ # Model paths (defaults under weights/ — see README.md)
72
+ parser.add_argument(
73
+ "--checkpoint",
74
+ type=str,
75
+ default=str(DEFAULT_CHECKPOINT),
76
+ help="Directory containing model.pt",
77
+ )
78
+ parser.add_argument(
79
+ "--merged-model-path",
80
+ type=str,
81
+ default=str(DEFAULT_MERGED_MODEL),
82
+ help="Directory with unet/ and adapter/ architecture configs",
83
+ )
84
+ parser.add_argument(
85
+ "--pretrained-sd",
86
+ type=str,
87
+ default=str(DEFAULT_PRETRAINED_SD),
88
+ help="Stable Diffusion folder with vae/ and scheduler/ subfolders",
89
+ )
90
+
91
+ # LLaVA paths (required for two-image mode)
92
+ parser.add_argument("--llava-base-path", type=str, default=None,
93
+ help="Path to base LLaVA model. Required for 'two-image' mode.")
94
+ parser.add_argument("--llava-lora-path", type=str, default=None,
95
+ help="Optional: Path to LLaVA LoRA weights")
96
+ parser.add_argument("--llava-prompt", type=str,
97
+ default="How would this RGB scene appear in long-wave thermal infrared spectrum",
98
+ help="Prompt for LLaVA feature extraction")
99
+
100
+ # Sampling parameters
101
+ parser.add_argument("--num-steps", type=int, default=100, help="DDIM sampling steps")
102
+ parser.add_argument("--cfg-text", type=float, default=3.5, help="CFG scale for text")
103
+ parser.add_argument("--cfg-image", type=float, default=1.5, help="CFG scale for image")
104
+ parser.add_argument("--seed", type=int, default=42, help="Random seed")
105
+
106
+ # Processing
107
+ parser.add_argument("--target-size", type=int, default=None,
108
+ help="Resize images to this size (default: keep original, round to 32)")
109
+ parser.add_argument("--device", type=str, default="cuda", help="Device (cuda/cpu)")
110
+
111
+ return parser.parse_args()
112
+
113
+
114
+ def validate_args(args):
115
+ """Validate argument combinations based on mode"""
116
+ if args.mode == "two-image":
117
+ if args.reference_image is None:
118
+ print("ERROR: --reference-image required for 'two-image' mode")
119
+ sys.exit(1)
120
+ if args.llava_base_path is None:
121
+ print("ERROR: --llava-base-path required for 'two-image' mode")
122
+ sys.exit(1)
123
+ if not Path(args.reference_image).exists():
124
+ print(f"ERROR: Reference image not found: {args.reference_image}")
125
+ sys.exit(1)
126
+
127
+ elif args.mode == "cached":
128
+ if args.reference_cache is None:
129
+ print("ERROR: --reference-cache required for 'cached' mode")
130
+ sys.exit(1)
131
+ if not Path(args.reference_cache).exists():
132
+ print(f"ERROR: Reference cache not found: {args.reference_cache}")
133
+ sys.exit(1)
134
+
135
+ if not Path(args.input_image).exists():
136
+ print(f"ERROR: Input image not found: {args.input_image}")
137
+ sys.exit(1)
138
+
139
+ if not Path(args.checkpoint, "model.pt").exists():
140
+ print(f"ERROR: Checkpoint not found: {Path(args.checkpoint) / 'model.pt'}")
141
+ sys.exit(1)
142
+
143
+
144
+ def load_models(args, need_llava=False):
145
+ """Load diffusion models and optionally LLaVA extractor"""
146
+ print("\n" + "="*80)
147
+ print(f"Loading models on device {args.device}...")
148
+ print("="*80)
149
+
150
+ device = torch.device(args.device)
151
+ checkpoint_dir = Path(args.checkpoint)
152
+
153
+ # 1. Load VAE
154
+ print("\n[1/5] Loading VAE...")
155
+ vae = AutoencoderKL.from_pretrained(args.pretrained_sd, subfolder="vae")
156
+ vae.requires_grad_(False)
157
+ vae.eval()
158
+ vae.to(device)
159
+ print("✓ VAE loaded")
160
+
161
+ # 2. Load Scheduler
162
+ print("\n[2/5] Loading scheduler...")
163
+ scheduler = DDIMScheduler.from_pretrained(args.pretrained_sd, subfolder="scheduler")
164
+ print("✓ Scheduler loaded")
165
+
166
+ # 3. Load UNet (load from checkpoint)
167
+ print(f"\n[3/5] Loading UNet from checkpoint: {checkpoint_dir}")
168
+ checkpoint_path = checkpoint_dir / "model.pt"
169
+ if not checkpoint_path.exists():
170
+ print(f"ERROR: Checkpoint not found: {checkpoint_path}")
171
+ sys.exit(1)
172
+
173
+ checkpoint = torch.load(checkpoint_path, map_location="cpu")
174
+
175
+ # Load base UNet architecture from merged model
176
+ merged_unet_path = Path(args.merged_model_path) / "unet"
177
+ unet = UNet2DConditionModel.from_pretrained(str(merged_unet_path))
178
+
179
+ # Convert to 8-channel for image-to-image task
180
+ print(" Converting UNet to 8-channel input...")
181
+ unet = convert_unet_to_8ch(unet)
182
+
183
+ # Load trained weights
184
+ unet.load_state_dict(checkpoint['unet'])
185
+ unet.requires_grad_(False)
186
+ unet.eval()
187
+ unet.to(device)
188
+
189
+ global_step = checkpoint.get('global_step', 'unknown')
190
+ epoch = checkpoint.get('epoch', 'unknown')
191
+ print(f"✓ UNet loaded (step={global_step}, epoch={epoch})")
192
+
193
+ # 4. Load Adapter
194
+ print("\n[4/5] Loading LLaVA Adapter...")
195
+ merged_adapter_path = Path(args.merged_model_path) / "adapter"
196
+ adapter = create_llava_adapter(
197
+ adapter_path=str(merged_adapter_path),
198
+ use_rms_norm=False,
199
+ learnable_scale=False,
200
+ init_scale=1.0,
201
+ freeze_adapter=True,
202
+ )
203
+
204
+ # Load trained adapter weights if available in checkpoint
205
+ if 'llava_adapter' in checkpoint:
206
+ adapter.load_state_dict(checkpoint['llava_adapter'])
207
+ print("✓ Adapter loaded from checkpoint")
208
+ else:
209
+ print("✓ Adapter loaded (using base weights)")
210
+
211
+ adapter.requires_grad_(False)
212
+ adapter.eval()
213
+ adapter.to(device)
214
+
215
+ # 5. Optionally load LLaVA
216
+ llava_extractor = None
217
+ if need_llava:
218
+ print("\n[5/5] Loading LLaVA Feature Extractor...")
219
+ if not args.llava_base_path:
220
+ print("ERROR: --llava-base-path is required for two-image mode")
221
+ sys.exit(1)
222
+ llava_extractor = create_frozen_llava_extractor(
223
+ llava_base_path=args.llava_base_path,
224
+ llava_lora_path=args.llava_lora_path,
225
+ device=args.device,
226
+ load_8bit=False,
227
+ load_4bit=False,
228
+ merge_lora=True,
229
+ )
230
+ print("✓ LLaVA extractor loaded")
231
+ else:
232
+ print("\n[5/5] Skipping LLaVA extractor (using cached features)")
233
+
234
+ return vae, unet, adapter, scheduler, llava_extractor, device
235
+
236
+
237
+ def load_and_prepare_image(image_path, target_size=None, device="cuda"):
238
+ """Load image and prepare tensor"""
239
+ rgb_img = Image.open(image_path).convert('RGB')
240
+ rgb_w, rgb_h = rgb_img.size
241
+
242
+ # Determine target dimensions
243
+ if target_size is not None:
244
+ target_w = target_h = target_size
245
+ else:
246
+ # Ensure dimensions divisible by 32 (required for VAE)
247
+ target_w = ((rgb_w + 31) // 32) * 32
248
+ target_h = ((rgb_h + 31) // 32) * 32
249
+
250
+ # Resize if needed
251
+ if target_w != rgb_w or target_h != rgb_h:
252
+ rgb_img = rgb_img.resize((target_w, target_h), Image.Resampling.LANCZOS)
253
+
254
+ # Convert to tensor for diffusion model
255
+ transform = transforms.Compose([
256
+ transforms.ToTensor(),
257
+ transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5]), # [-1, 1]
258
+ ])
259
+
260
+ rgb_tensor = transform(rgb_img).unsqueeze(0)
261
+ if device is not None:
262
+ rgb_tensor = rgb_tensor.to(device)
263
+
264
+ return rgb_tensor, rgb_img # Return both tensor and PIL image
265
+
266
+
267
+ def load_llava_cache(cache_path, device):
268
+ """Load pre-cached LLaVA hidden states"""
269
+ try:
270
+ llava_hidden = torch.load(cache_path, map_location="cpu", weights_only=True)
271
+ except TypeError:
272
+ # For older torch versions without weights_only
273
+ llava_hidden = torch.load(cache_path, map_location="cpu")
274
+
275
+ if not isinstance(llava_hidden, torch.Tensor):
276
+ llava_hidden = torch.tensor(llava_hidden)
277
+
278
+ # Add batch dimension if needed
279
+ if llava_hidden.ndim == 2:
280
+ llava_hidden = llava_hidden.unsqueeze(0)
281
+
282
+ return llava_hidden.to(device)
283
+
284
+
285
+ @torch.no_grad()
286
+ def translate_image(vae, unet, adapter, scheduler, rgb_tensor, llava_hidden,
287
+ num_steps=100, cfg_text=3.5, cfg_image=1.5, device="cuda"):
288
+ """Translate RGB to TIR using LLaVA features + conditional generation with CFG"""
289
+
290
+ # Encode RGB
291
+ rgb_latents = vae.encode(rgb_tensor).latent_dist.mode() * vae.config.scaling_factor
292
+ batch_size = rgb_latents.shape[0]
293
+
294
+ # Process LLaVA features through adapter
295
+ use_autocast = device.type == "cuda"
296
+ llava_input = llava_hidden.to(device)
297
+ # If using a single cached reference for a batch of RGB images, repeat it across batch.
298
+ if llava_input.shape[0] == 1 and batch_size > 1:
299
+ llava_input = llava_input.expand(batch_size, *llava_input.shape[1:])
300
+ if use_autocast:
301
+ llava_input = llava_input.to(dtype=torch.bfloat16)
302
+
303
+ autocast_ctx = (
304
+ torch.autocast(device_type=device.type, dtype=torch.bfloat16)
305
+ if use_autocast else nullcontext()
306
+ )
307
+ with autocast_ctx:
308
+ llava_tokens = adapter(llava_input)
309
+ llava_tokens = llava_tokens.to(device=device, dtype=next(unet.parameters()).dtype)
310
+ # Ensure token batch matches RGB batch (some adapters may return batch=1 even if input was expanded).
311
+ if llava_tokens.shape[0] == 1 and batch_size > 1:
312
+ llava_tokens = llava_tokens.expand(batch_size, *llava_tokens.shape[1:])
313
+
314
+ # Create null tokens for CFG
315
+ null_tokens = torch.zeros_like(llava_tokens)
316
+
317
+ # Initialize random noise
318
+ latent_shape = (batch_size, 4, rgb_latents.shape[2], rgb_latents.shape[3])
319
+ latents = torch.randn(latent_shape, device=device, dtype=rgb_latents.dtype)
320
+
321
+ # Setup scheduler
322
+ scheduler.set_timesteps(num_steps, device=device)
323
+
324
+ zeros_rgb = torch.zeros_like(rgb_latents)
325
+
326
+ for t in scheduler.timesteps:
327
+ t_batch = torch.full((batch_size,), int(t), device=device, dtype=torch.long)
328
+
329
+ # 3 forward passes for dual-CFG
330
+ x8_full = torch.cat([latents, rgb_latents], dim=1)
331
+ x8_no_img = torch.cat([latents, zeros_rgb], dim=1)
332
+
333
+ # Full conditioning
334
+ eps_full = unet(x8_full, t_batch, encoder_hidden_states=llava_tokens).sample
335
+
336
+ # No text (image only)
337
+ eps_no_text = unet(x8_full, t_batch, encoder_hidden_states=null_tokens).sample
338
+
339
+ # No image (text only)
340
+ eps_no_img = unet(x8_no_img, t_batch, encoder_hidden_states=llava_tokens).sample
341
+
342
+ # Combine with dual-CFG
343
+ eps = eps_full + cfg_text * (eps_full - eps_no_text) + cfg_image * (eps_full - eps_no_img)
344
+ eps = torch.clamp(eps, -5.0, 5.0) # Safety guard
345
+
346
+ latents = scheduler.step(eps, t, latents, eta=0.0).prev_sample
347
+
348
+ # Decode
349
+ pred_tir = vae.decode(latents / vae.config.scaling_factor).sample
350
+ pred_tir = (pred_tir / 2 + 0.5).clamp(0, 1)
351
+
352
+ return pred_tir
353
+
354
+
355
+ def main():
356
+ args = parse_args()
357
+ validate_args(args)
358
+
359
+ # Set seed
360
+ torch.manual_seed(args.seed)
361
+ if torch.cuda.is_available():
362
+ torch.cuda.manual_seed_all(args.seed)
363
+
364
+ print("\n" + "="*80)
365
+ print(f"Example-Guided Translation - Mode: {args.mode.upper()}")
366
+ print("="*80)
367
+ print(f"Input image (B): {args.input_image}")
368
+ if args.mode == "two-image":
369
+ print(f"Reference image (A): {args.reference_image}")
370
+ else:
371
+ print(f"Reference cache: {args.reference_cache}")
372
+ print(f"Output: {args.output}")
373
+ print(f"Checkpoint: {args.checkpoint}")
374
+ print(f"DDIM steps: {args.num_steps}")
375
+ print(f"CFG scales: text={args.cfg_text}, image={args.cfg_image}")
376
+ print("="*80)
377
+
378
+ # Load models
379
+ need_llava = (args.mode == "two-image")
380
+ vae, unet, adapter, scheduler, llava_extractor, device = load_models(args, need_llava=need_llava)
381
+
382
+ # Get reference hidden states
383
+ print("\n" + "-"*80)
384
+ if args.mode == "two-image":
385
+ print(f"Extracting features from reference image: {args.reference_image}")
386
+ ref_tensor, ref_pil = load_and_prepare_image(
387
+ args.reference_image,
388
+ target_size=args.target_size,
389
+ device=device
390
+ )
391
+ llava_hidden = llava_extractor.extract_hidden_states([ref_pil], [args.llava_prompt])
392
+ print(f"✓ Extracted hidden states: {llava_hidden.shape}")
393
+ else:
394
+ print(f"Loading cached reference: {args.reference_cache}")
395
+ llava_hidden = load_llava_cache(Path(args.reference_cache), device)
396
+ print(f"✓ Loaded hidden states: {llava_hidden.shape}")
397
+ print("-"*80)
398
+
399
+ # Load input image (Image B)
400
+ print(f"\nLoading input image: {args.input_image}")
401
+ input_tensor, input_pil = load_and_prepare_image(
402
+ args.input_image,
403
+ target_size=args.target_size,
404
+ device=device
405
+ )
406
+ print(f"✓ Input image loaded: {input_tensor.shape}")
407
+
408
+ # Translate
409
+ print("\nTranslating image...")
410
+ pred_tir = translate_image(
411
+ vae, unet, adapter, scheduler,
412
+ input_tensor, llava_hidden,
413
+ num_steps=args.num_steps,
414
+ cfg_text=args.cfg_text,
415
+ cfg_image=args.cfg_image,
416
+ device=device
417
+ )
418
+
419
+ # Save output
420
+ output_path = Path(args.output)
421
+ output_path.parent.mkdir(parents=True, exist_ok=True)
422
+ save_image(pred_tir.cpu(), str(output_path))
423
+
424
+ print("="*80)
425
+ print(f"✓ Translation complete!")
426
+ print(f"✓ Saved to: {output_path}")
427
+ print("="*80)
428
+
429
+
430
+ if __name__ == "__main__":
431
+ main()
432
+
infer_palette.sh ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # Run TherA inference with weather/style palette reference caches.
3
+ #
4
+ # Usage:
5
+ # bash scripts/infer_palette.sh /path/to/rgb [output_dir]
6
+ #
7
+ # Requires weights/reference_caches/{SUNNY,CLOUDY,RAINY,NIGHT}.pt
8
+
9
+ set -euo pipefail
10
+
11
+ cd "$(dirname "$0")/.."
12
+
13
+ RGB_DIR="${1:?RGB directory required}"
14
+ OUT_BASE="${2:-preds_palette}"
15
+
16
+ for PAL in SUNNY CLOUDY RAINY NIGHT; do
17
+ CACHE="weights/reference_caches/${PAL}.pt"
18
+ if [[ ! -f "$CACHE" ]]; then
19
+ echo "Skipping ${PAL}: missing ${CACHE}"
20
+ continue
21
+ fi
22
+ echo ">>> ${PAL}"
23
+ python infer_custom.py \
24
+ --rgb-dir "$RGB_DIR" \
25
+ --output-dir "${OUT_BASE}/${PAL}" \
26
+ --reference-cache "$CACHE"
27
+ done
28
+
29
+ echo ""
30
+ echo "Done. Outputs in: ${OUT_BASE}/"
lavi_ip2p/__init__.py ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ """
2
+ LaVi-IP2P Module
3
+
4
+ RGB→TIR translation using LaVi-Bridge + cached LLaVA semantics.
5
+ """
6
+
7
+ __version__ = "0.1.0"
8
+
lavi_ip2p/llava_adapter.py ADDED
@@ -0,0 +1,135 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ LLaVA Token Adapter for LaVi-IP2P
3
+
4
+ Adapts cached LLaVA hidden states (4096-dim) to LaVi-Bridge UNet cross-attention (768-dim).
5
+ Uses LaVi-Bridge's TextAdapter with optional preprocessing (RMSNorm, scaling).
6
+ """
7
+
8
+ import torch
9
+ import torch.nn as nn
10
+ from typing import Optional
11
+ import sys
12
+ import os
13
+
14
+ # Add LaVi-Bridge to path
15
+ sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../LaVi-Bridge"))
16
+ from modules.adapters import TextAdapter
17
+
18
+
19
+ class RMSNorm(nn.Module):
20
+ """Root Mean Square Layer Normalization."""
21
+
22
+ def __init__(self, dim: int, eps: float = 1e-6):
23
+ super().__init__()
24
+ self.eps = eps
25
+ self.weight = nn.Parameter(torch.ones(dim))
26
+
27
+ def forward(self, x):
28
+ norm = torch.rsqrt(x.pow(2).mean(dim=-1, keepdim=True) + self.eps)
29
+ return x * norm * self.weight
30
+
31
+
32
+ class LLaVAAdapter(nn.Module):
33
+ """
34
+ Adapter: LLaVA hidden (4096) → LaVi-Bridge UNet conditioning (768).
35
+
36
+ FROZEN by default (use pretrained LaVi-Bridge TextAdapter as-is).
37
+ """
38
+
39
+ def __init__(
40
+ self,
41
+ adapter_path: str,
42
+ use_rms_norm: bool = False,
43
+ learnable_scale: bool = False,
44
+ init_scale: float = 1.0,
45
+ freeze_adapter: bool = True,
46
+ ):
47
+ super().__init__()
48
+
49
+ self.use_rms_norm = use_rms_norm
50
+ self.learnable_scale = learnable_scale
51
+
52
+ # Load pretrained TextAdapter
53
+ print(f"\nLoading TextAdapter from {adapter_path}...")
54
+ self.adapter = TextAdapter.from_pretrained(adapter_path)
55
+ print(f"✓ TextAdapter loaded (4096→768)")
56
+
57
+ # Freeze by default
58
+ if freeze_adapter:
59
+ for param in self.adapter.parameters():
60
+ param.requires_grad = False
61
+ print(" ✓ FROZEN (using pretrained weights)")
62
+ else:
63
+ print(" ⚠️ TRAINABLE")
64
+
65
+ # Optional: RMSNorm
66
+ if use_rms_norm:
67
+ self.rms_norm = RMSNorm(4096, eps=1e-6)
68
+ print("✓ RMSNorm enabled")
69
+
70
+ # Optional: Learnable scale
71
+ if learnable_scale:
72
+ self.scale = nn.Parameter(torch.tensor(init_scale))
73
+ print(f"✓ Learnable scale (init={init_scale})")
74
+ else:
75
+ self.register_buffer('scale', torch.tensor(init_scale))
76
+
77
+ def forward(self, llava_hidden: torch.Tensor) -> torch.Tensor:
78
+ """LLaVA (B,L,4096) → UNet conditioning (B,L,768)"""
79
+ x = llava_hidden
80
+
81
+ if self.use_rms_norm:
82
+ x = self.rms_norm(x)
83
+
84
+ x = self.adapter(x).sample
85
+
86
+ if self.learnable_scale:
87
+ x = x * self.scale
88
+
89
+ return x
90
+
91
+ def get_stats(self):
92
+ """Get adapter statistics for logging"""
93
+ stats = {}
94
+ if self.learnable_scale:
95
+ stats['scale'] = self.scale.item()
96
+ return stats
97
+
98
+
99
+ def create_llava_adapter(
100
+ adapter_path: str,
101
+ use_rms_norm: bool = False,
102
+ learnable_scale: bool = False,
103
+ init_scale: float = 1.0,
104
+ freeze_adapter: bool = True,
105
+ ) -> LLaVAAdapter:
106
+ """
107
+ Factory: Create LLaVA adapter.
108
+
109
+ DEFAULT (simple mode):
110
+ - Freeze TextAdapter (use LaVi-Bridge pretrained)
111
+ - No RMSNorm, no scale
112
+ - Train UNet only
113
+ """
114
+
115
+ print("\n" + "="*60)
116
+ print("Creating LLaVA Token Adapter")
117
+ print("="*60)
118
+ print(f"Mode: {'SIMPLE (frozen)' if freeze_adapter else 'ADVANCED (trainable)'}")
119
+
120
+ adapter = LLaVAAdapter(
121
+ adapter_path=adapter_path,
122
+ use_rms_norm=use_rms_norm,
123
+ learnable_scale=learnable_scale,
124
+ init_scale=init_scale,
125
+ freeze_adapter=freeze_adapter,
126
+ )
127
+
128
+ total = sum(p.numel() for p in adapter.parameters())
129
+ trainable = sum(p.numel() for p in adapter.parameters() if p.requires_grad)
130
+
131
+ print(f"\nParameters: {total:,} total, {trainable:,} trainable")
132
+ print("="*60 + "\n")
133
+
134
+ return adapter
135
+
lavi_ip2p/unet_8ch.py ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ UNet 8-channel modification for LaVi-IP2P
3
+
4
+ Safely converts LaVi-Bridge UNet from 4-channel to 8-channel input
5
+ by expanding conv_in with zero-initialized extra channels (InstructPix2Pix style).
6
+ """
7
+
8
+ import torch
9
+ import torch.nn as nn
10
+ from diffusers import UNet2DConditionModel
11
+ from typing import Optional
12
+
13
+
14
+ def convert_unet_to_8ch(
15
+ unet: UNet2DConditionModel,
16
+ init_scale: float = 1e-5,
17
+ ) -> UNet2DConditionModel:
18
+ """
19
+ Convert UNet from 4-channel to 8-channel input.
20
+
21
+ Strategy (InstructPix2Pix style):
22
+ 1. Copy first 4 channels from pretrained conv_in weights
23
+ 2. Initialize extra 4 channels with small random values (scaled by init_scale)
24
+ 3. This ensures the UNet starts close to the original behavior
25
+
26
+ Args:
27
+ unet: Pretrained 4-channel UNet
28
+ init_scale: Scale for initializing extra channels (default: 1e-5 for stability)
29
+
30
+ Returns:
31
+ Modified 8-channel UNet
32
+ """
33
+
34
+ if unet.config.in_channels == 8:
35
+ print("⚠️ UNet already has 8 input channels, skipping conversion")
36
+ return unet
37
+
38
+ if unet.config.in_channels != 4:
39
+ raise ValueError(f"Expected 4-channel UNet, got {unet.config.in_channels}")
40
+
41
+ print("\n" + "="*60)
42
+ print("Converting UNet to 8-channel input (IP2P style)")
43
+ print("="*60)
44
+
45
+ old_conv = unet.conv_in
46
+ print(f"Original conv_in: {old_conv}")
47
+ print(f" in_channels: {old_conv.in_channels}")
48
+ print(f" out_channels: {old_conv.out_channels}")
49
+ print(f" kernel_size: {old_conv.kernel_size}")
50
+ print(f" weight shape: {old_conv.weight.shape}")
51
+
52
+ # Create new 8-channel conv
53
+ new_conv = nn.Conv2d(
54
+ in_channels=8,
55
+ out_channels=old_conv.out_channels,
56
+ kernel_size=old_conv.kernel_size,
57
+ stride=old_conv.stride,
58
+ padding=old_conv.padding,
59
+ bias=(old_conv.bias is not None),
60
+ )
61
+
62
+ # Initialize weights
63
+ with torch.no_grad():
64
+ # Copy first 4 channels from pretrained weights
65
+ new_conv.weight[:, :4, :, :].copy_(old_conv.weight)
66
+
67
+ # Initialize extra 4 channels with small random values
68
+ # This ensures the UNet starts close to original behavior
69
+ nn.init.normal_(new_conv.weight[:, 4:, :, :], mean=0.0, std=init_scale)
70
+
71
+ # Copy bias if present
72
+ if old_conv.bias is not None:
73
+ new_conv.bias.copy_(old_conv.bias)
74
+
75
+ # Replace conv_in
76
+ unet.conv_in = new_conv
77
+
78
+ # Update config
79
+ unet.register_to_config(in_channels=8)
80
+
81
+ print(f"\n✓ New conv_in: {new_conv}")
82
+ print(f" weight shape: {new_conv.weight.shape}")
83
+ print(f" Channels 0-3: copied from pretrained")
84
+ print(f" Channels 4-7: initialized with std={init_scale}")
85
+ print("="*60 + "\n")
86
+
87
+ return unet
88
+
89
+
90
+ def load_lavi_unet_8ch(
91
+ pretrained_path: str,
92
+ lora_path: Optional[str] = None,
93
+ lora_rank: int = 32,
94
+ init_scale: float = 1e-5,
95
+ device: str = "cuda",
96
+ ) -> UNet2DConditionModel:
97
+ """
98
+ Load LaVi-Bridge UNet with LoRA and convert to 8-channel.
99
+
100
+ Args:
101
+ pretrained_path: Path to pretrained SD UNet (e.g., "CompVis/stable-diffusion-v1-4")
102
+ lora_path: Path to LaVi-Bridge LoRA weights (lora_vis.pt)
103
+ lora_rank: LoRA rank (default: 32)
104
+ init_scale: Scale for extra channels
105
+ device: Device to load on
106
+
107
+ Returns:
108
+ 8-channel UNet with LaVi-Bridge LoRA applied
109
+ """
110
+
111
+ print("\n" + "="*60)
112
+ print("Loading LaVi-Bridge UNet (8-channel)")
113
+ print("="*60)
114
+
115
+ # Load base UNet
116
+ print(f"\n[1/3] Loading base UNet from {pretrained_path}...")
117
+
118
+ # Determine subfolder based on filesystem check
119
+ from pathlib import Path
120
+ subfolder = "unet" if Path(pretrained_path).is_dir() and (Path(pretrained_path) / "unet").exists() else None
121
+
122
+ unet = UNet2DConditionModel.from_pretrained(
123
+ pretrained_path,
124
+ subfolder=subfolder,
125
+ )
126
+ print(f"✓ Base UNet loaded (subfolder: {subfolder})")
127
+
128
+ # Apply LoRA if provided
129
+ if lora_path is not None:
130
+ print(f"\n[2/3] Applying LaVi-Bridge LoRA from {lora_path}...")
131
+
132
+ # Import LoRA utilities (robust path resolution)
133
+ import sys
134
+ import os
135
+ lavi_bridge_path = os.path.join(os.path.dirname(__file__), "../LaVi-Bridge")
136
+ sys.path.insert(0, lavi_bridge_path)
137
+ from modules.lora import monkeypatch_or_replace_lora_extended
138
+
139
+ VIS_REPLACE_MODULES = {"ResnetBlock2D", "CrossAttention", "Attention", "GEGLU"}
140
+
141
+ monkeypatch_or_replace_lora_extended(
142
+ unet,
143
+ torch.load(lora_path, map_location='cpu'),
144
+ r=lora_rank,
145
+ target_replace_module=VIS_REPLACE_MODULES,
146
+ )
147
+ print(f"✓ LoRA applied (rank={lora_rank})")
148
+ else:
149
+ print(f"\n[2/3] No LoRA path provided, using base UNet")
150
+
151
+ # Convert to 8-channel
152
+ print(f"\n[3/3] Converting to 8-channel input...")
153
+ unet = convert_unet_to_8ch(unet, init_scale=init_scale)
154
+
155
+ # Move to device
156
+ unet = unet.to(device)
157
+ print(f"✓ Moved to {device}")
158
+ print("="*60 + "\n")
159
+
160
+ return unet
161
+
llava/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ from .model import LlavaLlamaForCausalLM
llava/constants.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ CONTROLLER_HEART_BEAT_EXPIRATION = 30
2
+ WORKER_HEART_BEAT_INTERVAL = 15
3
+
4
+ LOGDIR = "."
5
+
6
+ # Model Constants
7
+ IGNORE_INDEX = -100
8
+ IMAGE_TOKEN_INDEX = -200
9
+ DEFAULT_IMAGE_TOKEN = "<image>"
10
+ DEFAULT_IMAGE_PATCH_TOKEN = "<im_patch>"
11
+ DEFAULT_IM_START_TOKEN = "<im_start>"
12
+ DEFAULT_IM_END_TOKEN = "<im_end>"
13
+ IMAGE_PLACEHOLDER = "<image-placeholder>"
14
+
15
+ # IMG tokens for VLM-guided diffusion (16 tokens for edit conditioning)
16
+ IMG_TOKENS = [f"[IMG{i}]" for i in range(16)]
llava/conversation.py ADDED
@@ -0,0 +1,396 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import dataclasses
2
+ from enum import auto, Enum
3
+ from typing import List, Tuple
4
+ import base64
5
+ from io import BytesIO
6
+ from PIL import Image
7
+
8
+
9
+ class SeparatorStyle(Enum):
10
+ """Different separator style."""
11
+ SINGLE = auto()
12
+ TWO = auto()
13
+ MPT = auto()
14
+ PLAIN = auto()
15
+ LLAMA_2 = auto()
16
+
17
+
18
+ @dataclasses.dataclass
19
+ class Conversation:
20
+ """A class that keeps all conversation history."""
21
+ system: str
22
+ roles: List[str]
23
+ messages: List[List[str]]
24
+ offset: int
25
+ sep_style: SeparatorStyle = SeparatorStyle.SINGLE
26
+ sep: str = "###"
27
+ sep2: str = None
28
+ version: str = "Unknown"
29
+
30
+ skip_next: bool = False
31
+
32
+ def get_prompt(self):
33
+ messages = self.messages
34
+ if len(messages) > 0 and type(messages[0][1]) is tuple:
35
+ messages = self.messages.copy()
36
+ init_role, init_msg = messages[0].copy()
37
+ init_msg = init_msg[0].replace("<image>", "").strip()
38
+ if 'mmtag' in self.version:
39
+ messages[0] = (init_role, init_msg)
40
+ messages.insert(0, (self.roles[0], "<Image><image></Image>"))
41
+ messages.insert(1, (self.roles[1], "Received."))
42
+ else:
43
+ messages[0] = (init_role, "<image>\n" + init_msg)
44
+
45
+ if self.sep_style == SeparatorStyle.SINGLE:
46
+ ret = self.system + self.sep
47
+ for role, message in messages:
48
+ if message:
49
+ if type(message) is tuple:
50
+ message, _, _ = message
51
+ ret += role + ": " + message + self.sep
52
+ else:
53
+ ret += role + ":"
54
+ elif self.sep_style == SeparatorStyle.TWO:
55
+ seps = [self.sep, self.sep2]
56
+ ret = self.system + seps[0]
57
+ for i, (role, message) in enumerate(messages):
58
+ if message:
59
+ if type(message) is tuple:
60
+ message, _, _ = message
61
+ ret += role + ": " + message + seps[i % 2]
62
+ else:
63
+ ret += role + ":"
64
+ elif self.sep_style == SeparatorStyle.MPT:
65
+ ret = self.system + self.sep
66
+ for role, message in messages:
67
+ if message:
68
+ if type(message) is tuple:
69
+ message, _, _ = message
70
+ ret += role + message + self.sep
71
+ else:
72
+ ret += role
73
+ elif self.sep_style == SeparatorStyle.LLAMA_2:
74
+ wrap_sys = lambda msg: f"<<SYS>>\n{msg}\n<</SYS>>\n\n" if len(msg) > 0 else msg
75
+ wrap_inst = lambda msg: f"[INST] {msg} [/INST]"
76
+ ret = ""
77
+
78
+ for i, (role, message) in enumerate(messages):
79
+ if i == 0:
80
+ assert message, "first message should not be none"
81
+ assert role == self.roles[0], "first message should come from user"
82
+ if message:
83
+ if type(message) is tuple:
84
+ message, _, _ = message
85
+ if i == 0: message = wrap_sys(self.system) + message
86
+ if i % 2 == 0:
87
+ message = wrap_inst(message)
88
+ ret += self.sep + message
89
+ else:
90
+ ret += " " + message + " " + self.sep2
91
+ else:
92
+ ret += ""
93
+ ret = ret.lstrip(self.sep)
94
+ elif self.sep_style == SeparatorStyle.PLAIN:
95
+ seps = [self.sep, self.sep2]
96
+ ret = self.system
97
+ for i, (role, message) in enumerate(messages):
98
+ if message:
99
+ if type(message) is tuple:
100
+ message, _, _ = message
101
+ ret += message + seps[i % 2]
102
+ else:
103
+ ret += ""
104
+ else:
105
+ raise ValueError(f"Invalid style: {self.sep_style}")
106
+
107
+ return ret
108
+
109
+ def append_message(self, role, message):
110
+ self.messages.append([role, message])
111
+
112
+ def process_image(self, image, image_process_mode, return_pil=False, image_format='PNG', max_len=1344, min_len=672):
113
+ if image_process_mode == "Pad":
114
+ def expand2square(pil_img, background_color=(122, 116, 104)):
115
+ width, height = pil_img.size
116
+ if width == height:
117
+ return pil_img
118
+ elif width > height:
119
+ result = Image.new(pil_img.mode, (width, width), background_color)
120
+ result.paste(pil_img, (0, (width - height) // 2))
121
+ return result
122
+ else:
123
+ result = Image.new(pil_img.mode, (height, height), background_color)
124
+ result.paste(pil_img, ((height - width) // 2, 0))
125
+ return result
126
+ image = expand2square(image)
127
+ elif image_process_mode in ["Default", "Crop"]:
128
+ pass
129
+ elif image_process_mode == "Resize":
130
+ image = image.resize((336, 336))
131
+ else:
132
+ raise ValueError(f"Invalid image_process_mode: {image_process_mode}")
133
+ if max(image.size) > max_len:
134
+ max_hw, min_hw = max(image.size), min(image.size)
135
+ aspect_ratio = max_hw / min_hw
136
+ shortest_edge = int(min(max_len / aspect_ratio, min_len, min_hw))
137
+ longest_edge = int(shortest_edge * aspect_ratio)
138
+ W, H = image.size
139
+ if H > W:
140
+ H, W = longest_edge, shortest_edge
141
+ else:
142
+ H, W = shortest_edge, longest_edge
143
+ image = image.resize((W, H))
144
+ if return_pil:
145
+ return image
146
+ else:
147
+ buffered = BytesIO()
148
+ image.save(buffered, format=image_format)
149
+ img_b64_str = base64.b64encode(buffered.getvalue()).decode()
150
+ return img_b64_str
151
+
152
+ def get_images(self, return_pil=False):
153
+ images = []
154
+ for i, (role, msg) in enumerate(self.messages[self.offset:]):
155
+ if i % 2 == 0:
156
+ if type(msg) is tuple:
157
+ msg, image, image_process_mode = msg
158
+ image = self.process_image(image, image_process_mode, return_pil=return_pil)
159
+ images.append(image)
160
+ return images
161
+
162
+ def to_gradio_chatbot(self):
163
+ ret = []
164
+ for i, (role, msg) in enumerate(self.messages[self.offset:]):
165
+ if i % 2 == 0:
166
+ if type(msg) is tuple:
167
+ msg, image, image_process_mode = msg
168
+ img_b64_str = self.process_image(
169
+ image, "Default", return_pil=False,
170
+ image_format='JPEG')
171
+ img_str = f'<img src="data:image/jpeg;base64,{img_b64_str}" alt="user upload image" />'
172
+ msg = img_str + msg.replace('<image>', '').strip()
173
+ ret.append([msg, None])
174
+ else:
175
+ ret.append([msg, None])
176
+ else:
177
+ ret[-1][-1] = msg
178
+ return ret
179
+
180
+ def copy(self):
181
+ return Conversation(
182
+ system=self.system,
183
+ roles=self.roles,
184
+ messages=[[x, y] for x, y in self.messages],
185
+ offset=self.offset,
186
+ sep_style=self.sep_style,
187
+ sep=self.sep,
188
+ sep2=self.sep2,
189
+ version=self.version)
190
+
191
+ def dict(self):
192
+ if len(self.get_images()) > 0:
193
+ return {
194
+ "system": self.system,
195
+ "roles": self.roles,
196
+ "messages": [[x, y[0] if type(y) is tuple else y] for x, y in self.messages],
197
+ "offset": self.offset,
198
+ "sep": self.sep,
199
+ "sep2": self.sep2,
200
+ }
201
+ return {
202
+ "system": self.system,
203
+ "roles": self.roles,
204
+ "messages": self.messages,
205
+ "offset": self.offset,
206
+ "sep": self.sep,
207
+ "sep2": self.sep2,
208
+ }
209
+
210
+
211
+ conv_vicuna_v0 = Conversation(
212
+ system="A chat between a curious human and an artificial intelligence assistant. "
213
+ "The assistant gives helpful, detailed, and polite answers to the human's questions.",
214
+ roles=("Human", "Assistant"),
215
+ messages=(
216
+ ("Human", "What are the key differences between renewable and non-renewable energy sources?"),
217
+ ("Assistant",
218
+ "Renewable energy sources are those that can be replenished naturally in a relatively "
219
+ "short amount of time, such as solar, wind, hydro, geothermal, and biomass. "
220
+ "Non-renewable energy sources, on the other hand, are finite and will eventually be "
221
+ "depleted, such as coal, oil, and natural gas. Here are some key differences between "
222
+ "renewable and non-renewable energy sources:\n"
223
+ "1. Availability: Renewable energy sources are virtually inexhaustible, while non-renewable "
224
+ "energy sources are finite and will eventually run out.\n"
225
+ "2. Environmental impact: Renewable energy sources have a much lower environmental impact "
226
+ "than non-renewable sources, which can lead to air and water pollution, greenhouse gas emissions, "
227
+ "and other negative effects.\n"
228
+ "3. Cost: Renewable energy sources can be more expensive to initially set up, but they typically "
229
+ "have lower operational costs than non-renewable sources.\n"
230
+ "4. Reliability: Renewable energy sources are often more reliable and can be used in more remote "
231
+ "locations than non-renewable sources.\n"
232
+ "5. Flexibility: Renewable energy sources are often more flexible and can be adapted to different "
233
+ "situations and needs, while non-renewable sources are more rigid and inflexible.\n"
234
+ "6. Sustainability: Renewable energy sources are more sustainable over the long term, while "
235
+ "non-renewable sources are not, and their depletion can lead to economic and social instability.\n")
236
+ ),
237
+ offset=2,
238
+ sep_style=SeparatorStyle.SINGLE,
239
+ sep="###",
240
+ )
241
+
242
+ conv_vicuna_v1 = Conversation(
243
+ system="A chat between a curious user and an artificial intelligence assistant. "
244
+ "The assistant gives helpful, detailed, and polite answers to the user's questions.",
245
+ roles=("USER", "ASSISTANT"),
246
+ version="v1",
247
+ messages=(),
248
+ offset=0,
249
+ sep_style=SeparatorStyle.TWO,
250
+ sep=" ",
251
+ sep2="</s>",
252
+ )
253
+
254
+ conv_llama_2 = Conversation(
255
+ system="""You are a helpful, respectful and honest assistant. Always answer as helpfully as possible, while being safe. Your answers should not include any harmful, unethical, racist, sexist, toxic, dangerous, or illegal content. Please ensure that your responses are socially unbiased and positive in nature.
256
+
257
+ If a question does not make any sense, or is not factually coherent, explain why instead of answering something not correct. If you don't know the answer to a question, please don't share false information.""",
258
+ roles=("USER", "ASSISTANT"),
259
+ version="llama_v2",
260
+ messages=(),
261
+ offset=0,
262
+ sep_style=SeparatorStyle.LLAMA_2,
263
+ sep="<s>",
264
+ sep2="</s>",
265
+ )
266
+
267
+ conv_llava_llama_2 = Conversation(
268
+ system="You are a helpful language and vision assistant. "
269
+ "You are able to understand the visual content that the user provides, "
270
+ "and assist the user with a variety of tasks using natural language.",
271
+ roles=("USER", "ASSISTANT"),
272
+ version="llama_v2",
273
+ messages=(),
274
+ offset=0,
275
+ sep_style=SeparatorStyle.LLAMA_2,
276
+ sep="<s>",
277
+ sep2="</s>",
278
+ )
279
+
280
+ conv_mpt = Conversation(
281
+ system="""<|im_start|>system
282
+ A conversation between a user and an LLM-based AI assistant. The assistant gives helpful and honest answers.""",
283
+ roles=("<|im_start|>user\n", "<|im_start|>assistant\n"),
284
+ version="mpt",
285
+ messages=(),
286
+ offset=0,
287
+ sep_style=SeparatorStyle.MPT,
288
+ sep="<|im_end|>",
289
+ )
290
+
291
+ conv_llava_plain = Conversation(
292
+ system="",
293
+ roles=("", ""),
294
+ messages=(
295
+ ),
296
+ offset=0,
297
+ sep_style=SeparatorStyle.PLAIN,
298
+ sep="\n",
299
+ )
300
+
301
+ conv_llava_v0 = Conversation(
302
+ system="A chat between a curious human and an artificial intelligence assistant. "
303
+ "The assistant gives helpful, detailed, and polite answers to the human's questions.",
304
+ roles=("Human", "Assistant"),
305
+ messages=(
306
+ ),
307
+ offset=0,
308
+ sep_style=SeparatorStyle.SINGLE,
309
+ sep="###",
310
+ )
311
+
312
+ conv_llava_v0_mmtag = Conversation(
313
+ system="A chat between a curious user and an artificial intelligence assistant. "
314
+ "The assistant is able to understand the visual content that the user provides, and assist the user with a variety of tasks using natural language."
315
+ "The visual content will be provided with the following format: <Image>visual content</Image>.",
316
+ roles=("Human", "Assistant"),
317
+ messages=(
318
+ ),
319
+ offset=0,
320
+ sep_style=SeparatorStyle.SINGLE,
321
+ sep="###",
322
+ version="v0_mmtag",
323
+ )
324
+
325
+ conv_llava_v1 = Conversation(
326
+ system="A chat between a curious human and an artificial intelligence assistant. "
327
+ "The assistant gives helpful, detailed, and polite answers to the human's questions.",
328
+ roles=("USER", "ASSISTANT"),
329
+ version="v1",
330
+ messages=(),
331
+ offset=0,
332
+ sep_style=SeparatorStyle.TWO,
333
+ sep=" ",
334
+ sep2="</s>",
335
+ )
336
+
337
+ conv_llava_v1_mmtag = Conversation(
338
+ system="A chat between a curious user and an artificial intelligence assistant. "
339
+ "The assistant is able to understand the visual content that the user provides, and assist the user with a variety of tasks using natural language."
340
+ "The visual content will be provided with the following format: <Image>visual content</Image>.",
341
+ roles=("USER", "ASSISTANT"),
342
+ messages=(),
343
+ offset=0,
344
+ sep_style=SeparatorStyle.TWO,
345
+ sep=" ",
346
+ sep2="</s>",
347
+ version="v1_mmtag",
348
+ )
349
+
350
+ conv_mistral_instruct = Conversation(
351
+ system="",
352
+ roles=("USER", "ASSISTANT"),
353
+ version="llama_v2",
354
+ messages=(),
355
+ offset=0,
356
+ sep_style=SeparatorStyle.LLAMA_2,
357
+ sep="",
358
+ sep2="</s>",
359
+ )
360
+
361
+ conv_chatml_direct = Conversation(
362
+ system="""<|im_start|>system
363
+ Answer the questions.""",
364
+ roles=("<|im_start|>user\n", "<|im_start|>assistant\n"),
365
+ version="mpt",
366
+ messages=(),
367
+ offset=0,
368
+ sep_style=SeparatorStyle.MPT,
369
+ sep="<|im_end|>",
370
+ )
371
+
372
+ default_conversation = conv_vicuna_v1
373
+ conv_templates = {
374
+ "default": conv_vicuna_v0,
375
+ "v0": conv_vicuna_v0,
376
+ "v1": conv_vicuna_v1,
377
+ "vicuna_v1": conv_vicuna_v1,
378
+ "llama_2": conv_llama_2,
379
+ "mistral_instruct": conv_mistral_instruct,
380
+ "chatml_direct": conv_chatml_direct,
381
+ "mistral_direct": conv_chatml_direct,
382
+
383
+ "plain": conv_llava_plain,
384
+ "v0_plain": conv_llava_plain,
385
+ "llava_v0": conv_llava_v0,
386
+ "v0_mmtag": conv_llava_v0_mmtag,
387
+ "llava_v1": conv_llava_v1,
388
+ "v1_mmtag": conv_llava_v1_mmtag,
389
+ "llava_llama_2": conv_llava_llama_2,
390
+
391
+ "mpt": conv_mpt,
392
+ }
393
+
394
+
395
+ if __name__ == "__main__":
396
+ print(default_conversation.get_prompt())
llava/eval/table/results/test_sqa_llava_13b_v0.json ADDED
The diff for this file is too large to render. See raw diff
 
llava/mm_utils.py ADDED
@@ -0,0 +1,247 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from PIL import Image
2
+ from io import BytesIO
3
+ import base64
4
+ import torch
5
+ import math
6
+ import ast
7
+
8
+ from transformers import StoppingCriteria
9
+ from llava.constants import IMAGE_TOKEN_INDEX
10
+
11
+
12
+ def select_best_resolution(original_size, possible_resolutions):
13
+ """
14
+ Selects the best resolution from a list of possible resolutions based on the original size.
15
+
16
+ Args:
17
+ original_size (tuple): The original size of the image in the format (width, height).
18
+ possible_resolutions (list): A list of possible resolutions in the format [(width1, height1), (width2, height2), ...].
19
+
20
+ Returns:
21
+ tuple: The best fit resolution in the format (width, height).
22
+ """
23
+ original_width, original_height = original_size
24
+ best_fit = None
25
+ max_effective_resolution = 0
26
+ min_wasted_resolution = float('inf')
27
+
28
+ for width, height in possible_resolutions:
29
+ scale = min(width / original_width, height / original_height)
30
+ downscaled_width, downscaled_height = int(original_width * scale), int(original_height * scale)
31
+ effective_resolution = min(downscaled_width * downscaled_height, original_width * original_height)
32
+ wasted_resolution = (width * height) - effective_resolution
33
+
34
+ if effective_resolution > max_effective_resolution or (effective_resolution == max_effective_resolution and wasted_resolution < min_wasted_resolution):
35
+ max_effective_resolution = effective_resolution
36
+ min_wasted_resolution = wasted_resolution
37
+ best_fit = (width, height)
38
+
39
+ return best_fit
40
+
41
+
42
+ def resize_and_pad_image(image, target_resolution):
43
+ """
44
+ Resize and pad an image to a target resolution while maintaining aspect ratio.
45
+
46
+ Args:
47
+ image (PIL.Image.Image): The input image.
48
+ target_resolution (tuple): The target resolution (width, height) of the image.
49
+
50
+ Returns:
51
+ PIL.Image.Image: The resized and padded image.
52
+ """
53
+ original_width, original_height = image.size
54
+ target_width, target_height = target_resolution
55
+
56
+ scale_w = target_width / original_width
57
+ scale_h = target_height / original_height
58
+
59
+ if scale_w < scale_h:
60
+ new_width = target_width
61
+ new_height = min(math.ceil(original_height * scale_w), target_height)
62
+ else:
63
+ new_height = target_height
64
+ new_width = min(math.ceil(original_width * scale_h), target_width)
65
+
66
+ # Resize the image
67
+ resized_image = image.resize((new_width, new_height))
68
+
69
+ new_image = Image.new('RGB', (target_width, target_height), (0, 0, 0))
70
+ paste_x = (target_width - new_width) // 2
71
+ paste_y = (target_height - new_height) // 2
72
+ new_image.paste(resized_image, (paste_x, paste_y))
73
+
74
+ return new_image
75
+
76
+
77
+ def divide_to_patches(image, patch_size):
78
+ """
79
+ Divides an image into patches of a specified size.
80
+
81
+ Args:
82
+ image (PIL.Image.Image): The input image.
83
+ patch_size (int): The size of each patch.
84
+
85
+ Returns:
86
+ list: A list of PIL.Image.Image objects representing the patches.
87
+ """
88
+ patches = []
89
+ width, height = image.size
90
+ for i in range(0, height, patch_size):
91
+ for j in range(0, width, patch_size):
92
+ box = (j, i, j + patch_size, i + patch_size)
93
+ patch = image.crop(box)
94
+ patches.append(patch)
95
+
96
+ return patches
97
+
98
+
99
+ def get_anyres_image_grid_shape(image_size, grid_pinpoints, patch_size):
100
+ """
101
+ Calculate the shape of the image patch grid after the preprocessing for images of any resolution.
102
+
103
+ Args:
104
+ image_size (tuple): The size of the input image in the format (width, height).
105
+ grid_pinpoints (str): A string representation of a list of possible resolutions.
106
+ patch_size (int): The size of each image patch.
107
+
108
+ Returns:
109
+ tuple: The shape of the image patch grid in the format (width, height).
110
+ """
111
+ if type(grid_pinpoints) is list:
112
+ possible_resolutions = grid_pinpoints
113
+ else:
114
+ possible_resolutions = ast.literal_eval(grid_pinpoints)
115
+ width, height = select_best_resolution(image_size, possible_resolutions)
116
+ return width // patch_size, height // patch_size
117
+
118
+
119
+ def process_anyres_image(image, processor, grid_pinpoints):
120
+ """
121
+ Process an image with variable resolutions.
122
+
123
+ Args:
124
+ image (PIL.Image.Image): The input image to be processed.
125
+ processor: The image processor object.
126
+ grid_pinpoints (str): A string representation of a list of possible resolutions.
127
+
128
+ Returns:
129
+ torch.Tensor: A tensor containing the processed image patches.
130
+ """
131
+ if type(grid_pinpoints) is list:
132
+ possible_resolutions = grid_pinpoints
133
+ else:
134
+ possible_resolutions = ast.literal_eval(grid_pinpoints)
135
+ best_resolution = select_best_resolution(image.size, possible_resolutions)
136
+ image_padded = resize_and_pad_image(image, best_resolution)
137
+
138
+ patches = divide_to_patches(image_padded, processor.crop_size['height'])
139
+
140
+ image_original_resize = image.resize((processor.size['shortest_edge'], processor.size['shortest_edge']))
141
+
142
+ image_patches = [image_original_resize] + patches
143
+ image_patches = [processor.preprocess(image_patch, return_tensors='pt')['pixel_values'][0]
144
+ for image_patch in image_patches]
145
+ return torch.stack(image_patches, dim=0)
146
+
147
+
148
+ def load_image_from_base64(image):
149
+ return Image.open(BytesIO(base64.b64decode(image)))
150
+
151
+
152
+ def expand2square(pil_img, background_color):
153
+ width, height = pil_img.size
154
+ if width == height:
155
+ return pil_img
156
+ elif width > height:
157
+ result = Image.new(pil_img.mode, (width, width), background_color)
158
+ result.paste(pil_img, (0, (width - height) // 2))
159
+ return result
160
+ else:
161
+ result = Image.new(pil_img.mode, (height, height), background_color)
162
+ result.paste(pil_img, ((height - width) // 2, 0))
163
+ return result
164
+
165
+
166
+ def process_images(images, image_processor, model_cfg):
167
+ image_aspect_ratio = getattr(model_cfg, "image_aspect_ratio", None)
168
+ new_images = []
169
+ if image_aspect_ratio == 'pad':
170
+ for image in images:
171
+ image = expand2square(image, tuple(int(x*255) for x in image_processor.image_mean))
172
+ image = image_processor.preprocess(image, return_tensors='pt')['pixel_values'][0]
173
+ new_images.append(image)
174
+ elif image_aspect_ratio == "anyres":
175
+ for image in images:
176
+ image = process_anyres_image(image, image_processor, model_cfg.image_grid_pinpoints)
177
+ new_images.append(image)
178
+ else:
179
+ return image_processor(images, return_tensors='pt')['pixel_values']
180
+ if all(x.shape == new_images[0].shape for x in new_images):
181
+ new_images = torch.stack(new_images, dim=0)
182
+ return new_images
183
+
184
+
185
+ def tokenizer_image_token(prompt, tokenizer, image_token_index=IMAGE_TOKEN_INDEX, return_tensors=None):
186
+ prompt_chunks = [tokenizer(chunk).input_ids for chunk in prompt.split('<image>')]
187
+
188
+ def insert_separator(X, sep):
189
+ return [ele for sublist in zip(X, [sep]*len(X)) for ele in sublist][:-1]
190
+
191
+ input_ids = []
192
+ offset = 0
193
+ if len(prompt_chunks) > 0 and len(prompt_chunks[0]) > 0 and prompt_chunks[0][0] == tokenizer.bos_token_id:
194
+ offset = 1
195
+ input_ids.append(prompt_chunks[0][0])
196
+
197
+ for x in insert_separator(prompt_chunks, [image_token_index] * (offset + 1)):
198
+ input_ids.extend(x[offset:])
199
+
200
+ if return_tensors is not None:
201
+ if return_tensors == 'pt':
202
+ return torch.tensor(input_ids, dtype=torch.long)
203
+ raise ValueError(f'Unsupported tensor type: {return_tensors}')
204
+ return input_ids
205
+
206
+
207
+ def get_model_name_from_path(model_path):
208
+ model_path = model_path.strip("/")
209
+ model_paths = model_path.split("/")
210
+ if model_paths[-1].startswith('checkpoint-'):
211
+ return model_paths[-2] + "_" + model_paths[-1]
212
+ else:
213
+ return model_paths[-1]
214
+
215
+ class KeywordsStoppingCriteria(StoppingCriteria):
216
+ def __init__(self, keywords, tokenizer, input_ids):
217
+ self.keywords = keywords
218
+ self.keyword_ids = []
219
+ self.max_keyword_len = 0
220
+ for keyword in keywords:
221
+ cur_keyword_ids = tokenizer(keyword).input_ids
222
+ if len(cur_keyword_ids) > 1 and cur_keyword_ids[0] == tokenizer.bos_token_id:
223
+ cur_keyword_ids = cur_keyword_ids[1:]
224
+ if len(cur_keyword_ids) > self.max_keyword_len:
225
+ self.max_keyword_len = len(cur_keyword_ids)
226
+ self.keyword_ids.append(torch.tensor(cur_keyword_ids))
227
+ self.tokenizer = tokenizer
228
+ self.start_len = input_ids.shape[1]
229
+
230
+ def call_for_batch(self, output_ids: torch.LongTensor, scores: torch.FloatTensor, **kwargs) -> bool:
231
+ offset = min(output_ids.shape[1] - self.start_len, self.max_keyword_len)
232
+ self.keyword_ids = [keyword_id.to(output_ids.device) for keyword_id in self.keyword_ids]
233
+ for keyword_id in self.keyword_ids:
234
+ truncated_output_ids = output_ids[0, -keyword_id.shape[0]:]
235
+ if torch.equal(truncated_output_ids, keyword_id):
236
+ return True
237
+ outputs = self.tokenizer.batch_decode(output_ids[:, -offset:], skip_special_tokens=True)[0]
238
+ for keyword in self.keywords:
239
+ if keyword in outputs:
240
+ return True
241
+ return False
242
+
243
+ def __call__(self, output_ids: torch.LongTensor, scores: torch.FloatTensor, **kwargs) -> bool:
244
+ outputs = []
245
+ for i in range(output_ids.shape[0]):
246
+ outputs.append(self.call_for_batch(output_ids[i].unsqueeze(0), scores))
247
+ return all(outputs)
llava/rgbt_dataset.py ADDED
@@ -0,0 +1,328 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # llava/data/rgb_tir_dataset.py
2
+ import os
3
+ import copy
4
+ import json
5
+ from typing import Dict, Sequence, Optional, Tuple
6
+
7
+ import torch
8
+ from torch.utils.data import Dataset
9
+ from PIL import Image
10
+ import torchvision.transforms as tvt
11
+
12
+ from llava.constants import (
13
+ IGNORE_INDEX, DEFAULT_IMAGE_TOKEN, DEFAULT_IM_START_TOKEN, DEFAULT_IM_END_TOKEN
14
+ )
15
+ from llava import conversation as conversation_lib
16
+ from llava.mm_utils import tokenizer_image_token
17
+
18
+ def _safe_replace_rgb_with_tir(path: str) -> str:
19
+ # handle /RGB/ or \RGB\ on any OS
20
+ path2 = path.replace(os.sep + "RGB" + os.sep, os.sep + "TIR" + os.sep)
21
+ path2 = path2.replace("/RGB/", "/TIR/").replace("\\RGB\\", "\\TIR\\")
22
+ return path2
23
+
24
+ def _expand2square(pil_img: Image.Image, background_color=(0, 0, 0)):
25
+ w, h = pil_img.size
26
+ if w == h:
27
+ return pil_img
28
+ if w > h:
29
+ result = Image.new(pil_img.mode, (w, w), background_color)
30
+ result.paste(pil_img, (0, (w - h) // 2))
31
+ return result
32
+ else:
33
+ result = Image.new(pil_img.mode, (h, h), background_color)
34
+ result.paste(pil_img, ((h - w) // 2, 0))
35
+ return result
36
+
37
+ class RGBTIRSupervisedDataset(Dataset):
38
+ """
39
+ LLaVA-compatible dataset that also (optionally) returns RGB/TIR pairs
40
+ for diffusion training (instructpix2pix). When diffusion pairs are off,
41
+ it behaves like the stock LazySupervisedDataset.
42
+
43
+ Keys:
44
+ - Always for LLaVA: input_ids, labels, image (-> collated as `images`)
45
+ - Optional for diffusion: rgb_diffusion, tir_diffusion
46
+ """
47
+
48
+ def __init__(
49
+ self,
50
+ data_path: str,
51
+ tokenizer,
52
+ image_processor,
53
+ image_folder: Optional[str] = None,
54
+ image_aspect_ratio: str = "square", # {"square","pad"}
55
+ model_max_length: int = 2048,
56
+ # diffusion extras
57
+ return_diffusion_pairs: bool = False,
58
+ diffusion_size: int = 512,
59
+ tir_as_rgb: bool = True, # True: convert TIR to 3ch; False: keep 1ch ("L")
60
+ mm_use_im_start_end: bool = False, # NEW
61
+ warn_missing_tir: bool = False, # optional
62
+ ):
63
+ super().__init__()
64
+ self.data = json.load(open(data_path, "r"))
65
+ self.tokenizer = tokenizer
66
+ self.image_processor = image_processor
67
+ self.image_folder = image_folder or ""
68
+ self.image_aspect_ratio = image_aspect_ratio
69
+ self.model_max_length = model_max_length
70
+ self.return_diffusion_pairs = return_diffusion_pairs
71
+ self.diffusion_size = diffusion_size
72
+ self.tir_as_rgb = tir_as_rgb
73
+ self.mm_use_im_start_end = mm_use_im_start_end # NEW
74
+ self.warn_missing_tir = warn_missing_tir
75
+
76
+
77
+ def make_rgb_transform():
78
+ return tvt.Compose([
79
+ tvt.CenterCrop(min(self.diffusion_size, 10**9)), # overwritten next line
80
+ tvt.Resize(self.diffusion_size, interpolation=Image.BICUBIC),
81
+ tvt.ToTensor(),
82
+ tvt.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5]),
83
+ ])
84
+
85
+ # CenterCrop to exact square first, then Resize
86
+ def square_then_resize(mode_rgb: bool):
87
+ norms = ([0.5, 0.5, 0.5], [0.5, 0.5, 0.5]) if mode_rgb else ([0.5], [0.5])
88
+ return tvt.Compose([
89
+ # crop to min side square
90
+ tvt.Lambda(lambda im: _expand2square(im, (0, 0, 0)) if im.size[0]!=im.size[1] else im),
91
+ tvt.Resize(self.diffusion_size, interpolation=Image.BICUBIC),
92
+ tvt.ToTensor(),
93
+ tvt.Normalize(*norms),
94
+ ])
95
+
96
+ self.diffusion_transform_rgb = square_then_resize(True)
97
+ self.diffusion_transform_tir = square_then_resize(self.tir_as_rgb)
98
+ # diffusion transforms ([-1,1])
99
+ # self.diffusion_transform_rgb = tvt.Compose([
100
+ # tvt.Resize(self.diffusion_size, interpolation=Image.BICUBIC),
101
+ # tvt.CenterCrop(self.diffusion_size),
102
+ # tvt.ToTensor(),
103
+ # tvt.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5]),
104
+ # ])
105
+ # allow 1ch or 3ch for TIR
106
+ # if self.tir_as_rgb:
107
+ # self.diffusion_transform_tir = tvt.Compose([
108
+ # tvt.Resize(self.diffusion_size, interpolation=Image.BICUBIC),
109
+ # tvt.CenterCrop(self.diffusion_size),
110
+ # tvt.ToTensor(),
111
+ # tvt.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5]),
112
+ # ])
113
+ # else:
114
+ # self.diffusion_transform_tir = tvt.Compose([
115
+ # tvt.Resize(self.diffusion_size, interpolation=Image.BICUBIC),
116
+ # tvt.CenterCrop(self.diffusion_size),
117
+ # tvt.ToTensor(), # 1 x H x W
118
+ # tvt.Normalize([0.5], [0.5]),
119
+ # ])
120
+
121
+ # in RGBTIRSupervisedDataset.__init__(...)
122
+ self.inject_edit_tokens = True # optional flag
123
+ self.edit_span = " ".join([f"<edit_{k}>" for k in range(8)])
124
+
125
+
126
+ def __len__(self):
127
+ return len(self.data)
128
+
129
+
130
+ @property
131
+ def lengths(self):
132
+ length_list = []
133
+ for sample in self.data:
134
+ img_tokens = 128 if 'image' in sample else 0
135
+ length_list.append(sum(len(conv['value'].split()) for conv in sample['conversations']) + img_tokens)
136
+ return length_list
137
+
138
+ @property
139
+ def modality_lengths(self):
140
+ length_list = []
141
+ for sample in self.data:
142
+ cur_len = sum(len(conv['value'].split()) for conv in sample['conversations'])
143
+ cur_len = cur_len if 'image' in sample else -cur_len
144
+ length_list.append(cur_len)
145
+ return length_list
146
+
147
+ # add this helper in the class
148
+ def _inject_edit_tokens_into_conversation(self, conv_rounds: list) -> list:
149
+ """
150
+ Ensure the last assistant ('gpt') turn is exactly the 8 edit tokens.
151
+ If there is no assistant turn yet, append one.
152
+ conv_rounds: [{'from': 'human'|'gpt', 'value': str}, ...]
153
+ """
154
+ if not self.inject_edit_tokens:
155
+ return conv_rounds
156
+
157
+ # find last assistant turn
158
+ last_gpt = None
159
+ for i in reversed(range(len(conv_rounds))):
160
+ if conv_rounds[i].get("from") == "gpt":
161
+ last_gpt = i
162
+ break
163
+
164
+ if last_gpt is None:
165
+ # append a new assistant turn with just the edit tokens
166
+ conv_rounds = conv_rounds + [{"from": "gpt", "value": self.edit_span}]
167
+ else:
168
+ # replace its content with exactly the edit tokens
169
+ conv_rounds = conv_rounds.copy()
170
+ conv_rounds[last_gpt] = {"from": "gpt", "value": self.edit_span}
171
+
172
+ return conv_rounds
173
+
174
+
175
+
176
+ # --- helpers mirroring your current preprocess path ---
177
+ def _preprocess_multimodal(self, sources):
178
+ use_im_tokens = self.mm_use_im_start_end
179
+ for source in sources:
180
+ for sentence in source:
181
+ if DEFAULT_IMAGE_TOKEN in sentence["value"]:
182
+ sentence["value"] = sentence["value"].replace(DEFAULT_IMAGE_TOKEN, "").strip()
183
+ sentence["value"] = DEFAULT_IMAGE_TOKEN + "\n" + sentence["value"]
184
+ sentence["value"] = sentence["value"].strip()
185
+ replace_token = DEFAULT_IMAGE_TOKEN
186
+ if use_im_tokens:
187
+ replace_token = DEFAULT_IM_START_TOKEN + replace_token + DEFAULT_IM_END_TOKEN
188
+ sentence["value"] = sentence["value"].replace(DEFAULT_IMAGE_TOKEN, replace_token)
189
+ return sources
190
+
191
+
192
+ def _preprocess_text(self, sources, has_image: bool):
193
+ # Follow the same path as llava.data.preprocess_v1 / llama_2 depending on conv template
194
+ conv = conversation_lib.default_conversation.copy()
195
+ roles = {"human": conv.roles[0], "gpt": conv.roles[1]}
196
+ conversations = []
197
+
198
+ for i, source in enumerate(sources):
199
+ if roles[source[0]["from"]] != conv.roles[0]:
200
+ source = source[1:] # skip non-human first
201
+ conv.messages = []
202
+ for j, sentence in enumerate(source):
203
+ role = roles[sentence["from"]]
204
+ assert role == conv.roles[j % 2]
205
+ conv.append_message(role, sentence["value"])
206
+ conversations.append(conv.get_prompt())
207
+
208
+ if has_image:
209
+ input_ids = torch.stack(
210
+ [tokenizer_image_token(p, self.tokenizer, return_tensors="pt") for p in conversations], dim=0
211
+ )
212
+ else:
213
+ input_ids = self.tokenizer(
214
+ conversations, return_tensors="pt", padding="longest",
215
+ max_length=self.tokenizer.model_max_length, truncation=True
216
+ ).input_ids
217
+
218
+ targets = input_ids.clone()
219
+
220
+ # mask human parts (match llava.data.preprocess_v1 / llama_2 implementations)
221
+ if conv.sep_style == conversation_lib.SeparatorStyle.TWO:
222
+ sep = conv.sep + conv.roles[1] + ": "
223
+ for conversation, target in zip(conversations, targets):
224
+ total_len = int(target.ne(self.tokenizer.pad_token_id).sum())
225
+ rounds = conversation.split(conv.sep2)
226
+ cur_len = 1
227
+ target[:cur_len] = IGNORE_INDEX
228
+ for i, rou in enumerate(rounds):
229
+ if rou == "":
230
+ break
231
+ parts = rou.split(sep)
232
+ if len(parts) != 2:
233
+ break
234
+ parts[0] += sep
235
+ if has_image:
236
+ round_len = len(tokenizer_image_token(rou, self.tokenizer))
237
+ instruction_len = len(tokenizer_image_token(parts[0], self.tokenizer)) - 2
238
+ else:
239
+ round_len = len(self.tokenizer(rou).input_ids)
240
+ instruction_len = len(self.tokenizer(parts[0]).input_ids) - 2
241
+ target[cur_len: cur_len + instruction_len] = IGNORE_INDEX
242
+ cur_len += round_len
243
+ target[cur_len:] = IGNORE_INDEX
244
+ if cur_len != total_len:
245
+ target[:] = IGNORE_INDEX # safe path
246
+ else:
247
+ # fall back to generic masking path (rare given your templates)
248
+ target = targets # already cloned
249
+ return dict(input_ids=input_ids[0], labels=targets[0])
250
+
251
+ def _load_rgb_for_llava(self, pil_img: Image.Image):
252
+ # honor aspect ratio option used by your current code
253
+ if self.image_aspect_ratio == "pad":
254
+ bg = tuple(int(x * 255) for x in self.image_processor.image_mean)
255
+ pil_img = _expand2square(pil_img, bg)
256
+ # LLaVA’s processor returns dict(pixel_values=...)
257
+ return self.image_processor.preprocess(pil_img, return_tensors="pt")["pixel_values"][0]
258
+
259
+ def __getitem__(self, idx) -> Dict[str, torch.Tensor]:
260
+ sample = self.data[idx]
261
+ rgb_rel = sample.get("image")
262
+ assert rgb_rel is not None, "Missing 'image' in sample"
263
+
264
+ rgb_path = os.path.join(self.image_folder, rgb_rel)
265
+ rgb = Image.open(rgb_path).convert("RGB")
266
+
267
+ # paired TIR (optional)
268
+ tir_path = _safe_replace_rgb_with_tir(rgb_path)
269
+ tir_exists = os.path.exists(tir_path)
270
+ if self.return_diffusion_pairs and (not tir_exists) and self.warn_missing_tir:
271
+ print(f"[RGBTIRDataset] Missing TIR for: {rgb_path}")
272
+
273
+ # LLaVA image tensor
274
+ image_tensor = self._load_rgb_for_llava(rgb)
275
+
276
+ # --------- NEW: build MGIE-style two-turn conversation from your JSON ---------
277
+ # human value is the "instruction"; gpt value is the "expressive" text
278
+ convs = sample["conversations"]
279
+ assert len(convs) >= 2, "Expected at least 2 turns (human, gpt)"
280
+
281
+ # take the first human turn as instruction
282
+ human_val = convs[0]["value"]
283
+ # strip a leading <image> (if present) to avoid double image tokens; we’ll insert ours below
284
+ if human_val.lstrip().startswith("<image>"):
285
+ human_val = human_val.lstrip()[len("<image>"):].lstrip()
286
+
287
+ # expressive text is the first gpt turn
288
+ expressive = convs[1]["value"].strip()
289
+
290
+ # choose the 8 tokens: use the ones you ALREADY added to the tokenizer/model
291
+ EDIT_TOKENS = [f"[IMG{k}]" for k in range(8)]
292
+ edit_span = " ".join(EDIT_TOKENS)
293
+
294
+ # build the two messages in MGIE style
295
+ query = f"{human_val}\n{DEFAULT_IMAGE_TOKEN}" # human: instruction + <image>
296
+ answer = f"{expressive} {edit_span}" # gpt: expressive + 8 tokens
297
+
298
+ sources = [[
299
+ {"from": "human", "value": query},
300
+ {"from": "gpt", "value": answer},
301
+ ]]
302
+
303
+ # make sure image token formatting matches your config
304
+ sources = self._preprocess_multimodal(copy.deepcopy(sources))
305
+ text_dict = self._preprocess_text(sources, has_image=True)
306
+
307
+ # pack outputs for the trainer
308
+ out = {
309
+ "input_ids": text_dict["input_ids"],
310
+ "labels": text_dict["labels"],
311
+ "image": image_tensor,
312
+ "image_sizes": [rgb.size],
313
+ }
314
+
315
+ # --------- optional diffusion pairs ---------
316
+ if self.return_diffusion_pairs:
317
+ rgb_for_diff = rgb
318
+ if tir_exists:
319
+ tir_for_diff = Image.open(tir_path).convert("RGB" if self.tir_as_rgb else "L")
320
+ else:
321
+ tir_for_diff = rgb_for_diff.convert("RGB" if self.tir_as_rgb else "L")
322
+
323
+ out["p2p_inp"] = self.diffusion_transform_rgb(rgb_for_diff)
324
+ out["p2p_ans"] = self.diffusion_transform_tir(tir_for_diff)
325
+
326
+ return out
327
+
328
+
llava/train/llama_flash_attn_monkey_patch.py ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Optional, Tuple
2
+ import warnings
3
+
4
+ import torch
5
+
6
+ import transformers
7
+ from transformers.models.llama.modeling_llama import apply_rotary_pos_emb, repeat_kv
8
+
9
+ try:
10
+ from flash_attn.flash_attn_interface import flash_attn_unpadded_qkvpacked_func
11
+ except ImportError:
12
+ from flash_attn.flash_attn_interface import flash_attn_varlen_qkvpacked_func as flash_attn_unpadded_qkvpacked_func
13
+ from flash_attn.bert_padding import unpad_input, pad_input
14
+
15
+
16
+ def forward(
17
+ self,
18
+ hidden_states: torch.Tensor,
19
+ attention_mask: Optional[torch.Tensor] = None,
20
+ position_ids: Optional[torch.Tensor] = None,
21
+ past_key_value: Optional[Tuple[torch.Tensor]] = None,
22
+ output_attentions: bool = False,
23
+ use_cache: bool = False,
24
+ ) -> Tuple[torch.Tensor, Optional[torch.Tensor], Optional[Tuple[torch.Tensor]]]:
25
+ if output_attentions:
26
+ warnings.warn(
27
+ "Output attentions is not supported for patched `LlamaAttention`, returning `None` instead."
28
+ )
29
+
30
+ bsz, q_len, _ = hidden_states.size()
31
+
32
+ query_states = (
33
+ self.q_proj(hidden_states)
34
+ .view(bsz, q_len, self.num_heads, self.head_dim)
35
+ .transpose(1, 2)
36
+ )
37
+ key_states = (
38
+ self.k_proj(hidden_states)
39
+ .view(bsz, q_len, self.num_key_value_heads, self.head_dim)
40
+ .transpose(1, 2)
41
+ )
42
+ value_states = (
43
+ self.v_proj(hidden_states)
44
+ .view(bsz, q_len, self.num_key_value_heads, self.head_dim)
45
+ .transpose(1, 2)
46
+ ) # shape: (b, num_heads, s, head_dim)
47
+
48
+ kv_seq_len = key_states.shape[-2]
49
+ if past_key_value is not None:
50
+ kv_seq_len += past_key_value[0].shape[-2]
51
+
52
+ cos, sin = self.rotary_emb(value_states, seq_len=kv_seq_len)
53
+ query_states, key_states = apply_rotary_pos_emb(
54
+ query_states, key_states, cos, sin, position_ids
55
+ )
56
+
57
+ if past_key_value is not None:
58
+ # reuse k, v
59
+ key_states = torch.cat([past_key_value[0], key_states], dim=2)
60
+ value_states = torch.cat([past_key_value[1], value_states], dim=2)
61
+
62
+ past_key_value = (key_states, value_states) if use_cache else None
63
+
64
+ # repeat k/v heads if n_kv_heads < n_heads
65
+ key_states = repeat_kv(key_states, self.num_key_value_groups)
66
+ value_states = repeat_kv(value_states, self.num_key_value_groups)
67
+
68
+ # Transform the data into the format required by flash attention
69
+ qkv = torch.stack([query_states, key_states, value_states], dim=2)
70
+ qkv = qkv.transpose(1, 3) # shape: [b, s, 3, num_heads, head_dim]
71
+ key_padding_mask = attention_mask
72
+
73
+ if key_padding_mask is None:
74
+ qkv = qkv.reshape(-1, 3, self.num_heads, self.head_dim)
75
+ cu_q_lens = torch.arange(
76
+ 0, (bsz + 1) * q_len, step=q_len, dtype=torch.int32, device=qkv.device
77
+ )
78
+ max_s = q_len
79
+ output = flash_attn_unpadded_qkvpacked_func(
80
+ qkv, cu_q_lens, max_s, 0.0, softmax_scale=None, causal=True
81
+ )
82
+ output = output.view(bsz, q_len, -1)
83
+ else:
84
+ qkv = qkv.reshape(bsz, q_len, -1)
85
+ qkv, indices, cu_q_lens, max_s = unpad_input(qkv, key_padding_mask)
86
+ qkv = qkv.view(-1, 3, self.num_heads, self.head_dim)
87
+ output_unpad = flash_attn_unpadded_qkvpacked_func(
88
+ qkv, cu_q_lens, max_s, 0.0, softmax_scale=None, causal=True
89
+ )
90
+ output_unpad = output_unpad.reshape(-1, self.num_heads * self.head_dim)
91
+ output = pad_input(output_unpad, indices, bsz, q_len)
92
+
93
+ return self.o_proj(output), None, past_key_value
94
+
95
+
96
+ # Disable the transformation of the attention mask in LlamaModel as the flash attention
97
+ # requires the attention mask to be the same as the key_padding_mask
98
+ def _prepare_decoder_attention_mask(
99
+ self, attention_mask, input_shape, inputs_embeds, past_key_values_length
100
+ ):
101
+ # [bsz, seq_len]
102
+ return attention_mask
103
+
104
+
105
+ def replace_llama_attn_with_flash_attn():
106
+ cuda_major, cuda_minor = torch.cuda.get_device_capability()
107
+ if cuda_major < 8:
108
+ warnings.warn(
109
+ "Flash attention is only supported on A100 or H100 GPU during training due to head dim > 64 backward."
110
+ "ref: https://github.com/HazyResearch/flash-attention/issues/190#issuecomment-1523359593"
111
+ )
112
+ transformers.models.llama.modeling_llama.LlamaModel._prepare_decoder_attention_mask = (
113
+ _prepare_decoder_attention_mask
114
+ )
115
+ transformers.models.llama.modeling_llama.LlamaAttention.forward = forward
llava/train/llama_xformers_attn_monkey_patch.py ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Directly copied the code from https://raw.githubusercontent.com/oobabooga/text-generation-webui/main/modules/llama_attn_hijack.py and made some adjustments
3
+ """
4
+
5
+ import logging
6
+ import math
7
+ from typing import Optional, Tuple
8
+
9
+ import torch
10
+ import transformers.models.llama.modeling_llama
11
+ from torch import nn
12
+
13
+ try:
14
+ import xformers.ops
15
+ except ImportError:
16
+ logging.error("xformers not found! Please install it before trying to use it.")
17
+
18
+
19
+ def replace_llama_attn_with_xformers_attn():
20
+ transformers.models.llama.modeling_llama.LlamaAttention.forward = xformers_forward
21
+
22
+
23
+ def xformers_forward(
24
+ self,
25
+ hidden_states: torch.Tensor,
26
+ attention_mask: Optional[torch.Tensor] = None,
27
+ position_ids: Optional[torch.LongTensor] = None,
28
+ past_key_value: Optional[Tuple[torch.Tensor]] = None,
29
+ output_attentions: bool = False,
30
+ use_cache: bool = False,
31
+ ) -> Tuple[torch.Tensor, Optional[torch.Tensor], Optional[Tuple[torch.Tensor]]]:
32
+ # pylint: disable=duplicate-code
33
+ bsz, q_len, _ = hidden_states.size()
34
+
35
+ query_states = (
36
+ self.q_proj(hidden_states)
37
+ .view(bsz, q_len, self.num_heads, self.head_dim)
38
+ .transpose(1, 2)
39
+ )
40
+ key_states = (
41
+ self.k_proj(hidden_states)
42
+ .view(bsz, q_len, self.num_heads, self.head_dim)
43
+ .transpose(1, 2)
44
+ )
45
+ value_states = (
46
+ self.v_proj(hidden_states)
47
+ .view(bsz, q_len, self.num_heads, self.head_dim)
48
+ .transpose(1, 2)
49
+ )
50
+
51
+ kv_seq_len = key_states.shape[-2]
52
+ if past_key_value is not None:
53
+ kv_seq_len += past_key_value[0].shape[-2]
54
+ cos, sin = self.rotary_emb(value_states, seq_len=kv_seq_len)
55
+ (
56
+ query_states,
57
+ key_states,
58
+ ) = transformers.models.llama.modeling_llama.apply_rotary_pos_emb(
59
+ query_states, key_states, cos, sin, position_ids
60
+ )
61
+ # [bsz, nh, t, hd]
62
+
63
+ if past_key_value is not None:
64
+ # reuse k, v, self_attention
65
+ key_states = torch.cat([past_key_value[0], key_states], dim=2)
66
+ value_states = torch.cat([past_key_value[1], value_states], dim=2)
67
+
68
+ past_key_value = (key_states, value_states) if use_cache else None
69
+
70
+ # We only apply xformers optimizations if we don't need to output the whole attention matrix
71
+ if not output_attentions:
72
+ query_states = query_states.transpose(1, 2)
73
+ key_states = key_states.transpose(1, 2)
74
+ value_states = value_states.transpose(1, 2)
75
+
76
+ # This is a nasty hack. We know attention_mask in transformers is either LowerTriangular or all Zeros.
77
+ # We therefore check if one element in the upper triangular portion is zero. If it is, then the mask is all zeros.
78
+ if attention_mask is None or attention_mask[0, 0, 0, 1] == 0:
79
+ # input and output should be of form (bsz, q_len, num_heads, head_dim)
80
+ attn_output = xformers.ops.memory_efficient_attention(
81
+ query_states, key_states, value_states, attn_bias=None
82
+ )
83
+ else:
84
+ # input and output should be of form (bsz, q_len, num_heads, head_dim)
85
+ attn_output = xformers.ops.memory_efficient_attention(
86
+ query_states,
87
+ key_states,
88
+ value_states,
89
+ attn_bias=xformers.ops.LowerTriangularMask(),
90
+ )
91
+ attn_weights = None
92
+ else:
93
+ attn_weights = torch.matmul(
94
+ query_states, key_states.transpose(2, 3)
95
+ ) / math.sqrt(self.head_dim)
96
+
97
+ if attn_weights.size() != (bsz, self.num_heads, q_len, kv_seq_len):
98
+ raise ValueError(
99
+ f"Attention weights should be of size {(bsz * self.num_heads, q_len, kv_seq_len)}, but is"
100
+ f" {attn_weights.size()}"
101
+ )
102
+
103
+ if attention_mask is not None:
104
+ if attention_mask.size() != (bsz, 1, q_len, kv_seq_len):
105
+ raise ValueError(
106
+ f"Attention mask should be of size {(bsz, 1, q_len, kv_seq_len)}, but is {attention_mask.size()}"
107
+ )
108
+ attn_weights = attn_weights + attention_mask
109
+ attn_weights = torch.max(
110
+ attn_weights, torch.tensor(torch.finfo(attn_weights.dtype).min)
111
+ )
112
+
113
+ # upcast attention to fp32
114
+ attn_weights = nn.functional.softmax(
115
+ attn_weights, dim=-1, dtype=torch.float32
116
+ ).to(query_states.dtype)
117
+ attn_output = torch.matmul(attn_weights, value_states)
118
+
119
+ if attn_output.size() != (bsz, self.num_heads, q_len, self.head_dim):
120
+ raise ValueError(
121
+ f"`attn_output` should be of size {(bsz, self.num_heads, q_len, self.head_dim)}, but is"
122
+ f" {attn_output.size()}"
123
+ )
124
+
125
+ attn_output = attn_output.transpose(1, 2)
126
+
127
+ attn_output = attn_output.reshape(bsz, q_len, self.hidden_size)
128
+ attn_output = self.o_proj(attn_output)
129
+ return attn_output, attn_weights, past_key_value
llava/train/llava_trainer.py ADDED
@@ -0,0 +1,273 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import torch
3
+ import torch.nn as nn
4
+
5
+ from torch.utils.data import Sampler
6
+
7
+ from transformers import Trainer
8
+ from transformers.trainer import (
9
+ is_sagemaker_mp_enabled,
10
+ get_parameter_names,
11
+ has_length,
12
+ ALL_LAYERNORM_LAYERS,
13
+ logger,
14
+ )
15
+ from typing import List, Optional
16
+
17
+
18
+ def maybe_zero_3(param, ignore_status=False, name=None):
19
+ from deepspeed import zero
20
+ from deepspeed.runtime.zero.partition_parameters import ZeroParamStatus
21
+ if hasattr(param, "ds_id"):
22
+ if param.ds_status == ZeroParamStatus.NOT_AVAILABLE:
23
+ if not ignore_status:
24
+ print(name, 'no ignore status')
25
+ with zero.GatheredParameters([param]):
26
+ param = param.data.detach().cpu().clone()
27
+ else:
28
+ param = param.detach().cpu().clone()
29
+ return param
30
+
31
+
32
+ def get_mm_adapter_state_maybe_zero_3(named_params, keys_to_match):
33
+ to_return = {k: t for k, t in named_params if any(key_match in k for key_match in keys_to_match)}
34
+ to_return = {k: maybe_zero_3(v, ignore_status=True, name=k).cpu() for k, v in to_return.items()}
35
+ return to_return
36
+
37
+
38
+ def split_to_even_chunks(indices, lengths, num_chunks):
39
+ """
40
+ Split a list of indices into `chunks` chunks of roughly equal lengths.
41
+ """
42
+
43
+ if len(indices) % num_chunks != 0:
44
+ return [indices[i::num_chunks] for i in range(num_chunks)]
45
+
46
+ num_indices_per_chunk = len(indices) // num_chunks
47
+
48
+ chunks = [[] for _ in range(num_chunks)]
49
+ chunks_lengths = [0 for _ in range(num_chunks)]
50
+ for index in indices:
51
+ shortest_chunk = chunks_lengths.index(min(chunks_lengths))
52
+ chunks[shortest_chunk].append(index)
53
+ chunks_lengths[shortest_chunk] += lengths[index]
54
+ if len(chunks[shortest_chunk]) == num_indices_per_chunk:
55
+ chunks_lengths[shortest_chunk] = float("inf")
56
+
57
+ return chunks
58
+
59
+
60
+ def get_modality_length_grouped_indices(lengths, batch_size, world_size, generator=None):
61
+ # We need to use torch for the random part as a distributed sampler will set the random seed for torch.
62
+ assert all(l != 0 for l in lengths), "Should not have zero length."
63
+ if all(l > 0 for l in lengths) or all(l < 0 for l in lengths):
64
+ # all samples are in the same modality
65
+ return get_length_grouped_indices(lengths, batch_size, world_size, generator=generator)
66
+ mm_indices, mm_lengths = zip(*[(i, l) for i, l in enumerate(lengths) if l > 0])
67
+ lang_indices, lang_lengths = zip(*[(i, -l) for i, l in enumerate(lengths) if l < 0])
68
+
69
+ mm_shuffle = [mm_indices[i] for i in get_length_grouped_indices(mm_lengths, batch_size, world_size, generator=None)]
70
+ lang_shuffle = [lang_indices[i] for i in get_length_grouped_indices(lang_lengths, batch_size, world_size, generator=None)]
71
+ megabatch_size = world_size * batch_size
72
+ mm_megabatches = [mm_shuffle[i : i + megabatch_size] for i in range(0, len(mm_shuffle), megabatch_size)]
73
+ lang_megabatches = [lang_shuffle[i : i + megabatch_size] for i in range(0, len(lang_shuffle), megabatch_size)]
74
+
75
+ last_mm = mm_megabatches[-1]
76
+ last_lang = lang_megabatches[-1]
77
+ additional_batch = last_mm + last_lang
78
+ megabatches = mm_megabatches[:-1] + lang_megabatches[:-1]
79
+ megabatch_indices = torch.randperm(len(megabatches), generator=generator)
80
+ megabatches = [megabatches[i] for i in megabatch_indices]
81
+
82
+ if len(additional_batch) > 0:
83
+ megabatches.append(sorted(additional_batch))
84
+
85
+ return [i for megabatch in megabatches for i in megabatch]
86
+
87
+
88
+ def get_length_grouped_indices(lengths, batch_size, world_size, generator=None, merge=True):
89
+ # We need to use torch for the random part as a distributed sampler will set the random seed for torch.
90
+ indices = torch.randperm(len(lengths), generator=generator)
91
+ megabatch_size = world_size * batch_size
92
+ megabatches = [indices[i : i + megabatch_size].tolist() for i in range(0, len(lengths), megabatch_size)]
93
+ megabatches = [sorted(megabatch, key=lambda i: lengths[i], reverse=True) for megabatch in megabatches]
94
+ megabatches = [split_to_even_chunks(megabatch, lengths, world_size) for megabatch in megabatches]
95
+
96
+ return [i for megabatch in megabatches for batch in megabatch for i in batch]
97
+
98
+
99
+ class LengthGroupedSampler(Sampler):
100
+ r"""
101
+ Sampler that samples indices in a way that groups together features of the dataset of roughly the same length while
102
+ keeping a bit of randomness.
103
+ """
104
+
105
+ def __init__(
106
+ self,
107
+ batch_size: int,
108
+ world_size: int,
109
+ lengths: Optional[List[int]] = None,
110
+ generator=None,
111
+ group_by_modality: bool = False,
112
+ ):
113
+ if lengths is None:
114
+ raise ValueError("Lengths must be provided.")
115
+
116
+ self.batch_size = batch_size
117
+ self.world_size = world_size
118
+ self.lengths = lengths
119
+ self.generator = generator
120
+ self.group_by_modality = group_by_modality
121
+
122
+ def __len__(self):
123
+ return len(self.lengths)
124
+
125
+ def __iter__(self):
126
+ if self.group_by_modality:
127
+ indices = get_modality_length_grouped_indices(self.lengths, self.batch_size, self.world_size, generator=self.generator)
128
+ else:
129
+ indices = get_length_grouped_indices(self.lengths, self.batch_size, self.world_size, generator=self.generator)
130
+ return iter(indices)
131
+
132
+
133
+ class LLaVATrainer(Trainer):
134
+
135
+ def _get_train_sampler(self) -> Optional[torch.utils.data.Sampler]:
136
+ if self.train_dataset is None or not has_length(self.train_dataset):
137
+ return None
138
+
139
+ if self.args.group_by_modality_length:
140
+ lengths = self.train_dataset.modality_lengths
141
+ return LengthGroupedSampler(
142
+ self.args.train_batch_size,
143
+ world_size=self.args.world_size * self.args.gradient_accumulation_steps,
144
+ lengths=lengths,
145
+ group_by_modality=True,
146
+ )
147
+ else:
148
+ return super()._get_train_sampler()
149
+
150
+ def create_optimizer(self):
151
+ """
152
+ Setup the optimizer.
153
+
154
+ We provide a reasonable default that works well. If you want to use something else, you can pass a tuple in the
155
+ Trainer's init through `optimizers`, or subclass and override this method in a subclass.
156
+ """
157
+ if is_sagemaker_mp_enabled():
158
+ return super().create_optimizer()
159
+
160
+ opt_model = self.model
161
+
162
+ if self.optimizer is None:
163
+ decay_parameters = get_parameter_names(opt_model, ALL_LAYERNORM_LAYERS)
164
+ decay_parameters = [name for name in decay_parameters if "bias" not in name]
165
+ if self.args.mm_projector_lr is not None:
166
+ projector_parameters = [name for name, _ in opt_model.named_parameters() if "mm_projector" in name]
167
+ optimizer_grouped_parameters = [
168
+ {
169
+ "params": [
170
+ p for n, p in opt_model.named_parameters() if (n in decay_parameters and n not in projector_parameters and p.requires_grad)
171
+ ],
172
+ "weight_decay": self.args.weight_decay,
173
+ },
174
+ {
175
+ "params": [
176
+ p for n, p in opt_model.named_parameters() if (n not in decay_parameters and n not in projector_parameters and p.requires_grad)
177
+ ],
178
+ "weight_decay": 0.0,
179
+ },
180
+ {
181
+ "params": [
182
+ p for n, p in opt_model.named_parameters() if (n in decay_parameters and n in projector_parameters and p.requires_grad)
183
+ ],
184
+ "weight_decay": self.args.weight_decay,
185
+ "lr": self.args.mm_projector_lr,
186
+ },
187
+ {
188
+ "params": [
189
+ p for n, p in opt_model.named_parameters() if (n not in decay_parameters and n in projector_parameters and p.requires_grad)
190
+ ],
191
+ "weight_decay": 0.0,
192
+ "lr": self.args.mm_projector_lr,
193
+ },
194
+ ]
195
+ else:
196
+ optimizer_grouped_parameters = [
197
+ {
198
+ "params": [
199
+ p for n, p in opt_model.named_parameters() if (n in decay_parameters and p.requires_grad)
200
+ ],
201
+ "weight_decay": self.args.weight_decay,
202
+ },
203
+ {
204
+ "params": [
205
+ p for n, p in opt_model.named_parameters() if (n not in decay_parameters and p.requires_grad)
206
+ ],
207
+ "weight_decay": 0.0,
208
+ },
209
+ ]
210
+
211
+ optimizer_cls, optimizer_kwargs = Trainer.get_optimizer_cls_and_kwargs(self.args)
212
+
213
+ self.optimizer = optimizer_cls(optimizer_grouped_parameters, **optimizer_kwargs)
214
+ if optimizer_cls.__name__ == "Adam8bit":
215
+ import bitsandbytes
216
+
217
+ manager = bitsandbytes.optim.GlobalOptimManager.get_instance()
218
+
219
+ skipped = 0
220
+ for module in opt_model.modules():
221
+ if isinstance(module, nn.Embedding):
222
+ skipped += sum({p.data_ptr(): p.numel() for p in module.parameters()}.values())
223
+ logger.info(f"skipped {module}: {skipped/2**20}M params")
224
+ manager.register_module_override(module, "weight", {"optim_bits": 32})
225
+ logger.debug(f"bitsandbytes: will optimize {module} in fp32")
226
+ logger.info(f"skipped: {skipped/2**20}M params")
227
+
228
+ return self.optimizer
229
+
230
+ def _save_checkpoint(self, model, trial, metrics=None):
231
+ if getattr(self.args, 'tune_mm_mlp_adapter', False):
232
+ from transformers.trainer_utils import PREFIX_CHECKPOINT_DIR
233
+ checkpoint_folder = f"{PREFIX_CHECKPOINT_DIR}-{self.state.global_step}"
234
+
235
+ run_dir = self._get_output_dir(trial=trial)
236
+ output_dir = os.path.join(run_dir, checkpoint_folder)
237
+
238
+ # Only save Adapter
239
+ keys_to_match = ['mm_projector', 'vision_resampler']
240
+ if getattr(self.args, "use_im_start_end", False):
241
+ keys_to_match.extend(['embed_tokens', 'embed_in'])
242
+
243
+ weight_to_save = get_mm_adapter_state_maybe_zero_3(self.model.named_parameters(), keys_to_match)
244
+
245
+ if self.args.local_rank == 0 or self.args.local_rank == -1:
246
+ self.model.config.save_pretrained(output_dir)
247
+ torch.save(weight_to_save, os.path.join(output_dir, f'mm_projector.bin'))
248
+ else:
249
+ super(LLaVATrainer, self)._save_checkpoint(model, trial, metrics)
250
+
251
+ def _save(self, output_dir: Optional[str] = None, state_dict=None):
252
+ if getattr(self.args, 'tune_mm_mlp_adapter', False):
253
+ pass
254
+ else:
255
+ super(LLaVATrainer, self)._save(output_dir, state_dict)
256
+
257
+ def compute_loss(self, model, inputs, return_outputs=False):
258
+ outputs = model(**inputs)
259
+ loss = outputs.loss
260
+
261
+ logs = {}
262
+ # ALWAYS convert tensors -> floats before self.log(...)
263
+ if hasattr(outputs, "loss_ce") and outputs.loss_ce is not None:
264
+ logs["ce_loss"] = outputs.loss_ce.detach().float().mean().item()
265
+ if hasattr(outputs, "loss_edit") and outputs.loss_edit is not None:
266
+ logs["diffusion_loss"] = outputs.loss_edit.detach().float().mean().item()
267
+ # (optional) also log total loss as a scalar
268
+ logs["loss"] = loss.detach().float().item()
269
+
270
+ if logs:
271
+ self.log(logs)
272
+
273
+ return (loss, outputs) if return_outputs else loss
llava/train/train_vlm_ip2p_256.py ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Training script for VLM-guided InstructPix2Pix (256x256 resolution).
4
+
5
+ Optimized for faster training with 256x256 images.
6
+
7
+ Key Features:
8
+ 1. 256x256 diffusion resolution (4x faster than 512x512)
9
+ 2. Choice of EditMapper: Simple MLP or MGIE-style Transformer
10
+ 3. All cross-attention blocks injected by default
11
+ 4. Compatible with base IP2P model (no need for fine-tuned checkpoint)
12
+
13
+ Usage:
14
+ deepspeed --num_gpus=4 llava/train/train_vlm_ip2p_256.py \\
15
+ --llava-base-path checkpoints/llava-1.5-7b-hf \\
16
+ --llava-lora-path checkpoints/llava-miragehd-prior-bbox \\
17
+ --ip2p-pretrained ../diffusers/ip2p_ema_safetensor \\
18
+ --data-path data/llava_no_ranking_nobbox.json \\
19
+ --image-folder ../ \\
20
+ --output-dir ./outputs/ip_adapter_256_v1 \\
21
+ --batch-size 4 \\
22
+ --num-epochs 100 \\
23
+ --use-mgie-mapper \\
24
+ --deepspeed ./scripts/deepspeed_zero2_vlm_ip2p.json
25
+ """
26
+
27
+ import argparse
28
+ import os
29
+ import sys
30
+ from pathlib import Path
31
+
32
+ import torch
33
+ import torch.nn as nn
34
+
35
+ try:
36
+ import deepspeed
37
+ DEEPSPEED_AVAILABLE = True
38
+ except ImportError:
39
+ DEEPSPEED_AVAILABLE = False
40
+
41
+ # Import the base trainer
42
+ sys.path.append(str(Path(__file__).parent.parent.parent))
43
+ from llava.train.train_vlm_guided_ip2p import VLMGuidedIP2PTrainer, parse_args
44
+
45
+
46
+ class VLMGuidedIP2P256Trainer(VLMGuidedIP2PTrainer):
47
+ """
48
+ Trainer optimized for 256x256 resolution.
49
+
50
+ Inherits from base trainer and overrides data loading
51
+ to use 256x256 images for diffusion.
52
+ """
53
+
54
+ def setup_dataloaders(self):
55
+ """Setup dataloaders with 256x256 resolution for diffusion"""
56
+ from llava.data import create_dataloaders
57
+
58
+ print("\n" + "="*80)
59
+ print("SETTING UP DATALOADERS (256x256 RESOLUTION)")
60
+ print("="*80)
61
+
62
+ # Override diffusion_size to 256
63
+ original_diffusion_size = self.args.diffusion_size if hasattr(self.args, 'diffusion_size') else 512
64
+ self.args.diffusion_size = 256 # Force 256x256 for diffusion
65
+
66
+ print(f" Diffusion resolution: {self.args.diffusion_size}x{self.args.diffusion_size}")
67
+ print(f" (Original was: {original_diffusion_size}x{original_diffusion_size})")
68
+
69
+ # Call parent setup with modified args
70
+ super().setup_dataloaders()
71
+
72
+ print("="*80 + "\n")
73
+
74
+
75
+ def main():
76
+ # Parse arguments
77
+ args = parse_args()
78
+
79
+ # Override defaults for 256x256 training
80
+ print("\n" + "="*80)
81
+ print("VLM-GUIDED IP2P TRAINING (256x256 OPTIMIZED)")
82
+ print("="*80)
83
+ print(f"Resolution: 256x256 (4x faster than 512x512)")
84
+ print(f"EditMapper: {'MGIE-style' if args.use_mgie_mapper else 'Simple MLP'}")
85
+ print(f"Target blocks: {'All cross-attention' if args.target_blocks is None else args.target_blocks}")
86
+ print(f"IP2P checkpoint: {args.ip2p_pretrained}")
87
+
88
+ # Warn if using fine-tuned checkpoint
89
+ if args.ip2p_checkpoint:
90
+ print("\n⚠ WARNING: You specified --ip2p-checkpoint")
91
+ print(" For 256x256 training, you should use the base model (--ip2p-pretrained only)")
92
+ print(" Fine-tuned checkpoints may be trained on 512x512 resolution")
93
+ response = input(" Continue anyway? (y/N): ")
94
+ if response.lower() != 'y':
95
+ print("Exiting...")
96
+ return
97
+
98
+ print("="*80 + "\n")
99
+
100
+ # Create trainer
101
+ trainer = VLMGuidedIP2P256Trainer(args)
102
+
103
+ # Train
104
+ trainer.train()
105
+
106
+
107
+ if __name__ == "__main__":
108
+ main()
109
+
llava/utils.py ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import datetime
2
+ import logging
3
+ import logging.handlers
4
+ import os
5
+ import sys
6
+
7
+ import requests
8
+
9
+ from llava.constants import LOGDIR
10
+
11
+ server_error_msg = "**NETWORK ERROR DUE TO HIGH TRAFFIC. PLEASE REGENERATE OR REFRESH THIS PAGE.**"
12
+ moderation_msg = "YOUR INPUT VIOLATES OUR CONTENT MODERATION GUIDELINES. PLEASE TRY AGAIN."
13
+
14
+ handler = None
15
+
16
+
17
+ def build_logger(logger_name, logger_filename):
18
+ global handler
19
+
20
+ formatter = logging.Formatter(
21
+ fmt="%(asctime)s | %(levelname)s | %(name)s | %(message)s",
22
+ datefmt="%Y-%m-%d %H:%M:%S",
23
+ )
24
+
25
+ # Set the format of root handlers
26
+ if not logging.getLogger().handlers:
27
+ logging.basicConfig(level=logging.INFO)
28
+ logging.getLogger().handlers[0].setFormatter(formatter)
29
+
30
+ # Redirect stdout and stderr to loggers
31
+ stdout_logger = logging.getLogger("stdout")
32
+ stdout_logger.setLevel(logging.INFO)
33
+ sl = StreamToLogger(stdout_logger, logging.INFO)
34
+ sys.stdout = sl
35
+
36
+ stderr_logger = logging.getLogger("stderr")
37
+ stderr_logger.setLevel(logging.ERROR)
38
+ sl = StreamToLogger(stderr_logger, logging.ERROR)
39
+ sys.stderr = sl
40
+
41
+ # Get logger
42
+ logger = logging.getLogger(logger_name)
43
+ logger.setLevel(logging.INFO)
44
+
45
+ # Add a file handler for all loggers
46
+ if handler is None:
47
+ os.makedirs(LOGDIR, exist_ok=True)
48
+ filename = os.path.join(LOGDIR, logger_filename)
49
+ handler = logging.handlers.TimedRotatingFileHandler(
50
+ filename, when='D', utc=True, encoding='UTF-8')
51
+ handler.setFormatter(formatter)
52
+
53
+ for name, item in logging.root.manager.loggerDict.items():
54
+ if isinstance(item, logging.Logger):
55
+ item.addHandler(handler)
56
+
57
+ return logger
58
+
59
+
60
+ class StreamToLogger(object):
61
+ """
62
+ Fake file-like stream object that redirects writes to a logger instance.
63
+ """
64
+ def __init__(self, logger, log_level=logging.INFO):
65
+ self.terminal = sys.stdout
66
+ self.logger = logger
67
+ self.log_level = log_level
68
+ self.linebuf = ''
69
+
70
+ def __getattr__(self, attr):
71
+ return getattr(self.terminal, attr)
72
+
73
+ def write(self, buf):
74
+ temp_linebuf = self.linebuf + buf
75
+ self.linebuf = ''
76
+ for line in temp_linebuf.splitlines(True):
77
+ # From the io.TextIOWrapper docs:
78
+ # On output, if newline is None, any '\n' characters written
79
+ # are translated to the system default line separator.
80
+ # By default sys.stdout.write() expects '\n' newlines and then
81
+ # translates them so this is still cross platform.
82
+ if line[-1] == '\n':
83
+ self.logger.log(self.log_level, line.rstrip())
84
+ else:
85
+ self.linebuf += line
86
+
87
+ def flush(self):
88
+ if self.linebuf != '':
89
+ self.logger.log(self.log_level, self.linebuf.rstrip())
90
+ self.linebuf = ''
91
+
92
+
93
+ def disable_torch_init():
94
+ """
95
+ Disable the redundant torch default initialization to accelerate model creation.
96
+ """
97
+ import torch
98
+ setattr(torch.nn.Linear, "reset_parameters", lambda self: None)
99
+ setattr(torch.nn.LayerNorm, "reset_parameters", lambda self: None)
100
+
101
+
102
+ def violates_moderation(text):
103
+ """
104
+ Check whether the text violates OpenAI moderation API.
105
+ """
106
+ url = "https://api.openai.com/v1/moderations"
107
+ headers = {"Content-Type": "application/json",
108
+ "Authorization": "Bearer " + os.environ["OPENAI_API_KEY"]}
109
+ text = text.replace("\n", "")
110
+ data = "{" + '"input": ' + f'"{text}"' + "}"
111
+ data = data.encode("utf-8")
112
+ try:
113
+ ret = requests.post(url, headers=headers, data=data, timeout=5)
114
+ flagged = ret.json()["results"][0]["flagged"]
115
+ except requests.exceptions.RequestException as e:
116
+ flagged = False
117
+ except KeyError as e:
118
+ flagged = False
119
+
120
+ return flagged
121
+
122
+
123
+ def pretty_print_semaphore(semaphore):
124
+ if semaphore is None:
125
+ return "None"
126
+ return f"Semaphore(value={semaphore._value}, locked={semaphore.locked()})"
requirements.txt ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Core inference
2
+ torch>=2.0.0
3
+ torchvision>=0.15.0
4
+ diffusers>=0.21.0
5
+ transformers>=4.36.0
6
+ accelerate>=0.25.0
7
+ safetensors>=0.4.0
8
+
9
+ # Image I/O
10
+ pillow>=9.0.0
11
+ tqdm>=4.65.0
12
+
13
+ # LLaVA on-the-fly mode only (optional for reference-cache inference)
14
+ peft>=0.7.0
15
+ sentencepiece>=0.1.99
16
+ protobuf>=3.20.0
17
+
18
+ # LLaVA vision backbone
19
+ timm>=0.9.0
20
+ einops>=0.7.0
21
+
22
+ # Hugging Face hub (weight download)
23
+ huggingface-hub>=0.20.0
thera_llava.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Lazy loader for FrozenLLaVAExtractor.
3
+
4
+ Reference-cache inference does not need LLaVA weights at runtime. The extractor
5
+ is imported only when on-the-fly feature extraction is requested.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import inspect
11
+ from typing import Any
12
+
13
+
14
+ def create_frozen_llava_extractor(**kwargs: Any):
15
+ """Construct FrozenLLaVAExtractor; imports LLaVA stack on first use."""
16
+ from llava.model.frozen_llava_extractor import FrozenLLaVAExtractor
17
+
18
+ sig = inspect.signature(FrozenLLaVAExtractor.__init__)
19
+ if "merge_lora" not in sig.parameters:
20
+ kwargs.pop("merge_lora", None)
21
+ return FrozenLLaVAExtractor(**kwargs)
thera_paths.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Default paths for TherA inference (relative to this repository root).
3
+
4
+ Download model weights into the `weights/` directory — see README.md.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import sys
10
+ from pathlib import Path
11
+
12
+ PROJECT_ROOT = Path(__file__).resolve().parent
13
+ WEIGHTS_DIR = PROJECT_ROOT / "weights"
14
+
15
+ DEFAULT_CHECKPOINT = WEIGHTS_DIR / "checkpoint"
16
+ DEFAULT_MERGED_MODEL = WEIGHTS_DIR / "merged_models"
17
+ DEFAULT_PRETRAINED_SD = WEIGHTS_DIR / "stable-diffusion"
18
+ DEFAULT_REFERENCE_CACHES = WEIGHTS_DIR / "reference_caches"
19
+
20
+
21
+ def setup_project_path() -> Path:
22
+ """Ensure TherA root is on sys.path so local packages import correctly."""
23
+ root = str(PROJECT_ROOT)
24
+ if root not in sys.path:
25
+ sys.path.insert(0, root)
26
+ return PROJECT_ROOT
weights/.gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
weights/README.md ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ ---
2
+ license: mit
3
+ ---
weights/TherA_VLM/adapter_config.json ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "alpha_pattern": {},
3
+ "auto_mapping": null,
4
+ "base_model_name_or_path": "./checkpoints/llava-1.5-7b-hf",
5
+ "bias": "none",
6
+ "fan_in_fan_out": false,
7
+ "inference_mode": true,
8
+ "init_lora_weights": true,
9
+ "layer_replication": null,
10
+ "layers_pattern": null,
11
+ "layers_to_transform": null,
12
+ "loftq_config": {},
13
+ "lora_alpha": 256,
14
+ "lora_dropout": 0.05,
15
+ "megatron_config": null,
16
+ "megatron_core": "megatron.core",
17
+ "modules_to_save": null,
18
+ "peft_type": "LORA",
19
+ "r": 128,
20
+ "rank_pattern": {},
21
+ "revision": null,
22
+ "target_modules": [
23
+ "up_proj",
24
+ "v_proj",
25
+ "q_proj",
26
+ "o_proj",
27
+ "gate_proj",
28
+ "down_proj",
29
+ "k_proj"
30
+ ],
31
+ "task_type": "CAUSAL_LM",
32
+ "use_dora": false,
33
+ "use_rslora": false
34
+ }
weights/TherA_VLM/config.json ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_name_or_path": "./checkpoints/llava-1.5-7b-hf",
3
+ "architectures": [
4
+ "LlavaLlamaForCausalLM"
5
+ ],
6
+ "attention_bias": false,
7
+ "attention_dropout": 0.0,
8
+ "bos_token_id": 1,
9
+ "eos_token_id": 2,
10
+ "freeze_mm_mlp_adapter": false,
11
+ "freeze_mm_vision_resampler": false,
12
+ "hidden_act": "silu",
13
+ "hidden_size": 4096,
14
+ "image_aspect_ratio": "pad",
15
+ "initializer_range": 0.02,
16
+ "intermediate_size": 11008,
17
+ "max_length": 4096,
18
+ "max_position_embeddings": 4096,
19
+ "mm_hidden_size": 1024,
20
+ "mm_patch_merge_type": "flat",
21
+ "mm_projector_lr": 2e-05,
22
+ "mm_projector_type": "mlp2x_gelu",
23
+ "mm_resampler_type": null,
24
+ "mm_use_im_patch_token": false,
25
+ "mm_use_im_start_end": false,
26
+ "mm_vision_select_feature": "patch",
27
+ "mm_vision_select_layer": -2,
28
+ "mm_vision_tower": "openai/clip-vit-large-patch14-336",
29
+ "model_type": "llava_llama",
30
+ "num_attention_heads": 32,
31
+ "num_hidden_layers": 32,
32
+ "num_key_value_heads": 32,
33
+ "pad_token_id": 0,
34
+ "pretraining_tp": 1,
35
+ "rms_norm_eps": 1e-05,
36
+ "rope_scaling": null,
37
+ "rope_theta": 10000.0,
38
+ "tie_word_embeddings": false,
39
+ "tokenizer_model_max_length": 2048,
40
+ "tokenizer_padding_side": "right",
41
+ "torch_dtype": "float16",
42
+ "transformers_version": "4.37.2",
43
+ "tune_mm_mlp_adapter": false,
44
+ "tune_mm_vision_resampler": false,
45
+ "unfreeze_mm_vision_tower": false,
46
+ "use_cache": true,
47
+ "use_mm_proj": true,
48
+ "vocab_size": 32000
49
+ }
weights/TherA_VLM/trainer_state.json ADDED
The diff for this file is too large to render. See raw diff
 
weights/llava-1.5-7b-hf/.gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
weights/llava-1.5-7b-hf/README.md ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ language:
3
+ - en
4
+ datasets:
5
+ - liuhaotian/LLaVA-Instruct-150K
6
+ pipeline_tag: image-text-to-text
7
+ arxiv: 2304.08485
8
+ license: llama2
9
+ tags:
10
+ - vision
11
+ - image-text-to-text
12
+ ---
13
+ # LLaVA Model Card
14
+
15
+ ![image/png](https://cdn-uploads.huggingface.co/production/uploads/62441d1d9fdefb55a0b7d12c/FPshq08TKYD0e-qwPLDVO.png)
16
+
17
+ Below is the model card of Llava model 7b, which is copied from the original Llava model card that you can find [here](https://huggingface.co/liuhaotian/llava-v1.5-13b).
18
+
19
+ Check out also the Google Colab demo to run Llava on a free-tier Google Colab instance: [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/1qsl6cd2c8gGtEW1xV5io7S8NHh-Cp1TV?usp=sharing)
20
+
21
+ Or check out our Spaces demo! [![Open in Spaces](https://huggingface.co/datasets/huggingface/badges/resolve/main/open-in-hf-spaces-md-dark.svg)](https://huggingface.co/spaces/llava-hf/llava-4bit)
22
+
23
+
24
+ ## Model details
25
+
26
+ **Model type:**
27
+ LLaVA is an open-source chatbot trained by fine-tuning LLaMA/Vicuna on GPT-generated multimodal instruction-following data.
28
+ It is an auto-regressive language model, based on the transformer architecture.
29
+
30
+ **Model date:**
31
+ LLaVA-v1.5-7B was trained in September 2023.
32
+
33
+ **Paper or resources for more information:**
34
+ https://llava-vl.github.io/
35
+
36
+ ## How to use the model
37
+
38
+ First, make sure to have `transformers >= 4.35.3`.
39
+ The model supports multi-image and multi-prompt generation. Meaning that you can pass multiple images in your prompt. Make sure also to follow the correct prompt template (`USER: xxx\nASSISTANT:`) and add the token `<image>` to the location where you want to query images:
40
+
41
+ ### Using `pipeline`:
42
+
43
+ Below we used [`"llava-hf/llava-1.5-7b-hf"`](https://huggingface.co/llava-hf/llava-1.5-7b-hf) checkpoint.
44
+
45
+ ```python
46
+ from transformers import pipeline
47
+
48
+ pipe = pipeline("image-text-to-text", model="llava-hf/llava-1.5-7b-hf")
49
+ messages = [
50
+ {
51
+ "role": "user",
52
+ "content": [
53
+ {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/tasks/ai2d-demo.jpg"},
54
+ {"type": "text", "text": "What does the label 15 represent? (1) lava (2) core (3) tunnel (4) ash cloud"},
55
+ ],
56
+ },
57
+ ]
58
+
59
+ out = pipe(text=messages, max_new_tokens=20)
60
+ print(out)
61
+ >>> [{'input_text': [{'role': 'user', 'content': [{'type': 'image', 'url': 'https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/tasks/ai2d-demo.jpg'}, {'type': 'text', 'text': 'What does the label 15 represent? (1) lava (2) core (3) tunnel (4) ash cloud'}]}], 'generated_text': 'Lava'}]
62
+ ```
63
+
64
+ ### Using pure `transformers`:
65
+
66
+ Below is an example script to run generation in `float16` precision on a GPU device:
67
+
68
+ ```python
69
+ import requests
70
+ from PIL import Image
71
+
72
+ import torch
73
+ from transformers import AutoProcessor, LlavaForConditionalGeneration
74
+
75
+ model_id = "llava-hf/llava-1.5-7b-hf"
76
+ model = LlavaForConditionalGeneration.from_pretrained(
77
+ model_id,
78
+ torch_dtype=torch.float16,
79
+ low_cpu_mem_usage=True,
80
+ ).to(0)
81
+
82
+ processor = AutoProcessor.from_pretrained(model_id)
83
+
84
+ # Define a chat history and use `apply_chat_template` to get correctly formatted prompt
85
+ # Each value in "content" has to be a list of dicts with types ("text", "image")
86
+ conversation = [
87
+ {
88
+
89
+ "role": "user",
90
+ "content": [
91
+ {"type": "text", "text": "What are these?"},
92
+ {"type": "image"},
93
+ ],
94
+ },
95
+ ]
96
+ prompt = processor.apply_chat_template(conversation, add_generation_prompt=True)
97
+
98
+ image_file = "http://images.cocodataset.org/val2017/000000039769.jpg"
99
+ raw_image = Image.open(requests.get(image_file, stream=True).raw)
100
+ inputs = processor(images=raw_image, text=prompt, return_tensors='pt').to(0, torch.float16)
101
+
102
+ output = model.generate(**inputs, max_new_tokens=200, do_sample=False)
103
+ print(processor.decode(output[0][2:], skip_special_tokens=True))
104
+ ```
105
+
106
+ -----------
107
+ From transformers>=v4.48, you can also pass image url or local path to the conversation history, and let the chat template handle the rest.
108
+ Chat template will load the image for you and return inputs in `torch.Tensor` which you can pass directly to `model.generate()`
109
+
110
+ ```python
111
+ messages = [
112
+ {
113
+ "role": "user",
114
+ "content": [
115
+ {"type": "image", "url": "https://www.ilankelman.org/stopsigns/australia.jpg"}
116
+ {"type": "text", "text": "What is shown in this image?"},
117
+ ],
118
+ },
119
+ ]
120
+
121
+ inputs = processor.apply_chat_template(messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors"pt")
122
+ output = model.generate(**inputs, max_new_tokens=50)
123
+ ```
124
+
125
+ ### Model optimization
126
+
127
+ #### 4-bit quantization through `bitsandbytes` library
128
+
129
+ First make sure to install `bitsandbytes`, `pip install bitsandbytes` and make sure to have access to a CUDA compatible GPU device. Simply change the snippet above with:
130
+
131
+ ```diff
132
+ model = LlavaForConditionalGeneration.from_pretrained(
133
+ model_id,
134
+ torch_dtype=torch.float16,
135
+ low_cpu_mem_usage=True,
136
+ + load_in_4bit=True
137
+ )
138
+ ```
139
+
140
+ #### Use Flash-Attention 2 to further speed-up generation
141
+
142
+ First make sure to install `flash-attn`. Refer to the [original repository of Flash Attention](https://github.com/Dao-AILab/flash-attention) regarding that package installation. Simply change the snippet above with:
143
+
144
+ ```diff
145
+ model = LlavaForConditionalGeneration.from_pretrained(
146
+ model_id,
147
+ torch_dtype=torch.float16,
148
+ low_cpu_mem_usage=True,
149
+ + use_flash_attention_2=True
150
+ ).to(0)
151
+ ```
152
+
153
+ ## License
154
+ Llama 2 is licensed under the LLAMA 2 Community License,
155
+ Copyright (c) Meta Platforms, Inc. All Rights Reserved.
weights/llava-1.5-7b-hf/added_tokens.json ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ {
2
+ "<image>": 32000,
3
+ "<pad>": 32001
4
+ }
weights/llava-1.5-7b-hf/chat_template.jinja ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ {% for message in messages %}{% if message['role'] != 'system' %}{{ message['role'].upper() + ': '}}{% endif %}{# Render all images first #}{% for content in message['content'] | selectattr('type', 'equalto', 'image') %}{{ '<image>
2
+ ' }}{% endfor %}{# Render all text next #}{% if message['role'] != 'assistant' %}{% for content in message['content'] | selectattr('type', 'equalto', 'text') %}{{ content['text'] + ' '}}{% endfor %}{% else %}{% for content in message['content'] | selectattr('type', 'equalto', 'text') %}{% generation %}{{ content['text'] + ' '}}{% endgeneration %}{% endfor %}{% endif %}{% endfor %}{% if add_generation_prompt %}{{ 'ASSISTANT:' }}{% endif %}
weights/llava-1.5-7b-hf/chat_template.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "chat_template": "{% for message in messages %}{% if message['role'] != 'system' %}{{ message['role'].upper() + ': '}}{% endif %}{# Render all images first #}{% for content in message['content'] | selectattr('type', 'equalto', 'image') %}{{ '<image>\n' }}{% endfor %}{# Render all text next #}{% if message['role'] != 'assistant' %}{% for content in message['content'] | selectattr('type', 'equalto', 'text') %}{{ content['text'] + ' '}}{% endfor %}{% else %}{% for content in message['content'] | selectattr('type', 'equalto', 'text') %}{% generation %}{{ content['text'] + ' '}}{% endgeneration %}{% endfor %}{% endif %}{% endfor %}{% if add_generation_prompt %}{{ 'ASSISTANT:' }}{% endif %}"
3
+ }
weights/llava-1.5-7b-hf/config.json ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "LlavaForConditionalGeneration"
4
+ ],
5
+ "ignore_index": -100,
6
+ "image_token_index": 32000,
7
+ "model_type": "llava",
8
+ "pad_token_id": 32001,
9
+ "projector_hidden_act": "gelu",
10
+ "text_config": {
11
+ "_name_or_path": "lmsys/vicuna-7b-v1.5",
12
+ "architectures": [
13
+ "LlamaForCausalLM"
14
+ ],
15
+ "max_position_embeddings": 4096,
16
+ "model_type": "llama",
17
+ "rms_norm_eps": 1e-05,
18
+ "torch_dtype": "float16",
19
+ "vocab_size": 32064
20
+ },
21
+ "tie_word_embeddings": false,
22
+ "torch_dtype": "float16",
23
+ "transformers_version": "4.36.0.dev0",
24
+ "vision_config": {
25
+ "hidden_size": 1024,
26
+ "image_size": 336,
27
+ "intermediate_size": 4096,
28
+ "model_type": "clip_vision_model",
29
+ "num_attention_heads": 16,
30
+ "num_hidden_layers": 24,
31
+ "patch_size": 14,
32
+ "projection_dim": 768,
33
+ "vocab_size": 32000
34
+ },
35
+ "vision_feature_layer": -2,
36
+ "vision_feature_select_strategy": "default",
37
+ "vocab_size": 32064
38
+ }
weights/llava-1.5-7b-hf/generation_config.json ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ {
2
+ "_from_model_config": true,
3
+ "bos_token_id": 1,
4
+ "eos_token_id": 2,
5
+ "pad_token_id": 32001,
6
+ "transformers_version": "4.36.0.dev0"
7
+ }
weights/llava-1.5-7b-hf/model.safetensors.index.json ADDED
@@ -0,0 +1,693 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "metadata": {
3
+ "total_size": 14126854144
4
+ },
5
+ "weight_map": {
6
+ "language_model.lm_head.weight": "model-00003-of-00003.safetensors",
7
+ "language_model.model.embed_tokens.weight": "model-00001-of-00003.safetensors",
8
+ "language_model.model.layers.0.input_layernorm.weight": "model-00001-of-00003.safetensors",
9
+ "language_model.model.layers.0.mlp.down_proj.weight": "model-00001-of-00003.safetensors",
10
+ "language_model.model.layers.0.mlp.gate_proj.weight": "model-00001-of-00003.safetensors",
11
+ "language_model.model.layers.0.mlp.up_proj.weight": "model-00001-of-00003.safetensors",
12
+ "language_model.model.layers.0.post_attention_layernorm.weight": "model-00001-of-00003.safetensors",
13
+ "language_model.model.layers.0.self_attn.k_proj.weight": "model-00001-of-00003.safetensors",
14
+ "language_model.model.layers.0.self_attn.o_proj.weight": "model-00001-of-00003.safetensors",
15
+ "language_model.model.layers.0.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
16
+ "language_model.model.layers.0.self_attn.v_proj.weight": "model-00001-of-00003.safetensors",
17
+ "language_model.model.layers.1.input_layernorm.weight": "model-00001-of-00003.safetensors",
18
+ "language_model.model.layers.1.mlp.down_proj.weight": "model-00001-of-00003.safetensors",
19
+ "language_model.model.layers.1.mlp.gate_proj.weight": "model-00001-of-00003.safetensors",
20
+ "language_model.model.layers.1.mlp.up_proj.weight": "model-00001-of-00003.safetensors",
21
+ "language_model.model.layers.1.post_attention_layernorm.weight": "model-00001-of-00003.safetensors",
22
+ "language_model.model.layers.1.self_attn.k_proj.weight": "model-00001-of-00003.safetensors",
23
+ "language_model.model.layers.1.self_attn.o_proj.weight": "model-00001-of-00003.safetensors",
24
+ "language_model.model.layers.1.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
25
+ "language_model.model.layers.1.self_attn.v_proj.weight": "model-00001-of-00003.safetensors",
26
+ "language_model.model.layers.10.input_layernorm.weight": "model-00002-of-00003.safetensors",
27
+ "language_model.model.layers.10.mlp.down_proj.weight": "model-00002-of-00003.safetensors",
28
+ "language_model.model.layers.10.mlp.gate_proj.weight": "model-00002-of-00003.safetensors",
29
+ "language_model.model.layers.10.mlp.up_proj.weight": "model-00002-of-00003.safetensors",
30
+ "language_model.model.layers.10.post_attention_layernorm.weight": "model-00002-of-00003.safetensors",
31
+ "language_model.model.layers.10.self_attn.k_proj.weight": "model-00002-of-00003.safetensors",
32
+ "language_model.model.layers.10.self_attn.o_proj.weight": "model-00002-of-00003.safetensors",
33
+ "language_model.model.layers.10.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
34
+ "language_model.model.layers.10.self_attn.v_proj.weight": "model-00002-of-00003.safetensors",
35
+ "language_model.model.layers.11.input_layernorm.weight": "model-00002-of-00003.safetensors",
36
+ "language_model.model.layers.11.mlp.down_proj.weight": "model-00002-of-00003.safetensors",
37
+ "language_model.model.layers.11.mlp.gate_proj.weight": "model-00002-of-00003.safetensors",
38
+ "language_model.model.layers.11.mlp.up_proj.weight": "model-00002-of-00003.safetensors",
39
+ "language_model.model.layers.11.post_attention_layernorm.weight": "model-00002-of-00003.safetensors",
40
+ "language_model.model.layers.11.self_attn.k_proj.weight": "model-00002-of-00003.safetensors",
41
+ "language_model.model.layers.11.self_attn.o_proj.weight": "model-00002-of-00003.safetensors",
42
+ "language_model.model.layers.11.self_attn.q_proj.weight": "model-00002-of-00003.safetensors",
43
+ "language_model.model.layers.11.self_attn.v_proj.weight": "model-00002-of-00003.safetensors",
44
+ "language_model.model.layers.12.input_layernorm.weight": "model-00002-of-00003.safetensors",
45
+ "language_model.model.layers.12.mlp.down_proj.weight": "model-00002-of-00003.safetensors",
46
+ "language_model.model.layers.12.mlp.gate_proj.weight": "model-00002-of-00003.safetensors",
47
+ "language_model.model.layers.12.mlp.up_proj.weight": "model-00002-of-00003.safetensors",
48
+ "language_model.model.layers.12.post_attention_layernorm.weight": "model-00002-of-00003.safetensors",
49
+ "language_model.model.layers.12.self_attn.k_proj.weight": "model-00002-of-00003.safetensors",
50
+ "language_model.model.layers.12.self_attn.o_proj.weight": "model-00002-of-00003.safetensors",
51
+ "language_model.model.layers.12.self_attn.q_proj.weight": "model-00002-of-00003.safetensors",
52
+ "language_model.model.layers.12.self_attn.v_proj.weight": "model-00002-of-00003.safetensors",
53
+ "language_model.model.layers.13.input_layernorm.weight": "model-00002-of-00003.safetensors",
54
+ "language_model.model.layers.13.mlp.down_proj.weight": "model-00002-of-00003.safetensors",
55
+ "language_model.model.layers.13.mlp.gate_proj.weight": "model-00002-of-00003.safetensors",
56
+ "language_model.model.layers.13.mlp.up_proj.weight": "model-00002-of-00003.safetensors",
57
+ "language_model.model.layers.13.post_attention_layernorm.weight": "model-00002-of-00003.safetensors",
58
+ "language_model.model.layers.13.self_attn.k_proj.weight": "model-00002-of-00003.safetensors",
59
+ "language_model.model.layers.13.self_attn.o_proj.weight": "model-00002-of-00003.safetensors",
60
+ "language_model.model.layers.13.self_attn.q_proj.weight": "model-00002-of-00003.safetensors",
61
+ "language_model.model.layers.13.self_attn.v_proj.weight": "model-00002-of-00003.safetensors",
62
+ "language_model.model.layers.14.input_layernorm.weight": "model-00002-of-00003.safetensors",
63
+ "language_model.model.layers.14.mlp.down_proj.weight": "model-00002-of-00003.safetensors",
64
+ "language_model.model.layers.14.mlp.gate_proj.weight": "model-00002-of-00003.safetensors",
65
+ "language_model.model.layers.14.mlp.up_proj.weight": "model-00002-of-00003.safetensors",
66
+ "language_model.model.layers.14.post_attention_layernorm.weight": "model-00002-of-00003.safetensors",
67
+ "language_model.model.layers.14.self_attn.k_proj.weight": "model-00002-of-00003.safetensors",
68
+ "language_model.model.layers.14.self_attn.o_proj.weight": "model-00002-of-00003.safetensors",
69
+ "language_model.model.layers.14.self_attn.q_proj.weight": "model-00002-of-00003.safetensors",
70
+ "language_model.model.layers.14.self_attn.v_proj.weight": "model-00002-of-00003.safetensors",
71
+ "language_model.model.layers.15.input_layernorm.weight": "model-00002-of-00003.safetensors",
72
+ "language_model.model.layers.15.mlp.down_proj.weight": "model-00002-of-00003.safetensors",
73
+ "language_model.model.layers.15.mlp.gate_proj.weight": "model-00002-of-00003.safetensors",
74
+ "language_model.model.layers.15.mlp.up_proj.weight": "model-00002-of-00003.safetensors",
75
+ "language_model.model.layers.15.post_attention_layernorm.weight": "model-00002-of-00003.safetensors",
76
+ "language_model.model.layers.15.self_attn.k_proj.weight": "model-00002-of-00003.safetensors",
77
+ "language_model.model.layers.15.self_attn.o_proj.weight": "model-00002-of-00003.safetensors",
78
+ "language_model.model.layers.15.self_attn.q_proj.weight": "model-00002-of-00003.safetensors",
79
+ "language_model.model.layers.15.self_attn.v_proj.weight": "model-00002-of-00003.safetensors",
80
+ "language_model.model.layers.16.input_layernorm.weight": "model-00002-of-00003.safetensors",
81
+ "language_model.model.layers.16.mlp.down_proj.weight": "model-00002-of-00003.safetensors",
82
+ "language_model.model.layers.16.mlp.gate_proj.weight": "model-00002-of-00003.safetensors",
83
+ "language_model.model.layers.16.mlp.up_proj.weight": "model-00002-of-00003.safetensors",
84
+ "language_model.model.layers.16.post_attention_layernorm.weight": "model-00002-of-00003.safetensors",
85
+ "language_model.model.layers.16.self_attn.k_proj.weight": "model-00002-of-00003.safetensors",
86
+ "language_model.model.layers.16.self_attn.o_proj.weight": "model-00002-of-00003.safetensors",
87
+ "language_model.model.layers.16.self_attn.q_proj.weight": "model-00002-of-00003.safetensors",
88
+ "language_model.model.layers.16.self_attn.v_proj.weight": "model-00002-of-00003.safetensors",
89
+ "language_model.model.layers.17.input_layernorm.weight": "model-00002-of-00003.safetensors",
90
+ "language_model.model.layers.17.mlp.down_proj.weight": "model-00002-of-00003.safetensors",
91
+ "language_model.model.layers.17.mlp.gate_proj.weight": "model-00002-of-00003.safetensors",
92
+ "language_model.model.layers.17.mlp.up_proj.weight": "model-00002-of-00003.safetensors",
93
+ "language_model.model.layers.17.post_attention_layernorm.weight": "model-00002-of-00003.safetensors",
94
+ "language_model.model.layers.17.self_attn.k_proj.weight": "model-00002-of-00003.safetensors",
95
+ "language_model.model.layers.17.self_attn.o_proj.weight": "model-00002-of-00003.safetensors",
96
+ "language_model.model.layers.17.self_attn.q_proj.weight": "model-00002-of-00003.safetensors",
97
+ "language_model.model.layers.17.self_attn.v_proj.weight": "model-00002-of-00003.safetensors",
98
+ "language_model.model.layers.18.input_layernorm.weight": "model-00002-of-00003.safetensors",
99
+ "language_model.model.layers.18.mlp.down_proj.weight": "model-00002-of-00003.safetensors",
100
+ "language_model.model.layers.18.mlp.gate_proj.weight": "model-00002-of-00003.safetensors",
101
+ "language_model.model.layers.18.mlp.up_proj.weight": "model-00002-of-00003.safetensors",
102
+ "language_model.model.layers.18.post_attention_layernorm.weight": "model-00002-of-00003.safetensors",
103
+ "language_model.model.layers.18.self_attn.k_proj.weight": "model-00002-of-00003.safetensors",
104
+ "language_model.model.layers.18.self_attn.o_proj.weight": "model-00002-of-00003.safetensors",
105
+ "language_model.model.layers.18.self_attn.q_proj.weight": "model-00002-of-00003.safetensors",
106
+ "language_model.model.layers.18.self_attn.v_proj.weight": "model-00002-of-00003.safetensors",
107
+ "language_model.model.layers.19.input_layernorm.weight": "model-00002-of-00003.safetensors",
108
+ "language_model.model.layers.19.mlp.down_proj.weight": "model-00002-of-00003.safetensors",
109
+ "language_model.model.layers.19.mlp.gate_proj.weight": "model-00002-of-00003.safetensors",
110
+ "language_model.model.layers.19.mlp.up_proj.weight": "model-00002-of-00003.safetensors",
111
+ "language_model.model.layers.19.post_attention_layernorm.weight": "model-00002-of-00003.safetensors",
112
+ "language_model.model.layers.19.self_attn.k_proj.weight": "model-00002-of-00003.safetensors",
113
+ "language_model.model.layers.19.self_attn.o_proj.weight": "model-00002-of-00003.safetensors",
114
+ "language_model.model.layers.19.self_attn.q_proj.weight": "model-00002-of-00003.safetensors",
115
+ "language_model.model.layers.19.self_attn.v_proj.weight": "model-00002-of-00003.safetensors",
116
+ "language_model.model.layers.2.input_layernorm.weight": "model-00001-of-00003.safetensors",
117
+ "language_model.model.layers.2.mlp.down_proj.weight": "model-00001-of-00003.safetensors",
118
+ "language_model.model.layers.2.mlp.gate_proj.weight": "model-00001-of-00003.safetensors",
119
+ "language_model.model.layers.2.mlp.up_proj.weight": "model-00001-of-00003.safetensors",
120
+ "language_model.model.layers.2.post_attention_layernorm.weight": "model-00001-of-00003.safetensors",
121
+ "language_model.model.layers.2.self_attn.k_proj.weight": "model-00001-of-00003.safetensors",
122
+ "language_model.model.layers.2.self_attn.o_proj.weight": "model-00001-of-00003.safetensors",
123
+ "language_model.model.layers.2.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
124
+ "language_model.model.layers.2.self_attn.v_proj.weight": "model-00001-of-00003.safetensors",
125
+ "language_model.model.layers.20.input_layernorm.weight": "model-00002-of-00003.safetensors",
126
+ "language_model.model.layers.20.mlp.down_proj.weight": "model-00002-of-00003.safetensors",
127
+ "language_model.model.layers.20.mlp.gate_proj.weight": "model-00002-of-00003.safetensors",
128
+ "language_model.model.layers.20.mlp.up_proj.weight": "model-00002-of-00003.safetensors",
129
+ "language_model.model.layers.20.post_attention_layernorm.weight": "model-00002-of-00003.safetensors",
130
+ "language_model.model.layers.20.self_attn.k_proj.weight": "model-00002-of-00003.safetensors",
131
+ "language_model.model.layers.20.self_attn.o_proj.weight": "model-00002-of-00003.safetensors",
132
+ "language_model.model.layers.20.self_attn.q_proj.weight": "model-00002-of-00003.safetensors",
133
+ "language_model.model.layers.20.self_attn.v_proj.weight": "model-00002-of-00003.safetensors",
134
+ "language_model.model.layers.21.input_layernorm.weight": "model-00002-of-00003.safetensors",
135
+ "language_model.model.layers.21.mlp.down_proj.weight": "model-00002-of-00003.safetensors",
136
+ "language_model.model.layers.21.mlp.gate_proj.weight": "model-00002-of-00003.safetensors",
137
+ "language_model.model.layers.21.mlp.up_proj.weight": "model-00002-of-00003.safetensors",
138
+ "language_model.model.layers.21.post_attention_layernorm.weight": "model-00002-of-00003.safetensors",
139
+ "language_model.model.layers.21.self_attn.k_proj.weight": "model-00002-of-00003.safetensors",
140
+ "language_model.model.layers.21.self_attn.o_proj.weight": "model-00002-of-00003.safetensors",
141
+ "language_model.model.layers.21.self_attn.q_proj.weight": "model-00002-of-00003.safetensors",
142
+ "language_model.model.layers.21.self_attn.v_proj.weight": "model-00002-of-00003.safetensors",
143
+ "language_model.model.layers.22.input_layernorm.weight": "model-00003-of-00003.safetensors",
144
+ "language_model.model.layers.22.mlp.down_proj.weight": "model-00003-of-00003.safetensors",
145
+ "language_model.model.layers.22.mlp.gate_proj.weight": "model-00003-of-00003.safetensors",
146
+ "language_model.model.layers.22.mlp.up_proj.weight": "model-00003-of-00003.safetensors",
147
+ "language_model.model.layers.22.post_attention_layernorm.weight": "model-00003-of-00003.safetensors",
148
+ "language_model.model.layers.22.self_attn.k_proj.weight": "model-00002-of-00003.safetensors",
149
+ "language_model.model.layers.22.self_attn.o_proj.weight": "model-00002-of-00003.safetensors",
150
+ "language_model.model.layers.22.self_attn.q_proj.weight": "model-00002-of-00003.safetensors",
151
+ "language_model.model.layers.22.self_attn.v_proj.weight": "model-00002-of-00003.safetensors",
152
+ "language_model.model.layers.23.input_layernorm.weight": "model-00003-of-00003.safetensors",
153
+ "language_model.model.layers.23.mlp.down_proj.weight": "model-00003-of-00003.safetensors",
154
+ "language_model.model.layers.23.mlp.gate_proj.weight": "model-00003-of-00003.safetensors",
155
+ "language_model.model.layers.23.mlp.up_proj.weight": "model-00003-of-00003.safetensors",
156
+ "language_model.model.layers.23.post_attention_layernorm.weight": "model-00003-of-00003.safetensors",
157
+ "language_model.model.layers.23.self_attn.k_proj.weight": "model-00003-of-00003.safetensors",
158
+ "language_model.model.layers.23.self_attn.o_proj.weight": "model-00003-of-00003.safetensors",
159
+ "language_model.model.layers.23.self_attn.q_proj.weight": "model-00003-of-00003.safetensors",
160
+ "language_model.model.layers.23.self_attn.v_proj.weight": "model-00003-of-00003.safetensors",
161
+ "language_model.model.layers.24.input_layernorm.weight": "model-00003-of-00003.safetensors",
162
+ "language_model.model.layers.24.mlp.down_proj.weight": "model-00003-of-00003.safetensors",
163
+ "language_model.model.layers.24.mlp.gate_proj.weight": "model-00003-of-00003.safetensors",
164
+ "language_model.model.layers.24.mlp.up_proj.weight": "model-00003-of-00003.safetensors",
165
+ "language_model.model.layers.24.post_attention_layernorm.weight": "model-00003-of-00003.safetensors",
166
+ "language_model.model.layers.24.self_attn.k_proj.weight": "model-00003-of-00003.safetensors",
167
+ "language_model.model.layers.24.self_attn.o_proj.weight": "model-00003-of-00003.safetensors",
168
+ "language_model.model.layers.24.self_attn.q_proj.weight": "model-00003-of-00003.safetensors",
169
+ "language_model.model.layers.24.self_attn.v_proj.weight": "model-00003-of-00003.safetensors",
170
+ "language_model.model.layers.25.input_layernorm.weight": "model-00003-of-00003.safetensors",
171
+ "language_model.model.layers.25.mlp.down_proj.weight": "model-00003-of-00003.safetensors",
172
+ "language_model.model.layers.25.mlp.gate_proj.weight": "model-00003-of-00003.safetensors",
173
+ "language_model.model.layers.25.mlp.up_proj.weight": "model-00003-of-00003.safetensors",
174
+ "language_model.model.layers.25.post_attention_layernorm.weight": "model-00003-of-00003.safetensors",
175
+ "language_model.model.layers.25.self_attn.k_proj.weight": "model-00003-of-00003.safetensors",
176
+ "language_model.model.layers.25.self_attn.o_proj.weight": "model-00003-of-00003.safetensors",
177
+ "language_model.model.layers.25.self_attn.q_proj.weight": "model-00003-of-00003.safetensors",
178
+ "language_model.model.layers.25.self_attn.v_proj.weight": "model-00003-of-00003.safetensors",
179
+ "language_model.model.layers.26.input_layernorm.weight": "model-00003-of-00003.safetensors",
180
+ "language_model.model.layers.26.mlp.down_proj.weight": "model-00003-of-00003.safetensors",
181
+ "language_model.model.layers.26.mlp.gate_proj.weight": "model-00003-of-00003.safetensors",
182
+ "language_model.model.layers.26.mlp.up_proj.weight": "model-00003-of-00003.safetensors",
183
+ "language_model.model.layers.26.post_attention_layernorm.weight": "model-00003-of-00003.safetensors",
184
+ "language_model.model.layers.26.self_attn.k_proj.weight": "model-00003-of-00003.safetensors",
185
+ "language_model.model.layers.26.self_attn.o_proj.weight": "model-00003-of-00003.safetensors",
186
+ "language_model.model.layers.26.self_attn.q_proj.weight": "model-00003-of-00003.safetensors",
187
+ "language_model.model.layers.26.self_attn.v_proj.weight": "model-00003-of-00003.safetensors",
188
+ "language_model.model.layers.27.input_layernorm.weight": "model-00003-of-00003.safetensors",
189
+ "language_model.model.layers.27.mlp.down_proj.weight": "model-00003-of-00003.safetensors",
190
+ "language_model.model.layers.27.mlp.gate_proj.weight": "model-00003-of-00003.safetensors",
191
+ "language_model.model.layers.27.mlp.up_proj.weight": "model-00003-of-00003.safetensors",
192
+ "language_model.model.layers.27.post_attention_layernorm.weight": "model-00003-of-00003.safetensors",
193
+ "language_model.model.layers.27.self_attn.k_proj.weight": "model-00003-of-00003.safetensors",
194
+ "language_model.model.layers.27.self_attn.o_proj.weight": "model-00003-of-00003.safetensors",
195
+ "language_model.model.layers.27.self_attn.q_proj.weight": "model-00003-of-00003.safetensors",
196
+ "language_model.model.layers.27.self_attn.v_proj.weight": "model-00003-of-00003.safetensors",
197
+ "language_model.model.layers.28.input_layernorm.weight": "model-00003-of-00003.safetensors",
198
+ "language_model.model.layers.28.mlp.down_proj.weight": "model-00003-of-00003.safetensors",
199
+ "language_model.model.layers.28.mlp.gate_proj.weight": "model-00003-of-00003.safetensors",
200
+ "language_model.model.layers.28.mlp.up_proj.weight": "model-00003-of-00003.safetensors",
201
+ "language_model.model.layers.28.post_attention_layernorm.weight": "model-00003-of-00003.safetensors",
202
+ "language_model.model.layers.28.self_attn.k_proj.weight": "model-00003-of-00003.safetensors",
203
+ "language_model.model.layers.28.self_attn.o_proj.weight": "model-00003-of-00003.safetensors",
204
+ "language_model.model.layers.28.self_attn.q_proj.weight": "model-00003-of-00003.safetensors",
205
+ "language_model.model.layers.28.self_attn.v_proj.weight": "model-00003-of-00003.safetensors",
206
+ "language_model.model.layers.29.input_layernorm.weight": "model-00003-of-00003.safetensors",
207
+ "language_model.model.layers.29.mlp.down_proj.weight": "model-00003-of-00003.safetensors",
208
+ "language_model.model.layers.29.mlp.gate_proj.weight": "model-00003-of-00003.safetensors",
209
+ "language_model.model.layers.29.mlp.up_proj.weight": "model-00003-of-00003.safetensors",
210
+ "language_model.model.layers.29.post_attention_layernorm.weight": "model-00003-of-00003.safetensors",
211
+ "language_model.model.layers.29.self_attn.k_proj.weight": "model-00003-of-00003.safetensors",
212
+ "language_model.model.layers.29.self_attn.o_proj.weight": "model-00003-of-00003.safetensors",
213
+ "language_model.model.layers.29.self_attn.q_proj.weight": "model-00003-of-00003.safetensors",
214
+ "language_model.model.layers.29.self_attn.v_proj.weight": "model-00003-of-00003.safetensors",
215
+ "language_model.model.layers.3.input_layernorm.weight": "model-00001-of-00003.safetensors",
216
+ "language_model.model.layers.3.mlp.down_proj.weight": "model-00001-of-00003.safetensors",
217
+ "language_model.model.layers.3.mlp.gate_proj.weight": "model-00001-of-00003.safetensors",
218
+ "language_model.model.layers.3.mlp.up_proj.weight": "model-00001-of-00003.safetensors",
219
+ "language_model.model.layers.3.post_attention_layernorm.weight": "model-00001-of-00003.safetensors",
220
+ "language_model.model.layers.3.self_attn.k_proj.weight": "model-00001-of-00003.safetensors",
221
+ "language_model.model.layers.3.self_attn.o_proj.weight": "model-00001-of-00003.safetensors",
222
+ "language_model.model.layers.3.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
223
+ "language_model.model.layers.3.self_attn.v_proj.weight": "model-00001-of-00003.safetensors",
224
+ "language_model.model.layers.30.input_layernorm.weight": "model-00003-of-00003.safetensors",
225
+ "language_model.model.layers.30.mlp.down_proj.weight": "model-00003-of-00003.safetensors",
226
+ "language_model.model.layers.30.mlp.gate_proj.weight": "model-00003-of-00003.safetensors",
227
+ "language_model.model.layers.30.mlp.up_proj.weight": "model-00003-of-00003.safetensors",
228
+ "language_model.model.layers.30.post_attention_layernorm.weight": "model-00003-of-00003.safetensors",
229
+ "language_model.model.layers.30.self_attn.k_proj.weight": "model-00003-of-00003.safetensors",
230
+ "language_model.model.layers.30.self_attn.o_proj.weight": "model-00003-of-00003.safetensors",
231
+ "language_model.model.layers.30.self_attn.q_proj.weight": "model-00003-of-00003.safetensors",
232
+ "language_model.model.layers.30.self_attn.v_proj.weight": "model-00003-of-00003.safetensors",
233
+ "language_model.model.layers.31.input_layernorm.weight": "model-00003-of-00003.safetensors",
234
+ "language_model.model.layers.31.mlp.down_proj.weight": "model-00003-of-00003.safetensors",
235
+ "language_model.model.layers.31.mlp.gate_proj.weight": "model-00003-of-00003.safetensors",
236
+ "language_model.model.layers.31.mlp.up_proj.weight": "model-00003-of-00003.safetensors",
237
+ "language_model.model.layers.31.post_attention_layernorm.weight": "model-00003-of-00003.safetensors",
238
+ "language_model.model.layers.31.self_attn.k_proj.weight": "model-00003-of-00003.safetensors",
239
+ "language_model.model.layers.31.self_attn.o_proj.weight": "model-00003-of-00003.safetensors",
240
+ "language_model.model.layers.31.self_attn.q_proj.weight": "model-00003-of-00003.safetensors",
241
+ "language_model.model.layers.31.self_attn.v_proj.weight": "model-00003-of-00003.safetensors",
242
+ "language_model.model.layers.4.input_layernorm.weight": "model-00001-of-00003.safetensors",
243
+ "language_model.model.layers.4.mlp.down_proj.weight": "model-00001-of-00003.safetensors",
244
+ "language_model.model.layers.4.mlp.gate_proj.weight": "model-00001-of-00003.safetensors",
245
+ "language_model.model.layers.4.mlp.up_proj.weight": "model-00001-of-00003.safetensors",
246
+ "language_model.model.layers.4.post_attention_layernorm.weight": "model-00001-of-00003.safetensors",
247
+ "language_model.model.layers.4.self_attn.k_proj.weight": "model-00001-of-00003.safetensors",
248
+ "language_model.model.layers.4.self_attn.o_proj.weight": "model-00001-of-00003.safetensors",
249
+ "language_model.model.layers.4.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
250
+ "language_model.model.layers.4.self_attn.v_proj.weight": "model-00001-of-00003.safetensors",
251
+ "language_model.model.layers.5.input_layernorm.weight": "model-00001-of-00003.safetensors",
252
+ "language_model.model.layers.5.mlp.down_proj.weight": "model-00001-of-00003.safetensors",
253
+ "language_model.model.layers.5.mlp.gate_proj.weight": "model-00001-of-00003.safetensors",
254
+ "language_model.model.layers.5.mlp.up_proj.weight": "model-00001-of-00003.safetensors",
255
+ "language_model.model.layers.5.post_attention_layernorm.weight": "model-00001-of-00003.safetensors",
256
+ "language_model.model.layers.5.self_attn.k_proj.weight": "model-00001-of-00003.safetensors",
257
+ "language_model.model.layers.5.self_attn.o_proj.weight": "model-00001-of-00003.safetensors",
258
+ "language_model.model.layers.5.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
259
+ "language_model.model.layers.5.self_attn.v_proj.weight": "model-00001-of-00003.safetensors",
260
+ "language_model.model.layers.6.input_layernorm.weight": "model-00001-of-00003.safetensors",
261
+ "language_model.model.layers.6.mlp.down_proj.weight": "model-00001-of-00003.safetensors",
262
+ "language_model.model.layers.6.mlp.gate_proj.weight": "model-00001-of-00003.safetensors",
263
+ "language_model.model.layers.6.mlp.up_proj.weight": "model-00001-of-00003.safetensors",
264
+ "language_model.model.layers.6.post_attention_layernorm.weight": "model-00001-of-00003.safetensors",
265
+ "language_model.model.layers.6.self_attn.k_proj.weight": "model-00001-of-00003.safetensors",
266
+ "language_model.model.layers.6.self_attn.o_proj.weight": "model-00001-of-00003.safetensors",
267
+ "language_model.model.layers.6.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
268
+ "language_model.model.layers.6.self_attn.v_proj.weight": "model-00001-of-00003.safetensors",
269
+ "language_model.model.layers.7.input_layernorm.weight": "model-00001-of-00003.safetensors",
270
+ "language_model.model.layers.7.mlp.down_proj.weight": "model-00001-of-00003.safetensors",
271
+ "language_model.model.layers.7.mlp.gate_proj.weight": "model-00001-of-00003.safetensors",
272
+ "language_model.model.layers.7.mlp.up_proj.weight": "model-00001-of-00003.safetensors",
273
+ "language_model.model.layers.7.post_attention_layernorm.weight": "model-00001-of-00003.safetensors",
274
+ "language_model.model.layers.7.self_attn.k_proj.weight": "model-00001-of-00003.safetensors",
275
+ "language_model.model.layers.7.self_attn.o_proj.weight": "model-00001-of-00003.safetensors",
276
+ "language_model.model.layers.7.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
277
+ "language_model.model.layers.7.self_attn.v_proj.weight": "model-00001-of-00003.safetensors",
278
+ "language_model.model.layers.8.input_layernorm.weight": "model-00001-of-00003.safetensors",
279
+ "language_model.model.layers.8.mlp.down_proj.weight": "model-00001-of-00003.safetensors",
280
+ "language_model.model.layers.8.mlp.gate_proj.weight": "model-00001-of-00003.safetensors",
281
+ "language_model.model.layers.8.mlp.up_proj.weight": "model-00001-of-00003.safetensors",
282
+ "language_model.model.layers.8.post_attention_layernorm.weight": "model-00001-of-00003.safetensors",
283
+ "language_model.model.layers.8.self_attn.k_proj.weight": "model-00001-of-00003.safetensors",
284
+ "language_model.model.layers.8.self_attn.o_proj.weight": "model-00001-of-00003.safetensors",
285
+ "language_model.model.layers.8.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
286
+ "language_model.model.layers.8.self_attn.v_proj.weight": "model-00001-of-00003.safetensors",
287
+ "language_model.model.layers.9.input_layernorm.weight": "model-00001-of-00003.safetensors",
288
+ "language_model.model.layers.9.mlp.down_proj.weight": "model-00001-of-00003.safetensors",
289
+ "language_model.model.layers.9.mlp.gate_proj.weight": "model-00001-of-00003.safetensors",
290
+ "language_model.model.layers.9.mlp.up_proj.weight": "model-00001-of-00003.safetensors",
291
+ "language_model.model.layers.9.post_attention_layernorm.weight": "model-00001-of-00003.safetensors",
292
+ "language_model.model.layers.9.self_attn.k_proj.weight": "model-00001-of-00003.safetensors",
293
+ "language_model.model.layers.9.self_attn.o_proj.weight": "model-00001-of-00003.safetensors",
294
+ "language_model.model.layers.9.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
295
+ "language_model.model.layers.9.self_attn.v_proj.weight": "model-00001-of-00003.safetensors",
296
+ "language_model.model.norm.weight": "model-00003-of-00003.safetensors",
297
+ "multi_modal_projector.linear_1.bias": "model-00001-of-00003.safetensors",
298
+ "multi_modal_projector.linear_1.weight": "model-00001-of-00003.safetensors",
299
+ "multi_modal_projector.linear_2.bias": "model-00001-of-00003.safetensors",
300
+ "multi_modal_projector.linear_2.weight": "model-00001-of-00003.safetensors",
301
+ "vision_tower.vision_model.embeddings.class_embedding": "model-00001-of-00003.safetensors",
302
+ "vision_tower.vision_model.embeddings.patch_embedding.weight": "model-00001-of-00003.safetensors",
303
+ "vision_tower.vision_model.embeddings.position_embedding.weight": "model-00001-of-00003.safetensors",
304
+ "vision_tower.vision_model.encoder.layers.0.layer_norm1.bias": "model-00001-of-00003.safetensors",
305
+ "vision_tower.vision_model.encoder.layers.0.layer_norm1.weight": "model-00001-of-00003.safetensors",
306
+ "vision_tower.vision_model.encoder.layers.0.layer_norm2.bias": "model-00001-of-00003.safetensors",
307
+ "vision_tower.vision_model.encoder.layers.0.layer_norm2.weight": "model-00001-of-00003.safetensors",
308
+ "vision_tower.vision_model.encoder.layers.0.mlp.fc1.bias": "model-00001-of-00003.safetensors",
309
+ "vision_tower.vision_model.encoder.layers.0.mlp.fc1.weight": "model-00001-of-00003.safetensors",
310
+ "vision_tower.vision_model.encoder.layers.0.mlp.fc2.bias": "model-00001-of-00003.safetensors",
311
+ "vision_tower.vision_model.encoder.layers.0.mlp.fc2.weight": "model-00001-of-00003.safetensors",
312
+ "vision_tower.vision_model.encoder.layers.0.self_attn.k_proj.bias": "model-00001-of-00003.safetensors",
313
+ "vision_tower.vision_model.encoder.layers.0.self_attn.k_proj.weight": "model-00001-of-00003.safetensors",
314
+ "vision_tower.vision_model.encoder.layers.0.self_attn.out_proj.bias": "model-00001-of-00003.safetensors",
315
+ "vision_tower.vision_model.encoder.layers.0.self_attn.out_proj.weight": "model-00001-of-00003.safetensors",
316
+ "vision_tower.vision_model.encoder.layers.0.self_attn.q_proj.bias": "model-00001-of-00003.safetensors",
317
+ "vision_tower.vision_model.encoder.layers.0.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
318
+ "vision_tower.vision_model.encoder.layers.0.self_attn.v_proj.bias": "model-00001-of-00003.safetensors",
319
+ "vision_tower.vision_model.encoder.layers.0.self_attn.v_proj.weight": "model-00001-of-00003.safetensors",
320
+ "vision_tower.vision_model.encoder.layers.1.layer_norm1.bias": "model-00001-of-00003.safetensors",
321
+ "vision_tower.vision_model.encoder.layers.1.layer_norm1.weight": "model-00001-of-00003.safetensors",
322
+ "vision_tower.vision_model.encoder.layers.1.layer_norm2.bias": "model-00001-of-00003.safetensors",
323
+ "vision_tower.vision_model.encoder.layers.1.layer_norm2.weight": "model-00001-of-00003.safetensors",
324
+ "vision_tower.vision_model.encoder.layers.1.mlp.fc1.bias": "model-00001-of-00003.safetensors",
325
+ "vision_tower.vision_model.encoder.layers.1.mlp.fc1.weight": "model-00001-of-00003.safetensors",
326
+ "vision_tower.vision_model.encoder.layers.1.mlp.fc2.bias": "model-00001-of-00003.safetensors",
327
+ "vision_tower.vision_model.encoder.layers.1.mlp.fc2.weight": "model-00001-of-00003.safetensors",
328
+ "vision_tower.vision_model.encoder.layers.1.self_attn.k_proj.bias": "model-00001-of-00003.safetensors",
329
+ "vision_tower.vision_model.encoder.layers.1.self_attn.k_proj.weight": "model-00001-of-00003.safetensors",
330
+ "vision_tower.vision_model.encoder.layers.1.self_attn.out_proj.bias": "model-00001-of-00003.safetensors",
331
+ "vision_tower.vision_model.encoder.layers.1.self_attn.out_proj.weight": "model-00001-of-00003.safetensors",
332
+ "vision_tower.vision_model.encoder.layers.1.self_attn.q_proj.bias": "model-00001-of-00003.safetensors",
333
+ "vision_tower.vision_model.encoder.layers.1.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
334
+ "vision_tower.vision_model.encoder.layers.1.self_attn.v_proj.bias": "model-00001-of-00003.safetensors",
335
+ "vision_tower.vision_model.encoder.layers.1.self_attn.v_proj.weight": "model-00001-of-00003.safetensors",
336
+ "vision_tower.vision_model.encoder.layers.10.layer_norm1.bias": "model-00001-of-00003.safetensors",
337
+ "vision_tower.vision_model.encoder.layers.10.layer_norm1.weight": "model-00001-of-00003.safetensors",
338
+ "vision_tower.vision_model.encoder.layers.10.layer_norm2.bias": "model-00001-of-00003.safetensors",
339
+ "vision_tower.vision_model.encoder.layers.10.layer_norm2.weight": "model-00001-of-00003.safetensors",
340
+ "vision_tower.vision_model.encoder.layers.10.mlp.fc1.bias": "model-00001-of-00003.safetensors",
341
+ "vision_tower.vision_model.encoder.layers.10.mlp.fc1.weight": "model-00001-of-00003.safetensors",
342
+ "vision_tower.vision_model.encoder.layers.10.mlp.fc2.bias": "model-00001-of-00003.safetensors",
343
+ "vision_tower.vision_model.encoder.layers.10.mlp.fc2.weight": "model-00001-of-00003.safetensors",
344
+ "vision_tower.vision_model.encoder.layers.10.self_attn.k_proj.bias": "model-00001-of-00003.safetensors",
345
+ "vision_tower.vision_model.encoder.layers.10.self_attn.k_proj.weight": "model-00001-of-00003.safetensors",
346
+ "vision_tower.vision_model.encoder.layers.10.self_attn.out_proj.bias": "model-00001-of-00003.safetensors",
347
+ "vision_tower.vision_model.encoder.layers.10.self_attn.out_proj.weight": "model-00001-of-00003.safetensors",
348
+ "vision_tower.vision_model.encoder.layers.10.self_attn.q_proj.bias": "model-00001-of-00003.safetensors",
349
+ "vision_tower.vision_model.encoder.layers.10.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
350
+ "vision_tower.vision_model.encoder.layers.10.self_attn.v_proj.bias": "model-00001-of-00003.safetensors",
351
+ "vision_tower.vision_model.encoder.layers.10.self_attn.v_proj.weight": "model-00001-of-00003.safetensors",
352
+ "vision_tower.vision_model.encoder.layers.11.layer_norm1.bias": "model-00001-of-00003.safetensors",
353
+ "vision_tower.vision_model.encoder.layers.11.layer_norm1.weight": "model-00001-of-00003.safetensors",
354
+ "vision_tower.vision_model.encoder.layers.11.layer_norm2.bias": "model-00001-of-00003.safetensors",
355
+ "vision_tower.vision_model.encoder.layers.11.layer_norm2.weight": "model-00001-of-00003.safetensors",
356
+ "vision_tower.vision_model.encoder.layers.11.mlp.fc1.bias": "model-00001-of-00003.safetensors",
357
+ "vision_tower.vision_model.encoder.layers.11.mlp.fc1.weight": "model-00001-of-00003.safetensors",
358
+ "vision_tower.vision_model.encoder.layers.11.mlp.fc2.bias": "model-00001-of-00003.safetensors",
359
+ "vision_tower.vision_model.encoder.layers.11.mlp.fc2.weight": "model-00001-of-00003.safetensors",
360
+ "vision_tower.vision_model.encoder.layers.11.self_attn.k_proj.bias": "model-00001-of-00003.safetensors",
361
+ "vision_tower.vision_model.encoder.layers.11.self_attn.k_proj.weight": "model-00001-of-00003.safetensors",
362
+ "vision_tower.vision_model.encoder.layers.11.self_attn.out_proj.bias": "model-00001-of-00003.safetensors",
363
+ "vision_tower.vision_model.encoder.layers.11.self_attn.out_proj.weight": "model-00001-of-00003.safetensors",
364
+ "vision_tower.vision_model.encoder.layers.11.self_attn.q_proj.bias": "model-00001-of-00003.safetensors",
365
+ "vision_tower.vision_model.encoder.layers.11.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
366
+ "vision_tower.vision_model.encoder.layers.11.self_attn.v_proj.bias": "model-00001-of-00003.safetensors",
367
+ "vision_tower.vision_model.encoder.layers.11.self_attn.v_proj.weight": "model-00001-of-00003.safetensors",
368
+ "vision_tower.vision_model.encoder.layers.12.layer_norm1.bias": "model-00001-of-00003.safetensors",
369
+ "vision_tower.vision_model.encoder.layers.12.layer_norm1.weight": "model-00001-of-00003.safetensors",
370
+ "vision_tower.vision_model.encoder.layers.12.layer_norm2.bias": "model-00001-of-00003.safetensors",
371
+ "vision_tower.vision_model.encoder.layers.12.layer_norm2.weight": "model-00001-of-00003.safetensors",
372
+ "vision_tower.vision_model.encoder.layers.12.mlp.fc1.bias": "model-00001-of-00003.safetensors",
373
+ "vision_tower.vision_model.encoder.layers.12.mlp.fc1.weight": "model-00001-of-00003.safetensors",
374
+ "vision_tower.vision_model.encoder.layers.12.mlp.fc2.bias": "model-00001-of-00003.safetensors",
375
+ "vision_tower.vision_model.encoder.layers.12.mlp.fc2.weight": "model-00001-of-00003.safetensors",
376
+ "vision_tower.vision_model.encoder.layers.12.self_attn.k_proj.bias": "model-00001-of-00003.safetensors",
377
+ "vision_tower.vision_model.encoder.layers.12.self_attn.k_proj.weight": "model-00001-of-00003.safetensors",
378
+ "vision_tower.vision_model.encoder.layers.12.self_attn.out_proj.bias": "model-00001-of-00003.safetensors",
379
+ "vision_tower.vision_model.encoder.layers.12.self_attn.out_proj.weight": "model-00001-of-00003.safetensors",
380
+ "vision_tower.vision_model.encoder.layers.12.self_attn.q_proj.bias": "model-00001-of-00003.safetensors",
381
+ "vision_tower.vision_model.encoder.layers.12.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
382
+ "vision_tower.vision_model.encoder.layers.12.self_attn.v_proj.bias": "model-00001-of-00003.safetensors",
383
+ "vision_tower.vision_model.encoder.layers.12.self_attn.v_proj.weight": "model-00001-of-00003.safetensors",
384
+ "vision_tower.vision_model.encoder.layers.13.layer_norm1.bias": "model-00001-of-00003.safetensors",
385
+ "vision_tower.vision_model.encoder.layers.13.layer_norm1.weight": "model-00001-of-00003.safetensors",
386
+ "vision_tower.vision_model.encoder.layers.13.layer_norm2.bias": "model-00001-of-00003.safetensors",
387
+ "vision_tower.vision_model.encoder.layers.13.layer_norm2.weight": "model-00001-of-00003.safetensors",
388
+ "vision_tower.vision_model.encoder.layers.13.mlp.fc1.bias": "model-00001-of-00003.safetensors",
389
+ "vision_tower.vision_model.encoder.layers.13.mlp.fc1.weight": "model-00001-of-00003.safetensors",
390
+ "vision_tower.vision_model.encoder.layers.13.mlp.fc2.bias": "model-00001-of-00003.safetensors",
391
+ "vision_tower.vision_model.encoder.layers.13.mlp.fc2.weight": "model-00001-of-00003.safetensors",
392
+ "vision_tower.vision_model.encoder.layers.13.self_attn.k_proj.bias": "model-00001-of-00003.safetensors",
393
+ "vision_tower.vision_model.encoder.layers.13.self_attn.k_proj.weight": "model-00001-of-00003.safetensors",
394
+ "vision_tower.vision_model.encoder.layers.13.self_attn.out_proj.bias": "model-00001-of-00003.safetensors",
395
+ "vision_tower.vision_model.encoder.layers.13.self_attn.out_proj.weight": "model-00001-of-00003.safetensors",
396
+ "vision_tower.vision_model.encoder.layers.13.self_attn.q_proj.bias": "model-00001-of-00003.safetensors",
397
+ "vision_tower.vision_model.encoder.layers.13.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
398
+ "vision_tower.vision_model.encoder.layers.13.self_attn.v_proj.bias": "model-00001-of-00003.safetensors",
399
+ "vision_tower.vision_model.encoder.layers.13.self_attn.v_proj.weight": "model-00001-of-00003.safetensors",
400
+ "vision_tower.vision_model.encoder.layers.14.layer_norm1.bias": "model-00001-of-00003.safetensors",
401
+ "vision_tower.vision_model.encoder.layers.14.layer_norm1.weight": "model-00001-of-00003.safetensors",
402
+ "vision_tower.vision_model.encoder.layers.14.layer_norm2.bias": "model-00001-of-00003.safetensors",
403
+ "vision_tower.vision_model.encoder.layers.14.layer_norm2.weight": "model-00001-of-00003.safetensors",
404
+ "vision_tower.vision_model.encoder.layers.14.mlp.fc1.bias": "model-00001-of-00003.safetensors",
405
+ "vision_tower.vision_model.encoder.layers.14.mlp.fc1.weight": "model-00001-of-00003.safetensors",
406
+ "vision_tower.vision_model.encoder.layers.14.mlp.fc2.bias": "model-00001-of-00003.safetensors",
407
+ "vision_tower.vision_model.encoder.layers.14.mlp.fc2.weight": "model-00001-of-00003.safetensors",
408
+ "vision_tower.vision_model.encoder.layers.14.self_attn.k_proj.bias": "model-00001-of-00003.safetensors",
409
+ "vision_tower.vision_model.encoder.layers.14.self_attn.k_proj.weight": "model-00001-of-00003.safetensors",
410
+ "vision_tower.vision_model.encoder.layers.14.self_attn.out_proj.bias": "model-00001-of-00003.safetensors",
411
+ "vision_tower.vision_model.encoder.layers.14.self_attn.out_proj.weight": "model-00001-of-00003.safetensors",
412
+ "vision_tower.vision_model.encoder.layers.14.self_attn.q_proj.bias": "model-00001-of-00003.safetensors",
413
+ "vision_tower.vision_model.encoder.layers.14.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
414
+ "vision_tower.vision_model.encoder.layers.14.self_attn.v_proj.bias": "model-00001-of-00003.safetensors",
415
+ "vision_tower.vision_model.encoder.layers.14.self_attn.v_proj.weight": "model-00001-of-00003.safetensors",
416
+ "vision_tower.vision_model.encoder.layers.15.layer_norm1.bias": "model-00001-of-00003.safetensors",
417
+ "vision_tower.vision_model.encoder.layers.15.layer_norm1.weight": "model-00001-of-00003.safetensors",
418
+ "vision_tower.vision_model.encoder.layers.15.layer_norm2.bias": "model-00001-of-00003.safetensors",
419
+ "vision_tower.vision_model.encoder.layers.15.layer_norm2.weight": "model-00001-of-00003.safetensors",
420
+ "vision_tower.vision_model.encoder.layers.15.mlp.fc1.bias": "model-00001-of-00003.safetensors",
421
+ "vision_tower.vision_model.encoder.layers.15.mlp.fc1.weight": "model-00001-of-00003.safetensors",
422
+ "vision_tower.vision_model.encoder.layers.15.mlp.fc2.bias": "model-00001-of-00003.safetensors",
423
+ "vision_tower.vision_model.encoder.layers.15.mlp.fc2.weight": "model-00001-of-00003.safetensors",
424
+ "vision_tower.vision_model.encoder.layers.15.self_attn.k_proj.bias": "model-00001-of-00003.safetensors",
425
+ "vision_tower.vision_model.encoder.layers.15.self_attn.k_proj.weight": "model-00001-of-00003.safetensors",
426
+ "vision_tower.vision_model.encoder.layers.15.self_attn.out_proj.bias": "model-00001-of-00003.safetensors",
427
+ "vision_tower.vision_model.encoder.layers.15.self_attn.out_proj.weight": "model-00001-of-00003.safetensors",
428
+ "vision_tower.vision_model.encoder.layers.15.self_attn.q_proj.bias": "model-00001-of-00003.safetensors",
429
+ "vision_tower.vision_model.encoder.layers.15.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
430
+ "vision_tower.vision_model.encoder.layers.15.self_attn.v_proj.bias": "model-00001-of-00003.safetensors",
431
+ "vision_tower.vision_model.encoder.layers.15.self_attn.v_proj.weight": "model-00001-of-00003.safetensors",
432
+ "vision_tower.vision_model.encoder.layers.16.layer_norm1.bias": "model-00001-of-00003.safetensors",
433
+ "vision_tower.vision_model.encoder.layers.16.layer_norm1.weight": "model-00001-of-00003.safetensors",
434
+ "vision_tower.vision_model.encoder.layers.16.layer_norm2.bias": "model-00001-of-00003.safetensors",
435
+ "vision_tower.vision_model.encoder.layers.16.layer_norm2.weight": "model-00001-of-00003.safetensors",
436
+ "vision_tower.vision_model.encoder.layers.16.mlp.fc1.bias": "model-00001-of-00003.safetensors",
437
+ "vision_tower.vision_model.encoder.layers.16.mlp.fc1.weight": "model-00001-of-00003.safetensors",
438
+ "vision_tower.vision_model.encoder.layers.16.mlp.fc2.bias": "model-00001-of-00003.safetensors",
439
+ "vision_tower.vision_model.encoder.layers.16.mlp.fc2.weight": "model-00001-of-00003.safetensors",
440
+ "vision_tower.vision_model.encoder.layers.16.self_attn.k_proj.bias": "model-00001-of-00003.safetensors",
441
+ "vision_tower.vision_model.encoder.layers.16.self_attn.k_proj.weight": "model-00001-of-00003.safetensors",
442
+ "vision_tower.vision_model.encoder.layers.16.self_attn.out_proj.bias": "model-00001-of-00003.safetensors",
443
+ "vision_tower.vision_model.encoder.layers.16.self_attn.out_proj.weight": "model-00001-of-00003.safetensors",
444
+ "vision_tower.vision_model.encoder.layers.16.self_attn.q_proj.bias": "model-00001-of-00003.safetensors",
445
+ "vision_tower.vision_model.encoder.layers.16.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
446
+ "vision_tower.vision_model.encoder.layers.16.self_attn.v_proj.bias": "model-00001-of-00003.safetensors",
447
+ "vision_tower.vision_model.encoder.layers.16.self_attn.v_proj.weight": "model-00001-of-00003.safetensors",
448
+ "vision_tower.vision_model.encoder.layers.17.layer_norm1.bias": "model-00001-of-00003.safetensors",
449
+ "vision_tower.vision_model.encoder.layers.17.layer_norm1.weight": "model-00001-of-00003.safetensors",
450
+ "vision_tower.vision_model.encoder.layers.17.layer_norm2.bias": "model-00001-of-00003.safetensors",
451
+ "vision_tower.vision_model.encoder.layers.17.layer_norm2.weight": "model-00001-of-00003.safetensors",
452
+ "vision_tower.vision_model.encoder.layers.17.mlp.fc1.bias": "model-00001-of-00003.safetensors",
453
+ "vision_tower.vision_model.encoder.layers.17.mlp.fc1.weight": "model-00001-of-00003.safetensors",
454
+ "vision_tower.vision_model.encoder.layers.17.mlp.fc2.bias": "model-00001-of-00003.safetensors",
455
+ "vision_tower.vision_model.encoder.layers.17.mlp.fc2.weight": "model-00001-of-00003.safetensors",
456
+ "vision_tower.vision_model.encoder.layers.17.self_attn.k_proj.bias": "model-00001-of-00003.safetensors",
457
+ "vision_tower.vision_model.encoder.layers.17.self_attn.k_proj.weight": "model-00001-of-00003.safetensors",
458
+ "vision_tower.vision_model.encoder.layers.17.self_attn.out_proj.bias": "model-00001-of-00003.safetensors",
459
+ "vision_tower.vision_model.encoder.layers.17.self_attn.out_proj.weight": "model-00001-of-00003.safetensors",
460
+ "vision_tower.vision_model.encoder.layers.17.self_attn.q_proj.bias": "model-00001-of-00003.safetensors",
461
+ "vision_tower.vision_model.encoder.layers.17.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
462
+ "vision_tower.vision_model.encoder.layers.17.self_attn.v_proj.bias": "model-00001-of-00003.safetensors",
463
+ "vision_tower.vision_model.encoder.layers.17.self_attn.v_proj.weight": "model-00001-of-00003.safetensors",
464
+ "vision_tower.vision_model.encoder.layers.18.layer_norm1.bias": "model-00001-of-00003.safetensors",
465
+ "vision_tower.vision_model.encoder.layers.18.layer_norm1.weight": "model-00001-of-00003.safetensors",
466
+ "vision_tower.vision_model.encoder.layers.18.layer_norm2.bias": "model-00001-of-00003.safetensors",
467
+ "vision_tower.vision_model.encoder.layers.18.layer_norm2.weight": "model-00001-of-00003.safetensors",
468
+ "vision_tower.vision_model.encoder.layers.18.mlp.fc1.bias": "model-00001-of-00003.safetensors",
469
+ "vision_tower.vision_model.encoder.layers.18.mlp.fc1.weight": "model-00001-of-00003.safetensors",
470
+ "vision_tower.vision_model.encoder.layers.18.mlp.fc2.bias": "model-00001-of-00003.safetensors",
471
+ "vision_tower.vision_model.encoder.layers.18.mlp.fc2.weight": "model-00001-of-00003.safetensors",
472
+ "vision_tower.vision_model.encoder.layers.18.self_attn.k_proj.bias": "model-00001-of-00003.safetensors",
473
+ "vision_tower.vision_model.encoder.layers.18.self_attn.k_proj.weight": "model-00001-of-00003.safetensors",
474
+ "vision_tower.vision_model.encoder.layers.18.self_attn.out_proj.bias": "model-00001-of-00003.safetensors",
475
+ "vision_tower.vision_model.encoder.layers.18.self_attn.out_proj.weight": "model-00001-of-00003.safetensors",
476
+ "vision_tower.vision_model.encoder.layers.18.self_attn.q_proj.bias": "model-00001-of-00003.safetensors",
477
+ "vision_tower.vision_model.encoder.layers.18.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
478
+ "vision_tower.vision_model.encoder.layers.18.self_attn.v_proj.bias": "model-00001-of-00003.safetensors",
479
+ "vision_tower.vision_model.encoder.layers.18.self_attn.v_proj.weight": "model-00001-of-00003.safetensors",
480
+ "vision_tower.vision_model.encoder.layers.19.layer_norm1.bias": "model-00001-of-00003.safetensors",
481
+ "vision_tower.vision_model.encoder.layers.19.layer_norm1.weight": "model-00001-of-00003.safetensors",
482
+ "vision_tower.vision_model.encoder.layers.19.layer_norm2.bias": "model-00001-of-00003.safetensors",
483
+ "vision_tower.vision_model.encoder.layers.19.layer_norm2.weight": "model-00001-of-00003.safetensors",
484
+ "vision_tower.vision_model.encoder.layers.19.mlp.fc1.bias": "model-00001-of-00003.safetensors",
485
+ "vision_tower.vision_model.encoder.layers.19.mlp.fc1.weight": "model-00001-of-00003.safetensors",
486
+ "vision_tower.vision_model.encoder.layers.19.mlp.fc2.bias": "model-00001-of-00003.safetensors",
487
+ "vision_tower.vision_model.encoder.layers.19.mlp.fc2.weight": "model-00001-of-00003.safetensors",
488
+ "vision_tower.vision_model.encoder.layers.19.self_attn.k_proj.bias": "model-00001-of-00003.safetensors",
489
+ "vision_tower.vision_model.encoder.layers.19.self_attn.k_proj.weight": "model-00001-of-00003.safetensors",
490
+ "vision_tower.vision_model.encoder.layers.19.self_attn.out_proj.bias": "model-00001-of-00003.safetensors",
491
+ "vision_tower.vision_model.encoder.layers.19.self_attn.out_proj.weight": "model-00001-of-00003.safetensors",
492
+ "vision_tower.vision_model.encoder.layers.19.self_attn.q_proj.bias": "model-00001-of-00003.safetensors",
493
+ "vision_tower.vision_model.encoder.layers.19.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
494
+ "vision_tower.vision_model.encoder.layers.19.self_attn.v_proj.bias": "model-00001-of-00003.safetensors",
495
+ "vision_tower.vision_model.encoder.layers.19.self_attn.v_proj.weight": "model-00001-of-00003.safetensors",
496
+ "vision_tower.vision_model.encoder.layers.2.layer_norm1.bias": "model-00001-of-00003.safetensors",
497
+ "vision_tower.vision_model.encoder.layers.2.layer_norm1.weight": "model-00001-of-00003.safetensors",
498
+ "vision_tower.vision_model.encoder.layers.2.layer_norm2.bias": "model-00001-of-00003.safetensors",
499
+ "vision_tower.vision_model.encoder.layers.2.layer_norm2.weight": "model-00001-of-00003.safetensors",
500
+ "vision_tower.vision_model.encoder.layers.2.mlp.fc1.bias": "model-00001-of-00003.safetensors",
501
+ "vision_tower.vision_model.encoder.layers.2.mlp.fc1.weight": "model-00001-of-00003.safetensors",
502
+ "vision_tower.vision_model.encoder.layers.2.mlp.fc2.bias": "model-00001-of-00003.safetensors",
503
+ "vision_tower.vision_model.encoder.layers.2.mlp.fc2.weight": "model-00001-of-00003.safetensors",
504
+ "vision_tower.vision_model.encoder.layers.2.self_attn.k_proj.bias": "model-00001-of-00003.safetensors",
505
+ "vision_tower.vision_model.encoder.layers.2.self_attn.k_proj.weight": "model-00001-of-00003.safetensors",
506
+ "vision_tower.vision_model.encoder.layers.2.self_attn.out_proj.bias": "model-00001-of-00003.safetensors",
507
+ "vision_tower.vision_model.encoder.layers.2.self_attn.out_proj.weight": "model-00001-of-00003.safetensors",
508
+ "vision_tower.vision_model.encoder.layers.2.self_attn.q_proj.bias": "model-00001-of-00003.safetensors",
509
+ "vision_tower.vision_model.encoder.layers.2.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
510
+ "vision_tower.vision_model.encoder.layers.2.self_attn.v_proj.bias": "model-00001-of-00003.safetensors",
511
+ "vision_tower.vision_model.encoder.layers.2.self_attn.v_proj.weight": "model-00001-of-00003.safetensors",
512
+ "vision_tower.vision_model.encoder.layers.20.layer_norm1.bias": "model-00001-of-00003.safetensors",
513
+ "vision_tower.vision_model.encoder.layers.20.layer_norm1.weight": "model-00001-of-00003.safetensors",
514
+ "vision_tower.vision_model.encoder.layers.20.layer_norm2.bias": "model-00001-of-00003.safetensors",
515
+ "vision_tower.vision_model.encoder.layers.20.layer_norm2.weight": "model-00001-of-00003.safetensors",
516
+ "vision_tower.vision_model.encoder.layers.20.mlp.fc1.bias": "model-00001-of-00003.safetensors",
517
+ "vision_tower.vision_model.encoder.layers.20.mlp.fc1.weight": "model-00001-of-00003.safetensors",
518
+ "vision_tower.vision_model.encoder.layers.20.mlp.fc2.bias": "model-00001-of-00003.safetensors",
519
+ "vision_tower.vision_model.encoder.layers.20.mlp.fc2.weight": "model-00001-of-00003.safetensors",
520
+ "vision_tower.vision_model.encoder.layers.20.self_attn.k_proj.bias": "model-00001-of-00003.safetensors",
521
+ "vision_tower.vision_model.encoder.layers.20.self_attn.k_proj.weight": "model-00001-of-00003.safetensors",
522
+ "vision_tower.vision_model.encoder.layers.20.self_attn.out_proj.bias": "model-00001-of-00003.safetensors",
523
+ "vision_tower.vision_model.encoder.layers.20.self_attn.out_proj.weight": "model-00001-of-00003.safetensors",
524
+ "vision_tower.vision_model.encoder.layers.20.self_attn.q_proj.bias": "model-00001-of-00003.safetensors",
525
+ "vision_tower.vision_model.encoder.layers.20.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
526
+ "vision_tower.vision_model.encoder.layers.20.self_attn.v_proj.bias": "model-00001-of-00003.safetensors",
527
+ "vision_tower.vision_model.encoder.layers.20.self_attn.v_proj.weight": "model-00001-of-00003.safetensors",
528
+ "vision_tower.vision_model.encoder.layers.21.layer_norm1.bias": "model-00001-of-00003.safetensors",
529
+ "vision_tower.vision_model.encoder.layers.21.layer_norm1.weight": "model-00001-of-00003.safetensors",
530
+ "vision_tower.vision_model.encoder.layers.21.layer_norm2.bias": "model-00001-of-00003.safetensors",
531
+ "vision_tower.vision_model.encoder.layers.21.layer_norm2.weight": "model-00001-of-00003.safetensors",
532
+ "vision_tower.vision_model.encoder.layers.21.mlp.fc1.bias": "model-00001-of-00003.safetensors",
533
+ "vision_tower.vision_model.encoder.layers.21.mlp.fc1.weight": "model-00001-of-00003.safetensors",
534
+ "vision_tower.vision_model.encoder.layers.21.mlp.fc2.bias": "model-00001-of-00003.safetensors",
535
+ "vision_tower.vision_model.encoder.layers.21.mlp.fc2.weight": "model-00001-of-00003.safetensors",
536
+ "vision_tower.vision_model.encoder.layers.21.self_attn.k_proj.bias": "model-00001-of-00003.safetensors",
537
+ "vision_tower.vision_model.encoder.layers.21.self_attn.k_proj.weight": "model-00001-of-00003.safetensors",
538
+ "vision_tower.vision_model.encoder.layers.21.self_attn.out_proj.bias": "model-00001-of-00003.safetensors",
539
+ "vision_tower.vision_model.encoder.layers.21.self_attn.out_proj.weight": "model-00001-of-00003.safetensors",
540
+ "vision_tower.vision_model.encoder.layers.21.self_attn.q_proj.bias": "model-00001-of-00003.safetensors",
541
+ "vision_tower.vision_model.encoder.layers.21.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
542
+ "vision_tower.vision_model.encoder.layers.21.self_attn.v_proj.bias": "model-00001-of-00003.safetensors",
543
+ "vision_tower.vision_model.encoder.layers.21.self_attn.v_proj.weight": "model-00001-of-00003.safetensors",
544
+ "vision_tower.vision_model.encoder.layers.22.layer_norm1.bias": "model-00001-of-00003.safetensors",
545
+ "vision_tower.vision_model.encoder.layers.22.layer_norm1.weight": "model-00001-of-00003.safetensors",
546
+ "vision_tower.vision_model.encoder.layers.22.layer_norm2.bias": "model-00001-of-00003.safetensors",
547
+ "vision_tower.vision_model.encoder.layers.22.layer_norm2.weight": "model-00001-of-00003.safetensors",
548
+ "vision_tower.vision_model.encoder.layers.22.mlp.fc1.bias": "model-00001-of-00003.safetensors",
549
+ "vision_tower.vision_model.encoder.layers.22.mlp.fc1.weight": "model-00001-of-00003.safetensors",
550
+ "vision_tower.vision_model.encoder.layers.22.mlp.fc2.bias": "model-00001-of-00003.safetensors",
551
+ "vision_tower.vision_model.encoder.layers.22.mlp.fc2.weight": "model-00001-of-00003.safetensors",
552
+ "vision_tower.vision_model.encoder.layers.22.self_attn.k_proj.bias": "model-00001-of-00003.safetensors",
553
+ "vision_tower.vision_model.encoder.layers.22.self_attn.k_proj.weight": "model-00001-of-00003.safetensors",
554
+ "vision_tower.vision_model.encoder.layers.22.self_attn.out_proj.bias": "model-00001-of-00003.safetensors",
555
+ "vision_tower.vision_model.encoder.layers.22.self_attn.out_proj.weight": "model-00001-of-00003.safetensors",
556
+ "vision_tower.vision_model.encoder.layers.22.self_attn.q_proj.bias": "model-00001-of-00003.safetensors",
557
+ "vision_tower.vision_model.encoder.layers.22.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
558
+ "vision_tower.vision_model.encoder.layers.22.self_attn.v_proj.bias": "model-00001-of-00003.safetensors",
559
+ "vision_tower.vision_model.encoder.layers.22.self_attn.v_proj.weight": "model-00001-of-00003.safetensors",
560
+ "vision_tower.vision_model.encoder.layers.23.layer_norm1.bias": "model-00001-of-00003.safetensors",
561
+ "vision_tower.vision_model.encoder.layers.23.layer_norm1.weight": "model-00001-of-00003.safetensors",
562
+ "vision_tower.vision_model.encoder.layers.23.layer_norm2.bias": "model-00001-of-00003.safetensors",
563
+ "vision_tower.vision_model.encoder.layers.23.layer_norm2.weight": "model-00001-of-00003.safetensors",
564
+ "vision_tower.vision_model.encoder.layers.23.mlp.fc1.bias": "model-00001-of-00003.safetensors",
565
+ "vision_tower.vision_model.encoder.layers.23.mlp.fc1.weight": "model-00001-of-00003.safetensors",
566
+ "vision_tower.vision_model.encoder.layers.23.mlp.fc2.bias": "model-00001-of-00003.safetensors",
567
+ "vision_tower.vision_model.encoder.layers.23.mlp.fc2.weight": "model-00001-of-00003.safetensors",
568
+ "vision_tower.vision_model.encoder.layers.23.self_attn.k_proj.bias": "model-00001-of-00003.safetensors",
569
+ "vision_tower.vision_model.encoder.layers.23.self_attn.k_proj.weight": "model-00001-of-00003.safetensors",
570
+ "vision_tower.vision_model.encoder.layers.23.self_attn.out_proj.bias": "model-00001-of-00003.safetensors",
571
+ "vision_tower.vision_model.encoder.layers.23.self_attn.out_proj.weight": "model-00001-of-00003.safetensors",
572
+ "vision_tower.vision_model.encoder.layers.23.self_attn.q_proj.bias": "model-00001-of-00003.safetensors",
573
+ "vision_tower.vision_model.encoder.layers.23.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
574
+ "vision_tower.vision_model.encoder.layers.23.self_attn.v_proj.bias": "model-00001-of-00003.safetensors",
575
+ "vision_tower.vision_model.encoder.layers.23.self_attn.v_proj.weight": "model-00001-of-00003.safetensors",
576
+ "vision_tower.vision_model.encoder.layers.3.layer_norm1.bias": "model-00001-of-00003.safetensors",
577
+ "vision_tower.vision_model.encoder.layers.3.layer_norm1.weight": "model-00001-of-00003.safetensors",
578
+ "vision_tower.vision_model.encoder.layers.3.layer_norm2.bias": "model-00001-of-00003.safetensors",
579
+ "vision_tower.vision_model.encoder.layers.3.layer_norm2.weight": "model-00001-of-00003.safetensors",
580
+ "vision_tower.vision_model.encoder.layers.3.mlp.fc1.bias": "model-00001-of-00003.safetensors",
581
+ "vision_tower.vision_model.encoder.layers.3.mlp.fc1.weight": "model-00001-of-00003.safetensors",
582
+ "vision_tower.vision_model.encoder.layers.3.mlp.fc2.bias": "model-00001-of-00003.safetensors",
583
+ "vision_tower.vision_model.encoder.layers.3.mlp.fc2.weight": "model-00001-of-00003.safetensors",
584
+ "vision_tower.vision_model.encoder.layers.3.self_attn.k_proj.bias": "model-00001-of-00003.safetensors",
585
+ "vision_tower.vision_model.encoder.layers.3.self_attn.k_proj.weight": "model-00001-of-00003.safetensors",
586
+ "vision_tower.vision_model.encoder.layers.3.self_attn.out_proj.bias": "model-00001-of-00003.safetensors",
587
+ "vision_tower.vision_model.encoder.layers.3.self_attn.out_proj.weight": "model-00001-of-00003.safetensors",
588
+ "vision_tower.vision_model.encoder.layers.3.self_attn.q_proj.bias": "model-00001-of-00003.safetensors",
589
+ "vision_tower.vision_model.encoder.layers.3.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
590
+ "vision_tower.vision_model.encoder.layers.3.self_attn.v_proj.bias": "model-00001-of-00003.safetensors",
591
+ "vision_tower.vision_model.encoder.layers.3.self_attn.v_proj.weight": "model-00001-of-00003.safetensors",
592
+ "vision_tower.vision_model.encoder.layers.4.layer_norm1.bias": "model-00001-of-00003.safetensors",
593
+ "vision_tower.vision_model.encoder.layers.4.layer_norm1.weight": "model-00001-of-00003.safetensors",
594
+ "vision_tower.vision_model.encoder.layers.4.layer_norm2.bias": "model-00001-of-00003.safetensors",
595
+ "vision_tower.vision_model.encoder.layers.4.layer_norm2.weight": "model-00001-of-00003.safetensors",
596
+ "vision_tower.vision_model.encoder.layers.4.mlp.fc1.bias": "model-00001-of-00003.safetensors",
597
+ "vision_tower.vision_model.encoder.layers.4.mlp.fc1.weight": "model-00001-of-00003.safetensors",
598
+ "vision_tower.vision_model.encoder.layers.4.mlp.fc2.bias": "model-00001-of-00003.safetensors",
599
+ "vision_tower.vision_model.encoder.layers.4.mlp.fc2.weight": "model-00001-of-00003.safetensors",
600
+ "vision_tower.vision_model.encoder.layers.4.self_attn.k_proj.bias": "model-00001-of-00003.safetensors",
601
+ "vision_tower.vision_model.encoder.layers.4.self_attn.k_proj.weight": "model-00001-of-00003.safetensors",
602
+ "vision_tower.vision_model.encoder.layers.4.self_attn.out_proj.bias": "model-00001-of-00003.safetensors",
603
+ "vision_tower.vision_model.encoder.layers.4.self_attn.out_proj.weight": "model-00001-of-00003.safetensors",
604
+ "vision_tower.vision_model.encoder.layers.4.self_attn.q_proj.bias": "model-00001-of-00003.safetensors",
605
+ "vision_tower.vision_model.encoder.layers.4.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
606
+ "vision_tower.vision_model.encoder.layers.4.self_attn.v_proj.bias": "model-00001-of-00003.safetensors",
607
+ "vision_tower.vision_model.encoder.layers.4.self_attn.v_proj.weight": "model-00001-of-00003.safetensors",
608
+ "vision_tower.vision_model.encoder.layers.5.layer_norm1.bias": "model-00001-of-00003.safetensors",
609
+ "vision_tower.vision_model.encoder.layers.5.layer_norm1.weight": "model-00001-of-00003.safetensors",
610
+ "vision_tower.vision_model.encoder.layers.5.layer_norm2.bias": "model-00001-of-00003.safetensors",
611
+ "vision_tower.vision_model.encoder.layers.5.layer_norm2.weight": "model-00001-of-00003.safetensors",
612
+ "vision_tower.vision_model.encoder.layers.5.mlp.fc1.bias": "model-00001-of-00003.safetensors",
613
+ "vision_tower.vision_model.encoder.layers.5.mlp.fc1.weight": "model-00001-of-00003.safetensors",
614
+ "vision_tower.vision_model.encoder.layers.5.mlp.fc2.bias": "model-00001-of-00003.safetensors",
615
+ "vision_tower.vision_model.encoder.layers.5.mlp.fc2.weight": "model-00001-of-00003.safetensors",
616
+ "vision_tower.vision_model.encoder.layers.5.self_attn.k_proj.bias": "model-00001-of-00003.safetensors",
617
+ "vision_tower.vision_model.encoder.layers.5.self_attn.k_proj.weight": "model-00001-of-00003.safetensors",
618
+ "vision_tower.vision_model.encoder.layers.5.self_attn.out_proj.bias": "model-00001-of-00003.safetensors",
619
+ "vision_tower.vision_model.encoder.layers.5.self_attn.out_proj.weight": "model-00001-of-00003.safetensors",
620
+ "vision_tower.vision_model.encoder.layers.5.self_attn.q_proj.bias": "model-00001-of-00003.safetensors",
621
+ "vision_tower.vision_model.encoder.layers.5.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
622
+ "vision_tower.vision_model.encoder.layers.5.self_attn.v_proj.bias": "model-00001-of-00003.safetensors",
623
+ "vision_tower.vision_model.encoder.layers.5.self_attn.v_proj.weight": "model-00001-of-00003.safetensors",
624
+ "vision_tower.vision_model.encoder.layers.6.layer_norm1.bias": "model-00001-of-00003.safetensors",
625
+ "vision_tower.vision_model.encoder.layers.6.layer_norm1.weight": "model-00001-of-00003.safetensors",
626
+ "vision_tower.vision_model.encoder.layers.6.layer_norm2.bias": "model-00001-of-00003.safetensors",
627
+ "vision_tower.vision_model.encoder.layers.6.layer_norm2.weight": "model-00001-of-00003.safetensors",
628
+ "vision_tower.vision_model.encoder.layers.6.mlp.fc1.bias": "model-00001-of-00003.safetensors",
629
+ "vision_tower.vision_model.encoder.layers.6.mlp.fc1.weight": "model-00001-of-00003.safetensors",
630
+ "vision_tower.vision_model.encoder.layers.6.mlp.fc2.bias": "model-00001-of-00003.safetensors",
631
+ "vision_tower.vision_model.encoder.layers.6.mlp.fc2.weight": "model-00001-of-00003.safetensors",
632
+ "vision_tower.vision_model.encoder.layers.6.self_attn.k_proj.bias": "model-00001-of-00003.safetensors",
633
+ "vision_tower.vision_model.encoder.layers.6.self_attn.k_proj.weight": "model-00001-of-00003.safetensors",
634
+ "vision_tower.vision_model.encoder.layers.6.self_attn.out_proj.bias": "model-00001-of-00003.safetensors",
635
+ "vision_tower.vision_model.encoder.layers.6.self_attn.out_proj.weight": "model-00001-of-00003.safetensors",
636
+ "vision_tower.vision_model.encoder.layers.6.self_attn.q_proj.bias": "model-00001-of-00003.safetensors",
637
+ "vision_tower.vision_model.encoder.layers.6.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
638
+ "vision_tower.vision_model.encoder.layers.6.self_attn.v_proj.bias": "model-00001-of-00003.safetensors",
639
+ "vision_tower.vision_model.encoder.layers.6.self_attn.v_proj.weight": "model-00001-of-00003.safetensors",
640
+ "vision_tower.vision_model.encoder.layers.7.layer_norm1.bias": "model-00001-of-00003.safetensors",
641
+ "vision_tower.vision_model.encoder.layers.7.layer_norm1.weight": "model-00001-of-00003.safetensors",
642
+ "vision_tower.vision_model.encoder.layers.7.layer_norm2.bias": "model-00001-of-00003.safetensors",
643
+ "vision_tower.vision_model.encoder.layers.7.layer_norm2.weight": "model-00001-of-00003.safetensors",
644
+ "vision_tower.vision_model.encoder.layers.7.mlp.fc1.bias": "model-00001-of-00003.safetensors",
645
+ "vision_tower.vision_model.encoder.layers.7.mlp.fc1.weight": "model-00001-of-00003.safetensors",
646
+ "vision_tower.vision_model.encoder.layers.7.mlp.fc2.bias": "model-00001-of-00003.safetensors",
647
+ "vision_tower.vision_model.encoder.layers.7.mlp.fc2.weight": "model-00001-of-00003.safetensors",
648
+ "vision_tower.vision_model.encoder.layers.7.self_attn.k_proj.bias": "model-00001-of-00003.safetensors",
649
+ "vision_tower.vision_model.encoder.layers.7.self_attn.k_proj.weight": "model-00001-of-00003.safetensors",
650
+ "vision_tower.vision_model.encoder.layers.7.self_attn.out_proj.bias": "model-00001-of-00003.safetensors",
651
+ "vision_tower.vision_model.encoder.layers.7.self_attn.out_proj.weight": "model-00001-of-00003.safetensors",
652
+ "vision_tower.vision_model.encoder.layers.7.self_attn.q_proj.bias": "model-00001-of-00003.safetensors",
653
+ "vision_tower.vision_model.encoder.layers.7.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
654
+ "vision_tower.vision_model.encoder.layers.7.self_attn.v_proj.bias": "model-00001-of-00003.safetensors",
655
+ "vision_tower.vision_model.encoder.layers.7.self_attn.v_proj.weight": "model-00001-of-00003.safetensors",
656
+ "vision_tower.vision_model.encoder.layers.8.layer_norm1.bias": "model-00001-of-00003.safetensors",
657
+ "vision_tower.vision_model.encoder.layers.8.layer_norm1.weight": "model-00001-of-00003.safetensors",
658
+ "vision_tower.vision_model.encoder.layers.8.layer_norm2.bias": "model-00001-of-00003.safetensors",
659
+ "vision_tower.vision_model.encoder.layers.8.layer_norm2.weight": "model-00001-of-00003.safetensors",
660
+ "vision_tower.vision_model.encoder.layers.8.mlp.fc1.bias": "model-00001-of-00003.safetensors",
661
+ "vision_tower.vision_model.encoder.layers.8.mlp.fc1.weight": "model-00001-of-00003.safetensors",
662
+ "vision_tower.vision_model.encoder.layers.8.mlp.fc2.bias": "model-00001-of-00003.safetensors",
663
+ "vision_tower.vision_model.encoder.layers.8.mlp.fc2.weight": "model-00001-of-00003.safetensors",
664
+ "vision_tower.vision_model.encoder.layers.8.self_attn.k_proj.bias": "model-00001-of-00003.safetensors",
665
+ "vision_tower.vision_model.encoder.layers.8.self_attn.k_proj.weight": "model-00001-of-00003.safetensors",
666
+ "vision_tower.vision_model.encoder.layers.8.self_attn.out_proj.bias": "model-00001-of-00003.safetensors",
667
+ "vision_tower.vision_model.encoder.layers.8.self_attn.out_proj.weight": "model-00001-of-00003.safetensors",
668
+ "vision_tower.vision_model.encoder.layers.8.self_attn.q_proj.bias": "model-00001-of-00003.safetensors",
669
+ "vision_tower.vision_model.encoder.layers.8.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
670
+ "vision_tower.vision_model.encoder.layers.8.self_attn.v_proj.bias": "model-00001-of-00003.safetensors",
671
+ "vision_tower.vision_model.encoder.layers.8.self_attn.v_proj.weight": "model-00001-of-00003.safetensors",
672
+ "vision_tower.vision_model.encoder.layers.9.layer_norm1.bias": "model-00001-of-00003.safetensors",
673
+ "vision_tower.vision_model.encoder.layers.9.layer_norm1.weight": "model-00001-of-00003.safetensors",
674
+ "vision_tower.vision_model.encoder.layers.9.layer_norm2.bias": "model-00001-of-00003.safetensors",
675
+ "vision_tower.vision_model.encoder.layers.9.layer_norm2.weight": "model-00001-of-00003.safetensors",
676
+ "vision_tower.vision_model.encoder.layers.9.mlp.fc1.bias": "model-00001-of-00003.safetensors",
677
+ "vision_tower.vision_model.encoder.layers.9.mlp.fc1.weight": "model-00001-of-00003.safetensors",
678
+ "vision_tower.vision_model.encoder.layers.9.mlp.fc2.bias": "model-00001-of-00003.safetensors",
679
+ "vision_tower.vision_model.encoder.layers.9.mlp.fc2.weight": "model-00001-of-00003.safetensors",
680
+ "vision_tower.vision_model.encoder.layers.9.self_attn.k_proj.bias": "model-00001-of-00003.safetensors",
681
+ "vision_tower.vision_model.encoder.layers.9.self_attn.k_proj.weight": "model-00001-of-00003.safetensors",
682
+ "vision_tower.vision_model.encoder.layers.9.self_attn.out_proj.bias": "model-00001-of-00003.safetensors",
683
+ "vision_tower.vision_model.encoder.layers.9.self_attn.out_proj.weight": "model-00001-of-00003.safetensors",
684
+ "vision_tower.vision_model.encoder.layers.9.self_attn.q_proj.bias": "model-00001-of-00003.safetensors",
685
+ "vision_tower.vision_model.encoder.layers.9.self_attn.q_proj.weight": "model-00001-of-00003.safetensors",
686
+ "vision_tower.vision_model.encoder.layers.9.self_attn.v_proj.bias": "model-00001-of-00003.safetensors",
687
+ "vision_tower.vision_model.encoder.layers.9.self_attn.v_proj.weight": "model-00001-of-00003.safetensors",
688
+ "vision_tower.vision_model.post_layernorm.bias": "model-00001-of-00003.safetensors",
689
+ "vision_tower.vision_model.post_layernorm.weight": "model-00001-of-00003.safetensors",
690
+ "vision_tower.vision_model.pre_layrnorm.bias": "model-00001-of-00003.safetensors",
691
+ "vision_tower.vision_model.pre_layrnorm.weight": "model-00001-of-00003.safetensors"
692
+ }
693
+ }
weights/llava-1.5-7b-hf/preprocessor_config.json ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "crop_size": {
3
+ "height": 336,
4
+ "width": 336
5
+ },
6
+ "do_center_crop": true,
7
+ "do_convert_rgb": true,
8
+ "do_normalize": true,
9
+ "do_rescale": true,
10
+ "do_resize": true,
11
+ "image_mean": [
12
+ 0.48145466,
13
+ 0.4578275,
14
+ 0.40821073
15
+ ],
16
+ "image_processor_type": "CLIPImageProcessor",
17
+ "image_std": [
18
+ 0.26862954,
19
+ 0.26130258,
20
+ 0.27577711
21
+ ],
22
+ "processor_class": "LlavaProcessor",
23
+ "resample": 3,
24
+ "rescale_factor": 0.00392156862745098,
25
+ "size": {
26
+ "shortest_edge": 336
27
+ }
28
+ }
weights/llava-1.5-7b-hf/processor_config.json ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ {
2
+ "image_token": "<image>",
3
+ "num_additional_image_tokens": 1,
4
+ "patch_size": 14,
5
+ "processor_class": "LlavaProcessor",
6
+ "vision_feature_select_strategy": "default"
7
+ }
weights/llava-1.5-7b-hf/special_tokens_map.json ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "bos_token": {
3
+ "content": "<s>",
4
+ "lstrip": false,
5
+ "normalized": false,
6
+ "rstrip": false,
7
+ "single_word": false
8
+ },
9
+ "eos_token": {
10
+ "content": "</s>",
11
+ "lstrip": false,
12
+ "normalized": false,
13
+ "rstrip": false,
14
+ "single_word": false
15
+ },
16
+ "pad_token": {
17
+ "content": "<pad>",
18
+ "lstrip": false,
19
+ "normalized": false,
20
+ "rstrip": false,
21
+ "single_word": false
22
+ },
23
+ "unk_token": {
24
+ "content": "<unk>",
25
+ "lstrip": false,
26
+ "normalized": false,
27
+ "rstrip": false,
28
+ "single_word": false
29
+ }
30
+ }
weights/llava-1.5-7b-hf/tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
weights/llava-1.5-7b-hf/tokenizer_config.json ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_bos_token": true,
3
+ "add_eos_token": false,
4
+ "add_prefix_space": null,
5
+ "added_tokens_decoder": {
6
+ "0": {
7
+ "content": "<unk>",
8
+ "lstrip": false,
9
+ "normalized": false,
10
+ "rstrip": false,
11
+ "single_word": false,
12
+ "special": true
13
+ },
14
+ "1": {
15
+ "content": "<s>",
16
+ "lstrip": false,
17
+ "normalized": false,
18
+ "rstrip": false,
19
+ "single_word": false,
20
+ "special": true
21
+ },
22
+ "2": {
23
+ "content": "</s>",
24
+ "lstrip": false,
25
+ "normalized": false,
26
+ "rstrip": false,
27
+ "single_word": false,
28
+ "special": true
29
+ },
30
+ "32000": {
31
+ "content": "<image>",
32
+ "lstrip": false,
33
+ "normalized": false,
34
+ "rstrip": false,
35
+ "single_word": false,
36
+ "special": true
37
+ },
38
+ "32001": {
39
+ "content": "<pad>",
40
+ "lstrip": false,
41
+ "normalized": false,
42
+ "rstrip": false,
43
+ "single_word": false,
44
+ "special": true
45
+ }
46
+ },
47
+ "bos_token": "<s>",
48
+ "clean_up_tokenization_spaces": false,
49
+ "eos_token": "</s>",
50
+ "extra_special_tokens": {
51
+ "image_token": "<image>"
52
+ },
53
+ "image_token": "<image>",
54
+ "legacy": false,
55
+ "model_max_length": 1000000000000000019884624838656,
56
+ "pad_token": "<pad>",
57
+ "padding_side": "left",
58
+ "processor_class": "LlavaProcessor",
59
+ "sp_model_kwargs": {},
60
+ "tokenizer_class": "LlamaTokenizer",
61
+ "trust_remote_code": false,
62
+ "unk_token": "<unk>",
63
+ "use_default_system_prompt": false
64
+ }
weights/merged_models/adapter/config.json ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_class_name": "TextAdapter",
3
+ "_diffusers_version": "0.24.0",
4
+ "_name_or_path": "pretrained_weights/lavi-bridge/llama2_unet/adapter",
5
+ "in_dim": 4096,
6
+ "int_dim": 2432,
7
+ "out_dim": 768
8
+ }
weights/merged_models/unet/config.json ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_class_name": "UNet2DConditionModel",
3
+ "_diffusers_version": "0.24.0",
4
+ "_name_or_path": "pretrained_weights/stable-diffusion",
5
+ "act_fn": "silu",
6
+ "addition_embed_type": null,
7
+ "addition_embed_type_num_heads": 64,
8
+ "addition_time_embed_dim": null,
9
+ "attention_head_dim": 8,
10
+ "attention_type": "default",
11
+ "block_out_channels": [
12
+ 320,
13
+ 640,
14
+ 1280,
15
+ 1280
16
+ ],
17
+ "center_input_sample": false,
18
+ "class_embed_type": null,
19
+ "class_embeddings_concat": false,
20
+ "conv_in_kernel": 3,
21
+ "conv_out_kernel": 3,
22
+ "cross_attention_dim": 768,
23
+ "cross_attention_norm": null,
24
+ "down_block_types": [
25
+ "CrossAttnDownBlock2D",
26
+ "CrossAttnDownBlock2D",
27
+ "CrossAttnDownBlock2D",
28
+ "DownBlock2D"
29
+ ],
30
+ "downsample_padding": 1,
31
+ "dropout": 0.0,
32
+ "dual_cross_attention": false,
33
+ "encoder_hid_dim": null,
34
+ "encoder_hid_dim_type": null,
35
+ "flip_sin_to_cos": true,
36
+ "freq_shift": 0,
37
+ "in_channels": 4,
38
+ "layers_per_block": 2,
39
+ "mid_block_only_cross_attention": null,
40
+ "mid_block_scale_factor": 1,
41
+ "mid_block_type": "UNetMidBlock2DCrossAttn",
42
+ "norm_eps": 1e-05,
43
+ "norm_num_groups": 32,
44
+ "num_attention_heads": null,
45
+ "num_class_embeds": null,
46
+ "only_cross_attention": false,
47
+ "out_channels": 4,
48
+ "projection_class_embeddings_input_dim": null,
49
+ "resnet_out_scale_factor": 1.0,
50
+ "resnet_skip_time_act": false,
51
+ "resnet_time_scale_shift": "default",
52
+ "reverse_transformer_layers_per_block": null,
53
+ "sample_size": 64,
54
+ "time_cond_proj_dim": null,
55
+ "time_embedding_act_fn": null,
56
+ "time_embedding_dim": null,
57
+ "time_embedding_type": "positional",
58
+ "timestep_post_act": null,
59
+ "transformer_layers_per_block": 1,
60
+ "up_block_types": [
61
+ "UpBlock2D",
62
+ "CrossAttnUpBlock2D",
63
+ "CrossAttnUpBlock2D",
64
+ "CrossAttnUpBlock2D"
65
+ ],
66
+ "upcast_attention": false,
67
+ "use_linear_projection": false
68
+ }
weights/stable-diffusion/scheduler/.ipynb_checkpoints/scheduler_config-checkpoint.json ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_class_name": "PNDMScheduler",
3
+ "_diffusers_version": "0.2.2",
4
+ "beta_end": 0.012,
5
+ "beta_schedule": "scaled_linear",
6
+ "beta_start": 0.00085,
7
+ "num_train_timesteps": 1000,
8
+ "skip_prk_steps": true
9
+ }
weights/stable-diffusion/scheduler/scheduler_config.json ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_class_name": "PNDMScheduler",
3
+ "_diffusers_version": "0.7.0.dev0",
4
+ "beta_end": 0.012,
5
+ "beta_schedule": "scaled_linear",
6
+ "beta_start": 0.00085,
7
+ "num_train_timesteps": 1000,
8
+ "set_alpha_to_one": false,
9
+ "skip_prk_steps": true,
10
+ "steps_offset": 1,
11
+ "trained_betas": null,
12
+ "clip_sample": false
13
+ }
weights/stable-diffusion/vae/config.json ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_class_name": "AutoencoderKL",
3
+ "_diffusers_version": "0.2.2",
4
+ "act_fn": "silu",
5
+ "block_out_channels": [
6
+ 128,
7
+ 256,
8
+ 512,
9
+ 512
10
+ ],
11
+ "down_block_types": [
12
+ "DownEncoderBlock2D",
13
+ "DownEncoderBlock2D",
14
+ "DownEncoderBlock2D",
15
+ "DownEncoderBlock2D"
16
+ ],
17
+ "in_channels": 3,
18
+ "latent_channels": 4,
19
+ "layers_per_block": 2,
20
+ "out_channels": 3,
21
+ "sample_size": 512,
22
+ "scaling_factor": 0.18215,
23
+ "up_block_types": [
24
+ "UpDecoderBlock2D",
25
+ "UpDecoderBlock2D",
26
+ "UpDecoderBlock2D",
27
+ "UpDecoderBlock2D"
28
+ ]
29
+ }