CCCCyx commited on
Commit
f55d7c8
·
verified ·
1 Parent(s): d784ba4

Upload MOSS-VL-Realtime-0708 release

Browse files
.gitattributes CHANGED
@@ -33,3 +33,7 @@ saved_model/**/* 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
 
 
 
 
 
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
36
+ assets/architecture.png filter=lfs diff=lfs merge=lfs -text
37
+ assets/benchmark-streaming.png filter=lfs diff=lfs merge=lfs -text
38
+ assets/logo.png filter=lfs diff=lfs merge=lfs -text
39
+ tokenizer.json filter=lfs diff=lfs merge=lfs -text
README.md CHANGED
@@ -1,3 +1,371 @@
1
  ---
2
  license: apache-2.0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
  license: apache-2.0
3
+ language:
4
+ - en
5
+ library_name: transformers
6
+ pipeline_tag: video-text-to-text
7
+ base_model: OpenMOSS-Team/MOSS-VL-Base-0708
8
+ tags:
9
+ - moss_vl
10
+ - feature-extraction
11
+ - Realtime
12
+ - Streaming
13
+ - Video-Understanding
14
+ - Image-Understanding
15
+ - MOSS-VL
16
+ - OpenMOSS
17
+ - multimodal
18
+ - video
19
+ - vision-language
20
+ - custom_code
21
  ---
22
+
23
+ <p align="center">
24
+ <img src="assets/logo.png" width="300" alt="MOSS-VL"/>
25
+ </p>
26
+
27
+ # MOSS-VL-Realtime-0708
28
+
29
+ ## Introduction
30
+
31
+ MOSS-VL-Realtime-0708 is the realtime streaming checkpoint of the MOSS-VL 0708 release, part of the OpenMOSS ecosystem for open visual understanding.
32
+
33
+ Unlike offline video-language models that first read a complete video and then answer, MOSS-VL-Realtime-0708 is designed for continuous video streams. It can perceive incoming frames and generate text in parallel, support multi-turn realtime interaction, answer questions at arbitrary moments in the stream, and decide whether to speak or keep observing when the visual evidence is not yet sufficient.
34
+
35
+ The 0708 release keeps the MOSS-VL cross-attention design and a 256K text context window while adding realtime streaming data and an inference interface for timestamped frame-by-frame input.
36
+
37
+ ## Highlights
38
+
39
+ - Interruptible realtime interaction: users can ask questions at any timestamp in a running video stream, and the model answers based on the frames observed so far.
40
+ - Proactive silence: the model can emit `<|silence|>` and continue observing when no important visual event has happened or the context is insufficient.
41
+ - Dynamic correction: as new frames arrive, the model can update or correct earlier responses instead of being locked to an initial interpretation.
42
+ - Native timestamped frames: each streamed frame is associated with an absolute timestamp, helping the model reason about event order, duration, pacing, and fine-grained temporal localization.
43
+ - Open MOSS-VL family: released together with MOSS-VL-Instruct-0708 and MOSS-VL-Base-0708 for offline use, continued pretraining, fine-tuning, and applied research.
44
+
45
+ ## Realtime Interaction
46
+
47
+ MOSS-VL-Realtime-0708 exposes a model-owned streaming loop through `create_realtime_session(...)`, `online_generate(...)`, and `real_time_generate(...)`.
48
+
49
+ The recommended deployment API is `create_realtime_session(...)`. A service or application owns the video capture pipeline, converts camera, screen, or video-file input into PIL-compatible frames, and pushes each frame with a non-decreasing timestamp:
50
+
51
+ - `session.push_frame(image, timestamp=...)` appends one visual frame.
52
+ - `session.push_prompt("...")` appends a user question while the stream is running.
53
+ - `session.push_prompt_frame(prompt, image, timestamp=...)` aligns a prompt with a specific frame.
54
+ - `session.poll_output(...)` or `session.stream_outputs(...)` returns incremental text chunks.
55
+
56
+ For backend systems that already use queues, `online_generate(...)` accepts dictionaries containing frames, prompts, events, reset controls, and stop controls.
57
+
58
+ ## Model Architecture
59
+
60
+ MOSS-VL-Realtime-0708 adopts a cross-attention-based vision-language architecture that decouples visual encoding from language reasoning. This design is important for realtime usage because incoming visual content can be integrated into the running generation context without forcing the model into a strictly offline "load all frames, then answer" workflow.
61
+
62
+ <p align="center">
63
+ <img src="assets/architecture.png" alt="MOSS-VL Architecture" width="100%"/>
64
+ </p>
65
+
66
+ Key configuration details:
67
+
68
+ | Item | Value |
69
+ | --- | --- |
70
+ | Parameters | 11B |
71
+ | Tensor type | BF16 |
72
+ | Context length | 256K |
73
+ | Vision patch size | 16 |
74
+ | Temporal patch size | 1 |
75
+ | Default video FPS | 1.0 |
76
+ | Default max video frames | 256 |
77
+ | Realtime frame format | PIL-compatible image plus timestamp |
78
+ | Realtime session scope | One active realtime session per model instance |
79
+
80
+ ## Absolute Timestamps
81
+
82
+ For video and realtime frame inputs, MOSS-VL injects absolute timestamps alongside sampled frames. This helps the model reason about when an event happens, how long it lasts, and how the scene changes over time instead of relying only on frame order.
83
+
84
+ ## Cross-attention RoPE (XRoPE)
85
+
86
+ MOSS-VL uses Cross-attention Rotary Position Embedding (XRoPE), which maps text tokens and visual patches into a unified three-dimensional coordinate space defined by Time (t), Height (h), and Width (w). This gives the model a consistent positional representation for image, offline video, and realtime streaming video reasoning.
87
+
88
+ ## Model Performance
89
+
90
+ MOSS-VL-Realtime-0708 is designed for streaming video understanding benchmarks where questions can arrive before a full video has been observed and correct answers may change as the scene evolves. It targets realtime interaction quality, proactive silence, and dynamic response updates in addition to standard video understanding accuracy.
91
+
92
+ <p align="center">
93
+ <img src="assets/benchmark-streaming.png" alt="MOSS-VL Streaming Benchmark" width="100%"/>
94
+ </p>
95
+
96
+ Detailed benchmark tables and comparisons for the 0708 release will be maintained in the MOSS-VL project resources.
97
+
98
+ ## Quickstart
99
+
100
+ ### Installation
101
+
102
+ Clone the MOSS-VL repository and install the project requirements:
103
+
104
+ ```bash
105
+ git clone https://github.com/OpenMOSS/MOSS-VL.git
106
+ cd MOSS-VL
107
+ conda create -n moss_vl python=3.12 pip -y
108
+ conda activate moss_vl
109
+ pip install -i https://pypi.org/simple --no-build-isolation -r requirements.txt
110
+ ```
111
+
112
+ ### Load Model
113
+
114
+ ```python
115
+ import torch
116
+ from transformers import AutoModelForCausalLM, AutoProcessor
117
+
118
+ checkpoint = "OpenMOSS-Team/MOSS-VL-Realtime-0708"
119
+
120
+ processor = AutoProcessor.from_pretrained(
121
+ checkpoint,
122
+ trust_remote_code=True,
123
+ frame_extract_num_threads=1,
124
+ )
125
+ model = AutoModelForCausalLM.from_pretrained(
126
+ checkpoint,
127
+ trust_remote_code=True,
128
+ device_map="auto",
129
+ torch_dtype=torch.bfloat16,
130
+ attn_implementation="flash_attention_2",
131
+ )
132
+ model.eval()
133
+ ```
134
+
135
+ If FlashAttention is unavailable in your environment, pass `attn_implementation="eager"` when loading the model.
136
+
137
+ ### Run Realtime Streaming
138
+
139
+ The session API keeps generation active while new frames and prompts are appended.
140
+
141
+ ```python
142
+ import time
143
+ from PIL import Image
144
+
145
+ session = model.create_realtime_session(
146
+ processor,
147
+ initial_prompt=(
148
+ "As the video streams frame by frame, describe important changes as they happen. "
149
+ "Stay silent when there is no relevant update."
150
+ ),
151
+ frame_queue_size=256,
152
+ max_tokens_per_turn=12,
153
+ max_new_tokens=4096,
154
+ do_sample=False,
155
+ )
156
+
157
+ frame_paths = [
158
+ "data/frame_0001.jpg",
159
+ "data/frame_0002.jpg",
160
+ "data/frame_0003.jpg",
161
+ ]
162
+
163
+ try:
164
+ session.start()
165
+
166
+ for index, frame_path in enumerate(frame_paths):
167
+ image = Image.open(frame_path).convert("RGB")
168
+ session.push_frame(image, timestamp=index / 1.0)
169
+
170
+ while True:
171
+ chunk = session.poll_output(timeout=0.0)
172
+ if chunk is None:
173
+ break
174
+ print(chunk, end="", flush=True)
175
+
176
+ time.sleep(1.0)
177
+
178
+ session.push_prompt("What changed in the latest frames?")
179
+
180
+ for chunk in session.stream_outputs(poll_interval=0.1):
181
+ print(chunk, end="", flush=True)
182
+ finally:
183
+ session.close()
184
+ ```
185
+
186
+ Frame timestamps are measured in seconds and must be non-decreasing within a session. The input producer can be a camera, screen capture, decoded video file, browser frame sampler, or any other source that yields images with timestamps.
187
+
188
+ ### Queue-style Online Inference
189
+
190
+ `online_generate(...)` is useful for services that separate frame production and model inference through queues.
191
+
192
+ ```python
193
+ import queue
194
+ import threading
195
+ from PIL import Image
196
+
197
+ input_queue = queue.Queue()
198
+ output_queue = queue.Queue()
199
+
200
+ worker = threading.Thread(
201
+ target=model.online_generate,
202
+ args=(processor, input_queue, output_queue),
203
+ kwargs={
204
+ "frame_queue_size": 256,
205
+ "max_tokens_per_turn": 12,
206
+ "max_new_tokens": 4096,
207
+ "do_sample": False,
208
+ },
209
+ daemon=True,
210
+ )
211
+ worker.start()
212
+
213
+ input_queue.put({
214
+ "initial_prompt": "Answer only when the streamed video provides enough evidence.",
215
+ })
216
+
217
+ input_queue.put({"frame": Image.open("data/frame_0001.jpg").convert("RGB"), "timestamp": 0.0})
218
+ input_queue.put({"frame": Image.open("data/frame_0002.jpg").convert("RGB"), "timestamp": 1.0})
219
+ input_queue.put({"prompt": "What is happening now?"})
220
+
221
+ try:
222
+ while True:
223
+ chunk = output_queue.get(timeout=0.5)
224
+ print(chunk, end="", flush=True)
225
+ except queue.Empty:
226
+ pass
227
+
228
+ input_queue.put({"stop_online_generate": True})
229
+ worker.join()
230
+ ```
231
+
232
+ Each queue item can contain `frame` or `image`, `timestamp`, `prompt`, `frames`, `event`, `events`, `initial_prompt`, `system_prompt`, `generate_kwargs`, `reset_session`, or stop controls such as `stop_online_generate`.
233
+
234
+ ### Offline Inference Compatibility
235
+
236
+ MOSS-VL-Realtime-0708 also keeps the offline helper APIs for image and video prompts. For purely offline use, MOSS-VL-Instruct-0708 is usually the preferred checkpoint, but the realtime checkpoint can still process complete image and video inputs.
237
+
238
+ <details>
239
+ <summary><b>Single-video Offline Inference</b></summary>
240
+
241
+ ```python
242
+ video_path = "data/example_video.mp4"
243
+ prompt = "Describe this video."
244
+
245
+ text = model.offline_video_generate(
246
+ processor,
247
+ prompt=prompt,
248
+ video=video_path,
249
+ shortest_edge=4096,
250
+ longest_edge=16777216,
251
+ video_max_pixels=201326592,
252
+ patch_size=16,
253
+ temporal_patch_size=1,
254
+ merge_size=2,
255
+ video_fps=1.0,
256
+ min_frames=1,
257
+ max_frames=256,
258
+ num_extract_threads=4,
259
+ image_mean=[0.5, 0.5, 0.5],
260
+ image_std=[0.5, 0.5, 0.5],
261
+ max_new_tokens=256,
262
+ temperature=1.0,
263
+ top_k=50,
264
+ top_p=1.0,
265
+ repetition_penalty=1.0,
266
+ do_sample=False,
267
+ vision_chunked_length=64,
268
+ )
269
+
270
+ print(text)
271
+ ```
272
+
273
+ </details>
274
+
275
+ <details>
276
+ <summary><b>Batched Offline Inference</b></summary>
277
+
278
+ `offline_batch_generate` accepts independent image/video/text queries. Queries in the same batch should share the same `media_kwargs` and `generate_kwargs`.
279
+
280
+ ```python
281
+ queries = [
282
+ {
283
+ "prompt": "Describe sample A.",
284
+ "images": [],
285
+ "videos": ["data/sample_a.mp4"],
286
+ "media_kwargs": {
287
+ "video_fps": 1.0,
288
+ "min_frames": 8,
289
+ "max_frames": 256,
290
+ },
291
+ "generate_kwargs": {
292
+ "temperature": 1.0,
293
+ "top_k": 50,
294
+ "top_p": 1.0,
295
+ "max_new_tokens": 256,
296
+ "repetition_penalty": 1.0,
297
+ "do_sample": False,
298
+ },
299
+ },
300
+ {
301
+ "prompt": "Describe sample B.",
302
+ "images": [],
303
+ "videos": ["data/sample_b.mp4"],
304
+ "media_kwargs": {
305
+ "video_fps": 1.0,
306
+ "min_frames": 8,
307
+ "max_frames": 256,
308
+ },
309
+ "generate_kwargs": {
310
+ "temperature": 1.0,
311
+ "top_k": 50,
312
+ "top_p": 1.0,
313
+ "max_new_tokens": 256,
314
+ "repetition_penalty": 1.0,
315
+ "do_sample": False,
316
+ },
317
+ },
318
+ ]
319
+
320
+ with torch.no_grad():
321
+ result = model.offline_batch_generate(
322
+ processor,
323
+ queries,
324
+ vision_chunked_length=64,
325
+ )
326
+
327
+ texts = [item["text"] for item in result["results"]]
328
+ print(texts)
329
+ ```
330
+
331
+ </details>
332
+
333
+ ## Related Checkpoints
334
+
335
+ | Model | Parameters | Context | Usage | Hugging Face |
336
+ | --- | ---: | ---: | --- | --- |
337
+ | MOSS-VL-Realtime-0708 | 11B | 256K | Realtime streaming video interaction | https://huggingface.co/OpenMOSS-Team/MOSS-VL-Realtime-0708 |
338
+ | MOSS-VL-Instruct-0708 | 11B | 256K | Offline multimodal instruction following | https://huggingface.co/OpenMOSS-Team/MOSS-VL-Instruct-0708 |
339
+ | MOSS-VL-Base-0708 | 11B | 256K | Continued pretraining and fine-tuning | https://huggingface.co/OpenMOSS-Team/MOSS-VL-Base-0708 |
340
+ | MOSS-VL-Instruct-0408 | 11B | 256K | Previous instruction-tuned checkpoint | https://huggingface.co/OpenMOSS-Team/MOSS-VL-Instruct-0408 |
341
+ | MOSS-VL-Base-0408 | 11B | 256K | Previous base checkpoint | https://huggingface.co/OpenMOSS-Team/MOSS-VL-Base-0408 |
342
+
343
+ ## Limitations and Future Work
344
+
345
+ MOSS-VL-Realtime-0708 is optimized for timestamped frame-by-frame streaming, but production latency depends on GPU hardware, frame sampling rate, transport overhead, and decoding speed. One model instance supports one active realtime session. The default frame queue bounds latency by dropping older pending frames when needed.
346
+
347
+ The model may emit realtime control tokens such as `<|silence|>`, `<|round_start|>`, and `<|round_end|>` depending on the application protocol. Downstream services should filter or render these tokens according to their UI needs.
348
+
349
+ We are continuing to improve realtime response timing, dynamic correction, broader streaming evaluations, RL post-training, and task-specific deployment recipes for future MOSS-VL releases.
350
+
351
+ ## Citation
352
+
353
+ ```bibtex
354
+ @misc{moss_vl_2026,
355
+ title = {{MOSS-VL Technical Report}},
356
+ author = {OpenMOSS Team},
357
+ year = {2026},
358
+ howpublished = {\url{https://github.com/OpenMOSS/MOSS-VL}},
359
+ note = {GitHub repository}
360
+ }
361
+
362
+ @misc{mossvideopreview2026,
363
+ title = {{MOSS-Video-Preview: Toward Real-Time Video Understanding via Cross-Attention}},
364
+ author = {Pengyu Wang and Chenkun Tan and Shaojun Zhou and Wei Huang and Qirui Zhou and Zhan Huang and Zhen Ye and Jijun Cheng and Xiaomeng Qian and Yanxin Chen and Xingyang He and Huazheng Zeng and Chenghao Wang and Pengfei Wang and Hongkai Wang and Shanqing Gao and Yixian Tian and Chenghao Liu and Xinghao Wang and Botian Jiang and Xipeng Qiu},
365
+ year = {2026},
366
+ eprint = {2606.07639},
367
+ archivePrefix = {arXiv},
368
+ primaryClass = {cs.CV},
369
+ url = {https://arxiv.org/abs/2606.07639}
370
+ }
371
+ ```
assets/architecture.png ADDED

Git LFS Details

  • SHA256: 28e51b34e031c884c540601d6b6651576c65836dc252694a1dc7dc0b1fc15237
  • Pointer size: 132 Bytes
  • Size of remote file: 6.09 MB
assets/benchmark-streaming.png ADDED

Git LFS Details

  • SHA256: 92ae97a04b09c7e8492005fcbae99ddc97516247711f9ea43d31e11c47094213
  • Pointer size: 131 Bytes
  • Size of remote file: 420 kB
assets/logo.png ADDED

Git LFS Details

  • SHA256: 37bf0241f5fbab73fc955827f477befc95b88b0d3618c31628099b70ea1dd232
  • Pointer size: 131 Bytes
  • Size of remote file: 941 kB
chat_template.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "chat_template": "{%- if tools %}\n {{- '<|im_start|>system\\n' }}\n {%- if messages[0].role == 'system' %}\n {%- if messages[0].content is string %}\n {{- messages[0].content }}\n {%- else %}\n {%- for content in messages[0].content %}\n {%- if 'text' in content %}\n {{- content.text }}\n {%- endif %}\n {%- endfor %}\n {%- endif %}\n {{- '\\n\\n' }}\n {%- endif %}\n {{- \"# Tools\\n\\nYou may call one or more functions to assist with the user query.\\n\\nYou are provided with function signatures within <tools></tools> XML tags:\\n<tools>\" }}\n {%- for tool in tools %}\n {{- \"\\n\" }}\n {{- tool | tojson }}\n {%- endfor %}\n {{- \"\\n</tools>\\n\\nFor each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags:\\n<tool_call>\\n{\\\"name\\\": <function-name>, \\\"arguments\\\": <args-json-object>}\\n</tool_call><|im_end|>\\n\" }}\n{%- else %}\n {%- if messages[0].role == 'system' %}\n {{- '<|im_start|>system\\n' }}\n {%- if messages[0].content is string %}\n {{- messages[0].content }}\n {%- else %}\n {%- for content in messages[0].content %}\n {%- if 'text' in content %}\n {{- content.text }}\n {%- endif %}\n {%- endfor %}\n {%- endif %}\n {{- '<|im_end|>\\n' }}\n {%- endif %}\n{%- endif %}\n{%- set image_count = namespace(value=0) %}\n{%- set video_count = namespace(value=0) %}\n{%- for message in messages %}\n {%- if message.role == \"user\" %}\n {{- '<|im_start|>' + message.role + '\\n' }}\n {%- if message.content is string %}\n {{- message.content }}\n {%- else %}\n {%- for content in message.content %}\n {%- if content.type == 'image' or 'image' in content or 'image_url' in content %}\n {%- set image_count.value = image_count.value + 1 %}\n {%- if add_vision_id %}Picture {{ image_count.value }}: {% endif -%}\n <|image|>\n {%- elif content.type == 'video' or 'video' in content %}\n {%- set video_count.value = video_count.value + 1 %}\n {%- if add_vision_id %}Video {{ video_count.value }}: {% endif -%}\n <|video|>\n {%- elif 'text' in content %}\n {{- content.text }}\n {%- endif %}\n {%- endfor %}\n {%- endif %}\n {{- '<|im_end|>\\n' }}\n {%- elif message.role == \"assistant\" %}\n {{- '<|im_start|>' + message.role + '\\n' }}\n {%- if message.content is string %}\n {{- message.content }}\n {%- else %}\n {%- for content_item in message.content %}\n {%- if 'text' in content_item %}\n {{- content_item.text }}\n {%- endif %}\n {%- endfor %}\n {%- endif %}\n {%- if message.tool_calls %}\n {%- for tool_call in message.tool_calls %}\n {%- if (loop.first and message.content) or (not loop.first) %}\n {{- '\\n' }}\n {%- endif %}\n {%- if tool_call.function %}\n {%- set tool_call = tool_call.function %}\n {%- endif %}\n {{- '<tool_call>\\n{\"name\": \"' }}\n {{- tool_call.name }}\n {{- '\", \"arguments\": ' }}\n {%- if tool_call.arguments is string %}\n {{- tool_call.arguments }}\n {%- else %}\n {{- tool_call.arguments | tojson }}\n {%- endif %}\n {{- '}\\n</tool_call>' }}\n {%- endfor %}\n {%- endif %}\n {{- '<|im_end|>\\n' }}\n {%- elif message.role == \"tool\" %}\n {%- if loop.first or (messages[loop.index0 - 1].role != \"tool\") %}\n {{- '<|im_start|>user' }}\n {%- endif %}\n {{- '\\n<tool_response>\\n' }}\n {%- if message.content is string %}\n {{- message.content }}\n {%- else %}\n {%- for content in message.content %}\n {%- if content.type == 'image' or 'image' in content or 'image_url' in content %}\n {%- set image_count.value = image_count.value + 1 %}\n {%- if add_vision_id %}Picture {{ image_count.value }}: {% endif -%}\n <|image|>\n {%- elif content.type == 'video' or 'video' in content %}\n {%- set video_count.value = video_count.value + 1 %}\n {%- if add_vision_id %}Video {{ video_count.value }}: {% endif -%}\n <|video|>\n {%- elif 'text' in content %}\n {{- content.text }}\n {%- endif %}\n {%- endfor %}\n {%- endif %}\n {{- '\\n</tool_response>' }}\n {%- if loop.last or (messages[loop.index0 + 1].role != \"tool\") %}\n {{- '<|im_end|>\\n' }}\n {%- endif %}\n {%- endif %}\n{%- endfor %}\n{%- if add_generation_prompt %}\n {{- '<|im_start|>assistant\\n' }}\n{%- endif %}\n"
3
+ }
config.json ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "MossVLForConditionalGeneration"
4
+ ],
5
+ "auto_map": {
6
+ "AutoConfig": "configuration_moss_vl.MossVLConfig",
7
+ "AutoModel": "modeling_moss_vl.MossVLForConditionalGeneration",
8
+ "AutoModelForCausalLM": "modeling_moss_vl.MossVLForConditionalGeneration"
9
+ },
10
+ "dtype": "bfloat16",
11
+ "image_token_id": 151655,
12
+ "model_type": "moss_vl",
13
+ "text_config": {
14
+ "attention_bias": false,
15
+ "attention_dropout": 0.0,
16
+ "bos_token_id": 151643,
17
+ "cross_attention_layers": [
18
+ 2,
19
+ 6,
20
+ 10,
21
+ 14,
22
+ 18,
23
+ 22,
24
+ 26,
25
+ 30,
26
+ 34,
27
+ 38,
28
+ 42,
29
+ 46
30
+ ],
31
+ "dtype": "bfloat16",
32
+ "eos_token_id": 151645,
33
+ "head_dim": 128,
34
+ "hidden_act": "silu",
35
+ "hidden_size": 4096,
36
+ "initializer_range": 0.02,
37
+ "intermediate_size": 12288,
38
+ "max_position_embeddings": 262144,
39
+ "model_type": "moss_vl_text",
40
+ "num_attention_heads": 32,
41
+ "num_hidden_layers": 48,
42
+ "num_key_value_heads": 8,
43
+ "rms_norm_eps": 1e-06,
44
+ "rope_scaling": {
45
+ "mrope_interleaved": true,
46
+ "mrope_section": [
47
+ 24,
48
+ 20,
49
+ 20
50
+ ],
51
+ "rope_type": "default"
52
+ },
53
+ "rope_theta": 5000000,
54
+ "use_cache": true,
55
+ "vocab_size": 151936
56
+ },
57
+ "tie_word_embeddings": false,
58
+ "transformers_version": "4.57.3",
59
+ "video_token_id": 151656,
60
+ "vision_config": {
61
+ "deepstack_visual_indexes": [
62
+ 8,
63
+ 16,
64
+ 24
65
+ ],
66
+ "depth": 27,
67
+ "hidden_act": "gelu_pytorch_tanh",
68
+ "hidden_size": 1152,
69
+ "in_channels": 3,
70
+ "initializer_range": 0.02,
71
+ "intermediate_size": 4304,
72
+ "model_type": "moss_vl_vision",
73
+ "num_heads": 16,
74
+ "num_position_embeddings": 2304,
75
+ "out_hidden_size": 4096,
76
+ "patch_size": 16,
77
+ "spatial_merge_size": 2,
78
+ "temporal_patch_size": 1
79
+ },
80
+ "vision_end_token_id": 151653,
81
+ "vision_seq_pad_multiple": 1,
82
+ "vision_start_token_id": 151652
83
+ }
configuration_moss_vl.py ADDED
@@ -0,0 +1,164 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # coding=utf-8
2
+ # Copyright 2025 The HuggingFace Inc. team. All rights reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ """MossVL model configuration"""
16
+
17
+ from transformers.configuration_utils import PretrainedConfig
18
+ from transformers.modeling_rope_utils import rope_config_validation
19
+ from transformers.utils import logging
20
+
21
+ logger = logging.get_logger(__name__)
22
+
23
+
24
+ class MossVLVisionConfig(PretrainedConfig):
25
+ """
26
+ Configuration for MossVL Vision Model
27
+ """
28
+
29
+ model_type = "moss_vl_vision"
30
+ base_config_key = "vision_config"
31
+
32
+ def __init__(
33
+ self,
34
+ depth=27,
35
+ hidden_size=1152,
36
+ hidden_act="gelu_pytorch_tanh",
37
+ intermediate_size=4304,
38
+ num_heads=16,
39
+ in_channels=3,
40
+ patch_size=16,
41
+ spatial_merge_size=2,
42
+ temporal_patch_size=1,
43
+ out_hidden_size=3584,
44
+ num_position_embeddings=2304,
45
+ deepstack_visual_indexes=[8, 16, 24],
46
+ initializer_range=0.02,
47
+ **kwargs,
48
+ ):
49
+ super().__init__(**kwargs)
50
+ self.depth = depth
51
+ self.hidden_size = hidden_size
52
+ self.hidden_act = hidden_act
53
+ self.intermediate_size = intermediate_size
54
+ self.num_heads = num_heads
55
+ self.in_channels = in_channels
56
+ self.patch_size = patch_size
57
+ self.spatial_merge_size = spatial_merge_size
58
+ self.temporal_patch_size = temporal_patch_size
59
+ self.out_hidden_size = out_hidden_size
60
+ self.num_position_embeddings = num_position_embeddings
61
+ self.initializer_range = initializer_range
62
+ self.deepstack_visual_indexes = deepstack_visual_indexes
63
+
64
+
65
+ class MossVLTextConfig(PretrainedConfig):
66
+ """
67
+ Configuration for MossVL Text Model
68
+ """
69
+
70
+ model_type = "moss_vl_text"
71
+ base_config_key = "text_config"
72
+
73
+ def __init__(
74
+ self,
75
+ vocab_size=151936,
76
+ hidden_size=4096,
77
+ intermediate_size=22016,
78
+ num_hidden_layers=32,
79
+ num_attention_heads=32,
80
+ num_key_value_heads=32,
81
+ head_dim=128,
82
+ hidden_act="silu",
83
+ max_position_embeddings=128000,
84
+ initializer_range=0.02,
85
+ rms_norm_eps=1e-6,
86
+ use_cache=True,
87
+ tie_word_embeddings=False,
88
+ rope_theta=5000000.0,
89
+ rope_scaling=None,
90
+ attention_bias=False,
91
+ attention_dropout=0.0,
92
+ # Cross attention specific
93
+ cross_attention_layers=None, # List of layer indices to insert cross attention
94
+ **kwargs,
95
+ ):
96
+
97
+ self.vocab_size = vocab_size
98
+ self.max_position_embeddings = max_position_embeddings
99
+ self.hidden_size = hidden_size
100
+ self.intermediate_size = intermediate_size
101
+ self.num_hidden_layers = num_hidden_layers
102
+ self.num_attention_heads = num_attention_heads
103
+
104
+ # for backward compatibility
105
+ if num_key_value_heads is None:
106
+ num_key_value_heads = num_attention_heads
107
+
108
+ self.num_key_value_heads = num_key_value_heads
109
+ self.head_dim = head_dim
110
+ self.hidden_act = hidden_act
111
+ self.initializer_range = initializer_range
112
+ self.rms_norm_eps = rms_norm_eps
113
+ self.use_cache = use_cache
114
+ self.rope_theta = rope_theta
115
+ self.rope_scaling = rope_scaling
116
+ self.attention_bias = attention_bias
117
+ self.attention_dropout = attention_dropout
118
+
119
+ rope_config_validation(self, ignore_keys={"mrope_section", "mrope_interleaved"})
120
+ self.cross_attention_layers = cross_attention_layers or [2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46]
121
+ super().__init__(tie_word_embeddings=tie_word_embeddings, **kwargs)
122
+
123
+ class MossVLConfig(PretrainedConfig):
124
+ """
125
+ Configuration for MossVL Model
126
+ """
127
+
128
+ model_type = "moss_vl"
129
+ sub_configs = {"vision_config": MossVLVisionConfig, "text_config": MossVLTextConfig}
130
+ keys_to_ignore_at_inference = ["past_key_values"]
131
+
132
+ def __init__(
133
+ self,
134
+ text_config=None,
135
+ vision_config=None,
136
+ image_token_id=151655,
137
+ video_token_id=151656,
138
+ vision_start_token_id=151652,
139
+ vision_end_token_id=151653,
140
+ vision_seq_pad_multiple=8,
141
+ tie_word_embeddings=False,
142
+ **kwargs,
143
+ ):
144
+ if isinstance(vision_config, dict):
145
+ self.vision_config = self.sub_configs["vision_config"](**vision_config)
146
+ elif vision_config is None:
147
+ self.vision_config = self.sub_configs["vision_config"]()
148
+
149
+ if isinstance(text_config, dict):
150
+ self.text_config = self.sub_configs["text_config"](**text_config)
151
+ elif text_config is None:
152
+ self.text_config = self.sub_configs["text_config"]()
153
+
154
+ self.image_token_id = image_token_id
155
+ self.video_token_id = video_token_id
156
+ self.vision_start_token_id = vision_start_token_id
157
+
158
+
159
+ self.vision_end_token_id = vision_end_token_id
160
+ self.vision_seq_pad_multiple = vision_seq_pad_multiple
161
+ super().__init__(**kwargs, tie_word_embeddings=tie_word_embeddings)
162
+
163
+
164
+ __all__ = ["MossVLConfig", "MossVLTextConfig"]
generation_config.json ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ {
2
+ "_from_model_config": true,
3
+ "bos_token_id": 151643,
4
+ "eos_token_id": 151645,
5
+ "transformers_version": "4.57.3"
6
+ }
model-00001-of-00005.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3fe2d46a92e3c036e8dfbb2519f65415f8f1ab4f731ffdcb9c8bbff4e66fc3d6
3
+ size 5274500800
model-00002-of-00005.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:18f3579907933bad721053b3ac405c51045db4539fedcc7ee3c8db79e79f70e5
3
+ size 5360568508
model-00003-of-00005.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:cecf1e02afe5c7250bb43d6b6e99c7cb430a02afc07a2d697ab1dc4b5f784567
3
+ size 5360577920
model-00004-of-00005.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:57d794a266a1283d209d054114d9888a6a6b36a0af87fbf314c92b76c89dc294
3
+ size 5366957460
model-00005-of-00005.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:34009172ba732eb447caf1293126bba35eb934a622677ac7c24bb2d6af462b0d
3
+ size 1310247928
model.safetensors.index.json ADDED
@@ -0,0 +1,902 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "metadata": {
3
+ "total_size": 22672742416
4
+ },
5
+ "weight_map": {
6
+ "model.language_model.embed_tokens.weight": "model-00001-of-00005.safetensors",
7
+ "model.separator_token": "model-00001-of-00005.safetensors",
8
+ "model.language_model.norm.weight": "model-00001-of-00005.safetensors",
9
+ "lm_head.weight": "model-00001-of-00005.safetensors",
10
+ "model.language_model.layers.0.input_layernorm.weight": "model-00001-of-00005.safetensors",
11
+ "model.language_model.layers.0.self_attn.q_proj.weight": "model-00001-of-00005.safetensors",
12
+ "model.language_model.layers.0.self_attn.k_proj.weight": "model-00001-of-00005.safetensors",
13
+ "model.language_model.layers.0.self_attn.v_proj.weight": "model-00001-of-00005.safetensors",
14
+ "model.language_model.layers.0.self_attn.o_proj.weight": "model-00001-of-00005.safetensors",
15
+ "model.language_model.layers.0.self_attn.q_norm.weight": "model-00001-of-00005.safetensors",
16
+ "model.language_model.layers.0.self_attn.k_norm.weight": "model-00001-of-00005.safetensors",
17
+ "model.language_model.layers.0.post_attention_layernorm.weight": "model-00001-of-00005.safetensors",
18
+ "model.language_model.layers.0.mlp.gate_proj.weight": "model-00001-of-00005.safetensors",
19
+ "model.language_model.layers.0.mlp.up_proj.weight": "model-00001-of-00005.safetensors",
20
+ "model.language_model.layers.0.mlp.down_proj.weight": "model-00001-of-00005.safetensors",
21
+ "model.language_model.layers.1.input_layernorm.weight": "model-00001-of-00005.safetensors",
22
+ "model.language_model.layers.1.self_attn.q_proj.weight": "model-00001-of-00005.safetensors",
23
+ "model.language_model.layers.1.self_attn.k_proj.weight": "model-00001-of-00005.safetensors",
24
+ "model.language_model.layers.1.self_attn.v_proj.weight": "model-00001-of-00005.safetensors",
25
+ "model.language_model.layers.1.self_attn.o_proj.weight": "model-00001-of-00005.safetensors",
26
+ "model.language_model.layers.1.self_attn.q_norm.weight": "model-00001-of-00005.safetensors",
27
+ "model.language_model.layers.1.self_attn.k_norm.weight": "model-00001-of-00005.safetensors",
28
+ "model.language_model.layers.1.post_attention_layernorm.weight": "model-00001-of-00005.safetensors",
29
+ "model.language_model.layers.1.mlp.gate_proj.weight": "model-00001-of-00005.safetensors",
30
+ "model.language_model.layers.1.mlp.up_proj.weight": "model-00001-of-00005.safetensors",
31
+ "model.language_model.layers.1.mlp.down_proj.weight": "model-00001-of-00005.safetensors",
32
+ "model.language_model.layers.2.input_layernorm.weight": "model-00001-of-00005.safetensors",
33
+ "model.language_model.layers.2.cross_attn.q_proj.weight": "model-00001-of-00005.safetensors",
34
+ "model.language_model.layers.2.cross_attn.k_proj.weight": "model-00001-of-00005.safetensors",
35
+ "model.language_model.layers.2.cross_attn.v_proj.weight": "model-00001-of-00005.safetensors",
36
+ "model.language_model.layers.2.cross_attn.o_proj.weight": "model-00001-of-00005.safetensors",
37
+ "model.language_model.layers.2.cross_attn.q_norm.weight": "model-00001-of-00005.safetensors",
38
+ "model.language_model.layers.2.cross_attn.k_norm.weight": "model-00001-of-00005.safetensors",
39
+ "model.language_model.layers.2.post_attention_layernorm.weight": "model-00001-of-00005.safetensors",
40
+ "model.language_model.layers.2.cross_attn_attn_gate": "model-00001-of-00005.safetensors",
41
+ "model.language_model.layers.2.cross_attn_mlp_gate": "model-00001-of-00005.safetensors",
42
+ "model.language_model.layers.2.mlp.gate_proj.weight": "model-00001-of-00005.safetensors",
43
+ "model.language_model.layers.2.mlp.up_proj.weight": "model-00001-of-00005.safetensors",
44
+ "model.language_model.layers.2.mlp.down_proj.weight": "model-00001-of-00005.safetensors",
45
+ "model.language_model.layers.3.input_layernorm.weight": "model-00001-of-00005.safetensors",
46
+ "model.language_model.layers.3.self_attn.q_proj.weight": "model-00001-of-00005.safetensors",
47
+ "model.language_model.layers.3.self_attn.k_proj.weight": "model-00001-of-00005.safetensors",
48
+ "model.language_model.layers.3.self_attn.v_proj.weight": "model-00001-of-00005.safetensors",
49
+ "model.language_model.layers.3.self_attn.o_proj.weight": "model-00001-of-00005.safetensors",
50
+ "model.language_model.layers.3.self_attn.q_norm.weight": "model-00001-of-00005.safetensors",
51
+ "model.language_model.layers.3.self_attn.k_norm.weight": "model-00001-of-00005.safetensors",
52
+ "model.language_model.layers.3.post_attention_layernorm.weight": "model-00001-of-00005.safetensors",
53
+ "model.language_model.layers.3.mlp.gate_proj.weight": "model-00001-of-00005.safetensors",
54
+ "model.language_model.layers.3.mlp.up_proj.weight": "model-00001-of-00005.safetensors",
55
+ "model.language_model.layers.3.mlp.down_proj.weight": "model-00001-of-00005.safetensors",
56
+ "model.language_model.layers.4.input_layernorm.weight": "model-00001-of-00005.safetensors",
57
+ "model.language_model.layers.4.self_attn.q_proj.weight": "model-00001-of-00005.safetensors",
58
+ "model.language_model.layers.4.self_attn.k_proj.weight": "model-00001-of-00005.safetensors",
59
+ "model.language_model.layers.4.self_attn.v_proj.weight": "model-00001-of-00005.safetensors",
60
+ "model.language_model.layers.4.self_attn.o_proj.weight": "model-00001-of-00005.safetensors",
61
+ "model.language_model.layers.4.self_attn.q_norm.weight": "model-00001-of-00005.safetensors",
62
+ "model.language_model.layers.4.self_attn.k_norm.weight": "model-00001-of-00005.safetensors",
63
+ "model.language_model.layers.4.post_attention_layernorm.weight": "model-00001-of-00005.safetensors",
64
+ "model.language_model.layers.4.mlp.gate_proj.weight": "model-00001-of-00005.safetensors",
65
+ "model.language_model.layers.4.mlp.up_proj.weight": "model-00001-of-00005.safetensors",
66
+ "model.language_model.layers.4.mlp.down_proj.weight": "model-00001-of-00005.safetensors",
67
+ "model.language_model.layers.5.input_layernorm.weight": "model-00001-of-00005.safetensors",
68
+ "model.language_model.layers.5.self_attn.q_proj.weight": "model-00001-of-00005.safetensors",
69
+ "model.language_model.layers.5.self_attn.k_proj.weight": "model-00001-of-00005.safetensors",
70
+ "model.language_model.layers.5.self_attn.v_proj.weight": "model-00001-of-00005.safetensors",
71
+ "model.language_model.layers.5.self_attn.o_proj.weight": "model-00001-of-00005.safetensors",
72
+ "model.language_model.layers.5.self_attn.q_norm.weight": "model-00001-of-00005.safetensors",
73
+ "model.language_model.layers.5.self_attn.k_norm.weight": "model-00001-of-00005.safetensors",
74
+ "model.language_model.layers.5.post_attention_layernorm.weight": "model-00001-of-00005.safetensors",
75
+ "model.language_model.layers.5.mlp.gate_proj.weight": "model-00001-of-00005.safetensors",
76
+ "model.language_model.layers.5.mlp.up_proj.weight": "model-00001-of-00005.safetensors",
77
+ "model.language_model.layers.5.mlp.down_proj.weight": "model-00001-of-00005.safetensors",
78
+ "model.language_model.layers.6.input_layernorm.weight": "model-00001-of-00005.safetensors",
79
+ "model.language_model.layers.6.cross_attn.q_proj.weight": "model-00001-of-00005.safetensors",
80
+ "model.language_model.layers.6.cross_attn.k_proj.weight": "model-00001-of-00005.safetensors",
81
+ "model.language_model.layers.6.cross_attn.v_proj.weight": "model-00001-of-00005.safetensors",
82
+ "model.language_model.layers.6.cross_attn.o_proj.weight": "model-00001-of-00005.safetensors",
83
+ "model.language_model.layers.6.cross_attn.q_norm.weight": "model-00001-of-00005.safetensors",
84
+ "model.language_model.layers.6.cross_attn.k_norm.weight": "model-00001-of-00005.safetensors",
85
+ "model.language_model.layers.6.post_attention_layernorm.weight": "model-00001-of-00005.safetensors",
86
+ "model.language_model.layers.6.cross_attn_attn_gate": "model-00001-of-00005.safetensors",
87
+ "model.language_model.layers.6.cross_attn_mlp_gate": "model-00001-of-00005.safetensors",
88
+ "model.language_model.layers.6.mlp.gate_proj.weight": "model-00001-of-00005.safetensors",
89
+ "model.language_model.layers.6.mlp.up_proj.weight": "model-00001-of-00005.safetensors",
90
+ "model.language_model.layers.6.mlp.down_proj.weight": "model-00001-of-00005.safetensors",
91
+ "model.language_model.layers.7.input_layernorm.weight": "model-00001-of-00005.safetensors",
92
+ "model.language_model.layers.7.self_attn.q_proj.weight": "model-00001-of-00005.safetensors",
93
+ "model.language_model.layers.7.self_attn.k_proj.weight": "model-00001-of-00005.safetensors",
94
+ "model.language_model.layers.7.self_attn.v_proj.weight": "model-00001-of-00005.safetensors",
95
+ "model.language_model.layers.7.self_attn.o_proj.weight": "model-00001-of-00005.safetensors",
96
+ "model.language_model.layers.7.self_attn.q_norm.weight": "model-00001-of-00005.safetensors",
97
+ "model.language_model.layers.7.self_attn.k_norm.weight": "model-00001-of-00005.safetensors",
98
+ "model.language_model.layers.7.post_attention_layernorm.weight": "model-00001-of-00005.safetensors",
99
+ "model.language_model.layers.7.mlp.gate_proj.weight": "model-00002-of-00005.safetensors",
100
+ "model.language_model.layers.7.mlp.up_proj.weight": "model-00002-of-00005.safetensors",
101
+ "model.language_model.layers.7.mlp.down_proj.weight": "model-00002-of-00005.safetensors",
102
+ "model.language_model.layers.8.input_layernorm.weight": "model-00002-of-00005.safetensors",
103
+ "model.language_model.layers.8.self_attn.q_proj.weight": "model-00002-of-00005.safetensors",
104
+ "model.language_model.layers.8.self_attn.k_proj.weight": "model-00002-of-00005.safetensors",
105
+ "model.language_model.layers.8.self_attn.v_proj.weight": "model-00002-of-00005.safetensors",
106
+ "model.language_model.layers.8.self_attn.o_proj.weight": "model-00002-of-00005.safetensors",
107
+ "model.language_model.layers.8.self_attn.q_norm.weight": "model-00002-of-00005.safetensors",
108
+ "model.language_model.layers.8.self_attn.k_norm.weight": "model-00002-of-00005.safetensors",
109
+ "model.language_model.layers.8.post_attention_layernorm.weight": "model-00002-of-00005.safetensors",
110
+ "model.language_model.layers.8.mlp.gate_proj.weight": "model-00002-of-00005.safetensors",
111
+ "model.language_model.layers.8.mlp.up_proj.weight": "model-00002-of-00005.safetensors",
112
+ "model.language_model.layers.8.mlp.down_proj.weight": "model-00002-of-00005.safetensors",
113
+ "model.language_model.layers.9.input_layernorm.weight": "model-00002-of-00005.safetensors",
114
+ "model.language_model.layers.9.self_attn.q_proj.weight": "model-00002-of-00005.safetensors",
115
+ "model.language_model.layers.9.self_attn.k_proj.weight": "model-00002-of-00005.safetensors",
116
+ "model.language_model.layers.9.self_attn.v_proj.weight": "model-00002-of-00005.safetensors",
117
+ "model.language_model.layers.9.self_attn.o_proj.weight": "model-00002-of-00005.safetensors",
118
+ "model.language_model.layers.9.self_attn.q_norm.weight": "model-00002-of-00005.safetensors",
119
+ "model.language_model.layers.9.self_attn.k_norm.weight": "model-00002-of-00005.safetensors",
120
+ "model.language_model.layers.9.post_attention_layernorm.weight": "model-00002-of-00005.safetensors",
121
+ "model.language_model.layers.9.mlp.gate_proj.weight": "model-00002-of-00005.safetensors",
122
+ "model.language_model.layers.9.mlp.up_proj.weight": "model-00002-of-00005.safetensors",
123
+ "model.language_model.layers.9.mlp.down_proj.weight": "model-00002-of-00005.safetensors",
124
+ "model.language_model.layers.10.input_layernorm.weight": "model-00002-of-00005.safetensors",
125
+ "model.language_model.layers.10.cross_attn.q_proj.weight": "model-00002-of-00005.safetensors",
126
+ "model.language_model.layers.10.cross_attn.k_proj.weight": "model-00002-of-00005.safetensors",
127
+ "model.language_model.layers.10.cross_attn.v_proj.weight": "model-00002-of-00005.safetensors",
128
+ "model.language_model.layers.10.cross_attn.o_proj.weight": "model-00002-of-00005.safetensors",
129
+ "model.language_model.layers.10.cross_attn.q_norm.weight": "model-00002-of-00005.safetensors",
130
+ "model.language_model.layers.10.cross_attn.k_norm.weight": "model-00002-of-00005.safetensors",
131
+ "model.language_model.layers.10.post_attention_layernorm.weight": "model-00002-of-00005.safetensors",
132
+ "model.language_model.layers.10.cross_attn_attn_gate": "model-00002-of-00005.safetensors",
133
+ "model.language_model.layers.10.cross_attn_mlp_gate": "model-00002-of-00005.safetensors",
134
+ "model.language_model.layers.10.mlp.gate_proj.weight": "model-00002-of-00005.safetensors",
135
+ "model.language_model.layers.10.mlp.up_proj.weight": "model-00002-of-00005.safetensors",
136
+ "model.language_model.layers.10.mlp.down_proj.weight": "model-00002-of-00005.safetensors",
137
+ "model.language_model.layers.11.input_layernorm.weight": "model-00002-of-00005.safetensors",
138
+ "model.language_model.layers.11.self_attn.q_proj.weight": "model-00002-of-00005.safetensors",
139
+ "model.language_model.layers.11.self_attn.k_proj.weight": "model-00002-of-00005.safetensors",
140
+ "model.language_model.layers.11.self_attn.v_proj.weight": "model-00002-of-00005.safetensors",
141
+ "model.language_model.layers.11.self_attn.o_proj.weight": "model-00002-of-00005.safetensors",
142
+ "model.language_model.layers.11.self_attn.q_norm.weight": "model-00002-of-00005.safetensors",
143
+ "model.language_model.layers.11.self_attn.k_norm.weight": "model-00002-of-00005.safetensors",
144
+ "model.language_model.layers.11.post_attention_layernorm.weight": "model-00002-of-00005.safetensors",
145
+ "model.language_model.layers.11.mlp.gate_proj.weight": "model-00002-of-00005.safetensors",
146
+ "model.language_model.layers.11.mlp.up_proj.weight": "model-00002-of-00005.safetensors",
147
+ "model.language_model.layers.11.mlp.down_proj.weight": "model-00002-of-00005.safetensors",
148
+ "model.language_model.layers.12.input_layernorm.weight": "model-00002-of-00005.safetensors",
149
+ "model.language_model.layers.12.self_attn.q_proj.weight": "model-00002-of-00005.safetensors",
150
+ "model.language_model.layers.12.self_attn.k_proj.weight": "model-00002-of-00005.safetensors",
151
+ "model.language_model.layers.12.self_attn.v_proj.weight": "model-00002-of-00005.safetensors",
152
+ "model.language_model.layers.12.self_attn.o_proj.weight": "model-00002-of-00005.safetensors",
153
+ "model.language_model.layers.12.self_attn.q_norm.weight": "model-00002-of-00005.safetensors",
154
+ "model.language_model.layers.12.self_attn.k_norm.weight": "model-00002-of-00005.safetensors",
155
+ "model.language_model.layers.12.post_attention_layernorm.weight": "model-00002-of-00005.safetensors",
156
+ "model.language_model.layers.12.mlp.gate_proj.weight": "model-00002-of-00005.safetensors",
157
+ "model.language_model.layers.12.mlp.up_proj.weight": "model-00002-of-00005.safetensors",
158
+ "model.language_model.layers.12.mlp.down_proj.weight": "model-00002-of-00005.safetensors",
159
+ "model.language_model.layers.13.input_layernorm.weight": "model-00002-of-00005.safetensors",
160
+ "model.language_model.layers.13.self_attn.q_proj.weight": "model-00002-of-00005.safetensors",
161
+ "model.language_model.layers.13.self_attn.k_proj.weight": "model-00002-of-00005.safetensors",
162
+ "model.language_model.layers.13.self_attn.v_proj.weight": "model-00002-of-00005.safetensors",
163
+ "model.language_model.layers.13.self_attn.o_proj.weight": "model-00002-of-00005.safetensors",
164
+ "model.language_model.layers.13.self_attn.q_norm.weight": "model-00002-of-00005.safetensors",
165
+ "model.language_model.layers.13.self_attn.k_norm.weight": "model-00002-of-00005.safetensors",
166
+ "model.language_model.layers.13.post_attention_layernorm.weight": "model-00002-of-00005.safetensors",
167
+ "model.language_model.layers.13.mlp.gate_proj.weight": "model-00002-of-00005.safetensors",
168
+ "model.language_model.layers.13.mlp.up_proj.weight": "model-00002-of-00005.safetensors",
169
+ "model.language_model.layers.13.mlp.down_proj.weight": "model-00002-of-00005.safetensors",
170
+ "model.language_model.layers.14.input_layernorm.weight": "model-00002-of-00005.safetensors",
171
+ "model.language_model.layers.14.cross_attn.q_proj.weight": "model-00002-of-00005.safetensors",
172
+ "model.language_model.layers.14.cross_attn.k_proj.weight": "model-00002-of-00005.safetensors",
173
+ "model.language_model.layers.14.cross_attn.v_proj.weight": "model-00002-of-00005.safetensors",
174
+ "model.language_model.layers.14.cross_attn.o_proj.weight": "model-00002-of-00005.safetensors",
175
+ "model.language_model.layers.14.cross_attn.q_norm.weight": "model-00002-of-00005.safetensors",
176
+ "model.language_model.layers.14.cross_attn.k_norm.weight": "model-00002-of-00005.safetensors",
177
+ "model.language_model.layers.14.post_attention_layernorm.weight": "model-00002-of-00005.safetensors",
178
+ "model.language_model.layers.14.cross_attn_attn_gate": "model-00002-of-00005.safetensors",
179
+ "model.language_model.layers.14.cross_attn_mlp_gate": "model-00002-of-00005.safetensors",
180
+ "model.language_model.layers.14.mlp.gate_proj.weight": "model-00002-of-00005.safetensors",
181
+ "model.language_model.layers.14.mlp.up_proj.weight": "model-00002-of-00005.safetensors",
182
+ "model.language_model.layers.14.mlp.down_proj.weight": "model-00002-of-00005.safetensors",
183
+ "model.language_model.layers.15.input_layernorm.weight": "model-00002-of-00005.safetensors",
184
+ "model.language_model.layers.15.self_attn.q_proj.weight": "model-00002-of-00005.safetensors",
185
+ "model.language_model.layers.15.self_attn.k_proj.weight": "model-00002-of-00005.safetensors",
186
+ "model.language_model.layers.15.self_attn.v_proj.weight": "model-00002-of-00005.safetensors",
187
+ "model.language_model.layers.15.self_attn.o_proj.weight": "model-00002-of-00005.safetensors",
188
+ "model.language_model.layers.15.self_attn.q_norm.weight": "model-00002-of-00005.safetensors",
189
+ "model.language_model.layers.15.self_attn.k_norm.weight": "model-00002-of-00005.safetensors",
190
+ "model.language_model.layers.15.post_attention_layernorm.weight": "model-00002-of-00005.safetensors",
191
+ "model.language_model.layers.15.mlp.gate_proj.weight": "model-00002-of-00005.safetensors",
192
+ "model.language_model.layers.15.mlp.up_proj.weight": "model-00002-of-00005.safetensors",
193
+ "model.language_model.layers.15.mlp.down_proj.weight": "model-00002-of-00005.safetensors",
194
+ "model.language_model.layers.16.input_layernorm.weight": "model-00002-of-00005.safetensors",
195
+ "model.language_model.layers.16.self_attn.q_proj.weight": "model-00002-of-00005.safetensors",
196
+ "model.language_model.layers.16.self_attn.k_proj.weight": "model-00002-of-00005.safetensors",
197
+ "model.language_model.layers.16.self_attn.v_proj.weight": "model-00002-of-00005.safetensors",
198
+ "model.language_model.layers.16.self_attn.o_proj.weight": "model-00002-of-00005.safetensors",
199
+ "model.language_model.layers.16.self_attn.q_norm.weight": "model-00002-of-00005.safetensors",
200
+ "model.language_model.layers.16.self_attn.k_norm.weight": "model-00002-of-00005.safetensors",
201
+ "model.language_model.layers.16.post_attention_layernorm.weight": "model-00002-of-00005.safetensors",
202
+ "model.language_model.layers.16.mlp.gate_proj.weight": "model-00002-of-00005.safetensors",
203
+ "model.language_model.layers.16.mlp.up_proj.weight": "model-00002-of-00005.safetensors",
204
+ "model.language_model.layers.16.mlp.down_proj.weight": "model-00002-of-00005.safetensors",
205
+ "model.language_model.layers.17.input_layernorm.weight": "model-00002-of-00005.safetensors",
206
+ "model.language_model.layers.17.self_attn.q_proj.weight": "model-00002-of-00005.safetensors",
207
+ "model.language_model.layers.17.self_attn.k_proj.weight": "model-00002-of-00005.safetensors",
208
+ "model.language_model.layers.17.self_attn.v_proj.weight": "model-00002-of-00005.safetensors",
209
+ "model.language_model.layers.17.self_attn.o_proj.weight": "model-00002-of-00005.safetensors",
210
+ "model.language_model.layers.17.self_attn.q_norm.weight": "model-00002-of-00005.safetensors",
211
+ "model.language_model.layers.17.self_attn.k_norm.weight": "model-00002-of-00005.safetensors",
212
+ "model.language_model.layers.17.post_attention_layernorm.weight": "model-00002-of-00005.safetensors",
213
+ "model.language_model.layers.17.mlp.gate_proj.weight": "model-00002-of-00005.safetensors",
214
+ "model.language_model.layers.17.mlp.up_proj.weight": "model-00002-of-00005.safetensors",
215
+ "model.language_model.layers.17.mlp.down_proj.weight": "model-00002-of-00005.safetensors",
216
+ "model.language_model.layers.18.input_layernorm.weight": "model-00002-of-00005.safetensors",
217
+ "model.language_model.layers.18.cross_attn.q_proj.weight": "model-00002-of-00005.safetensors",
218
+ "model.language_model.layers.18.cross_attn.k_proj.weight": "model-00002-of-00005.safetensors",
219
+ "model.language_model.layers.18.cross_attn.v_proj.weight": "model-00002-of-00005.safetensors",
220
+ "model.language_model.layers.18.cross_attn.o_proj.weight": "model-00002-of-00005.safetensors",
221
+ "model.language_model.layers.18.cross_attn.q_norm.weight": "model-00002-of-00005.safetensors",
222
+ "model.language_model.layers.18.cross_attn.k_norm.weight": "model-00002-of-00005.safetensors",
223
+ "model.language_model.layers.18.post_attention_layernorm.weight": "model-00002-of-00005.safetensors",
224
+ "model.language_model.layers.18.cross_attn_attn_gate": "model-00002-of-00005.safetensors",
225
+ "model.language_model.layers.18.cross_attn_mlp_gate": "model-00002-of-00005.safetensors",
226
+ "model.language_model.layers.18.mlp.gate_proj.weight": "model-00002-of-00005.safetensors",
227
+ "model.language_model.layers.18.mlp.up_proj.weight": "model-00002-of-00005.safetensors",
228
+ "model.language_model.layers.18.mlp.down_proj.weight": "model-00002-of-00005.safetensors",
229
+ "model.language_model.layers.19.input_layernorm.weight": "model-00002-of-00005.safetensors",
230
+ "model.language_model.layers.19.self_attn.q_proj.weight": "model-00002-of-00005.safetensors",
231
+ "model.language_model.layers.19.self_attn.k_proj.weight": "model-00002-of-00005.safetensors",
232
+ "model.language_model.layers.19.self_attn.v_proj.weight": "model-00002-of-00005.safetensors",
233
+ "model.language_model.layers.19.self_attn.o_proj.weight": "model-00002-of-00005.safetensors",
234
+ "model.language_model.layers.19.self_attn.q_norm.weight": "model-00002-of-00005.safetensors",
235
+ "model.language_model.layers.19.self_attn.k_norm.weight": "model-00002-of-00005.safetensors",
236
+ "model.language_model.layers.19.post_attention_layernorm.weight": "model-00002-of-00005.safetensors",
237
+ "model.language_model.layers.19.mlp.gate_proj.weight": "model-00002-of-00005.safetensors",
238
+ "model.language_model.layers.19.mlp.up_proj.weight": "model-00002-of-00005.safetensors",
239
+ "model.language_model.layers.19.mlp.down_proj.weight": "model-00002-of-00005.safetensors",
240
+ "model.language_model.layers.20.input_layernorm.weight": "model-00002-of-00005.safetensors",
241
+ "model.language_model.layers.20.self_attn.q_proj.weight": "model-00002-of-00005.safetensors",
242
+ "model.language_model.layers.20.self_attn.k_proj.weight": "model-00002-of-00005.safetensors",
243
+ "model.language_model.layers.20.self_attn.v_proj.weight": "model-00002-of-00005.safetensors",
244
+ "model.language_model.layers.20.self_attn.o_proj.weight": "model-00002-of-00005.safetensors",
245
+ "model.language_model.layers.20.self_attn.q_norm.weight": "model-00002-of-00005.safetensors",
246
+ "model.language_model.layers.20.self_attn.k_norm.weight": "model-00002-of-00005.safetensors",
247
+ "model.language_model.layers.20.post_attention_layernorm.weight": "model-00002-of-00005.safetensors",
248
+ "model.language_model.layers.20.mlp.gate_proj.weight": "model-00002-of-00005.safetensors",
249
+ "model.language_model.layers.20.mlp.up_proj.weight": "model-00002-of-00005.safetensors",
250
+ "model.language_model.layers.20.mlp.down_proj.weight": "model-00002-of-00005.safetensors",
251
+ "model.language_model.layers.21.input_layernorm.weight": "model-00002-of-00005.safetensors",
252
+ "model.language_model.layers.21.self_attn.q_proj.weight": "model-00002-of-00005.safetensors",
253
+ "model.language_model.layers.21.self_attn.k_proj.weight": "model-00002-of-00005.safetensors",
254
+ "model.language_model.layers.21.self_attn.v_proj.weight": "model-00003-of-00005.safetensors",
255
+ "model.language_model.layers.21.self_attn.o_proj.weight": "model-00003-of-00005.safetensors",
256
+ "model.language_model.layers.21.self_attn.q_norm.weight": "model-00003-of-00005.safetensors",
257
+ "model.language_model.layers.21.self_attn.k_norm.weight": "model-00003-of-00005.safetensors",
258
+ "model.language_model.layers.21.post_attention_layernorm.weight": "model-00003-of-00005.safetensors",
259
+ "model.language_model.layers.21.mlp.gate_proj.weight": "model-00003-of-00005.safetensors",
260
+ "model.language_model.layers.21.mlp.up_proj.weight": "model-00003-of-00005.safetensors",
261
+ "model.language_model.layers.21.mlp.down_proj.weight": "model-00003-of-00005.safetensors",
262
+ "model.language_model.layers.22.input_layernorm.weight": "model-00003-of-00005.safetensors",
263
+ "model.language_model.layers.22.cross_attn.q_proj.weight": "model-00003-of-00005.safetensors",
264
+ "model.language_model.layers.22.cross_attn.k_proj.weight": "model-00003-of-00005.safetensors",
265
+ "model.language_model.layers.22.cross_attn.v_proj.weight": "model-00003-of-00005.safetensors",
266
+ "model.language_model.layers.22.cross_attn.o_proj.weight": "model-00003-of-00005.safetensors",
267
+ "model.language_model.layers.22.cross_attn.q_norm.weight": "model-00003-of-00005.safetensors",
268
+ "model.language_model.layers.22.cross_attn.k_norm.weight": "model-00003-of-00005.safetensors",
269
+ "model.language_model.layers.22.post_attention_layernorm.weight": "model-00003-of-00005.safetensors",
270
+ "model.language_model.layers.22.cross_attn_attn_gate": "model-00003-of-00005.safetensors",
271
+ "model.language_model.layers.22.cross_attn_mlp_gate": "model-00003-of-00005.safetensors",
272
+ "model.language_model.layers.22.mlp.gate_proj.weight": "model-00003-of-00005.safetensors",
273
+ "model.language_model.layers.22.mlp.up_proj.weight": "model-00003-of-00005.safetensors",
274
+ "model.language_model.layers.22.mlp.down_proj.weight": "model-00003-of-00005.safetensors",
275
+ "model.language_model.layers.23.input_layernorm.weight": "model-00003-of-00005.safetensors",
276
+ "model.language_model.layers.23.self_attn.q_proj.weight": "model-00003-of-00005.safetensors",
277
+ "model.language_model.layers.23.self_attn.k_proj.weight": "model-00003-of-00005.safetensors",
278
+ "model.language_model.layers.23.self_attn.v_proj.weight": "model-00003-of-00005.safetensors",
279
+ "model.language_model.layers.23.self_attn.o_proj.weight": "model-00003-of-00005.safetensors",
280
+ "model.language_model.layers.23.self_attn.q_norm.weight": "model-00003-of-00005.safetensors",
281
+ "model.language_model.layers.23.self_attn.k_norm.weight": "model-00003-of-00005.safetensors",
282
+ "model.language_model.layers.23.post_attention_layernorm.weight": "model-00003-of-00005.safetensors",
283
+ "model.language_model.layers.23.mlp.gate_proj.weight": "model-00003-of-00005.safetensors",
284
+ "model.language_model.layers.23.mlp.up_proj.weight": "model-00003-of-00005.safetensors",
285
+ "model.language_model.layers.23.mlp.down_proj.weight": "model-00003-of-00005.safetensors",
286
+ "model.language_model.layers.24.input_layernorm.weight": "model-00003-of-00005.safetensors",
287
+ "model.language_model.layers.24.self_attn.q_proj.weight": "model-00003-of-00005.safetensors",
288
+ "model.language_model.layers.24.self_attn.k_proj.weight": "model-00003-of-00005.safetensors",
289
+ "model.language_model.layers.24.self_attn.v_proj.weight": "model-00003-of-00005.safetensors",
290
+ "model.language_model.layers.24.self_attn.o_proj.weight": "model-00003-of-00005.safetensors",
291
+ "model.language_model.layers.24.self_attn.q_norm.weight": "model-00003-of-00005.safetensors",
292
+ "model.language_model.layers.24.self_attn.k_norm.weight": "model-00003-of-00005.safetensors",
293
+ "model.language_model.layers.24.post_attention_layernorm.weight": "model-00003-of-00005.safetensors",
294
+ "model.language_model.layers.24.mlp.gate_proj.weight": "model-00003-of-00005.safetensors",
295
+ "model.language_model.layers.24.mlp.up_proj.weight": "model-00003-of-00005.safetensors",
296
+ "model.language_model.layers.24.mlp.down_proj.weight": "model-00003-of-00005.safetensors",
297
+ "model.language_model.layers.25.input_layernorm.weight": "model-00003-of-00005.safetensors",
298
+ "model.language_model.layers.25.self_attn.q_proj.weight": "model-00003-of-00005.safetensors",
299
+ "model.language_model.layers.25.self_attn.k_proj.weight": "model-00003-of-00005.safetensors",
300
+ "model.language_model.layers.25.self_attn.v_proj.weight": "model-00003-of-00005.safetensors",
301
+ "model.language_model.layers.25.self_attn.o_proj.weight": "model-00003-of-00005.safetensors",
302
+ "model.language_model.layers.25.self_attn.q_norm.weight": "model-00003-of-00005.safetensors",
303
+ "model.language_model.layers.25.self_attn.k_norm.weight": "model-00003-of-00005.safetensors",
304
+ "model.language_model.layers.25.post_attention_layernorm.weight": "model-00003-of-00005.safetensors",
305
+ "model.language_model.layers.25.mlp.gate_proj.weight": "model-00003-of-00005.safetensors",
306
+ "model.language_model.layers.25.mlp.up_proj.weight": "model-00003-of-00005.safetensors",
307
+ "model.language_model.layers.25.mlp.down_proj.weight": "model-00003-of-00005.safetensors",
308
+ "model.language_model.layers.26.input_layernorm.weight": "model-00003-of-00005.safetensors",
309
+ "model.language_model.layers.26.cross_attn.q_proj.weight": "model-00003-of-00005.safetensors",
310
+ "model.language_model.layers.26.cross_attn.k_proj.weight": "model-00003-of-00005.safetensors",
311
+ "model.language_model.layers.26.cross_attn.v_proj.weight": "model-00003-of-00005.safetensors",
312
+ "model.language_model.layers.26.cross_attn.o_proj.weight": "model-00003-of-00005.safetensors",
313
+ "model.language_model.layers.26.cross_attn.q_norm.weight": "model-00003-of-00005.safetensors",
314
+ "model.language_model.layers.26.cross_attn.k_norm.weight": "model-00003-of-00005.safetensors",
315
+ "model.language_model.layers.26.post_attention_layernorm.weight": "model-00003-of-00005.safetensors",
316
+ "model.language_model.layers.26.cross_attn_attn_gate": "model-00003-of-00005.safetensors",
317
+ "model.language_model.layers.26.cross_attn_mlp_gate": "model-00003-of-00005.safetensors",
318
+ "model.language_model.layers.26.mlp.gate_proj.weight": "model-00003-of-00005.safetensors",
319
+ "model.language_model.layers.26.mlp.up_proj.weight": "model-00003-of-00005.safetensors",
320
+ "model.language_model.layers.26.mlp.down_proj.weight": "model-00003-of-00005.safetensors",
321
+ "model.language_model.layers.27.input_layernorm.weight": "model-00003-of-00005.safetensors",
322
+ "model.language_model.layers.27.self_attn.q_proj.weight": "model-00003-of-00005.safetensors",
323
+ "model.language_model.layers.27.self_attn.k_proj.weight": "model-00003-of-00005.safetensors",
324
+ "model.language_model.layers.27.self_attn.v_proj.weight": "model-00003-of-00005.safetensors",
325
+ "model.language_model.layers.27.self_attn.o_proj.weight": "model-00003-of-00005.safetensors",
326
+ "model.language_model.layers.27.self_attn.q_norm.weight": "model-00003-of-00005.safetensors",
327
+ "model.language_model.layers.27.self_attn.k_norm.weight": "model-00003-of-00005.safetensors",
328
+ "model.language_model.layers.27.post_attention_layernorm.weight": "model-00003-of-00005.safetensors",
329
+ "model.language_model.layers.27.mlp.gate_proj.weight": "model-00003-of-00005.safetensors",
330
+ "model.language_model.layers.27.mlp.up_proj.weight": "model-00003-of-00005.safetensors",
331
+ "model.language_model.layers.27.mlp.down_proj.weight": "model-00003-of-00005.safetensors",
332
+ "model.language_model.layers.28.input_layernorm.weight": "model-00003-of-00005.safetensors",
333
+ "model.language_model.layers.28.self_attn.q_proj.weight": "model-00003-of-00005.safetensors",
334
+ "model.language_model.layers.28.self_attn.k_proj.weight": "model-00003-of-00005.safetensors",
335
+ "model.language_model.layers.28.self_attn.v_proj.weight": "model-00003-of-00005.safetensors",
336
+ "model.language_model.layers.28.self_attn.o_proj.weight": "model-00003-of-00005.safetensors",
337
+ "model.language_model.layers.28.self_attn.q_norm.weight": "model-00003-of-00005.safetensors",
338
+ "model.language_model.layers.28.self_attn.k_norm.weight": "model-00003-of-00005.safetensors",
339
+ "model.language_model.layers.28.post_attention_layernorm.weight": "model-00003-of-00005.safetensors",
340
+ "model.language_model.layers.28.mlp.gate_proj.weight": "model-00003-of-00005.safetensors",
341
+ "model.language_model.layers.28.mlp.up_proj.weight": "model-00003-of-00005.safetensors",
342
+ "model.language_model.layers.28.mlp.down_proj.weight": "model-00003-of-00005.safetensors",
343
+ "model.language_model.layers.29.input_layernorm.weight": "model-00003-of-00005.safetensors",
344
+ "model.language_model.layers.29.self_attn.q_proj.weight": "model-00003-of-00005.safetensors",
345
+ "model.language_model.layers.29.self_attn.k_proj.weight": "model-00003-of-00005.safetensors",
346
+ "model.language_model.layers.29.self_attn.v_proj.weight": "model-00003-of-00005.safetensors",
347
+ "model.language_model.layers.29.self_attn.o_proj.weight": "model-00003-of-00005.safetensors",
348
+ "model.language_model.layers.29.self_attn.q_norm.weight": "model-00003-of-00005.safetensors",
349
+ "model.language_model.layers.29.self_attn.k_norm.weight": "model-00003-of-00005.safetensors",
350
+ "model.language_model.layers.29.post_attention_layernorm.weight": "model-00003-of-00005.safetensors",
351
+ "model.language_model.layers.29.mlp.gate_proj.weight": "model-00003-of-00005.safetensors",
352
+ "model.language_model.layers.29.mlp.up_proj.weight": "model-00003-of-00005.safetensors",
353
+ "model.language_model.layers.29.mlp.down_proj.weight": "model-00003-of-00005.safetensors",
354
+ "model.language_model.layers.30.input_layernorm.weight": "model-00003-of-00005.safetensors",
355
+ "model.language_model.layers.30.cross_attn.q_proj.weight": "model-00003-of-00005.safetensors",
356
+ "model.language_model.layers.30.cross_attn.k_proj.weight": "model-00003-of-00005.safetensors",
357
+ "model.language_model.layers.30.cross_attn.v_proj.weight": "model-00003-of-00005.safetensors",
358
+ "model.language_model.layers.30.cross_attn.o_proj.weight": "model-00003-of-00005.safetensors",
359
+ "model.language_model.layers.30.cross_attn.q_norm.weight": "model-00003-of-00005.safetensors",
360
+ "model.language_model.layers.30.cross_attn.k_norm.weight": "model-00003-of-00005.safetensors",
361
+ "model.language_model.layers.30.post_attention_layernorm.weight": "model-00003-of-00005.safetensors",
362
+ "model.language_model.layers.30.cross_attn_attn_gate": "model-00003-of-00005.safetensors",
363
+ "model.language_model.layers.30.cross_attn_mlp_gate": "model-00003-of-00005.safetensors",
364
+ "model.language_model.layers.30.mlp.gate_proj.weight": "model-00003-of-00005.safetensors",
365
+ "model.language_model.layers.30.mlp.up_proj.weight": "model-00003-of-00005.safetensors",
366
+ "model.language_model.layers.30.mlp.down_proj.weight": "model-00003-of-00005.safetensors",
367
+ "model.language_model.layers.31.input_layernorm.weight": "model-00003-of-00005.safetensors",
368
+ "model.language_model.layers.31.self_attn.q_proj.weight": "model-00003-of-00005.safetensors",
369
+ "model.language_model.layers.31.self_attn.k_proj.weight": "model-00003-of-00005.safetensors",
370
+ "model.language_model.layers.31.self_attn.v_proj.weight": "model-00003-of-00005.safetensors",
371
+ "model.language_model.layers.31.self_attn.o_proj.weight": "model-00003-of-00005.safetensors",
372
+ "model.language_model.layers.31.self_attn.q_norm.weight": "model-00003-of-00005.safetensors",
373
+ "model.language_model.layers.31.self_attn.k_norm.weight": "model-00003-of-00005.safetensors",
374
+ "model.language_model.layers.31.post_attention_layernorm.weight": "model-00003-of-00005.safetensors",
375
+ "model.language_model.layers.31.mlp.gate_proj.weight": "model-00003-of-00005.safetensors",
376
+ "model.language_model.layers.31.mlp.up_proj.weight": "model-00003-of-00005.safetensors",
377
+ "model.language_model.layers.31.mlp.down_proj.weight": "model-00003-of-00005.safetensors",
378
+ "model.language_model.layers.32.input_layernorm.weight": "model-00003-of-00005.safetensors",
379
+ "model.language_model.layers.32.self_attn.q_proj.weight": "model-00003-of-00005.safetensors",
380
+ "model.language_model.layers.32.self_attn.k_proj.weight": "model-00003-of-00005.safetensors",
381
+ "model.language_model.layers.32.self_attn.v_proj.weight": "model-00003-of-00005.safetensors",
382
+ "model.language_model.layers.32.self_attn.o_proj.weight": "model-00003-of-00005.safetensors",
383
+ "model.language_model.layers.32.self_attn.q_norm.weight": "model-00003-of-00005.safetensors",
384
+ "model.language_model.layers.32.self_attn.k_norm.weight": "model-00003-of-00005.safetensors",
385
+ "model.language_model.layers.32.post_attention_layernorm.weight": "model-00003-of-00005.safetensors",
386
+ "model.language_model.layers.32.mlp.gate_proj.weight": "model-00003-of-00005.safetensors",
387
+ "model.language_model.layers.32.mlp.up_proj.weight": "model-00003-of-00005.safetensors",
388
+ "model.language_model.layers.32.mlp.down_proj.weight": "model-00003-of-00005.safetensors",
389
+ "model.language_model.layers.33.input_layernorm.weight": "model-00003-of-00005.safetensors",
390
+ "model.language_model.layers.33.self_attn.q_proj.weight": "model-00003-of-00005.safetensors",
391
+ "model.language_model.layers.33.self_attn.k_proj.weight": "model-00003-of-00005.safetensors",
392
+ "model.language_model.layers.33.self_attn.v_proj.weight": "model-00003-of-00005.safetensors",
393
+ "model.language_model.layers.33.self_attn.o_proj.weight": "model-00003-of-00005.safetensors",
394
+ "model.language_model.layers.33.self_attn.q_norm.weight": "model-00003-of-00005.safetensors",
395
+ "model.language_model.layers.33.self_attn.k_norm.weight": "model-00003-of-00005.safetensors",
396
+ "model.language_model.layers.33.post_attention_layernorm.weight": "model-00003-of-00005.safetensors",
397
+ "model.language_model.layers.33.mlp.gate_proj.weight": "model-00003-of-00005.safetensors",
398
+ "model.language_model.layers.33.mlp.up_proj.weight": "model-00003-of-00005.safetensors",
399
+ "model.language_model.layers.33.mlp.down_proj.weight": "model-00003-of-00005.safetensors",
400
+ "model.language_model.layers.34.input_layernorm.weight": "model-00003-of-00005.safetensors",
401
+ "model.language_model.layers.34.cross_attn.q_proj.weight": "model-00003-of-00005.safetensors",
402
+ "model.language_model.layers.34.cross_attn.k_proj.weight": "model-00003-of-00005.safetensors",
403
+ "model.language_model.layers.34.cross_attn.v_proj.weight": "model-00003-of-00005.safetensors",
404
+ "model.language_model.layers.34.cross_attn.o_proj.weight": "model-00003-of-00005.safetensors",
405
+ "model.language_model.layers.34.cross_attn.q_norm.weight": "model-00003-of-00005.safetensors",
406
+ "model.language_model.layers.34.cross_attn.k_norm.weight": "model-00003-of-00005.safetensors",
407
+ "model.language_model.layers.34.post_attention_layernorm.weight": "model-00003-of-00005.safetensors",
408
+ "model.language_model.layers.34.cross_attn_attn_gate": "model-00003-of-00005.safetensors",
409
+ "model.language_model.layers.34.cross_attn_mlp_gate": "model-00003-of-00005.safetensors",
410
+ "model.language_model.layers.34.mlp.gate_proj.weight": "model-00003-of-00005.safetensors",
411
+ "model.language_model.layers.34.mlp.up_proj.weight": "model-00003-of-00005.safetensors",
412
+ "model.language_model.layers.34.mlp.down_proj.weight": "model-00003-of-00005.safetensors",
413
+ "model.language_model.layers.35.input_layernorm.weight": "model-00003-of-00005.safetensors",
414
+ "model.language_model.layers.35.self_attn.q_proj.weight": "model-00004-of-00005.safetensors",
415
+ "model.language_model.layers.35.self_attn.k_proj.weight": "model-00004-of-00005.safetensors",
416
+ "model.language_model.layers.35.self_attn.v_proj.weight": "model-00004-of-00005.safetensors",
417
+ "model.language_model.layers.35.self_attn.o_proj.weight": "model-00004-of-00005.safetensors",
418
+ "model.language_model.layers.35.self_attn.q_norm.weight": "model-00004-of-00005.safetensors",
419
+ "model.language_model.layers.35.self_attn.k_norm.weight": "model-00004-of-00005.safetensors",
420
+ "model.language_model.layers.35.post_attention_layernorm.weight": "model-00004-of-00005.safetensors",
421
+ "model.language_model.layers.35.mlp.gate_proj.weight": "model-00004-of-00005.safetensors",
422
+ "model.language_model.layers.35.mlp.up_proj.weight": "model-00004-of-00005.safetensors",
423
+ "model.language_model.layers.35.mlp.down_proj.weight": "model-00004-of-00005.safetensors",
424
+ "model.language_model.layers.36.input_layernorm.weight": "model-00004-of-00005.safetensors",
425
+ "model.language_model.layers.36.self_attn.q_proj.weight": "model-00004-of-00005.safetensors",
426
+ "model.language_model.layers.36.self_attn.k_proj.weight": "model-00004-of-00005.safetensors",
427
+ "model.language_model.layers.36.self_attn.v_proj.weight": "model-00004-of-00005.safetensors",
428
+ "model.language_model.layers.36.self_attn.o_proj.weight": "model-00004-of-00005.safetensors",
429
+ "model.language_model.layers.36.self_attn.q_norm.weight": "model-00004-of-00005.safetensors",
430
+ "model.language_model.layers.36.self_attn.k_norm.weight": "model-00004-of-00005.safetensors",
431
+ "model.language_model.layers.36.post_attention_layernorm.weight": "model-00004-of-00005.safetensors",
432
+ "model.language_model.layers.36.mlp.gate_proj.weight": "model-00004-of-00005.safetensors",
433
+ "model.language_model.layers.36.mlp.up_proj.weight": "model-00004-of-00005.safetensors",
434
+ "model.language_model.layers.36.mlp.down_proj.weight": "model-00004-of-00005.safetensors",
435
+ "model.language_model.layers.37.input_layernorm.weight": "model-00004-of-00005.safetensors",
436
+ "model.language_model.layers.37.self_attn.q_proj.weight": "model-00004-of-00005.safetensors",
437
+ "model.language_model.layers.37.self_attn.k_proj.weight": "model-00004-of-00005.safetensors",
438
+ "model.language_model.layers.37.self_attn.v_proj.weight": "model-00004-of-00005.safetensors",
439
+ "model.language_model.layers.37.self_attn.o_proj.weight": "model-00004-of-00005.safetensors",
440
+ "model.language_model.layers.37.self_attn.q_norm.weight": "model-00004-of-00005.safetensors",
441
+ "model.language_model.layers.37.self_attn.k_norm.weight": "model-00004-of-00005.safetensors",
442
+ "model.language_model.layers.37.post_attention_layernorm.weight": "model-00004-of-00005.safetensors",
443
+ "model.language_model.layers.37.mlp.gate_proj.weight": "model-00004-of-00005.safetensors",
444
+ "model.language_model.layers.37.mlp.up_proj.weight": "model-00004-of-00005.safetensors",
445
+ "model.language_model.layers.37.mlp.down_proj.weight": "model-00004-of-00005.safetensors",
446
+ "model.language_model.layers.38.input_layernorm.weight": "model-00004-of-00005.safetensors",
447
+ "model.language_model.layers.38.cross_attn.q_proj.weight": "model-00004-of-00005.safetensors",
448
+ "model.language_model.layers.38.cross_attn.k_proj.weight": "model-00004-of-00005.safetensors",
449
+ "model.language_model.layers.38.cross_attn.v_proj.weight": "model-00004-of-00005.safetensors",
450
+ "model.language_model.layers.38.cross_attn.o_proj.weight": "model-00004-of-00005.safetensors",
451
+ "model.language_model.layers.38.cross_attn.q_norm.weight": "model-00004-of-00005.safetensors",
452
+ "model.language_model.layers.38.cross_attn.k_norm.weight": "model-00004-of-00005.safetensors",
453
+ "model.language_model.layers.38.post_attention_layernorm.weight": "model-00004-of-00005.safetensors",
454
+ "model.language_model.layers.38.cross_attn_attn_gate": "model-00004-of-00005.safetensors",
455
+ "model.language_model.layers.38.cross_attn_mlp_gate": "model-00004-of-00005.safetensors",
456
+ "model.language_model.layers.38.mlp.gate_proj.weight": "model-00004-of-00005.safetensors",
457
+ "model.language_model.layers.38.mlp.up_proj.weight": "model-00004-of-00005.safetensors",
458
+ "model.language_model.layers.38.mlp.down_proj.weight": "model-00004-of-00005.safetensors",
459
+ "model.language_model.layers.39.input_layernorm.weight": "model-00004-of-00005.safetensors",
460
+ "model.language_model.layers.39.self_attn.q_proj.weight": "model-00004-of-00005.safetensors",
461
+ "model.language_model.layers.39.self_attn.k_proj.weight": "model-00004-of-00005.safetensors",
462
+ "model.language_model.layers.39.self_attn.v_proj.weight": "model-00004-of-00005.safetensors",
463
+ "model.language_model.layers.39.self_attn.o_proj.weight": "model-00004-of-00005.safetensors",
464
+ "model.language_model.layers.39.self_attn.q_norm.weight": "model-00004-of-00005.safetensors",
465
+ "model.language_model.layers.39.self_attn.k_norm.weight": "model-00004-of-00005.safetensors",
466
+ "model.language_model.layers.39.post_attention_layernorm.weight": "model-00004-of-00005.safetensors",
467
+ "model.language_model.layers.39.mlp.gate_proj.weight": "model-00004-of-00005.safetensors",
468
+ "model.language_model.layers.39.mlp.up_proj.weight": "model-00004-of-00005.safetensors",
469
+ "model.language_model.layers.39.mlp.down_proj.weight": "model-00004-of-00005.safetensors",
470
+ "model.language_model.layers.40.input_layernorm.weight": "model-00004-of-00005.safetensors",
471
+ "model.language_model.layers.40.self_attn.q_proj.weight": "model-00004-of-00005.safetensors",
472
+ "model.language_model.layers.40.self_attn.k_proj.weight": "model-00004-of-00005.safetensors",
473
+ "model.language_model.layers.40.self_attn.v_proj.weight": "model-00004-of-00005.safetensors",
474
+ "model.language_model.layers.40.self_attn.o_proj.weight": "model-00004-of-00005.safetensors",
475
+ "model.language_model.layers.40.self_attn.q_norm.weight": "model-00004-of-00005.safetensors",
476
+ "model.language_model.layers.40.self_attn.k_norm.weight": "model-00004-of-00005.safetensors",
477
+ "model.language_model.layers.40.post_attention_layernorm.weight": "model-00004-of-00005.safetensors",
478
+ "model.language_model.layers.40.mlp.gate_proj.weight": "model-00004-of-00005.safetensors",
479
+ "model.language_model.layers.40.mlp.up_proj.weight": "model-00004-of-00005.safetensors",
480
+ "model.language_model.layers.40.mlp.down_proj.weight": "model-00004-of-00005.safetensors",
481
+ "model.language_model.layers.41.input_layernorm.weight": "model-00004-of-00005.safetensors",
482
+ "model.language_model.layers.41.self_attn.q_proj.weight": "model-00004-of-00005.safetensors",
483
+ "model.language_model.layers.41.self_attn.k_proj.weight": "model-00004-of-00005.safetensors",
484
+ "model.language_model.layers.41.self_attn.v_proj.weight": "model-00004-of-00005.safetensors",
485
+ "model.language_model.layers.41.self_attn.o_proj.weight": "model-00004-of-00005.safetensors",
486
+ "model.language_model.layers.41.self_attn.q_norm.weight": "model-00004-of-00005.safetensors",
487
+ "model.language_model.layers.41.self_attn.k_norm.weight": "model-00004-of-00005.safetensors",
488
+ "model.language_model.layers.41.post_attention_layernorm.weight": "model-00004-of-00005.safetensors",
489
+ "model.language_model.layers.41.mlp.gate_proj.weight": "model-00004-of-00005.safetensors",
490
+ "model.language_model.layers.41.mlp.up_proj.weight": "model-00004-of-00005.safetensors",
491
+ "model.language_model.layers.41.mlp.down_proj.weight": "model-00004-of-00005.safetensors",
492
+ "model.language_model.layers.42.input_layernorm.weight": "model-00004-of-00005.safetensors",
493
+ "model.language_model.layers.42.cross_attn.q_proj.weight": "model-00004-of-00005.safetensors",
494
+ "model.language_model.layers.42.cross_attn.k_proj.weight": "model-00004-of-00005.safetensors",
495
+ "model.language_model.layers.42.cross_attn.v_proj.weight": "model-00004-of-00005.safetensors",
496
+ "model.language_model.layers.42.cross_attn.o_proj.weight": "model-00004-of-00005.safetensors",
497
+ "model.language_model.layers.42.cross_attn.q_norm.weight": "model-00004-of-00005.safetensors",
498
+ "model.language_model.layers.42.cross_attn.k_norm.weight": "model-00004-of-00005.safetensors",
499
+ "model.language_model.layers.42.post_attention_layernorm.weight": "model-00004-of-00005.safetensors",
500
+ "model.language_model.layers.42.cross_attn_attn_gate": "model-00004-of-00005.safetensors",
501
+ "model.language_model.layers.42.cross_attn_mlp_gate": "model-00004-of-00005.safetensors",
502
+ "model.language_model.layers.42.mlp.gate_proj.weight": "model-00004-of-00005.safetensors",
503
+ "model.language_model.layers.42.mlp.up_proj.weight": "model-00004-of-00005.safetensors",
504
+ "model.language_model.layers.42.mlp.down_proj.weight": "model-00004-of-00005.safetensors",
505
+ "model.language_model.layers.43.input_layernorm.weight": "model-00004-of-00005.safetensors",
506
+ "model.language_model.layers.43.self_attn.q_proj.weight": "model-00004-of-00005.safetensors",
507
+ "model.language_model.layers.43.self_attn.k_proj.weight": "model-00004-of-00005.safetensors",
508
+ "model.language_model.layers.43.self_attn.v_proj.weight": "model-00004-of-00005.safetensors",
509
+ "model.language_model.layers.43.self_attn.o_proj.weight": "model-00004-of-00005.safetensors",
510
+ "model.language_model.layers.43.self_attn.q_norm.weight": "model-00004-of-00005.safetensors",
511
+ "model.language_model.layers.43.self_attn.k_norm.weight": "model-00004-of-00005.safetensors",
512
+ "model.language_model.layers.43.post_attention_layernorm.weight": "model-00004-of-00005.safetensors",
513
+ "model.language_model.layers.43.mlp.gate_proj.weight": "model-00004-of-00005.safetensors",
514
+ "model.language_model.layers.43.mlp.up_proj.weight": "model-00004-of-00005.safetensors",
515
+ "model.language_model.layers.43.mlp.down_proj.weight": "model-00004-of-00005.safetensors",
516
+ "model.language_model.layers.44.input_layernorm.weight": "model-00004-of-00005.safetensors",
517
+ "model.language_model.layers.44.self_attn.q_proj.weight": "model-00004-of-00005.safetensors",
518
+ "model.language_model.layers.44.self_attn.k_proj.weight": "model-00004-of-00005.safetensors",
519
+ "model.language_model.layers.44.self_attn.v_proj.weight": "model-00004-of-00005.safetensors",
520
+ "model.language_model.layers.44.self_attn.o_proj.weight": "model-00004-of-00005.safetensors",
521
+ "model.language_model.layers.44.self_attn.q_norm.weight": "model-00004-of-00005.safetensors",
522
+ "model.language_model.layers.44.self_attn.k_norm.weight": "model-00004-of-00005.safetensors",
523
+ "model.language_model.layers.44.post_attention_layernorm.weight": "model-00004-of-00005.safetensors",
524
+ "model.language_model.layers.44.mlp.gate_proj.weight": "model-00004-of-00005.safetensors",
525
+ "model.language_model.layers.44.mlp.up_proj.weight": "model-00004-of-00005.safetensors",
526
+ "model.language_model.layers.44.mlp.down_proj.weight": "model-00004-of-00005.safetensors",
527
+ "model.language_model.layers.45.input_layernorm.weight": "model-00004-of-00005.safetensors",
528
+ "model.language_model.layers.45.self_attn.q_proj.weight": "model-00004-of-00005.safetensors",
529
+ "model.language_model.layers.45.self_attn.k_proj.weight": "model-00004-of-00005.safetensors",
530
+ "model.language_model.layers.45.self_attn.v_proj.weight": "model-00004-of-00005.safetensors",
531
+ "model.language_model.layers.45.self_attn.o_proj.weight": "model-00004-of-00005.safetensors",
532
+ "model.language_model.layers.45.self_attn.q_norm.weight": "model-00004-of-00005.safetensors",
533
+ "model.language_model.layers.45.self_attn.k_norm.weight": "model-00004-of-00005.safetensors",
534
+ "model.language_model.layers.45.post_attention_layernorm.weight": "model-00004-of-00005.safetensors",
535
+ "model.language_model.layers.45.mlp.gate_proj.weight": "model-00004-of-00005.safetensors",
536
+ "model.language_model.layers.45.mlp.up_proj.weight": "model-00004-of-00005.safetensors",
537
+ "model.language_model.layers.45.mlp.down_proj.weight": "model-00004-of-00005.safetensors",
538
+ "model.language_model.layers.46.input_layernorm.weight": "model-00004-of-00005.safetensors",
539
+ "model.language_model.layers.46.cross_attn.q_proj.weight": "model-00004-of-00005.safetensors",
540
+ "model.language_model.layers.46.cross_attn.k_proj.weight": "model-00004-of-00005.safetensors",
541
+ "model.language_model.layers.46.cross_attn.v_proj.weight": "model-00004-of-00005.safetensors",
542
+ "model.language_model.layers.46.cross_attn.o_proj.weight": "model-00004-of-00005.safetensors",
543
+ "model.language_model.layers.46.cross_attn.q_norm.weight": "model-00004-of-00005.safetensors",
544
+ "model.language_model.layers.46.cross_attn.k_norm.weight": "model-00004-of-00005.safetensors",
545
+ "model.language_model.layers.46.post_attention_layernorm.weight": "model-00004-of-00005.safetensors",
546
+ "model.language_model.layers.46.cross_attn_attn_gate": "model-00004-of-00005.safetensors",
547
+ "model.language_model.layers.46.cross_attn_mlp_gate": "model-00004-of-00005.safetensors",
548
+ "model.language_model.layers.46.mlp.gate_proj.weight": "model-00004-of-00005.safetensors",
549
+ "model.language_model.layers.46.mlp.up_proj.weight": "model-00004-of-00005.safetensors",
550
+ "model.language_model.layers.46.mlp.down_proj.weight": "model-00004-of-00005.safetensors",
551
+ "model.language_model.layers.47.input_layernorm.weight": "model-00004-of-00005.safetensors",
552
+ "model.language_model.layers.47.self_attn.q_proj.weight": "model-00004-of-00005.safetensors",
553
+ "model.language_model.layers.47.self_attn.k_proj.weight": "model-00004-of-00005.safetensors",
554
+ "model.language_model.layers.47.self_attn.v_proj.weight": "model-00004-of-00005.safetensors",
555
+ "model.language_model.layers.47.self_attn.o_proj.weight": "model-00004-of-00005.safetensors",
556
+ "model.language_model.layers.47.self_attn.q_norm.weight": "model-00004-of-00005.safetensors",
557
+ "model.language_model.layers.47.self_attn.k_norm.weight": "model-00004-of-00005.safetensors",
558
+ "model.language_model.layers.47.post_attention_layernorm.weight": "model-00004-of-00005.safetensors",
559
+ "model.language_model.layers.47.mlp.gate_proj.weight": "model-00004-of-00005.safetensors",
560
+ "model.language_model.layers.47.mlp.up_proj.weight": "model-00004-of-00005.safetensors",
561
+ "model.language_model.layers.47.mlp.down_proj.weight": "model-00004-of-00005.safetensors",
562
+ "model.visual.patch_embed.proj.weight": "model-00004-of-00005.safetensors",
563
+ "model.visual.patch_embed.proj.bias": "model-00004-of-00005.safetensors",
564
+ "model.visual.pos_embed.weight": "model-00004-of-00005.safetensors",
565
+ "model.visual.blocks.0.norm1.weight": "model-00004-of-00005.safetensors",
566
+ "model.visual.blocks.0.norm1.bias": "model-00004-of-00005.safetensors",
567
+ "model.visual.blocks.0.attn.qkv.weight": "model-00004-of-00005.safetensors",
568
+ "model.visual.blocks.0.attn.qkv.bias": "model-00004-of-00005.safetensors",
569
+ "model.visual.blocks.0.attn.proj.weight": "model-00004-of-00005.safetensors",
570
+ "model.visual.blocks.0.attn.proj.bias": "model-00004-of-00005.safetensors",
571
+ "model.visual.blocks.0.norm2.weight": "model-00004-of-00005.safetensors",
572
+ "model.visual.blocks.0.norm2.bias": "model-00004-of-00005.safetensors",
573
+ "model.visual.blocks.0.mlp.linear_fc1.weight": "model-00004-of-00005.safetensors",
574
+ "model.visual.blocks.0.mlp.linear_fc1.bias": "model-00004-of-00005.safetensors",
575
+ "model.visual.blocks.0.mlp.linear_fc2.weight": "model-00004-of-00005.safetensors",
576
+ "model.visual.blocks.0.mlp.linear_fc2.bias": "model-00004-of-00005.safetensors",
577
+ "model.visual.blocks.1.norm1.weight": "model-00004-of-00005.safetensors",
578
+ "model.visual.blocks.1.norm1.bias": "model-00004-of-00005.safetensors",
579
+ "model.visual.blocks.1.attn.qkv.weight": "model-00004-of-00005.safetensors",
580
+ "model.visual.blocks.1.attn.qkv.bias": "model-00004-of-00005.safetensors",
581
+ "model.visual.blocks.1.attn.proj.weight": "model-00004-of-00005.safetensors",
582
+ "model.visual.blocks.1.attn.proj.bias": "model-00004-of-00005.safetensors",
583
+ "model.visual.blocks.1.norm2.weight": "model-00004-of-00005.safetensors",
584
+ "model.visual.blocks.1.norm2.bias": "model-00004-of-00005.safetensors",
585
+ "model.visual.blocks.1.mlp.linear_fc1.weight": "model-00004-of-00005.safetensors",
586
+ "model.visual.blocks.1.mlp.linear_fc1.bias": "model-00004-of-00005.safetensors",
587
+ "model.visual.blocks.1.mlp.linear_fc2.weight": "model-00004-of-00005.safetensors",
588
+ "model.visual.blocks.1.mlp.linear_fc2.bias": "model-00004-of-00005.safetensors",
589
+ "model.visual.blocks.2.norm1.weight": "model-00004-of-00005.safetensors",
590
+ "model.visual.blocks.2.norm1.bias": "model-00004-of-00005.safetensors",
591
+ "model.visual.blocks.2.attn.qkv.weight": "model-00004-of-00005.safetensors",
592
+ "model.visual.blocks.2.attn.qkv.bias": "model-00004-of-00005.safetensors",
593
+ "model.visual.blocks.2.attn.proj.weight": "model-00004-of-00005.safetensors",
594
+ "model.visual.blocks.2.attn.proj.bias": "model-00004-of-00005.safetensors",
595
+ "model.visual.blocks.2.norm2.weight": "model-00004-of-00005.safetensors",
596
+ "model.visual.blocks.2.norm2.bias": "model-00004-of-00005.safetensors",
597
+ "model.visual.blocks.2.mlp.linear_fc1.weight": "model-00004-of-00005.safetensors",
598
+ "model.visual.blocks.2.mlp.linear_fc1.bias": "model-00004-of-00005.safetensors",
599
+ "model.visual.blocks.2.mlp.linear_fc2.weight": "model-00004-of-00005.safetensors",
600
+ "model.visual.blocks.2.mlp.linear_fc2.bias": "model-00004-of-00005.safetensors",
601
+ "model.visual.blocks.3.norm1.weight": "model-00004-of-00005.safetensors",
602
+ "model.visual.blocks.3.norm1.bias": "model-00004-of-00005.safetensors",
603
+ "model.visual.blocks.3.attn.qkv.weight": "model-00004-of-00005.safetensors",
604
+ "model.visual.blocks.3.attn.qkv.bias": "model-00004-of-00005.safetensors",
605
+ "model.visual.blocks.3.attn.proj.weight": "model-00004-of-00005.safetensors",
606
+ "model.visual.blocks.3.attn.proj.bias": "model-00004-of-00005.safetensors",
607
+ "model.visual.blocks.3.norm2.weight": "model-00004-of-00005.safetensors",
608
+ "model.visual.blocks.3.norm2.bias": "model-00004-of-00005.safetensors",
609
+ "model.visual.blocks.3.mlp.linear_fc1.weight": "model-00004-of-00005.safetensors",
610
+ "model.visual.blocks.3.mlp.linear_fc1.bias": "model-00004-of-00005.safetensors",
611
+ "model.visual.blocks.3.mlp.linear_fc2.weight": "model-00004-of-00005.safetensors",
612
+ "model.visual.blocks.3.mlp.linear_fc2.bias": "model-00004-of-00005.safetensors",
613
+ "model.visual.blocks.4.norm1.weight": "model-00004-of-00005.safetensors",
614
+ "model.visual.blocks.4.norm1.bias": "model-00004-of-00005.safetensors",
615
+ "model.visual.blocks.4.attn.qkv.weight": "model-00004-of-00005.safetensors",
616
+ "model.visual.blocks.4.attn.qkv.bias": "model-00004-of-00005.safetensors",
617
+ "model.visual.blocks.4.attn.proj.weight": "model-00004-of-00005.safetensors",
618
+ "model.visual.blocks.4.attn.proj.bias": "model-00004-of-00005.safetensors",
619
+ "model.visual.blocks.4.norm2.weight": "model-00004-of-00005.safetensors",
620
+ "model.visual.blocks.4.norm2.bias": "model-00004-of-00005.safetensors",
621
+ "model.visual.blocks.4.mlp.linear_fc1.weight": "model-00004-of-00005.safetensors",
622
+ "model.visual.blocks.4.mlp.linear_fc1.bias": "model-00004-of-00005.safetensors",
623
+ "model.visual.blocks.4.mlp.linear_fc2.weight": "model-00004-of-00005.safetensors",
624
+ "model.visual.blocks.4.mlp.linear_fc2.bias": "model-00004-of-00005.safetensors",
625
+ "model.visual.blocks.5.norm1.weight": "model-00004-of-00005.safetensors",
626
+ "model.visual.blocks.5.norm1.bias": "model-00004-of-00005.safetensors",
627
+ "model.visual.blocks.5.attn.qkv.weight": "model-00004-of-00005.safetensors",
628
+ "model.visual.blocks.5.attn.qkv.bias": "model-00004-of-00005.safetensors",
629
+ "model.visual.blocks.5.attn.proj.weight": "model-00004-of-00005.safetensors",
630
+ "model.visual.blocks.5.attn.proj.bias": "model-00004-of-00005.safetensors",
631
+ "model.visual.blocks.5.norm2.weight": "model-00004-of-00005.safetensors",
632
+ "model.visual.blocks.5.norm2.bias": "model-00004-of-00005.safetensors",
633
+ "model.visual.blocks.5.mlp.linear_fc1.weight": "model-00004-of-00005.safetensors",
634
+ "model.visual.blocks.5.mlp.linear_fc1.bias": "model-00004-of-00005.safetensors",
635
+ "model.visual.blocks.5.mlp.linear_fc2.weight": "model-00004-of-00005.safetensors",
636
+ "model.visual.blocks.5.mlp.linear_fc2.bias": "model-00004-of-00005.safetensors",
637
+ "model.visual.blocks.6.norm1.weight": "model-00004-of-00005.safetensors",
638
+ "model.visual.blocks.6.norm1.bias": "model-00004-of-00005.safetensors",
639
+ "model.visual.blocks.6.attn.qkv.weight": "model-00004-of-00005.safetensors",
640
+ "model.visual.blocks.6.attn.qkv.bias": "model-00004-of-00005.safetensors",
641
+ "model.visual.blocks.6.attn.proj.weight": "model-00004-of-00005.safetensors",
642
+ "model.visual.blocks.6.attn.proj.bias": "model-00004-of-00005.safetensors",
643
+ "model.visual.blocks.6.norm2.weight": "model-00004-of-00005.safetensors",
644
+ "model.visual.blocks.6.norm2.bias": "model-00004-of-00005.safetensors",
645
+ "model.visual.blocks.6.mlp.linear_fc1.weight": "model-00004-of-00005.safetensors",
646
+ "model.visual.blocks.6.mlp.linear_fc1.bias": "model-00004-of-00005.safetensors",
647
+ "model.visual.blocks.6.mlp.linear_fc2.weight": "model-00004-of-00005.safetensors",
648
+ "model.visual.blocks.6.mlp.linear_fc2.bias": "model-00004-of-00005.safetensors",
649
+ "model.visual.blocks.7.norm1.weight": "model-00004-of-00005.safetensors",
650
+ "model.visual.blocks.7.norm1.bias": "model-00004-of-00005.safetensors",
651
+ "model.visual.blocks.7.attn.qkv.weight": "model-00004-of-00005.safetensors",
652
+ "model.visual.blocks.7.attn.qkv.bias": "model-00004-of-00005.safetensors",
653
+ "model.visual.blocks.7.attn.proj.weight": "model-00004-of-00005.safetensors",
654
+ "model.visual.blocks.7.attn.proj.bias": "model-00004-of-00005.safetensors",
655
+ "model.visual.blocks.7.norm2.weight": "model-00004-of-00005.safetensors",
656
+ "model.visual.blocks.7.norm2.bias": "model-00004-of-00005.safetensors",
657
+ "model.visual.blocks.7.mlp.linear_fc1.weight": "model-00004-of-00005.safetensors",
658
+ "model.visual.blocks.7.mlp.linear_fc1.bias": "model-00004-of-00005.safetensors",
659
+ "model.visual.blocks.7.mlp.linear_fc2.weight": "model-00004-of-00005.safetensors",
660
+ "model.visual.blocks.7.mlp.linear_fc2.bias": "model-00004-of-00005.safetensors",
661
+ "model.visual.blocks.8.norm1.weight": "model-00004-of-00005.safetensors",
662
+ "model.visual.blocks.8.norm1.bias": "model-00004-of-00005.safetensors",
663
+ "model.visual.blocks.8.attn.qkv.weight": "model-00004-of-00005.safetensors",
664
+ "model.visual.blocks.8.attn.qkv.bias": "model-00004-of-00005.safetensors",
665
+ "model.visual.blocks.8.attn.proj.weight": "model-00004-of-00005.safetensors",
666
+ "model.visual.blocks.8.attn.proj.bias": "model-00004-of-00005.safetensors",
667
+ "model.visual.blocks.8.norm2.weight": "model-00004-of-00005.safetensors",
668
+ "model.visual.blocks.8.norm2.bias": "model-00004-of-00005.safetensors",
669
+ "model.visual.blocks.8.mlp.linear_fc1.weight": "model-00004-of-00005.safetensors",
670
+ "model.visual.blocks.8.mlp.linear_fc1.bias": "model-00004-of-00005.safetensors",
671
+ "model.visual.blocks.8.mlp.linear_fc2.weight": "model-00004-of-00005.safetensors",
672
+ "model.visual.blocks.8.mlp.linear_fc2.bias": "model-00004-of-00005.safetensors",
673
+ "model.visual.blocks.9.norm1.weight": "model-00004-of-00005.safetensors",
674
+ "model.visual.blocks.9.norm1.bias": "model-00004-of-00005.safetensors",
675
+ "model.visual.blocks.9.attn.qkv.weight": "model-00004-of-00005.safetensors",
676
+ "model.visual.blocks.9.attn.qkv.bias": "model-00004-of-00005.safetensors",
677
+ "model.visual.blocks.9.attn.proj.weight": "model-00004-of-00005.safetensors",
678
+ "model.visual.blocks.9.attn.proj.bias": "model-00004-of-00005.safetensors",
679
+ "model.visual.blocks.9.norm2.weight": "model-00004-of-00005.safetensors",
680
+ "model.visual.blocks.9.norm2.bias": "model-00004-of-00005.safetensors",
681
+ "model.visual.blocks.9.mlp.linear_fc1.weight": "model-00004-of-00005.safetensors",
682
+ "model.visual.blocks.9.mlp.linear_fc1.bias": "model-00004-of-00005.safetensors",
683
+ "model.visual.blocks.9.mlp.linear_fc2.weight": "model-00004-of-00005.safetensors",
684
+ "model.visual.blocks.9.mlp.linear_fc2.bias": "model-00004-of-00005.safetensors",
685
+ "model.visual.blocks.10.norm1.weight": "model-00004-of-00005.safetensors",
686
+ "model.visual.blocks.10.norm1.bias": "model-00004-of-00005.safetensors",
687
+ "model.visual.blocks.10.attn.qkv.weight": "model-00004-of-00005.safetensors",
688
+ "model.visual.blocks.10.attn.qkv.bias": "model-00004-of-00005.safetensors",
689
+ "model.visual.blocks.10.attn.proj.weight": "model-00004-of-00005.safetensors",
690
+ "model.visual.blocks.10.attn.proj.bias": "model-00004-of-00005.safetensors",
691
+ "model.visual.blocks.10.norm2.weight": "model-00004-of-00005.safetensors",
692
+ "model.visual.blocks.10.norm2.bias": "model-00004-of-00005.safetensors",
693
+ "model.visual.blocks.10.mlp.linear_fc1.weight": "model-00004-of-00005.safetensors",
694
+ "model.visual.blocks.10.mlp.linear_fc1.bias": "model-00004-of-00005.safetensors",
695
+ "model.visual.blocks.10.mlp.linear_fc2.weight": "model-00004-of-00005.safetensors",
696
+ "model.visual.blocks.10.mlp.linear_fc2.bias": "model-00004-of-00005.safetensors",
697
+ "model.visual.blocks.11.norm1.weight": "model-00004-of-00005.safetensors",
698
+ "model.visual.blocks.11.norm1.bias": "model-00004-of-00005.safetensors",
699
+ "model.visual.blocks.11.attn.qkv.weight": "model-00004-of-00005.safetensors",
700
+ "model.visual.blocks.11.attn.qkv.bias": "model-00004-of-00005.safetensors",
701
+ "model.visual.blocks.11.attn.proj.weight": "model-00005-of-00005.safetensors",
702
+ "model.visual.blocks.11.attn.proj.bias": "model-00005-of-00005.safetensors",
703
+ "model.visual.blocks.11.norm2.weight": "model-00005-of-00005.safetensors",
704
+ "model.visual.blocks.11.norm2.bias": "model-00005-of-00005.safetensors",
705
+ "model.visual.blocks.11.mlp.linear_fc1.weight": "model-00005-of-00005.safetensors",
706
+ "model.visual.blocks.11.mlp.linear_fc1.bias": "model-00005-of-00005.safetensors",
707
+ "model.visual.blocks.11.mlp.linear_fc2.weight": "model-00005-of-00005.safetensors",
708
+ "model.visual.blocks.11.mlp.linear_fc2.bias": "model-00005-of-00005.safetensors",
709
+ "model.visual.blocks.12.norm1.weight": "model-00005-of-00005.safetensors",
710
+ "model.visual.blocks.12.norm1.bias": "model-00005-of-00005.safetensors",
711
+ "model.visual.blocks.12.attn.qkv.weight": "model-00005-of-00005.safetensors",
712
+ "model.visual.blocks.12.attn.qkv.bias": "model-00005-of-00005.safetensors",
713
+ "model.visual.blocks.12.attn.proj.weight": "model-00005-of-00005.safetensors",
714
+ "model.visual.blocks.12.attn.proj.bias": "model-00005-of-00005.safetensors",
715
+ "model.visual.blocks.12.norm2.weight": "model-00005-of-00005.safetensors",
716
+ "model.visual.blocks.12.norm2.bias": "model-00005-of-00005.safetensors",
717
+ "model.visual.blocks.12.mlp.linear_fc1.weight": "model-00005-of-00005.safetensors",
718
+ "model.visual.blocks.12.mlp.linear_fc1.bias": "model-00005-of-00005.safetensors",
719
+ "model.visual.blocks.12.mlp.linear_fc2.weight": "model-00005-of-00005.safetensors",
720
+ "model.visual.blocks.12.mlp.linear_fc2.bias": "model-00005-of-00005.safetensors",
721
+ "model.visual.blocks.13.norm1.weight": "model-00005-of-00005.safetensors",
722
+ "model.visual.blocks.13.norm1.bias": "model-00005-of-00005.safetensors",
723
+ "model.visual.blocks.13.attn.qkv.weight": "model-00005-of-00005.safetensors",
724
+ "model.visual.blocks.13.attn.qkv.bias": "model-00005-of-00005.safetensors",
725
+ "model.visual.blocks.13.attn.proj.weight": "model-00005-of-00005.safetensors",
726
+ "model.visual.blocks.13.attn.proj.bias": "model-00005-of-00005.safetensors",
727
+ "model.visual.blocks.13.norm2.weight": "model-00005-of-00005.safetensors",
728
+ "model.visual.blocks.13.norm2.bias": "model-00005-of-00005.safetensors",
729
+ "model.visual.blocks.13.mlp.linear_fc1.weight": "model-00005-of-00005.safetensors",
730
+ "model.visual.blocks.13.mlp.linear_fc1.bias": "model-00005-of-00005.safetensors",
731
+ "model.visual.blocks.13.mlp.linear_fc2.weight": "model-00005-of-00005.safetensors",
732
+ "model.visual.blocks.13.mlp.linear_fc2.bias": "model-00005-of-00005.safetensors",
733
+ "model.visual.blocks.14.norm1.weight": "model-00005-of-00005.safetensors",
734
+ "model.visual.blocks.14.norm1.bias": "model-00005-of-00005.safetensors",
735
+ "model.visual.blocks.14.attn.qkv.weight": "model-00005-of-00005.safetensors",
736
+ "model.visual.blocks.14.attn.qkv.bias": "model-00005-of-00005.safetensors",
737
+ "model.visual.blocks.14.attn.proj.weight": "model-00005-of-00005.safetensors",
738
+ "model.visual.blocks.14.attn.proj.bias": "model-00005-of-00005.safetensors",
739
+ "model.visual.blocks.14.norm2.weight": "model-00005-of-00005.safetensors",
740
+ "model.visual.blocks.14.norm2.bias": "model-00005-of-00005.safetensors",
741
+ "model.visual.blocks.14.mlp.linear_fc1.weight": "model-00005-of-00005.safetensors",
742
+ "model.visual.blocks.14.mlp.linear_fc1.bias": "model-00005-of-00005.safetensors",
743
+ "model.visual.blocks.14.mlp.linear_fc2.weight": "model-00005-of-00005.safetensors",
744
+ "model.visual.blocks.14.mlp.linear_fc2.bias": "model-00005-of-00005.safetensors",
745
+ "model.visual.blocks.15.norm1.weight": "model-00005-of-00005.safetensors",
746
+ "model.visual.blocks.15.norm1.bias": "model-00005-of-00005.safetensors",
747
+ "model.visual.blocks.15.attn.qkv.weight": "model-00005-of-00005.safetensors",
748
+ "model.visual.blocks.15.attn.qkv.bias": "model-00005-of-00005.safetensors",
749
+ "model.visual.blocks.15.attn.proj.weight": "model-00005-of-00005.safetensors",
750
+ "model.visual.blocks.15.attn.proj.bias": "model-00005-of-00005.safetensors",
751
+ "model.visual.blocks.15.norm2.weight": "model-00005-of-00005.safetensors",
752
+ "model.visual.blocks.15.norm2.bias": "model-00005-of-00005.safetensors",
753
+ "model.visual.blocks.15.mlp.linear_fc1.weight": "model-00005-of-00005.safetensors",
754
+ "model.visual.blocks.15.mlp.linear_fc1.bias": "model-00005-of-00005.safetensors",
755
+ "model.visual.blocks.15.mlp.linear_fc2.weight": "model-00005-of-00005.safetensors",
756
+ "model.visual.blocks.15.mlp.linear_fc2.bias": "model-00005-of-00005.safetensors",
757
+ "model.visual.blocks.16.norm1.weight": "model-00005-of-00005.safetensors",
758
+ "model.visual.blocks.16.norm1.bias": "model-00005-of-00005.safetensors",
759
+ "model.visual.blocks.16.attn.qkv.weight": "model-00005-of-00005.safetensors",
760
+ "model.visual.blocks.16.attn.qkv.bias": "model-00005-of-00005.safetensors",
761
+ "model.visual.blocks.16.attn.proj.weight": "model-00005-of-00005.safetensors",
762
+ "model.visual.blocks.16.attn.proj.bias": "model-00005-of-00005.safetensors",
763
+ "model.visual.blocks.16.norm2.weight": "model-00005-of-00005.safetensors",
764
+ "model.visual.blocks.16.norm2.bias": "model-00005-of-00005.safetensors",
765
+ "model.visual.blocks.16.mlp.linear_fc1.weight": "model-00005-of-00005.safetensors",
766
+ "model.visual.blocks.16.mlp.linear_fc1.bias": "model-00005-of-00005.safetensors",
767
+ "model.visual.blocks.16.mlp.linear_fc2.weight": "model-00005-of-00005.safetensors",
768
+ "model.visual.blocks.16.mlp.linear_fc2.bias": "model-00005-of-00005.safetensors",
769
+ "model.visual.blocks.17.norm1.weight": "model-00005-of-00005.safetensors",
770
+ "model.visual.blocks.17.norm1.bias": "model-00005-of-00005.safetensors",
771
+ "model.visual.blocks.17.attn.qkv.weight": "model-00005-of-00005.safetensors",
772
+ "model.visual.blocks.17.attn.qkv.bias": "model-00005-of-00005.safetensors",
773
+ "model.visual.blocks.17.attn.proj.weight": "model-00005-of-00005.safetensors",
774
+ "model.visual.blocks.17.attn.proj.bias": "model-00005-of-00005.safetensors",
775
+ "model.visual.blocks.17.norm2.weight": "model-00005-of-00005.safetensors",
776
+ "model.visual.blocks.17.norm2.bias": "model-00005-of-00005.safetensors",
777
+ "model.visual.blocks.17.mlp.linear_fc1.weight": "model-00005-of-00005.safetensors",
778
+ "model.visual.blocks.17.mlp.linear_fc1.bias": "model-00005-of-00005.safetensors",
779
+ "model.visual.blocks.17.mlp.linear_fc2.weight": "model-00005-of-00005.safetensors",
780
+ "model.visual.blocks.17.mlp.linear_fc2.bias": "model-00005-of-00005.safetensors",
781
+ "model.visual.blocks.18.norm1.weight": "model-00005-of-00005.safetensors",
782
+ "model.visual.blocks.18.norm1.bias": "model-00005-of-00005.safetensors",
783
+ "model.visual.blocks.18.attn.qkv.weight": "model-00005-of-00005.safetensors",
784
+ "model.visual.blocks.18.attn.qkv.bias": "model-00005-of-00005.safetensors",
785
+ "model.visual.blocks.18.attn.proj.weight": "model-00005-of-00005.safetensors",
786
+ "model.visual.blocks.18.attn.proj.bias": "model-00005-of-00005.safetensors",
787
+ "model.visual.blocks.18.norm2.weight": "model-00005-of-00005.safetensors",
788
+ "model.visual.blocks.18.norm2.bias": "model-00005-of-00005.safetensors",
789
+ "model.visual.blocks.18.mlp.linear_fc1.weight": "model-00005-of-00005.safetensors",
790
+ "model.visual.blocks.18.mlp.linear_fc1.bias": "model-00005-of-00005.safetensors",
791
+ "model.visual.blocks.18.mlp.linear_fc2.weight": "model-00005-of-00005.safetensors",
792
+ "model.visual.blocks.18.mlp.linear_fc2.bias": "model-00005-of-00005.safetensors",
793
+ "model.visual.blocks.19.norm1.weight": "model-00005-of-00005.safetensors",
794
+ "model.visual.blocks.19.norm1.bias": "model-00005-of-00005.safetensors",
795
+ "model.visual.blocks.19.attn.qkv.weight": "model-00005-of-00005.safetensors",
796
+ "model.visual.blocks.19.attn.qkv.bias": "model-00005-of-00005.safetensors",
797
+ "model.visual.blocks.19.attn.proj.weight": "model-00005-of-00005.safetensors",
798
+ "model.visual.blocks.19.attn.proj.bias": "model-00005-of-00005.safetensors",
799
+ "model.visual.blocks.19.norm2.weight": "model-00005-of-00005.safetensors",
800
+ "model.visual.blocks.19.norm2.bias": "model-00005-of-00005.safetensors",
801
+ "model.visual.blocks.19.mlp.linear_fc1.weight": "model-00005-of-00005.safetensors",
802
+ "model.visual.blocks.19.mlp.linear_fc1.bias": "model-00005-of-00005.safetensors",
803
+ "model.visual.blocks.19.mlp.linear_fc2.weight": "model-00005-of-00005.safetensors",
804
+ "model.visual.blocks.19.mlp.linear_fc2.bias": "model-00005-of-00005.safetensors",
805
+ "model.visual.blocks.20.norm1.weight": "model-00005-of-00005.safetensors",
806
+ "model.visual.blocks.20.norm1.bias": "model-00005-of-00005.safetensors",
807
+ "model.visual.blocks.20.attn.qkv.weight": "model-00005-of-00005.safetensors",
808
+ "model.visual.blocks.20.attn.qkv.bias": "model-00005-of-00005.safetensors",
809
+ "model.visual.blocks.20.attn.proj.weight": "model-00005-of-00005.safetensors",
810
+ "model.visual.blocks.20.attn.proj.bias": "model-00005-of-00005.safetensors",
811
+ "model.visual.blocks.20.norm2.weight": "model-00005-of-00005.safetensors",
812
+ "model.visual.blocks.20.norm2.bias": "model-00005-of-00005.safetensors",
813
+ "model.visual.blocks.20.mlp.linear_fc1.weight": "model-00005-of-00005.safetensors",
814
+ "model.visual.blocks.20.mlp.linear_fc1.bias": "model-00005-of-00005.safetensors",
815
+ "model.visual.blocks.20.mlp.linear_fc2.weight": "model-00005-of-00005.safetensors",
816
+ "model.visual.blocks.20.mlp.linear_fc2.bias": "model-00005-of-00005.safetensors",
817
+ "model.visual.blocks.21.norm1.weight": "model-00005-of-00005.safetensors",
818
+ "model.visual.blocks.21.norm1.bias": "model-00005-of-00005.safetensors",
819
+ "model.visual.blocks.21.attn.qkv.weight": "model-00005-of-00005.safetensors",
820
+ "model.visual.blocks.21.attn.qkv.bias": "model-00005-of-00005.safetensors",
821
+ "model.visual.blocks.21.attn.proj.weight": "model-00005-of-00005.safetensors",
822
+ "model.visual.blocks.21.attn.proj.bias": "model-00005-of-00005.safetensors",
823
+ "model.visual.blocks.21.norm2.weight": "model-00005-of-00005.safetensors",
824
+ "model.visual.blocks.21.norm2.bias": "model-00005-of-00005.safetensors",
825
+ "model.visual.blocks.21.mlp.linear_fc1.weight": "model-00005-of-00005.safetensors",
826
+ "model.visual.blocks.21.mlp.linear_fc1.bias": "model-00005-of-00005.safetensors",
827
+ "model.visual.blocks.21.mlp.linear_fc2.weight": "model-00005-of-00005.safetensors",
828
+ "model.visual.blocks.21.mlp.linear_fc2.bias": "model-00005-of-00005.safetensors",
829
+ "model.visual.blocks.22.norm1.weight": "model-00005-of-00005.safetensors",
830
+ "model.visual.blocks.22.norm1.bias": "model-00005-of-00005.safetensors",
831
+ "model.visual.blocks.22.attn.qkv.weight": "model-00005-of-00005.safetensors",
832
+ "model.visual.blocks.22.attn.qkv.bias": "model-00005-of-00005.safetensors",
833
+ "model.visual.blocks.22.attn.proj.weight": "model-00005-of-00005.safetensors",
834
+ "model.visual.blocks.22.attn.proj.bias": "model-00005-of-00005.safetensors",
835
+ "model.visual.blocks.22.norm2.weight": "model-00005-of-00005.safetensors",
836
+ "model.visual.blocks.22.norm2.bias": "model-00005-of-00005.safetensors",
837
+ "model.visual.blocks.22.mlp.linear_fc1.weight": "model-00005-of-00005.safetensors",
838
+ "model.visual.blocks.22.mlp.linear_fc1.bias": "model-00005-of-00005.safetensors",
839
+ "model.visual.blocks.22.mlp.linear_fc2.weight": "model-00005-of-00005.safetensors",
840
+ "model.visual.blocks.22.mlp.linear_fc2.bias": "model-00005-of-00005.safetensors",
841
+ "model.visual.blocks.23.norm1.weight": "model-00005-of-00005.safetensors",
842
+ "model.visual.blocks.23.norm1.bias": "model-00005-of-00005.safetensors",
843
+ "model.visual.blocks.23.attn.qkv.weight": "model-00005-of-00005.safetensors",
844
+ "model.visual.blocks.23.attn.qkv.bias": "model-00005-of-00005.safetensors",
845
+ "model.visual.blocks.23.attn.proj.weight": "model-00005-of-00005.safetensors",
846
+ "model.visual.blocks.23.attn.proj.bias": "model-00005-of-00005.safetensors",
847
+ "model.visual.blocks.23.norm2.weight": "model-00005-of-00005.safetensors",
848
+ "model.visual.blocks.23.norm2.bias": "model-00005-of-00005.safetensors",
849
+ "model.visual.blocks.23.mlp.linear_fc1.weight": "model-00005-of-00005.safetensors",
850
+ "model.visual.blocks.23.mlp.linear_fc1.bias": "model-00005-of-00005.safetensors",
851
+ "model.visual.blocks.23.mlp.linear_fc2.weight": "model-00005-of-00005.safetensors",
852
+ "model.visual.blocks.23.mlp.linear_fc2.bias": "model-00005-of-00005.safetensors",
853
+ "model.visual.blocks.24.norm1.weight": "model-00005-of-00005.safetensors",
854
+ "model.visual.blocks.24.norm1.bias": "model-00005-of-00005.safetensors",
855
+ "model.visual.blocks.24.attn.qkv.weight": "model-00005-of-00005.safetensors",
856
+ "model.visual.blocks.24.attn.qkv.bias": "model-00005-of-00005.safetensors",
857
+ "model.visual.blocks.24.attn.proj.weight": "model-00005-of-00005.safetensors",
858
+ "model.visual.blocks.24.attn.proj.bias": "model-00005-of-00005.safetensors",
859
+ "model.visual.blocks.24.norm2.weight": "model-00005-of-00005.safetensors",
860
+ "model.visual.blocks.24.norm2.bias": "model-00005-of-00005.safetensors",
861
+ "model.visual.blocks.24.mlp.linear_fc1.weight": "model-00005-of-00005.safetensors",
862
+ "model.visual.blocks.24.mlp.linear_fc1.bias": "model-00005-of-00005.safetensors",
863
+ "model.visual.blocks.24.mlp.linear_fc2.weight": "model-00005-of-00005.safetensors",
864
+ "model.visual.blocks.24.mlp.linear_fc2.bias": "model-00005-of-00005.safetensors",
865
+ "model.visual.blocks.25.norm1.weight": "model-00005-of-00005.safetensors",
866
+ "model.visual.blocks.25.norm1.bias": "model-00005-of-00005.safetensors",
867
+ "model.visual.blocks.25.attn.qkv.weight": "model-00005-of-00005.safetensors",
868
+ "model.visual.blocks.25.attn.qkv.bias": "model-00005-of-00005.safetensors",
869
+ "model.visual.blocks.25.attn.proj.weight": "model-00005-of-00005.safetensors",
870
+ "model.visual.blocks.25.attn.proj.bias": "model-00005-of-00005.safetensors",
871
+ "model.visual.blocks.25.norm2.weight": "model-00005-of-00005.safetensors",
872
+ "model.visual.blocks.25.norm2.bias": "model-00005-of-00005.safetensors",
873
+ "model.visual.blocks.25.mlp.linear_fc1.weight": "model-00005-of-00005.safetensors",
874
+ "model.visual.blocks.25.mlp.linear_fc1.bias": "model-00005-of-00005.safetensors",
875
+ "model.visual.blocks.25.mlp.linear_fc2.weight": "model-00005-of-00005.safetensors",
876
+ "model.visual.blocks.25.mlp.linear_fc2.bias": "model-00005-of-00005.safetensors",
877
+ "model.visual.blocks.26.norm1.weight": "model-00005-of-00005.safetensors",
878
+ "model.visual.blocks.26.norm1.bias": "model-00005-of-00005.safetensors",
879
+ "model.visual.blocks.26.attn.qkv.weight": "model-00005-of-00005.safetensors",
880
+ "model.visual.blocks.26.attn.qkv.bias": "model-00005-of-00005.safetensors",
881
+ "model.visual.blocks.26.attn.proj.weight": "model-00005-of-00005.safetensors",
882
+ "model.visual.blocks.26.attn.proj.bias": "model-00005-of-00005.safetensors",
883
+ "model.visual.blocks.26.norm2.weight": "model-00005-of-00005.safetensors",
884
+ "model.visual.blocks.26.norm2.bias": "model-00005-of-00005.safetensors",
885
+ "model.visual.blocks.26.mlp.linear_fc1.weight": "model-00005-of-00005.safetensors",
886
+ "model.visual.blocks.26.mlp.linear_fc1.bias": "model-00005-of-00005.safetensors",
887
+ "model.visual.blocks.26.mlp.linear_fc2.weight": "model-00005-of-00005.safetensors",
888
+ "model.visual.blocks.26.mlp.linear_fc2.bias": "model-00005-of-00005.safetensors",
889
+ "model.visual.merger.linear_fc1.weight": "model-00005-of-00005.safetensors",
890
+ "model.visual.merger.linear_fc1.bias": "model-00005-of-00005.safetensors",
891
+ "model.visual.merger.linear_fc2.weight": "model-00005-of-00005.safetensors",
892
+ "model.visual.merger.linear_fc2.bias": "model-00005-of-00005.safetensors",
893
+ "model.visual.merger.norms.0.weight": "model-00005-of-00005.safetensors",
894
+ "model.visual.merger.norms.0.bias": "model-00005-of-00005.safetensors",
895
+ "model.visual.merger.norms.1.weight": "model-00005-of-00005.safetensors",
896
+ "model.visual.merger.norms.1.bias": "model-00005-of-00005.safetensors",
897
+ "model.visual.merger.norms.2.weight": "model-00005-of-00005.safetensors",
898
+ "model.visual.merger.norms.2.bias": "model-00005-of-00005.safetensors",
899
+ "model.visual.merger.norms.3.weight": "model-00005-of-00005.safetensors",
900
+ "model.visual.merger.norms.3.bias": "model-00005-of-00005.safetensors"
901
+ }
902
+ }
modeling_moss_vl.py ADDED
The diff for this file is too large to render. See raw diff
 
preprocessor_config.json ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "auto_map": {
3
+ "AutoProcessor": "processing_moss_vl.MossVLProcessor",
4
+ "AutoImageProcessor": "processing_moss_vl.MossVLImageProcessorFast"
5
+ },
6
+ "size": {
7
+ "longest_edge": 16777216,
8
+ "shortest_edge": 4096
9
+ },
10
+ "multi_image_max_pixels": 65536000,
11
+ "patch_size": 16,
12
+ "temporal_patch_size": 1,
13
+ "merge_size": 2,
14
+ "image_mean": [
15
+ 0.5,
16
+ 0.5,
17
+ 0.5
18
+ ],
19
+ "image_std": [
20
+ 0.5,
21
+ 0.5,
22
+ 0.5
23
+ ],
24
+ "processor_class": "MossVLProcessor",
25
+ "image_processor_type": "MossVLImageProcessorFast"
26
+ }
processing_moss_vl.py ADDED
@@ -0,0 +1,1143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # coding=utf-8
2
+ # Copyright 2025 The FNLP Vision Team and The HuggingFace Inc. team. All rights reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ """
16
+ Processor class for Moss-VL.
17
+ """
18
+
19
+ from typing import Any, Dict, List, Optional, Union
20
+
21
+ import numpy as np
22
+ import torch
23
+ from torchvision.transforms.v2 import functional as F
24
+ from PIL import Image
25
+ from transformers.feature_extraction_utils import BatchFeature
26
+ from transformers.image_utils import ImageInput, SizeDict
27
+ from transformers.image_processing_utils_fast import group_images_by_shape, reorder_images
28
+ from transformers.utils import TensorType
29
+ from transformers.processing_utils import (
30
+ ImagesKwargs,
31
+ ProcessingKwargs,
32
+ ProcessorMixin,
33
+ Unpack,
34
+ VideosKwargs,
35
+ )
36
+ from transformers.tokenization_utils_base import PreTokenizedInput, TextInput
37
+ from transformers.utils import logging
38
+ from transformers.models.qwen2_vl.image_processing_qwen2_vl_fast import Qwen2VLImageProcessorFast
39
+ from transformers.models.qwen2_vl.image_processing_qwen2_vl import smart_resize
40
+
41
+
42
+ logger = logging.get_logger(__name__)
43
+
44
+
45
+ class MossVLImageProcessorFast(Qwen2VLImageProcessorFast):
46
+ """
47
+ Custom image processor that overrides _preprocess to support multi_image_max_pixels.
48
+ Inherits from Qwen2VLImageProcessorFast.
49
+ """
50
+ # Multi-image batch total pixels limit (read from config)
51
+ multi_image_max_pixels = None
52
+
53
+
54
+ def _preprocess(
55
+ self,
56
+ images: list["torch.Tensor"],
57
+ do_resize: bool,
58
+ size: SizeDict,
59
+ interpolation: Optional["F.InterpolationMode"],
60
+ do_rescale: bool,
61
+ rescale_factor: float,
62
+ do_normalize: bool,
63
+ image_mean: Optional[Union[float, list[float]]],
64
+ image_std: Optional[Union[float, list[float]]],
65
+ patch_size: int,
66
+ temporal_patch_size: int,
67
+ merge_size: int,
68
+ disable_grouping: Optional[bool],
69
+ return_tensors: Optional[Union[str, TensorType]],
70
+ **kwargs,
71
+ ):
72
+ """Override _preprocess to use custom smart_resize with batch-level max_pixels.
73
+
74
+ multi_image_max_pixels is treated as a batch-level total budget, proportionally allocated
75
+ to each image based on its original pixel count. min_pixels remains a per-image
76
+ constraint. multi_image_max_pixels can be configured separately from longest_edge.
77
+ """
78
+ min_pixels = size["shortest_edge"]
79
+ max_pixels = size["longest_edge"] # Per-image upper limit
80
+ # Use multi_image_max_pixels if configured, otherwise fall back to longest_edge
81
+ multi_image_max_pixels = getattr(self, "multi_image_max_pixels", None) or max_pixels
82
+
83
+ # Calculate total original pixels across all images in the batch
84
+ # This is used to proportionally allocate max_pixels to each image
85
+ total_original_pixels = sum(img.shape[-2] * img.shape[-1] for img in images)
86
+
87
+ # Group images by size for batched resizing
88
+ grouped_images, grouped_images_index = group_images_by_shape(images, disable_grouping=disable_grouping)
89
+ resized_images_grouped = {}
90
+ for shape, stacked_images in grouped_images.items():
91
+ height, width = stacked_images.shape[-2:]
92
+ if do_resize:
93
+ # Calculate proportional max_pixels for images with this shape
94
+ # Each image's max_pixels is allocated based on its proportion of total pixels
95
+ original_pixels = height * width
96
+ if total_original_pixels > 0:
97
+ proportion = original_pixels / total_original_pixels
98
+ proportional_max_pixels = int(multi_image_max_pixels * proportion)
99
+ else:
100
+ proportional_max_pixels = multi_image_max_pixels
101
+
102
+ # Ensure proportional max_pixels is within [min_pixels, max_pixels] range
103
+ # min_pixels: per-image lower limit (shortest_edge)
104
+ # max_pixels: per-image upper limit (longest_edge)
105
+ proportional_max_pixels = max(proportional_max_pixels, min_pixels)
106
+ proportional_max_pixels = min(proportional_max_pixels, max_pixels)
107
+
108
+ resized_height, resized_width = smart_resize(
109
+ height,
110
+ width,
111
+ factor=patch_size * merge_size,
112
+ min_pixels=min_pixels,
113
+ max_pixels=proportional_max_pixels,
114
+ )
115
+ stacked_images = self.resize(
116
+ image=stacked_images,
117
+ size=SizeDict(height=resized_height, width=resized_width),
118
+ interpolation=interpolation,
119
+ )
120
+ resized_images_grouped[shape] = stacked_images
121
+ resized_images = reorder_images(resized_images_grouped, grouped_images_index)
122
+
123
+ # Warn if multi-image batch exceeds multi_image_max_pixels due to min_pixels constraint
124
+ if len(images) > 1:
125
+ total_resized_pixels = sum(img.shape[-2] * img.shape[-1] for img in resized_images)
126
+ if total_resized_pixels > multi_image_max_pixels:
127
+ logger.warning_once(
128
+ f"Multi-image batch total pixels ({total_resized_pixels}) exceeds multi_image_max_pixels ({multi_image_max_pixels}). "
129
+ f"This may happen when image_count * min_pixels > multi_image_max_pixels."
130
+ )
131
+
132
+ # Group images by size for further processing
133
+ # Needed in case do_resize is False, or resize returns images with different sizes
134
+ grouped_images, grouped_images_index = group_images_by_shape(resized_images, disable_grouping=disable_grouping)
135
+ processed_images_grouped = {}
136
+ processed_grids = {}
137
+ for shape, stacked_images in grouped_images.items():
138
+ resized_height, resized_width = stacked_images.shape[-2:]
139
+ # Fused rescale and normalize
140
+ patches = self.rescale_and_normalize(
141
+ stacked_images, do_rescale, rescale_factor, do_normalize, image_mean, image_std
142
+ )
143
+ if patches.ndim == 4:
144
+ # add a temporal dimension if we have images
145
+ patches = patches.unsqueeze(1)
146
+ if patches.shape[1] % temporal_patch_size != 0:
147
+ repeats = patches[:, -1:].repeat(1, temporal_patch_size - 1, 1, 1, 1)
148
+ patches = torch.cat([patches, repeats], dim=1)
149
+ batch_size, grid_t, channel = patches.shape[:3]
150
+ grid_t = grid_t // temporal_patch_size
151
+ grid_h, grid_w = resized_height // patch_size, resized_width // patch_size
152
+
153
+ patches = patches.view(
154
+ batch_size,
155
+ grid_t,
156
+ temporal_patch_size,
157
+ channel,
158
+ grid_h // merge_size,
159
+ merge_size,
160
+ patch_size,
161
+ grid_w // merge_size,
162
+ merge_size,
163
+ patch_size,
164
+ )
165
+ # Reorder dimensions to group grid and patch information for subsequent flattening.
166
+ # (batch, grid_t, grid_h, grid_w, merge_h, merge_w, channel, temp_patch_size, patch_h, patch_w)
167
+ patches = patches.permute(0, 1, 4, 7, 5, 8, 3, 2, 6, 9)
168
+ flatten_patches = patches.reshape(
169
+ batch_size,
170
+ grid_t * grid_h * grid_w,
171
+ channel * temporal_patch_size * patch_size * patch_size,
172
+ )
173
+
174
+ processed_images_grouped[shape] = flatten_patches
175
+ processed_grids[shape] = [[grid_t, grid_h, grid_w]] * batch_size
176
+
177
+ processed_images = reorder_images(processed_images_grouped, grouped_images_index)
178
+ processed_grids = reorder_images(processed_grids, grouped_images_index)
179
+ pixel_values = torch.cat(processed_images, dim=0)
180
+ image_grid_thw = torch.tensor(processed_grids)
181
+
182
+ return BatchFeature(
183
+ data={"pixel_values": pixel_values, "image_grid_thw": image_grid_thw}, tensor_type=return_tensors
184
+ )
185
+
186
+ def _to_numpy(x):
187
+ """
188
+ Convert various tensor types to numpy array.
189
+ Supports torch.Tensor, tf.Tensor, jax.Array, np.ndarray, lists, and primitives.
190
+
191
+ Args:
192
+ x: Input value that can be a tensor from various frameworks or a Python primitive
193
+
194
+ Returns:
195
+ np.ndarray: NumPy array representation of the input
196
+ """
197
+ # Already numpy
198
+ if isinstance(x, np.ndarray):
199
+ return x
200
+
201
+ # Torch tensor or TensorFlow tensor (both have .numpy() method)
202
+ if hasattr(x, 'numpy'):
203
+ # For torch tensors on CUDA, need to move to CPU first
204
+ if hasattr(x, 'cpu'):
205
+ return x.cpu().numpy()
206
+ # For TensorFlow or already on CPU
207
+ return x.numpy()
208
+
209
+ # JAX arrays and other array-like objects that support __array__ protocol
210
+ if hasattr(x, '__array__'):
211
+ return np.asarray(x)
212
+
213
+ # Python primitives (list, tuple, int, float)
214
+ return np.array(x)
215
+
216
+
217
+ def _split_array_or_tensor(x, split_indices):
218
+ """Split along the first dimension while preserving tensor/array type."""
219
+ split_indices = [int(idx) for idx in split_indices]
220
+ if isinstance(x, torch.Tensor):
221
+ if not split_indices:
222
+ return [x]
223
+ chunks = []
224
+ start = 0
225
+ for end in split_indices:
226
+ chunks.append(x[start:end])
227
+ start = end
228
+ chunks.append(x[start:])
229
+ return chunks
230
+ return np.split(x, split_indices)
231
+
232
+
233
+ def _concat_array_or_tensor(items, axis=0):
234
+ """Concatenate while preserving tensor/array type and device."""
235
+ if not items:
236
+ return None
237
+
238
+ if any(isinstance(item, torch.Tensor) for item in items):
239
+ ref = next(item for item in items if isinstance(item, torch.Tensor))
240
+ tensor_items = [
241
+ item
242
+ if isinstance(item, torch.Tensor)
243
+ else torch.as_tensor(item, device=ref.device, dtype=ref.dtype)
244
+ for item in items
245
+ ]
246
+ return torch.cat(tensor_items, dim=axis)
247
+
248
+ return np.concatenate(items, axis=axis)
249
+
250
+
251
+ def _stack_array_or_tensor(items, axis=0):
252
+ """Stack while preserving tensor/array type and device."""
253
+ if not items:
254
+ return None
255
+
256
+ if any(isinstance(item, torch.Tensor) for item in items):
257
+ ref = next(item for item in items if isinstance(item, torch.Tensor))
258
+ tensor_items = [
259
+ item
260
+ if isinstance(item, torch.Tensor)
261
+ else torch.as_tensor(item, device=ref.device, dtype=ref.dtype)
262
+ for item in items
263
+ ]
264
+ return torch.stack(tensor_items, dim=axis)
265
+
266
+ return np.stack(items, axis=axis)
267
+
268
+
269
+ class MossVLImagesKwargs(ImagesKwargs):
270
+ min_pixels: Optional[int]
271
+ max_pixels: Optional[int]
272
+ patch_size: Optional[int]
273
+ temporal_patch_size: Optional[int]
274
+ merge_size: Optional[int]
275
+
276
+
277
+
278
+ class MossVLVideosKwargs(VideosKwargs, total=False):
279
+ video_fps: Optional[Union[int, float]]
280
+ min_frames: Optional[int]
281
+ max_frames: Optional[int]
282
+ num_extract_threads: Optional[int]
283
+
284
+
285
+ class MossVLProcessorKwargs(ProcessingKwargs, total=False):
286
+ images_kwargs: MossVLImagesKwargs
287
+ videos_kwargs: MossVLVideosKwargs
288
+ # _defaults = {
289
+ # "text_kwargs": {
290
+ # "padding": True, # 👈 启用 padding
291
+ # "padding_side": "left", # 👈 左 padding
292
+ # "pad_to_multiple_of": 8, # 👈 pad 到 8 的倍数
293
+ # "return_token_type_ids": False,
294
+ # "return_mm_token_type_ids": False,
295
+ # },
296
+ # "videos_kwargs": {"return_metadata": True},
297
+ # }
298
+ _defaults = {
299
+ "text_kwargs": {
300
+ "padding": False,
301
+ "return_token_type_ids": False,
302
+ "return_mm_token_type_ids": False,
303
+ },
304
+ "videos_kwargs": {"return_metadata": True},
305
+ }
306
+
307
+ class MossVLProcessor(ProcessorMixin):
308
+ r"""
309
+ Constructs a Moss-VL processor which wraps a Qwen2VL image processor, Moss-VL video processor and a Qwen2 tokenizer
310
+ into a single processor.
311
+
312
+ [`MossVLProcessor`] offers all the functionalities of [`Qwen2VLImageProcessor`], [`MossVLVideoProcessor`] and [`Qwen2TokenizerFast`].
313
+ See the [`~MossVLProcessor.__call__`] and [`~MossVLProcessor.decode`] for more information.
314
+
315
+ Args:
316
+ image_processor ([`Qwen2VLImageProcessor`], *optional*):
317
+ The image processor is a required input.
318
+ tokenizer ([`Qwen2TokenizerFast`], *optional*):
319
+ The tokenizer is a required input.
320
+ video_processor ([`MossVLVideoProcessor`], *optional*):
321
+ The video processor is a required input.
322
+ chat_template (`str`, *optional*): A Jinja template which will be used to convert lists of messages
323
+ in a chat into a tokenizable string.
324
+ """
325
+
326
+ attributes = ["image_processor", "tokenizer", "video_processor"]
327
+ image_processor_class = "AutoImageProcessor"
328
+ video_processor_class = "AutoVideoProcessor"
329
+ tokenizer_class = ("Qwen2Tokenizer", "Qwen2TokenizerFast")
330
+
331
+ def __init__(
332
+ self,
333
+ image_processor=None,
334
+ tokenizer=None,
335
+ video_processor=None,
336
+ chat_template=None,
337
+ **kwargs
338
+ ):
339
+ super().__init__(image_processor, tokenizer, video_processor, chat_template=chat_template)
340
+
341
+
342
+ self.image_token = "<|image_pad|>" if not hasattr(tokenizer, "image_token") else tokenizer.image_token
343
+ self.video_token = "<|video_pad|>" if not hasattr(tokenizer, "video_token") else tokenizer.video_token
344
+
345
+
346
+ self.image_token_id = (
347
+ tokenizer.image_token_id
348
+ if getattr(tokenizer, "image_token_id", None)
349
+ else tokenizer.convert_tokens_to_ids(self.image_token)
350
+ )
351
+ self.video_token_id = (
352
+ tokenizer.video_token_id
353
+ if getattr(tokenizer, "video_token_id", None)
354
+ else tokenizer.convert_tokens_to_ids(self.video_token)
355
+ )
356
+
357
+ self.vision_start_token = (
358
+ "<|vision_start|>" if not hasattr(tokenizer, "vision_start_token") else tokenizer.vision_start_token
359
+ )
360
+ self.vision_end_token = (
361
+ "<|vision_end|>" if not hasattr(tokenizer, "vision_end_token") else tokenizer.vision_end_token
362
+ )
363
+
364
+ # Placeholders used in input text
365
+ self.image_placeholder = "<|image|>"
366
+ self.video_placeholder = "<|video|>"
367
+
368
+ self.time_start_token = "<|time_start|>"
369
+ self.time_end_token = "<|time_end|>"
370
+
371
+ # EOS token for labels generation (assistant's response should end with this)
372
+ self.im_end_token = "<|im_end|>"
373
+ self.im_end_token_id = tokenizer.convert_tokens_to_ids(self.im_end_token)
374
+
375
+ # Vision-related token ids (all should be masked in labels)
376
+ self.vision_start_token_id = tokenizer.convert_tokens_to_ids(self.vision_start_token)
377
+ self.vision_end_token_id = tokenizer.convert_tokens_to_ids(self.vision_end_token)
378
+
379
+ # Token ids that should always be masked in labels (e.g. <|image_pad|>)
380
+ self.mask_token_ids = {self.image_token_id}
381
+
382
+ def __call__(
383
+ self,
384
+ text: Union[TextInput, PreTokenizedInput, List[TextInput], List[PreTokenizedInput]] = None,
385
+ images: ImageInput = None,
386
+ videos: Union[str, Dict[str, Any], List[Union[str, Dict[str, Any]]]] = None,
387
+ labels_spans: Optional[Union[List[tuple], List[List[tuple]]]] = None,
388
+ ignore_index: int = -100,
389
+ **kwargs: Unpack[MossVLProcessorKwargs],
390
+ ) -> BatchFeature:
391
+ """
392
+ Main method to prepare for the model one or several sequences(s) and image(s)/video(s).
393
+
394
+ Args:
395
+ text (`str`, `list[str]`, `list[list[str]]`):
396
+ The sequence or batch of sequences to be encoded.
397
+ images (`PIL.Image.Image`, `np.ndarray`, `torch.Tensor`, `list[PIL.Image.Image]`, `list[np.ndarray]`, `list[torch.Tensor]`):
398
+ The image or batch of images to be prepared.
399
+ videos (`str`, `Dict`, `list[str]`, `list[Dict]`):
400
+ The video or batch of videos to be prepared. Each video can be:
401
+ - A string path to a video file
402
+ - A dict with keys:
403
+ - "video_path": str, path to the video file
404
+ - "segments": list of segments, where each segment is:
405
+ - [start, end]: a time segment (left-closed, right-open interval in seconds)
406
+ - [time]: a single frame at the specified time (in seconds)
407
+ The number of segments should match the number of video placeholders in the text.
408
+ labels_spans (`list[list[int]]`, `list[list[list[int]]]`, *optional*):
409
+ Character-level spans indicating assistant regions in original text.
410
+ Each span is a [start, end] list with inclusive start and exclusive end.
411
+ Example: [[10, 50], [100, 150]] means characters [10:50) and [100:150) are assistant.
412
+ Note: Use list (not tuple) for spans as they will be modified in place during processing.
413
+ When provided, the processor will generate `labels` in the output, where:
414
+ - Non-assistant tokens have value `ignore_index` (-100 by default)
415
+ - Image tokens always have value `ignore_index` even in assistant part
416
+ - Other assistant tokens have their token id as label
417
+ ignore_index (`int`, *optional*, defaults to -100):
418
+ Value for masked positions in labels.
419
+ return_tensors (`str` or [`~utils.TensorType`], *optional*):
420
+ If set, will return tensors of a particular framework. Acceptable values are:
421
+ - `'tf'`: Return TensorFlow `tf.constant` objects.
422
+ - `'pt'`: Return PyTorch `torch.Tensor` objects.
423
+ - `'np'`: Return NumPy `np.ndarray` objects.
424
+ - `'jax'`: Return JAX `jnp.ndarray` objects.
425
+
426
+
427
+ Returns:
428
+ [`BatchFeature`]: A [`BatchFeature`] with the following fields:
429
+ - **input_ids** -- List of token ids to be fed to a model.
430
+ - **attention_mask** -- List of indices specifying which tokens should be attended to by the model.
431
+ - **pixel_values** -- Pixel values to be fed to a model (concatenation of images and videos).
432
+ - **grid_thw** -- List of grid sizes (t, h, w) for each media item.
433
+ - **media_nums_per_sample** -- List of number of media items per sample.
434
+ - **labels** -- (Optional) Labels for training, only present when `labels_spans` is provided.
435
+ """
436
+ # Merge kwargs with defaults
437
+ output_kwargs = self._merge_kwargs(
438
+ MossVLProcessorKwargs,
439
+ tokenizer_init_kwargs=self.tokenizer.init_kwargs,
440
+ **kwargs,
441
+ )
442
+
443
+ # Step 1: Process images if provided
444
+ if images is not None:
445
+ images_kwargs = output_kwargs["images_kwargs"].copy()
446
+ images_kwargs["return_tensors"] = None
447
+ image_inputs = self.image_processor(images=images, **images_kwargs)
448
+ image_grid_thw = image_inputs["image_grid_thw"]
449
+ else:
450
+ image_inputs = {}
451
+ image_grid_thw = None
452
+
453
+ # Step 2: Process videos if provided
454
+ if videos is not None:
455
+ videos_kwargs = output_kwargs["videos_kwargs"].copy()
456
+ videos_kwargs["return_tensors"] = None
457
+ videos_inputs = self.video_processor(videos=videos, **videos_kwargs)
458
+ video_grid_thw = videos_inputs["video_grid_thw"]
459
+ # If user has not requested video metadata, pop it
460
+ if "return_metadata" not in kwargs:
461
+ video_metadata = videos_inputs.pop("video_metadata")
462
+ else:
463
+ video_metadata = videos_inputs["video_metadata"]
464
+ else:
465
+ videos_inputs = {}
466
+ video_grid_thw = None
467
+ video_metadata = None
468
+
469
+ # Step 3: Process text with placeholder replacement
470
+ if text is None or (isinstance(text, str) and len(text.strip()) == 0):
471
+ raise ValueError("Text input is required for MossVL processor and cannot be empty.")
472
+
473
+ if not isinstance(text, list):
474
+ text = [text]
475
+
476
+ text = text.copy() # Copy to avoid in-place modifications
477
+
478
+ # Prepare labels_spans if provided
479
+ # labels_spans format: List[List[List[int]]] - batch of samples, each sample has multiple spans
480
+ # Each span is [start, end] (list, not tuple) so it can be modified in place
481
+ should_create_labels = labels_spans is not None
482
+ if should_create_labels:
483
+ # Ensure batch format: convert single sample spans to batch format
484
+ # Single sample: [[start, end], [start, end], ...]
485
+ # Batch: [[[start, end], ...], [[start, end], ...], ...]
486
+ if labels_spans and isinstance(labels_spans[0], list) and len(labels_spans[0]) == 2 and isinstance(labels_spans[0][0], int):
487
+ labels_spans = [labels_spans]
488
+
489
+ # Step 3.0-pre: Check if we need to reorder (when both images and videos exist)
490
+ # If only one media type exists, we can skip the expensive split+reorder+concat
491
+ has_images = images is not None and "pixel_values" in image_inputs
492
+ has_videos = videos is not None and "pixel_values_videos" in videos_inputs
493
+ needs_reorder = has_images and has_videos
494
+
495
+ image_pixel_values_list = []
496
+ video_pixel_values_list = []
497
+
498
+ # Step 3.0: Record the order of media in original text (before replacement)
499
+ # This will be used later to correctly order pixel_values and grid_thw
500
+ media_order_per_sample = []
501
+ for i in range(len(text)):
502
+ media_order = []
503
+ temp_text = text[i]
504
+ pos = 0
505
+ while pos < len(temp_text):
506
+ img_pos = temp_text.find(self.image_placeholder, pos)
507
+ vid_pos = temp_text.find(self.video_placeholder, pos)
508
+
509
+ if img_pos == -1 and vid_pos == -1:
510
+ break
511
+
512
+ if img_pos != -1 and (vid_pos == -1 or img_pos < vid_pos):
513
+ media_order.append(("image", img_pos))
514
+ pos = img_pos + len(self.image_placeholder)
515
+ elif vid_pos != -1:
516
+ media_order.append(("video", vid_pos))
517
+ pos = vid_pos + len(self.video_placeholder)
518
+
519
+ media_order_per_sample.append(media_order)
520
+
521
+ # Step 3.0.1: Check if any sample has no media (empty samples need blank image)
522
+ # If there are empty samples, we need to enter slow path to handle them properly
523
+ has_empty_samples = any(len(order) == 0 for order in media_order_per_sample)
524
+ if has_empty_samples:
525
+ needs_reorder = True
526
+
527
+ # Split pixel values for reordering if needed
528
+ if needs_reorder:
529
+ if has_images:
530
+ flat_pixel_values = image_inputs["pixel_values"]
531
+ flat_grid_thw = image_inputs["image_grid_thw"]
532
+ # grid_thw is (t, h, w), num_patches = t * h * w
533
+ patch_counts = [int(np.prod(_to_numpy(grid))) for grid in flat_grid_thw]
534
+ if len(patch_counts) == 1:
535
+ # Single image case: no need to split
536
+ image_pixel_values_list = [flat_pixel_values]
537
+ elif len(patch_counts) > 1:
538
+ # Multiple images: split by cumulative counts
539
+ split_indices = np.cumsum(patch_counts)[:-1]
540
+ image_pixel_values_list = _split_array_or_tensor(
541
+ flat_pixel_values, split_indices
542
+ )
543
+
544
+ if has_videos:
545
+ flat_video_values = videos_inputs["pixel_values_videos"]
546
+ flat_video_grid = videos_inputs["video_grid_thw"]
547
+ video_patch_counts = [int(np.prod(_to_numpy(grid))) for grid in flat_video_grid]
548
+ if len(video_patch_counts) == 1:
549
+ # Single video case: no need to split
550
+ video_pixel_values_list = [flat_video_values]
551
+ elif len(video_patch_counts) > 1:
552
+ # Multiple videos: split by cumulative counts
553
+ split_indices = np.cumsum(video_patch_counts)[:-1]
554
+ video_pixel_values_list = _split_array_or_tensor(
555
+ flat_video_values, split_indices
556
+ )
557
+
558
+ # Step 3.1: Replace placeholders (simple replacement, no expansion yet)
559
+ # In MossVL, one image placeholder = one image token
560
+ # One video placeholder = one video token (will be expanded later)
561
+ for i in range(len(text)):
562
+ if should_create_labels:
563
+ # Replace and update spans for image placeholders
564
+ text[i], labels_spans[i] = self._replace_and_update_spans(
565
+ text[i], self.image_placeholder, self.image_token, labels_spans[i]
566
+ )
567
+ # Replace and update spans for video placeholders
568
+ text[i], labels_spans[i] = self._replace_and_update_spans(
569
+ text[i], self.video_placeholder, self.video_token, labels_spans[i]
570
+ )
571
+ else:
572
+ text[i] = text[i].replace(self.image_placeholder, self.image_token)
573
+ text[i] = text[i].replace(self.video_placeholder, self.video_token)
574
+
575
+ # Step 3.2: Validate token counts
576
+ n_images_in_text = [t.count(self.image_token) for t in text]
577
+ n_videos_in_text = [t.count(self.video_token) for t in text]
578
+
579
+ # Count placeholders in text
580
+ total_images_in_text = sum(n_images_in_text)
581
+ total_videos_in_text = sum(n_videos_in_text)
582
+
583
+ # Count actual images and videos provided
584
+ total_images_provided = len(image_grid_thw) if image_grid_thw is not None else 0
585
+ total_videos_provided = len(video_grid_thw) if video_grid_thw is not None else 0
586
+
587
+ # Validate image counts
588
+ if total_images_in_text != total_images_provided:
589
+ raise ValueError(
590
+ "Number of image tokens does not match number of images provided. "
591
+ f"Found {total_images_in_text} image tokens in text and {total_images_provided} images."
592
+ )
593
+
594
+ # Validate video counts
595
+ if total_videos_in_text != total_videos_provided:
596
+ raise ValueError(
597
+ "Number of video tokens does not match number of videos provided. "
598
+ f"Found {total_videos_in_text} video tokens in text and {total_videos_provided} videos."
599
+ )
600
+
601
+ # Step 3.3: Expand video tokens with timestamps
602
+ # Now expand each video token to multiple tokens (one per frame) with timestamps
603
+ if video_grid_thw is not None:
604
+ index = 0
605
+ for i in range(len(text)):
606
+ while self.video_token in text[i]:
607
+ metadata = video_metadata[index]
608
+ if metadata.fps is None:
609
+ logger.warning_once(
610
+ "MossVL requires frame timestamps to construct prompts, but the `fps` of the input video could not be inferred. "
611
+ "Probably `video_metadata` was missing from inputs and you passed pre-sampled frames. "
612
+ "Defaulting to `fps=24`. Please provide `video_metadata` for more accurate results."
613
+ )
614
+ metadata.fps = 24 if metadata.fps is None else metadata.fps
615
+
616
+ # Calculate timestamps
617
+ # Use actual_timestamps if available (for segments), otherwise use frames_indices
618
+ actual_timestamps = getattr(metadata, 'actual_timestamps', None)
619
+ curr_timestamp = self._calculate_timestamps(
620
+ metadata.frames_indices,
621
+ metadata.total_num_frames,
622
+ metadata.fps,
623
+ metadata.duration,
624
+ self.video_processor.temporal_patch_size,
625
+ actual_timestamps=actual_timestamps,
626
+ )
627
+
628
+ # Build video placeholder: one video token per frame with timestamp
629
+ # video_grid_thw[index][0] is the temporal dimension (number of frames after merging)
630
+
631
+ video_tokens = []
632
+ for frame_idx in range(video_grid_thw[index][0]):
633
+ curr_time = curr_timestamp[frame_idx]
634
+ # Format: <|time_start|>X.X seconds<|time_end|><|image_pad|>
635
+ video_tokens.append(
636
+ f"{self.time_start_token}{curr_time:.1f} seconds{self.time_end_token}{self.image_token}"
637
+ )
638
+
639
+ # Wrap the entire video sequence with vision_start and vision_end tokens
640
+ video_placeholder = f"{self.vision_start_token}{''.join(video_tokens)}{self.vision_end_token}"
641
+
642
+ # Replace the video token with expanded sequence and update spans if needed
643
+ if should_create_labels:
644
+ text[i], labels_spans[i] = self._replace_and_update_spans(
645
+ text[i], self.video_token, video_placeholder, labels_spans[i], replace_count=1
646
+ )
647
+ else:
648
+ text[i] = text[i].replace(self.video_token, video_placeholder, 1)
649
+ index += 1
650
+
651
+
652
+
653
+ # Step 4: Tokenize text
654
+ return_tensors = output_kwargs["text_kwargs"].pop("return_tensors", None)
655
+ return_mm_token_type_ids = output_kwargs["text_kwargs"].pop("return_mm_token_type_ids", None)
656
+
657
+ # Request offset_mapping if we need to create labels
658
+ if should_create_labels:
659
+ output_kwargs["text_kwargs"]["return_offsets_mapping"] = True
660
+
661
+ text_inputs = self.tokenizer(text, **output_kwargs["text_kwargs"])
662
+
663
+ # ignore check_special_mm_tokens nums in test and input ids.
664
+ # self._check_special_mm_tokens(text, text_inputs, modalities=["image", "video"])
665
+
666
+ # Create labels if labels_spans was provided
667
+ if should_create_labels:
668
+ offset_mapping = text_inputs.pop("offset_mapping")
669
+ labels = self._create_labels_from_spans(
670
+ text_inputs["input_ids"],
671
+ offset_mapping,
672
+ labels_spans,
673
+ ignore_index
674
+ )
675
+
676
+ if return_mm_token_type_ids:
677
+ array_ids = np.array(text_inputs["input_ids"])
678
+ mm_token_type_ids = np.zeros_like(text_inputs["input_ids"])
679
+ mm_token_type_ids[array_ids == self.image_token_id] = 1
680
+ text_inputs["mm_token_type_ids"] = mm_token_type_ids.tolist()
681
+
682
+ # Step 5: Concatenate pixel_values and grid_thw in sequence order
683
+ # Prepare output
684
+ output_data = {**text_inputs}
685
+
686
+ if not needs_reorder:
687
+ # Fast path: only one media type, no reordering needed
688
+ final_pixel_values = []
689
+ final_grid_thw = []
690
+
691
+ if has_images:
692
+ final_pixel_values.append(image_inputs["pixel_values"])
693
+ final_grid_thw.extend(image_grid_thw)
694
+
695
+ if has_videos:
696
+ final_pixel_values.append(videos_inputs["pixel_values_videos"])
697
+ final_grid_thw.extend(video_grid_thw)
698
+
699
+ if final_pixel_values:
700
+ output_data["pixel_values"] = np.concatenate(final_pixel_values, axis=0) if len(final_pixel_values) > 1 else final_pixel_values[0]
701
+
702
+ if final_grid_thw:
703
+ output_data["grid_thw"] = np.stack(final_grid_thw, axis=0)
704
+
705
+ # Calculate media_nums_per_sample
706
+ media_nums_per_sample = []
707
+ for batch_idx in range(len(text)):
708
+ media_order = media_order_per_sample[batch_idx]
709
+ media_nums_per_sample.append(len(media_order) if len(media_order) > 0 else 1)
710
+
711
+ # Don't add media_nums_per_sample to output_data yet
712
+ # Will add it after BatchFeature to keep it as list
713
+
714
+ else:
715
+ # Slow path: both images and videos exist, need reordering
716
+ final_pixel_values = []
717
+ final_grid_thw = []
718
+ media_nums_per_sample = []
719
+
720
+ # Global indices to track position in flattened image/video arrays
721
+ global_image_idx = 0
722
+ global_video_idx = 0
723
+
724
+ for batch_idx in range(len(text)):
725
+ # Use the recorded media order from Step 3.0
726
+ media_order = media_order_per_sample[batch_idx]
727
+
728
+ if len(media_order) == 0:
729
+ # If no media provided for this sample, add a blank image
730
+ media_nums_per_sample.append(1)
731
+ min_pixels = 128 * 128
732
+ patch_size = getattr(self.image_processor, "patch_size", None) or 16
733
+ temporal_patch_size = getattr(self.image_processor, "temporal_patch_size", None) or 1
734
+ merge_size = getattr(self.image_processor, "merge_size", None) or 2
735
+
736
+ factor = patch_size * merge_size
737
+ side = int(np.ceil(np.sqrt(min_pixels) / factor) * factor)
738
+ grid_h = side // patch_size
739
+ grid_w = side // patch_size
740
+ grid_t = 1
741
+
742
+ # Channel = 3 (RGB)
743
+ channel = 3
744
+ dim = channel * temporal_patch_size * patch_size * patch_size
745
+ num_patches = grid_t * grid_h * grid_w
746
+
747
+ blank_pixel_values = np.zeros((num_patches, dim), dtype=np.float32)
748
+ blank_grid_thw = np.array([grid_t, grid_h, grid_w], dtype=np.int64)
749
+
750
+ final_pixel_values.append(blank_pixel_values)
751
+ final_grid_thw.append(blank_grid_thw)
752
+ else:
753
+ media_nums_per_sample.append(len(media_order))
754
+
755
+ # Collect media data according to the recorded order
756
+ for media_type, _ in media_order:
757
+ if media_type == "image" and image_grid_thw is not None:
758
+ # Get image data
759
+ if image_pixel_values_list:
760
+ final_pixel_values.append(image_pixel_values_list[global_image_idx])
761
+ final_grid_thw.append(image_grid_thw[global_image_idx])
762
+ global_image_idx += 1
763
+ elif media_type == "video" and video_grid_thw is not None:
764
+ # Get video data
765
+ if video_pixel_values_list:
766
+ final_pixel_values.append(video_pixel_values_list[global_video_idx])
767
+ final_grid_thw.append(video_grid_thw[global_video_idx])
768
+ global_video_idx += 1
769
+
770
+ # Concatenate/stack to unified format
771
+ if final_pixel_values:
772
+ output_data["pixel_values"] = _concat_array_or_tensor(
773
+ final_pixel_values, axis=0
774
+ )
775
+
776
+ if final_grid_thw:
777
+ output_data["grid_thw"] = _stack_array_or_tensor(
778
+ final_grid_thw, axis=0
779
+ )
780
+
781
+ # Don't add media_nums_per_sample to output_data yet
782
+ # Will add it after BatchFeature to keep it as list
783
+
784
+ # Create cross_attention_mask using media_nums_per_sample
785
+ if "input_ids" in output_data and "grid_thw" in output_data and media_nums_per_sample:
786
+ cross_attention_mask = self._create_cross_attention_mask(
787
+ output_data["input_ids"],
788
+ output_data["grid_thw"],
789
+ media_nums_per_sample,
790
+ output_data.get("attention_mask", None)
791
+ )
792
+ output_data["cross_attention_mask"] = cross_attention_mask
793
+
794
+ # Add labels to output if created
795
+ if should_create_labels:
796
+ output_data["labels"] = labels
797
+
798
+ # BatchFeature will handle conversion to pt/tf/jax/np based on tensor_type
799
+ batch_feature = BatchFeature(data=output_data, tensor_type=return_tensors)
800
+
801
+ # Add media_nums_per_sample after BatchFeature to keep it as list (not tensor)
802
+ if media_nums_per_sample:
803
+ batch_feature["media_nums_per_sample"] = media_nums_per_sample
804
+
805
+ return batch_feature
806
+
807
+ def _create_cross_attention_mask(self, input_ids, grid_thw, media_nums_per_sample, attention_mask=None):
808
+ """
809
+ Create cross_attention_mask of shape (batch_size, 1, text_len, num_images).
810
+ Video frames are treated as individual images.
811
+ Mask values: True for masked, False for visible.
812
+ Causal masking: text can see images that appear at or before the text position.
813
+
814
+ Args:
815
+ input_ids: List of token ids
816
+ grid_thw: Grid sizes for each media item
817
+ media_nums_per_sample: Number of media items per sample
818
+ attention_mask: Optional attention mask to filter out padding positions
819
+ """
820
+ batch_size = len(input_ids)
821
+ max_text_len = max(len(ids) for ids in input_ids)
822
+
823
+ # Calculate total frames per sample to find max_num_frames
824
+ total_frames_per_sample = []
825
+ media_idx = 0
826
+ for b in range(batch_size):
827
+ num_media = media_nums_per_sample[b]
828
+ if num_media == 0:
829
+ total_frames_per_sample.append(0)
830
+ continue
831
+
832
+ sample_frames = 0
833
+ for _ in range(num_media):
834
+ # grid_thw is (N, 3) where first dim is t (num_frames)
835
+ t = grid_thw[media_idx][0]
836
+ if isinstance(t, torch.Tensor):
837
+ t = int(t.item())
838
+ else:
839
+ t = int(t)
840
+ sample_frames += t
841
+ media_idx += 1
842
+ total_frames_per_sample.append(sample_frames)
843
+
844
+ max_num_frames = max(total_frames_per_sample) if total_frames_per_sample else 0
845
+
846
+ if max_num_frames == 0:
847
+ return None
848
+
849
+ # Vectorized implementation for speed
850
+
851
+ # 1. Pad input_ids to create a tensor
852
+ # We use -1 as pad value since token ids are positive
853
+ input_ids_tensor = torch.full((batch_size, max_text_len), -1, dtype=torch.long)
854
+ for b, ids in enumerate(input_ids):
855
+ l = len(ids)
856
+ input_ids_tensor[b, :l] = torch.tensor(ids, dtype=torch.long)
857
+
858
+ # 2. Identify image tokens
859
+ is_image_token = (input_ids_tensor == self.image_token_id)
860
+
861
+ # 3. Compute cumulative image tokens (how many image tokens appeared up to position t)
862
+ # shape: (batch_size, text_len)
863
+ cum_image_tokens = is_image_token.cumsum(dim=1)
864
+
865
+ # 4. Create frame indices
866
+ # shape: (1, 1, max_num_frames)
867
+ frame_indices = torch.arange(max_num_frames).reshape(1, 1, -1)
868
+
869
+ # 5. Determine visibility based on causal relationship
870
+ # Text at `t` sees frame `i` if `cum_image_tokens[t] > i`
871
+ # Because if frame `i` is the (i+1)-th image token, it becomes visible when count reaches i+1
872
+ # shape: (batch_size, text_len, max_num_frames)
873
+ visible_mask = cum_image_tokens.unsqueeze(-1) > frame_indices
874
+
875
+ # 6. Apply attention_mask if provided
876
+ if attention_mask is not None:
877
+ # Convert to tensor if needed
878
+ if isinstance(attention_mask, torch.Tensor):
879
+ attn_mask_tensor = attention_mask
880
+ else:
881
+ # List of lists
882
+ attn_mask_tensor = torch.zeros((batch_size, max_text_len), dtype=torch.long)
883
+ for b, mask_row in enumerate(attention_mask):
884
+ l = len(mask_row)
885
+ attn_mask_tensor[b, :l] = torch.tensor(mask_row, dtype=torch.long)
886
+
887
+ # shape: (batch_size, text_len, 1)
888
+ valid_text = (attn_mask_tensor.unsqueeze(-1) == 1)
889
+ visible_mask = visible_mask & valid_text
890
+
891
+ # 7. Mask out frames that don't exist for a sample
892
+ # shape: (batch_size, 1, 1)
893
+ total_frames_tensor = torch.tensor(total_frames_per_sample).reshape(batch_size, 1, 1)
894
+ # shape: (batch_size, 1, max_num_frames)
895
+ valid_frames = frame_indices < total_frames_tensor
896
+
897
+ visible_mask = visible_mask & valid_frames
898
+
899
+ # 8. Create final mask (True for masked, False for visible)
900
+ mask = ~visible_mask
901
+
902
+ # 9. Add channel dimension: (batch_size, 1, text_len, max_num_frames)
903
+ mask = mask.unsqueeze(1)
904
+
905
+ return mask
906
+
907
+ def _replace_and_update_spans(
908
+ self,
909
+ text: str,
910
+ old_str: str,
911
+ new_str: str,
912
+ spans: List[List[int]],
913
+ replace_count: int = -1
914
+ ) -> tuple:
915
+ """
916
+ Replace occurrences of old_str with new_str and update spans accordingly.
917
+
918
+ Args:
919
+ text: The text to perform replacement on
920
+ old_str: String to be replaced
921
+ new_str: String to replace with
922
+ spans: List of [start, end] spans to update (modified in place)
923
+ replace_count: Maximum number of replacements (-1 for all)
924
+
925
+ Returns:
926
+ Tuple of (new_text, updated_spans)
927
+ """
928
+ delta = len(new_str) - len(old_str)
929
+ result_text = text
930
+ count = 0
931
+ search_start = 0
932
+
933
+ while True:
934
+ pos = result_text.find(old_str, search_start)
935
+ if pos == -1:
936
+ break
937
+ if replace_count != -1 and count >= replace_count:
938
+ break
939
+
940
+ # Update all spans that come after this position
941
+ for span in spans:
942
+ if span[0] > pos:
943
+ # Span starts after replacement point
944
+ span[0] += delta
945
+ span[1] += delta
946
+ elif span[1] > pos:
947
+ # Span ends after replacement point (spans the replacement)
948
+ span[1] += delta
949
+
950
+ # Perform the replacement
951
+ result_text = result_text[:pos] + new_str + result_text[pos + len(old_str):]
952
+ search_start = pos + len(new_str)
953
+ count += 1
954
+
955
+ return result_text, spans
956
+
957
+ def _create_labels_from_spans(
958
+ self,
959
+ input_ids: List[List[int]],
960
+ offset_mapping: List[List[tuple]],
961
+ labels_spans: List[List[List[int]]],
962
+ ignore_index: int = -100,
963
+ mask_token_ids: Optional[set] = None
964
+ ) -> List[List[int]]:
965
+ """
966
+ Create labels from spans and offset_mapping.
967
+
968
+ Args:
969
+ input_ids: Tokenized input ids
970
+ offset_mapping: Character offsets for each token from tokenizer (special tokens included)
971
+ labels_spans: Updated spans indicating assistant regions (after text transformations)
972
+ ignore_index: Value for masked positions
973
+ mask_token_ids: Set of token ids that should always be masked (set to ignore_index)
974
+ in labels, regardless of whether they fall inside a span.
975
+ Defaults to self.mask_token_ids if not provided.
976
+
977
+ Returns:
978
+ labels: List of label ids, same shape as input_ids
979
+
980
+ Note:
981
+ - Tokenizer's offset_mapping already includes correct offsets for special tokens in text
982
+ - Only need to mask tokens inside <|vision_start|>...<|vision_end|>
983
+ - Tokens whose id is in mask_token_ids are always masked
984
+ - All other tokens in spans (including special tokens like <|im_end|>) get labels
985
+ """
986
+ if mask_token_ids is None:
987
+ mask_token_ids = self.mask_token_ids
988
+
989
+ batch_labels = []
990
+
991
+ for batch_idx in range(len(input_ids)):
992
+ ids = input_ids[batch_idx]
993
+ offsets = offset_mapping[batch_idx]
994
+ spans = labels_spans[batch_idx]
995
+
996
+ labels = [ignore_index] * len(ids)
997
+
998
+ # Process each span: find token range and set labels
999
+ for span_start, span_end in spans:
1000
+ in_vision = False
1001
+
1002
+ # Find tokens that overlap with this span
1003
+ for token_idx, (token_id, (char_start, char_end)) in enumerate(zip(ids, offsets)):
1004
+ # Skip tokens completely before this span
1005
+ if char_end <= span_start:
1006
+ continue
1007
+ # Stop when tokens are completely after this span
1008
+ if char_start >= span_end:
1009
+ break
1010
+
1011
+ # Token overlaps with span, process it
1012
+ # Track vision region: <|vision_start|> ... <|vision_end|>
1013
+ if token_id == self.vision_start_token_id:
1014
+ in_vision = True
1015
+ continue
1016
+ if token_id == self.vision_end_token_id:
1017
+ in_vision = False
1018
+ continue
1019
+
1020
+ # Skip tokens inside vision region
1021
+ if in_vision:
1022
+ continue
1023
+
1024
+ # Always mask special tokens that should never have labels
1025
+ if token_id in mask_token_ids:
1026
+ continue
1027
+
1028
+ # Set label for this token
1029
+ labels[token_idx] = token_id
1030
+
1031
+ batch_labels.append(labels)
1032
+
1033
+ return batch_labels
1034
+
1035
+ def _calculate_timestamps(
1036
+ self,
1037
+ frames_indices: Optional[Union[List[int], np.ndarray]],
1038
+ total_num_frames: int,
1039
+ video_fps: float,
1040
+ duration: float,
1041
+ merge_size: int = 1,
1042
+ actual_timestamps: Optional[List[float]] = None
1043
+ ):
1044
+ """
1045
+ Calculate timestamps for video frames.
1046
+
1047
+ Args:
1048
+ frames_indices: Actual frame indices extracted (if available)
1049
+ total_num_frames: Total number of sampled frames
1050
+ video_fps: Video frames per second
1051
+ duration: Video duration in seconds
1052
+ merge_size: Temporal merge size
1053
+ actual_timestamps: Pre-calculated actual timestamps (for segments)
1054
+
1055
+ Returns:
1056
+ List of timestamps (one per merged temporal patch)
1057
+ """
1058
+ # If actual timestamps are provided (from segment), use them directly
1059
+ if actual_timestamps is not None:
1060
+ timestamps = list(actual_timestamps)
1061
+
1062
+ # Pad timestamps to be multiple of merge_size
1063
+ if len(timestamps) % merge_size != 0:
1064
+ timestamps.extend([timestamps[-1]] * (merge_size - len(timestamps) % merge_size))
1065
+
1066
+ # Frames are merged by merge_size, so we average the timestamps within each temporal patch
1067
+ timestamps = [
1068
+ (timestamps[i] + timestamps[i + merge_size - 1]) / 2
1069
+ for i in range(0, len(timestamps), merge_size)
1070
+ ]
1071
+ return timestamps
1072
+
1073
+ # Use frames_indices if available, otherwise generate uniformly sampled indices
1074
+ if frames_indices is not None:
1075
+ if isinstance(frames_indices, np.ndarray):
1076
+ indices = frames_indices.tolist()
1077
+ else:
1078
+ indices = list(frames_indices)
1079
+ else:
1080
+ # Generate uniformly sampled frame indices
1081
+ if total_num_frames <= 1:
1082
+ indices = [0]
1083
+ else:
1084
+ # Uniformly sample frames across the video duration
1085
+ indices = np.linspace(0, duration * video_fps - 1, total_num_frames).astype(np.int32).tolist()
1086
+
1087
+ # Pad indices to be multiple of merge_size
1088
+ if len(indices) % merge_size != 0:
1089
+ indices.extend([indices[-1]] * (merge_size - len(indices) % merge_size))
1090
+
1091
+ # Convert frame indices to timestamps
1092
+ timestamps = [idx / video_fps for idx in indices]
1093
+
1094
+ # Frames are merged by merge_size, so we average the timestamps within each temporal patch
1095
+ timestamps = [
1096
+ (timestamps[i] + timestamps[i + merge_size - 1]) / 2
1097
+ for i in range(0, len(timestamps), merge_size)
1098
+ ]
1099
+ return timestamps
1100
+
1101
+ def batch_decode(self, *args, **kwargs):
1102
+ """
1103
+ This method forwards all its arguments to the tokenizer's batch_decode.
1104
+ Please refer to the docstring of this method for more information.
1105
+ """
1106
+ return self.tokenizer.batch_decode(*args, **kwargs)
1107
+
1108
+ def decode(self, *args, **kwargs):
1109
+ """
1110
+ This method forwards all its arguments to the tokenizer's decode.
1111
+ Please refer to the docstring of this method for more information.
1112
+ """
1113
+ return self.tokenizer.decode(*args, **kwargs)
1114
+
1115
+ def post_process_image_text_to_text(
1116
+ self, generated_outputs, skip_special_tokens=True, clean_up_tokenization_spaces=False, **kwargs
1117
+ ):
1118
+ """
1119
+ Post-process the output of the model to decode the text.
1120
+
1121
+ Args:
1122
+ generated_outputs (`torch.Tensor` or `np.ndarray`):
1123
+ The output of the model `generate` function. The output is expected to be a tensor
1124
+ of shape `(batch_size, sequence_length)` or `(sequence_length,)`.
1125
+ skip_special_tokens (`bool`, *optional*, defaults to `True`):
1126
+ Whether or not to remove special tokens in the output.
1127
+ clean_up_tokenization_spaces (`bool`, *optional*, defaults to `False`):
1128
+ Whether or not to clean up the tokenization spaces.
1129
+ **kwargs:
1130
+ Additional arguments to be passed to the tokenizer's `batch_decode` method.
1131
+
1132
+ Returns:
1133
+ `list[str]`: The decoded text.
1134
+ """
1135
+ return self.tokenizer.batch_decode(
1136
+ generated_outputs,
1137
+ skip_special_tokens=skip_special_tokens,
1138
+ clean_up_tokenization_spaces=clean_up_tokenization_spaces,
1139
+ **kwargs,
1140
+ )
1141
+
1142
+
1143
+ __all__ = ["MossVLProcessor", "MossVLImageProcessorFast"]
tokenizer.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e7bbd0f9784004df51aca562befc3c7a8f294b4045aa8685536c35804c9aa493
3
+ size 11423411
tokenizer_config.json ADDED
@@ -0,0 +1,276 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_bos_token": false,
3
+ "add_prefix_space": false,
4
+ "added_tokens_decoder": {
5
+ "151643": {
6
+ "content": "<|endoftext|>",
7
+ "lstrip": false,
8
+ "normalized": false,
9
+ "rstrip": false,
10
+ "single_word": false,
11
+ "special": true
12
+ },
13
+ "151644": {
14
+ "content": "<|im_start|>",
15
+ "lstrip": false,
16
+ "normalized": false,
17
+ "rstrip": false,
18
+ "single_word": false,
19
+ "special": true
20
+ },
21
+ "151645": {
22
+ "content": "<|im_end|>",
23
+ "lstrip": false,
24
+ "normalized": false,
25
+ "rstrip": false,
26
+ "single_word": false,
27
+ "special": true
28
+ },
29
+ "151646": {
30
+ "content": "<|object_ref_start|>",
31
+ "lstrip": false,
32
+ "normalized": false,
33
+ "rstrip": false,
34
+ "single_word": false,
35
+ "special": true
36
+ },
37
+ "151647": {
38
+ "content": "<|object_ref_end|>",
39
+ "lstrip": false,
40
+ "normalized": false,
41
+ "rstrip": false,
42
+ "single_word": false,
43
+ "special": true
44
+ },
45
+ "151648": {
46
+ "content": "<|box_start|>",
47
+ "lstrip": false,
48
+ "normalized": false,
49
+ "rstrip": false,
50
+ "single_word": false,
51
+ "special": true
52
+ },
53
+ "151649": {
54
+ "content": "<|box_end|>",
55
+ "lstrip": false,
56
+ "normalized": false,
57
+ "rstrip": false,
58
+ "single_word": false,
59
+ "special": true
60
+ },
61
+ "151650": {
62
+ "content": "<|quad_start|>",
63
+ "lstrip": false,
64
+ "normalized": false,
65
+ "rstrip": false,
66
+ "single_word": false,
67
+ "special": true
68
+ },
69
+ "151651": {
70
+ "content": "<|quad_end|>",
71
+ "lstrip": false,
72
+ "normalized": false,
73
+ "rstrip": false,
74
+ "single_word": false,
75
+ "special": true
76
+ },
77
+ "151652": {
78
+ "content": "<|vision_start|>",
79
+ "lstrip": false,
80
+ "normalized": false,
81
+ "rstrip": false,
82
+ "single_word": false,
83
+ "special": true
84
+ },
85
+ "151653": {
86
+ "content": "<|vision_end|>",
87
+ "lstrip": false,
88
+ "normalized": false,
89
+ "rstrip": false,
90
+ "single_word": false,
91
+ "special": true
92
+ },
93
+ "151654": {
94
+ "content": "<|vision_pad|>",
95
+ "lstrip": false,
96
+ "normalized": false,
97
+ "rstrip": false,
98
+ "single_word": false,
99
+ "special": true
100
+ },
101
+ "151655": {
102
+ "content": "<|image_pad|>",
103
+ "lstrip": false,
104
+ "normalized": false,
105
+ "rstrip": false,
106
+ "single_word": false,
107
+ "special": true
108
+ },
109
+ "151656": {
110
+ "content": "<|video_pad|>",
111
+ "lstrip": false,
112
+ "normalized": false,
113
+ "rstrip": false,
114
+ "single_word": false,
115
+ "special": true
116
+ },
117
+ "151657": {
118
+ "content": "<tool_call>",
119
+ "lstrip": false,
120
+ "normalized": false,
121
+ "rstrip": false,
122
+ "single_word": false,
123
+ "special": false
124
+ },
125
+ "151658": {
126
+ "content": "</tool_call>",
127
+ "lstrip": false,
128
+ "normalized": false,
129
+ "rstrip": false,
130
+ "single_word": false,
131
+ "special": false
132
+ },
133
+ "151659": {
134
+ "content": "<|fim_prefix|>",
135
+ "lstrip": false,
136
+ "normalized": false,
137
+ "rstrip": false,
138
+ "single_word": false,
139
+ "special": false
140
+ },
141
+ "151660": {
142
+ "content": "<|fim_middle|>",
143
+ "lstrip": false,
144
+ "normalized": false,
145
+ "rstrip": false,
146
+ "single_word": false,
147
+ "special": false
148
+ },
149
+ "151661": {
150
+ "content": "<|fim_suffix|>",
151
+ "lstrip": false,
152
+ "normalized": false,
153
+ "rstrip": false,
154
+ "single_word": false,
155
+ "special": false
156
+ },
157
+ "151662": {
158
+ "content": "<|fim_pad|>",
159
+ "lstrip": false,
160
+ "normalized": false,
161
+ "rstrip": false,
162
+ "single_word": false,
163
+ "special": false
164
+ },
165
+ "151663": {
166
+ "content": "<|repo_name|>",
167
+ "lstrip": false,
168
+ "normalized": false,
169
+ "rstrip": false,
170
+ "single_word": false,
171
+ "special": false
172
+ },
173
+ "151664": {
174
+ "content": "<|file_sep|>",
175
+ "lstrip": false,
176
+ "normalized": false,
177
+ "rstrip": false,
178
+ "single_word": false,
179
+ "special": false
180
+ },
181
+ "151665": {
182
+ "content": "<tool_response>",
183
+ "lstrip": false,
184
+ "normalized": false,
185
+ "rstrip": false,
186
+ "single_word": false,
187
+ "special": false
188
+ },
189
+ "151666": {
190
+ "content": "</tool_response>",
191
+ "lstrip": false,
192
+ "normalized": false,
193
+ "rstrip": false,
194
+ "single_word": false,
195
+ "special": false
196
+ },
197
+ "151667": {
198
+ "content": "<think>",
199
+ "lstrip": false,
200
+ "normalized": false,
201
+ "rstrip": false,
202
+ "single_word": false,
203
+ "special": false
204
+ },
205
+ "151668": {
206
+ "content": "</think>",
207
+ "lstrip": false,
208
+ "normalized": false,
209
+ "rstrip": false,
210
+ "single_word": false,
211
+ "special": false
212
+ },
213
+ "151669": {
214
+ "content": "<|time_start|>",
215
+ "lstrip": false,
216
+ "normalized": false,
217
+ "rstrip": false,
218
+ "single_word": false,
219
+ "special": true
220
+ },
221
+ "151670": {
222
+ "content": "<|time_end|>",
223
+ "lstrip": false,
224
+ "normalized": false,
225
+ "rstrip": false,
226
+ "single_word": false,
227
+ "special": true
228
+ },
229
+ "151671": {
230
+ "content": "<|silence|>",
231
+ "lstrip": false,
232
+ "normalized": false,
233
+ "rstrip": false,
234
+ "single_word": false,
235
+ "special": true
236
+ },
237
+ "151672": {
238
+ "content": "<|response|>",
239
+ "lstrip": false,
240
+ "normalized": false,
241
+ "rstrip": false,
242
+ "single_word": false,
243
+ "special": true
244
+ }
245
+ },
246
+ "additional_special_tokens": [
247
+ "<|im_start|>",
248
+ "<|im_end|>",
249
+ "<|object_ref_start|>",
250
+ "<|object_ref_end|>",
251
+ "<|box_start|>",
252
+ "<|box_end|>",
253
+ "<|quad_start|>",
254
+ "<|quad_end|>",
255
+ "<|vision_start|>",
256
+ "<|vision_end|>",
257
+ "<|vision_pad|>",
258
+ "<|image_pad|>",
259
+ "<|video_pad|>",
260
+ "<|time_start|>",
261
+ "<|time_end|>",
262
+ "<|silence|>",
263
+ "<|response|>"
264
+ ],
265
+ "bos_token": null,
266
+ "clean_up_tokenization_spaces": false,
267
+ "eos_token": "<|im_end|>",
268
+ "errors": "replace",
269
+ "extra_special_tokens": {},
270
+ "model_max_length": 262144,
271
+ "pad_token": "<|endoftext|>",
272
+ "split_special_tokens": false,
273
+ "tokenizer_class": "Qwen2Tokenizer",
274
+ "unk_token": null,
275
+ "chat_template": "{%- if tools %}\n {{- '<|im_start|>system\\n' }}\n {%- if messages[0].role == 'system' %}\n {%- if messages[0].content is string %}\n {{- messages[0].content }}\n {%- else %}\n {%- for content in messages[0].content %}\n {%- if 'text' in content %}\n {{- content.text }}\n {%- endif %}\n {%- endfor %}\n {%- endif %}\n {{- '\\n\\n' }}\n {%- endif %}\n {{- \"# Tools\\n\\nYou may call one or more functions to assist with the user query.\\n\\nYou are provided with function signatures within <tools></tools> XML tags:\\n<tools>\" }}\n {%- for tool in tools %}\n {{- \"\\n\" }}\n {{- tool | tojson }}\n {%- endfor %}\n {{- \"\\n</tools>\\n\\nFor each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags:\\n<tool_call>\\n{\\\"name\\\": <function-name>, \\\"arguments\\\": <args-json-object>}\\n</tool_call><|im_end|>\\n\" }}\n{%- else %}\n {%- if messages[0].role == 'system' %}\n {{- '<|im_start|>system\\n' }}\n {%- if messages[0].content is string %}\n {{- messages[0].content }}\n {%- else %}\n {%- for content in messages[0].content %}\n {%- if 'text' in content %}\n {{- content.text }}\n {%- endif %}\n {%- endfor %}\n {%- endif %}\n {{- '<|im_end|>\\n' }}\n {%- endif %}\n{%- endif %}\n{%- set image_count = namespace(value=0) %}\n{%- set video_count = namespace(value=0) %}\n{%- for message in messages %}\n {%- if message.role == \"user\" %}\n {{- '<|im_start|>' + message.role + '\\n' }}\n {%- if message.content is string %}\n {{- message.content }}\n {%- else %}\n {%- for content in message.content %}\n {%- if content.type == 'image' or 'image' in content or 'image_url' in content %}\n {%- set image_count.value = image_count.value + 1 %}\n {%- if add_vision_id %}Picture {{ image_count.value }}: {% endif -%}\n <|image|>\n {%- elif content.type == 'video' or 'video' in content %}\n {%- set video_count.value = video_count.value + 1 %}\n {%- if add_vision_id %}Video {{ video_count.value }}: {% endif -%}\n <|video|>\n {%- elif 'text' in content %}\n {{- content.text }}\n {%- endif %}\n {%- endfor %}\n {%- endif %}\n {{- '<|im_end|>\\n' }}\n {%- elif message.role == \"assistant\" %}\n {{- '<|im_start|>' + message.role + '\\n' }}\n {%- if message.content is string %}\n {{- message.content }}\n {%- else %}\n {%- for content_item in message.content %}\n {%- if 'text' in content_item %}\n {{- content_item.text }}\n {%- endif %}\n {%- endfor %}\n {%- endif %}\n {%- if message.tool_calls %}\n {%- for tool_call in message.tool_calls %}\n {%- if (loop.first and message.content) or (not loop.first) %}\n {{- '\\n' }}\n {%- endif %}\n {%- if tool_call.function %}\n {%- set tool_call = tool_call.function %}\n {%- endif %}\n {{- '<tool_call>\\n{\"name\": \"' }}\n {{- tool_call.name }}\n {{- '\", \"arguments\": ' }}\n {%- if tool_call.arguments is string %}\n {{- tool_call.arguments }}\n {%- else %}\n {{- tool_call.arguments | tojson }}\n {%- endif %}\n {{- '}\\n</tool_call>' }}\n {%- endfor %}\n {%- endif %}\n {{- '<|im_end|>\\n' }}\n {%- elif message.role == \"tool\" %}\n {%- if loop.first or (messages[loop.index0 - 1].role != \"tool\") %}\n {{- '<|im_start|>user' }}\n {%- endif %}\n {{- '\\n<tool_response>\\n' }}\n {%- if message.content is string %}\n {{- message.content }}\n {%- else %}\n {%- for content in message.content %}\n {%- if content.type == 'image' or 'image' in content or 'image_url' in content %}\n {%- set image_count.value = image_count.value + 1 %}\n {%- if add_vision_id %}Picture {{ image_count.value }}: {% endif -%}\n <|image|>\n {%- elif content.type == 'video' or 'video' in content %}\n {%- set video_count.value = video_count.value + 1 %}\n {%- if add_vision_id %}Video {{ video_count.value }}: {% endif -%}\n <|video|>\n {%- elif 'text' in content %}\n {{- content.text }}\n {%- endif %}\n {%- endfor %}\n {%- endif %}\n {{- '\\n</tool_response>' }}\n {%- if loop.last or (messages[loop.index0 + 1].role != \"tool\") %}\n {{- '<|im_end|>\\n' }}\n {%- endif %}\n {%- endif %}\n{%- endfor %}\n{%- if add_generation_prompt %}\n {{- '<|im_start|>assistant\\n' }}\n{%- endif %}\n"
276
+ }
video_preprocessor_config.json ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "auto_map": {
3
+ "AutoProcessor": "processing_moss_vl.MossVLProcessor",
4
+ "AutoVideoProcessor": "video_processing_moss_vl.MossVLVideoProcessor"
5
+ },
6
+ "size": {
7
+ "longest_edge": 16777216,
8
+ "shortest_edge": 4096
9
+ },
10
+ "video_max_pixels": 65536000,
11
+ "patch_size": 16,
12
+ "temporal_patch_size": 1,
13
+ "merge_size": 2,
14
+ "video_fps": 1.0,
15
+ "min_frames": 1,
16
+ "max_frames": 256,
17
+ "num_extract_threads": 4,
18
+ "image_mean": [
19
+ 0.5,
20
+ 0.5,
21
+ 0.5
22
+ ],
23
+ "image_std": [
24
+ 0.5,
25
+ 0.5,
26
+ 0.5
27
+ ],
28
+ "processor_class": "MossVLProcessor",
29
+ "video_processor_type": "MossVLVideoProcessor"
30
+ }
video_processing_moss_vl.py ADDED
@@ -0,0 +1,1248 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # coding=utf-8
2
+ # Copyright 2025 The FNLP Vision Team and The HuggingFace Inc. team. All rights reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ """video processor class for Moss-VL."""
16
+
17
+ import json
18
+ import logging as system_logging
19
+ import math
20
+ import os
21
+ import re
22
+ import subprocess
23
+ import traceback
24
+ from functools import lru_cache
25
+ from typing import Any, Dict, List, Optional, Union
26
+
27
+ import numpy as np
28
+ import torch
29
+ from joblib import Parallel, delayed
30
+ from torchcodec.decoders import VideoDecoder
31
+
32
+ from transformers.feature_extraction_utils import BatchFeature
33
+ from transformers.image_utils import ChannelDimension, PILImageResampling, SizeDict, get_image_size, validate_kwargs
34
+ from transformers.processing_utils import Unpack, VideosKwargs
35
+ from transformers.utils import TensorType, add_start_docstrings, logging
36
+ from transformers.video_processing_utils import BASE_VIDEO_PROCESSOR_DOCSTRING, BaseVideoProcessor
37
+ from transformers.video_utils import VideoMetadata, group_videos_by_shape, reorder_videos
38
+
39
+
40
+ logger = logging.get_logger(__name__)
41
+
42
+ TORCHCODEC_TIMESTAMP_EPSILON = 1e-6
43
+
44
+
45
+ # -----------------------------------------------------------------------------
46
+ # Torchcodec video frame extraction utilities
47
+ # -----------------------------------------------------------------------------
48
+
49
+ def check_video_for_extra_streams_and_errors(video_path: str) -> dict:
50
+ """
51
+ Check if video file has abnormal streams or errors reported by ffprobe.
52
+
53
+ Args:
54
+ video_path: Path to the video file.
55
+
56
+ Returns:
57
+ A dictionary containing:
58
+ - 'has_extra_streams': bool, whether there are streams other than video and audio.
59
+ - 'unsupported_codec_errors': list, all "Unsupported codec" error messages.
60
+ - 'ffprobe_output_error': str, other errors/warnings from ffprobe stderr.
61
+ - 'ffprobe_successful': bool, whether ffprobe command executed successfully (return code 0).
62
+ - 'stream_details': list, codec_type and index for each stream.
63
+ - 'num_streams': int, total number of streams identified in the video file.
64
+ """
65
+ result = {
66
+ 'has_extra_streams': False,
67
+ 'unsupported_codec_errors': [],
68
+ 'ffprobe_output_error': '',
69
+ 'ffprobe_successful': False,
70
+ 'stream_details': [],
71
+ 'num_streams': 0
72
+ }
73
+
74
+ command = [
75
+ "ffprobe",
76
+ "-v", "error",
77
+ "-show_streams",
78
+ "-show_format",
79
+ "-of", "json",
80
+ video_path
81
+ ]
82
+
83
+ try:
84
+ process = subprocess.run(
85
+ command,
86
+ capture_output=True,
87
+ text=True,
88
+ check=False
89
+ )
90
+ result['ffprobe_successful'] = (process.returncode == 0)
91
+
92
+ if process.stderr:
93
+ result['ffprobe_output_error'] = process.stderr
94
+ unsupported_codec_pattern = re.compile(r"Unsupported codec with id \d+ for input stream \d+")
95
+ result['unsupported_codec_errors'] = unsupported_codec_pattern.findall(process.stderr)
96
+
97
+ if process.stdout:
98
+ ffprobe_data = json.loads(process.stdout)
99
+ if 'streams' in ffprobe_data:
100
+ result['num_streams'] = len(ffprobe_data['streams'])
101
+ for stream in ffprobe_data['streams']:
102
+ stream_type = stream.get('codec_type')
103
+ stream_index = stream.get('index')
104
+ result['stream_details'].append({'index': stream_index, 'codec_type': stream_type})
105
+ if stream_type not in ['video', 'audio']:
106
+ result['has_extra_streams'] = True
107
+
108
+ if 'format' in ffprobe_data and 'nb_streams' in ffprobe_data['format']:
109
+ if result['num_streams'] == 0:
110
+ result['num_streams'] = ffprobe_data['format']['nb_streams']
111
+ elif result['num_streams'] != ffprobe_data['format']['nb_streams']:
112
+ logger.warning(
113
+ f"Number of streams in 'streams' list ({result['num_streams']}) "
114
+ f"differs from 'nb_streams' in 'format' ({ffprobe_data['format']['nb_streams']})."
115
+ )
116
+ except FileNotFoundError:
117
+ result['ffprobe_output_error'] = "ffprobe command not found. Please ensure FFmpeg is installed and in your PATH."
118
+ result['ffprobe_successful'] = False
119
+ except json.JSONDecodeError:
120
+ result['ffprobe_output_error'] = "Failed to parse ffprobe JSON output. Check ffprobe installation or video file."
121
+ result['ffprobe_successful'] = False
122
+ except Exception as e:
123
+ result['ffprobe_output_error'] = f"An unexpected error occurred: {e}"
124
+ result['ffprobe_successful'] = False
125
+
126
+ return result
127
+
128
+
129
+ def remove_video_extra_stream_ffmpeg(input_video: str, output_video: str) -> bool:
130
+ """
131
+ Remove extra streams from video using ffmpeg.
132
+
133
+ Args:
134
+ input_video: Path to input video.
135
+ output_video: Path to output video.
136
+
137
+ Returns:
138
+ bool: True if successful, False otherwise.
139
+ """
140
+ command_list = [
141
+ "ffmpeg", "-y", "-i", input_video,
142
+ "-map", "0:v:0",
143
+ "-c", "copy",
144
+ "-an",
145
+ "-sn",
146
+ "-dn",
147
+ "-map_metadata", "-1",
148
+ "-map_chapters", "-1",
149
+ "-movflags", "faststart",
150
+ output_video,
151
+ ]
152
+
153
+ try:
154
+ subprocess.run(command_list, shell=False, check=True, capture_output=True)
155
+ return True
156
+ except subprocess.CalledProcessError as e:
157
+ system_logging.error(f"Command execution failed with return code: {e.returncode}, video: {input_video}")
158
+ system_logging.error(f"Error output:\n{e.stderr}")
159
+ return False
160
+ except FileNotFoundError:
161
+ system_logging.error("Error: ffmpeg command not found. Please ensure ffmpeg is installed and in PATH.")
162
+ return False
163
+ except Exception as e:
164
+ system_logging.error(f"Unexpected error executing command: {e}, video: {input_video}", exc_info=True)
165
+ return False
166
+
167
+
168
+ def clean_video_streams(video_path: str) -> str:
169
+ """
170
+ Clean video streams if extra streams are detected.
171
+
172
+ Args:
173
+ video_path: Path to the video file.
174
+
175
+ Returns:
176
+ str: Path to cleaned video (or original if no cleaning needed).
177
+ """
178
+ ffprobe_res = check_video_for_extra_streams_and_errors(video_path)
179
+ if ffprobe_res['has_extra_streams']:
180
+ base_name = os.path.basename(video_path)
181
+ output_folder = os.path.dirname(video_path)
182
+ file_name_without_ext, file_ext = os.path.splitext(base_name)
183
+ new_base_name = f"{file_name_without_ext}_fix{file_ext}"
184
+ video_path_output = os.path.join(output_folder, new_base_name)
185
+
186
+ process_flag = remove_video_extra_stream_ffmpeg(video_path, video_path_output)
187
+ if not process_flag:
188
+ logger.warning("Failed to remove extra streams with ffmpeg")
189
+ return video_path
190
+ return video_path_output
191
+ return video_path
192
+
193
+
194
+ @lru_cache(maxsize=8192)
195
+ def cached_clean_video_streams(video_path: str) -> str:
196
+ return clean_video_streams(video_path)
197
+
198
+
199
+ def clamp_timestamps_for_torchcodec(timestamps: List[float], torchcodec_metadata) -> List[float]:
200
+ if not timestamps:
201
+ return timestamps
202
+
203
+ min_pts = torchcodec_metadata.begin_stream_seconds_from_content
204
+ if min_pts is None:
205
+ min_pts = 0.0
206
+
207
+ max_pts_candidates = []
208
+ if torchcodec_metadata.num_frames_from_content and torchcodec_metadata.average_fps:
209
+ max_pts_candidates.append(
210
+ (torchcodec_metadata.num_frames_from_content - 1) / torchcodec_metadata.average_fps + min_pts
211
+ )
212
+ if torchcodec_metadata.end_stream_seconds_from_content is not None:
213
+ # TorchCodec requires requested PTS to be strictly smaller than the content end.
214
+ max_pts_candidates.append(torchcodec_metadata.end_stream_seconds_from_content - TORCHCODEC_TIMESTAMP_EPSILON)
215
+ if not max_pts_candidates and torchcodec_metadata.duration_seconds is not None:
216
+ max_pts_candidates.append(torchcodec_metadata.duration_seconds - TORCHCODEC_TIMESTAMP_EPSILON)
217
+
218
+ if max_pts_candidates:
219
+ max_pts = max(min_pts, min(max_pts_candidates))
220
+ return [max(min_pts, min(float(t), max_pts)) for t in timestamps]
221
+ if min_pts > 0:
222
+ return [max(min_pts, float(t)) for t in timestamps]
223
+ return [float(t) for t in timestamps]
224
+
225
+
226
+ def split_indices(indices: List[Union[int, float]], num_chunks: int) -> List[List[Union[int, float]]]:
227
+ """
228
+ Split an index list into roughly equal chunks.
229
+
230
+ Args:
231
+ indices: List of indices to split.
232
+ num_chunks: Number of chunks to create.
233
+
234
+ Returns:
235
+ List of index chunks.
236
+ """
237
+ chunk_size = len(indices) // num_chunks
238
+ chunks = []
239
+ for i in range(num_chunks - 1):
240
+ chunks.append(indices[i * chunk_size:(i + 1) * chunk_size])
241
+ chunks.append(indices[(num_chunks - 1) * chunk_size:])
242
+ return chunks
243
+
244
+
245
+ def decode_sequentially(indices: List[int], video_path: str, ffmpeg_threads: int = 0):
246
+ """
247
+ Decode frames sequentially from a video.
248
+
249
+ Args:
250
+ indices: List of frame indices to decode.
251
+ video_path: Path to the video file.
252
+ ffmpeg_threads: Number of ffmpeg threads to use.
253
+
254
+ Returns:
255
+ FrameBatch from torchcodec.
256
+ """
257
+ decoder = VideoDecoder(video_path, num_ffmpeg_threads=ffmpeg_threads)
258
+ try:
259
+ return decoder.get_frames_at(indices)
260
+ finally:
261
+ del decoder
262
+
263
+
264
+ def decode_with_multithreading(indices: List[int], num_threads: int, video_path: str) -> dict:
265
+ """
266
+ Decode frames using multithreading with joblib.
267
+
268
+ Args:
269
+ indices: List of frame indices to decode.
270
+ num_threads: Number of threads to use.
271
+ video_path: Path to the video file.
272
+
273
+ Returns:
274
+ dict: Contains 'data', 'duration_seconds', 'pts_seconds' tensors.
275
+ """
276
+ chunks = split_indices(indices, num_chunks=num_threads)
277
+ results = Parallel(n_jobs=num_threads, prefer="threads", verbose=0)(
278
+ delayed(decode_sequentially)(chunk, video_path) for chunk in chunks
279
+ )
280
+
281
+ return {
282
+ "data": torch.cat([frame_batch.data for frame_batch in results], dim=0),
283
+ "duration_seconds": torch.cat([frame_batch.duration_seconds for frame_batch in results], dim=0),
284
+ "pts_seconds": torch.cat([frame_batch.pts_seconds for frame_batch in results], dim=0)
285
+ }
286
+
287
+
288
+ def decode_sequentially_timestamp(timestamp_list: List[float], video_path: str, ffmpeg_threads: int = 0):
289
+ """
290
+ Decode frames sequentially from a video based on timestamps.
291
+
292
+ Args:
293
+ timestamp_list: List of timestamps (in seconds) to decode.
294
+ video_path: Path to the video file.
295
+ ffmpeg_threads: Number of ffmpeg threads to use.
296
+
297
+ Returns:
298
+ FrameBatch from torchcodec.
299
+ """
300
+ decoder = VideoDecoder(video_path, num_ffmpeg_threads=ffmpeg_threads)
301
+ try:
302
+ metadata = decoder.metadata
303
+ timestamp_list = clamp_timestamps_for_torchcodec(timestamp_list, metadata)
304
+
305
+ return decoder.get_frames_played_at(timestamp_list)
306
+ finally:
307
+ del decoder
308
+
309
+
310
+ def timestamp_decode_with_multithreading(timestamp_list: List[float], num_threads: int, video_path: str) -> dict:
311
+ """
312
+ Decode frames using multithreading based on timestamps.
313
+
314
+ Args:
315
+ timestamp_list: List of timestamps (in seconds) to decode.
316
+ num_threads: Number of threads to use.
317
+ video_path: Path to the video file.
318
+
319
+ Returns:
320
+ dict: Contains 'data', 'duration_seconds', 'pts_seconds' tensors.
321
+ """
322
+ chunks = split_indices(timestamp_list, num_chunks=num_threads)
323
+ results = Parallel(n_jobs=num_threads, prefer="threads", verbose=0)(
324
+ delayed(decode_sequentially_timestamp)(chunk, video_path) for chunk in chunks
325
+ )
326
+
327
+ # Concatenate results from all threads
328
+ data_list = [frame_batch.data for frame_batch in results]
329
+ duration_list = [frame_batch.duration_seconds for frame_batch in results]
330
+ pts_list = [frame_batch.pts_seconds for frame_batch in results]
331
+
332
+ if not data_list:
333
+ logger.warning("No frames were successfully decoded.")
334
+ return {"data": torch.empty(0), "duration_seconds": torch.empty(0), "pts_seconds": torch.empty(0)}
335
+
336
+ return {
337
+ "data": torch.cat(data_list, dim=0),
338
+ "duration_seconds": torch.cat(duration_list, dim=0),
339
+ "pts_seconds": torch.cat(pts_list, dim=0)
340
+ }
341
+
342
+
343
+ def extract_frames_with_torchcodec(
344
+ video_path: str,
345
+ sample_frames_count: int,
346
+ num_threads: int = 4,
347
+
348
+ ) -> Optional[dict]:
349
+ """
350
+ Extract frames from video using torchcodec with multithreading.
351
+
352
+ Args:
353
+ video_path: Path to the video file.
354
+ sample_frames_count: Number of frames to sample.
355
+ num_threads: Number of threads to use for extraction.
356
+ sampling_method: Sampling method, either "index" (uniform frame indices) or "timestamp" (uniform timestamps).
357
+
358
+ Returns:
359
+ dict: Contains 'data' (N, C, H, W), 'duration_seconds' (N,), 'pts_seconds' (N,) tensors.
360
+ Returns None if extraction fails.
361
+ """
362
+ try:
363
+ video_path = cached_clean_video_streams(video_path)
364
+ decoder = VideoDecoder(video_path, num_ffmpeg_threads=0)
365
+ metadata = decoder.metadata
366
+
367
+
368
+ total_frames_in_video = metadata.num_frames_from_content
369
+
370
+ effective_sample_count = min(sample_frames_count, total_frames_in_video)
371
+ if effective_sample_count == 0:
372
+ logger.error("Cannot extract frames: video has 0 frames or specified frame count is 0")
373
+ return None
374
+
375
+ # Generate uniform frame indices
376
+ frame_indices = np.linspace(0, total_frames_in_video - 1, effective_sample_count).astype(np.int32)
377
+ # Ensure indices are valid and remove duplicates
378
+ frame_indices = np.unique(np.clip(frame_indices, 0, total_frames_in_video - 1))
379
+
380
+ result = decode_with_multithreading(frame_indices.tolist(), num_threads=num_threads, video_path=video_path)
381
+ # Add frame_indices to the result for later use
382
+ result["frame_indices"] = frame_indices
383
+ return result
384
+
385
+
386
+
387
+ except Exception:
388
+ traceback.print_exc()
389
+ return None
390
+
391
+
392
+ def smart_resize(
393
+ num_frames: int,
394
+ height: int,
395
+ width: int,
396
+ temporal_factor: int = 1,
397
+ factor: int = 32,
398
+ min_pixels: int = 128 * 128,
399
+ max_pixels: int = 16 * 16 * 2 * 2 * 2 * 6144,
400
+ per_frame_min_pixels: int = None,
401
+ per_frame_max_pixels: int = None,
402
+ ):
403
+ if num_frames < temporal_factor:
404
+ raise ValueError(f"t:{num_frames} must be larger than temporal_factor:{temporal_factor}")
405
+ if height < factor or width < factor:
406
+ raise ValueError(f"height:{height} or width:{width} must be larger than factor:{factor}")
407
+ elif max(height, width) / min(height, width) > 200:
408
+ raise ValueError(
409
+ f"absolute aspect ratio must be smaller than 200, got {max(height, width) / min(height, width)}"
410
+ )
411
+ h_bar = round(height / factor) * factor
412
+ w_bar = round(width / factor) * factor
413
+ t_bar = round(num_frames / temporal_factor) * temporal_factor
414
+
415
+ # Step 1: Apply per-frame upper limit constraint
416
+ if per_frame_max_pixels is not None and h_bar * w_bar > per_frame_max_pixels:
417
+ beta = math.sqrt((height * width) / per_frame_max_pixels)
418
+ h_bar = max(factor, math.floor(height / beta / factor) * factor)
419
+ w_bar = max(factor, math.floor(width / beta / factor) * factor)
420
+
421
+ # Step 2: Apply 3D volume constraints (frames * height * width)
422
+ if t_bar * h_bar * w_bar > max_pixels:
423
+ beta = math.sqrt((num_frames * height * width) / max_pixels)
424
+ h_bar = max(factor, math.floor(height / beta / factor) * factor)
425
+ w_bar = max(factor, math.floor(width / beta / factor) * factor)
426
+ elif t_bar * h_bar * w_bar < min_pixels:
427
+ beta = math.sqrt(min_pixels / (num_frames * height * width))
428
+ h_bar = math.ceil(height * beta / factor) * factor
429
+ w_bar = math.ceil(width * beta / factor) * factor
430
+
431
+ # Step 3: Ensure per-frame lower limit is respected (after volume constraint)
432
+ # This guarantees single frame stays within [per_frame_min_pixels, per_frame_max_pixels]
433
+ if per_frame_min_pixels is not None and h_bar * w_bar < per_frame_min_pixels:
434
+ beta = math.sqrt(per_frame_min_pixels / (height * width))
435
+ h_bar = math.ceil(height * beta / factor) * factor
436
+ w_bar = math.ceil(width * beta / factor) * factor
437
+
438
+ return h_bar, w_bar
439
+
440
+
441
+ class MossVLVideoProcessorInitKwargs(VideosKwargs):
442
+ patch_size: Optional[int]
443
+ temporal_patch_size: Optional[int]
444
+ merge_size: Optional[int]
445
+ min_frames: Optional[int]
446
+ max_frames: Optional[int]
447
+ video_fps: Optional[Union[int, float]]
448
+ num_extract_threads: Optional[int]
449
+ # Total 3D volume budget across all videos; distributed proportionally per video by T*H*W
450
+ video_max_pixels: Optional[int]
451
+
452
+
453
+ @add_start_docstrings(
454
+ "Constructs a fast Moss-VL video processor that dynamically resizes videos based on the original videos.",
455
+ BASE_VIDEO_PROCESSOR_DOCSTRING,
456
+ """
457
+ patch_size (`int`, *optional*, defaults to 16):
458
+ The spacial patch size of the vision encoder.
459
+ temporal_patch_size (`int`, *optional*, defaults to 1):
460
+ The temporal patch size of the vision encoder.
461
+ merge_size (`int`, *optional*, defaults to 2):
462
+ The merge size of the vision encoder to llm encoder.
463
+ video_fps (`float`, *optional*, defaults to 1.0):
464
+ Target frames per second for video sampling.
465
+ min_frames (`int`, *optional*, defaults to 1):
466
+ Minimum number of frames to sample from a video.
467
+ max_frames (`int`, *optional*, defaults to 256):
468
+ Maximum number of frames to sample from a video.
469
+ num_extract_threads (`int`, *optional*, defaults to 4):
470
+ Number of threads to use for frame extraction.
471
+ """,
472
+ )
473
+ class MossVLVideoProcessor(BaseVideoProcessor):
474
+ resample = PILImageResampling.BICUBIC
475
+ size = {"shortest_edge": 128 * 32 * 32, "longest_edge": 32 * 32 * 768}
476
+ image_mean = [0.5, 0.5, 0.5]
477
+ image_std = [0.5, 0.5, 0.5]
478
+ do_resize = True
479
+ do_rescale = True
480
+ do_normalize = True
481
+ do_convert_rgb = True
482
+ patch_size = 16
483
+ temporal_patch_size = 1
484
+ merge_size = 2
485
+ video_fps = 1.0
486
+ min_frames = 1
487
+ max_frames = 256
488
+ num_extract_threads = 4
489
+ do_sample_frames = True
490
+ # Total 3D volume budget across all videos; distributed proportionally per video by T*H*W
491
+ video_max_pixels = None # read from config
492
+ valid_kwargs = MossVLVideoProcessorInitKwargs
493
+ model_input_names = ["pixel_values_videos", "video_grid_thw"]
494
+
495
+ def __init__(self, **kwargs: Unpack[MossVLVideoProcessorInitKwargs]):
496
+ super().__init__(**kwargs)
497
+ if self.size is not None and (
498
+ self.size.get("shortest_edge", None) is None or self.size.get("longest_edge", None) is None
499
+ ):
500
+ raise ValueError("size must contain 'shortest_edge' and 'longest_edge' keys.")
501
+
502
+ def _further_process_kwargs(
503
+ self,
504
+ size: Optional[SizeDict] = None,
505
+ **kwargs,
506
+ ) -> dict:
507
+ """
508
+ Update kwargs that need further processing before being validated
509
+ Can be overridden by subclasses to customize the processing of kwargs.
510
+ """
511
+ if size is not None and ("shortest_edge" not in size or "longest_edge" not in size):
512
+ raise ValueError("size must contain 'shortest_edge' and 'longest_edge' keys.")
513
+
514
+ return super()._further_process_kwargs(size=size, **kwargs)
515
+
516
+ def _get_video_path_from_input(self, video_input: Union[str, Dict[str, Any]]) -> str:
517
+ """Normalize a video input into a video path."""
518
+ if isinstance(video_input, dict):
519
+ return video_input["video_path"]
520
+ return video_input
521
+
522
+ def _get_video_duration_seconds(self, video_input: Union[str, Dict[str, Any]]) -> float:
523
+ """Get video duration in seconds for weighted frame-budget allocation."""
524
+ video_path = cached_clean_video_streams(self._get_video_path_from_input(video_input))
525
+ decoder = VideoDecoder(video_path, num_ffmpeg_threads=0)
526
+ try:
527
+ metadata = decoder.metadata
528
+ duration = None
529
+ if (
530
+ metadata.end_stream_seconds_from_content is not None
531
+ and metadata.begin_stream_seconds_from_content is not None
532
+ ):
533
+ duration = metadata.end_stream_seconds_from_content - metadata.begin_stream_seconds_from_content
534
+ if duration is None or duration <= 0:
535
+ duration = metadata.duration_seconds
536
+ return max(0.0, float(duration or 0.0))
537
+ finally:
538
+ del decoder
539
+
540
+ def _allocate_max_frames_for_multiple_videos(
541
+ self,
542
+ video_inputs: List[Union[str, Dict[str, Any]]],
543
+ total_max_frames: Optional[int],
544
+ ) -> List[Optional[int]]:
545
+ """
546
+ Treat max_frames as a total budget for multi-video input and allocate it by duration.
547
+
548
+ The returned values are per-video max_frames. Segment dict inputs still keep their
549
+ existing per-segment weighting logic after receiving the video-level allocation.
550
+ """
551
+ if not video_inputs:
552
+ return []
553
+ if total_max_frames is None or len(video_inputs) == 1:
554
+ return [total_max_frames] * len(video_inputs)
555
+
556
+ total_max_frames = int(total_max_frames)
557
+ num_videos = len(video_inputs)
558
+ if total_max_frames < num_videos:
559
+ logger.warning(
560
+ "Received max_frames=%s for %s videos. At least one frame per video is required, "
561
+ "so falling back to 1 frame per video.",
562
+ total_max_frames,
563
+ num_videos,
564
+ )
565
+ return [1] * num_videos
566
+
567
+ video_durations = [self._get_video_duration_seconds(video_input) for video_input in video_inputs]
568
+ total_duration = sum(video_durations)
569
+
570
+ # Reserve one frame per video first, then distribute the remaining budget by duration.
571
+ allocations = [1] * num_videos
572
+ remaining_budget = total_max_frames - num_videos
573
+ if remaining_budget == 0:
574
+ return allocations
575
+
576
+ if total_duration <= 0:
577
+ raw_extra_allocations = [remaining_budget / num_videos] * num_videos
578
+ else:
579
+ raw_extra_allocations = [
580
+ remaining_budget * (duration / total_duration) for duration in video_durations
581
+ ]
582
+
583
+ base_extra_allocations = [int(math.floor(value)) for value in raw_extra_allocations]
584
+ allocations = [base + extra for base, extra in zip(allocations, base_extra_allocations)]
585
+
586
+ remainder = remaining_budget - sum(base_extra_allocations)
587
+ if remainder > 0:
588
+ fractional_parts = [
589
+ (raw_value - base_value, index)
590
+ for index, (raw_value, base_value) in enumerate(zip(raw_extra_allocations, base_extra_allocations))
591
+ ]
592
+ fractional_parts.sort(key=lambda item: (-item[0], item[1]))
593
+ for _, index in fractional_parts[:remainder]:
594
+ allocations[index] += 1
595
+
596
+ return allocations
597
+
598
+ def calculate_num_frames(
599
+ self,
600
+ metadata: VideoMetadata,
601
+ num_frames: Optional[int] = None,
602
+ fps: Optional[Union[int, float]] = None,
603
+ min_frames: Optional[int] = None,
604
+ max_frames: Optional[int] = None,
605
+ **kwargs,
606
+ ) -> int:
607
+ """
608
+ Calculate the number of frames to sample using fps-based logic with min/max constraints.
609
+
610
+ Logic:
611
+ 1. Calculate target_frames based on fps and video duration
612
+ 2. Apply min_frames and max_frames constraints
613
+ 3. Apply max_allowed_frames protection (rough cap from total video_max_pixels budget)
614
+ 4. Return the number of frames to sample
615
+
616
+ Args:
617
+ metadata (`VideoMetadata`):
618
+ Metadata of the video containing information about total duration, fps and total number of frames.
619
+ num_frames (`int`, *optional*):
620
+ Maximum number of frames to sample. If provided, overrides fps-based calculation.
621
+ fps (`int` or `float`, *optional*):
622
+ Target frames to sample per second. Defaults to `self.video_fps`.
623
+ min_frames (`int`, *optional*):
624
+ Minimum number of frames to sample. If None, uses self.min_frames.
625
+ max_frames (`int`, *optional*):
626
+ Maximum number of frames to sample. If None, uses self.max_frames.
627
+ Returns:
628
+ int:
629
+ Number of frames to sample.
630
+ """
631
+ if fps is not None and num_frames is not None:
632
+ raise ValueError("`num_frames` and `fps` are mutually exclusive arguments, please use only one!")
633
+
634
+ total_num_frames = metadata.total_num_frames
635
+
636
+ # Use provided min/max or fall back to defaults
637
+ effective_min_frames = min_frames if min_frames is not None else self.min_frames
638
+ effective_max_frames = max_frames if max_frames is not None else self.max_frames
639
+
640
+ # Rough per-video frame cap derived from the multi-video total budget
641
+ # (exact allocation happens later in _preprocess via weighted distribution)
642
+ per_frame_min_pixels = self.size.get("shortest_edge", None) if self.size else None
643
+ video_max_pixels = getattr(self, "video_max_pixels", None)
644
+ if per_frame_min_pixels is not None and video_max_pixels is not None and per_frame_min_pixels > 0:
645
+ max_allowed_frames = video_max_pixels // per_frame_min_pixels
646
+ effective_max_frames = min(effective_max_frames, max_allowed_frames)
647
+
648
+ # Get video duration
649
+ if hasattr(metadata, 'duration') and metadata.duration is not None:
650
+ duration = metadata.duration
651
+ else:
652
+ video_fps = metadata.fps
653
+ if video_fps is not None and video_fps > 0:
654
+ duration = total_num_frames / video_fps
655
+ else:
656
+ # Fallback: assume 24 fps
657
+ video_fps = 24.0
658
+ duration = total_num_frames / video_fps
659
+ logger.warning_once(
660
+ "Could not determine video fps from metadata, defaulting to 24 fps for duration calculation."
661
+ )
662
+
663
+ # Use provided fps or default
664
+ target_fps = fps if fps is not None else self.video_fps
665
+
666
+ # Calculate target frames based on fps and duration
667
+ if num_frames is None:
668
+ # Calculate how many frames we should sample based on target fps
669
+ target_total_frames = int(math.ceil(duration * target_fps - 1e-6))
670
+
671
+ # Apply min/max constraints
672
+ sample_frames = max(target_total_frames, effective_min_frames)
673
+ sample_frames = min(sample_frames, effective_max_frames, total_num_frames)
674
+ else:
675
+ # If num_frames is explicitly provided, use it directly with constraints
676
+ sample_frames = min(max(num_frames, effective_min_frames), effective_max_frames, total_num_frames)
677
+
678
+ return sample_frames
679
+
680
+
681
+ def _decode_timestamps_with_decoder(
682
+ self,
683
+ decoder: VideoDecoder,
684
+ timestamps: List[float],
685
+ chunk_size: int = 128,
686
+ ) -> torch.Tensor:
687
+ if not timestamps:
688
+ return torch.empty(0)
689
+
690
+ frame_chunks = []
691
+ for start in range(0, len(timestamps), chunk_size):
692
+ frame_batch = decoder.get_frames_played_at(timestamps[start:start + chunk_size])
693
+ frame_chunks.append(frame_batch.data)
694
+
695
+ if len(frame_chunks) == 1:
696
+ return frame_chunks[0]
697
+ return torch.cat(frame_chunks, dim=0)
698
+
699
+ def _clamp_timestamps_for_decoder(
700
+ self,
701
+ timestamps: List[float],
702
+ torchcodec_metadata,
703
+ ) -> List[float]:
704
+ return clamp_timestamps_for_torchcodec(timestamps, torchcodec_metadata)
705
+
706
+ def _fetch_video_segments_batched(
707
+ self,
708
+ video_path: str,
709
+ segments: List[List[float]],
710
+ min_frames: Optional[int] = None,
711
+ max_frames: Optional[int] = None,
712
+ video_fps: Optional[float] = None,
713
+ ):
714
+ min_frames = max(1, min_frames if min_frames is not None else self.min_frames)
715
+ max_frames = max(1, max_frames if max_frames is not None else self.max_frames)
716
+ target_video_fps = video_fps if video_fps is not None else self.video_fps
717
+
718
+ video_path = cached_clean_video_streams(video_path)
719
+ decoder = VideoDecoder(video_path, num_ffmpeg_threads=0)
720
+ try:
721
+ torchcodec_metadata = decoder.metadata
722
+ source_video_fps = torchcodec_metadata.average_fps
723
+
724
+ duration = None
725
+ if (
726
+ torchcodec_metadata.end_stream_seconds_from_content is not None
727
+ and torchcodec_metadata.begin_stream_seconds_from_content is not None
728
+ ):
729
+ duration = (
730
+ torchcodec_metadata.end_stream_seconds_from_content
731
+ - torchcodec_metadata.begin_stream_seconds_from_content
732
+ )
733
+ if duration is None or duration <= 0:
734
+ duration = torchcodec_metadata.duration_seconds
735
+
736
+ segment_durations = [
737
+ segment[1] - segment[0] if len(segment) == 2 else None
738
+ for segment in segments
739
+ ]
740
+ total_segment_duration = sum(d for d in segment_durations if d is not None)
741
+ num_range_segments = sum(1 for d in segment_durations if d is not None)
742
+
743
+ segment_timestamps = []
744
+ decode_timestamps = []
745
+ for i, segment in enumerate(segments):
746
+ if len(segment) == 1:
747
+ actual_timestamps = self._clamp_timestamps_for_decoder([segment[0]], torchcodec_metadata)
748
+ segment_timestamps.append(actual_timestamps)
749
+ decode_timestamps.extend(actual_timestamps)
750
+ continue
751
+
752
+ start_time, end_time = segment
753
+ segment_duration = end_time - start_time
754
+ target_frames = int(math.ceil(segment_duration * target_video_fps))
755
+
756
+ if total_segment_duration > 0:
757
+ weight = segment_durations[i] / total_segment_duration
758
+ else:
759
+ weight = 1.0 / num_range_segments if num_range_segments > 0 else 1.0
760
+
761
+ weighted_min_frames = max(1, int(round(min_frames * weight)))
762
+ weighted_max_frames = max(1, int(round(max_frames * weight)))
763
+ target_frames = max(target_frames, weighted_min_frames)
764
+ target_frames = min(target_frames, weighted_max_frames)
765
+
766
+ if target_frames == 1:
767
+ actual_timestamps = [start_time]
768
+ else:
769
+ actual_timestamps = np.linspace(
770
+ start_time,
771
+ end_time,
772
+ target_frames,
773
+ endpoint=False,
774
+ ).tolist()
775
+
776
+ actual_timestamps = self._clamp_timestamps_for_decoder(actual_timestamps, torchcodec_metadata)
777
+ segment_timestamps.append(actual_timestamps)
778
+ decode_timestamps.extend(actual_timestamps)
779
+
780
+ flat_frames = self._decode_timestamps_with_decoder(decoder, decode_timestamps)
781
+
782
+ videos = []
783
+ metadata = []
784
+ frame_offset = 0
785
+ for actual_timestamps in segment_timestamps:
786
+ sample_count = len(actual_timestamps)
787
+ video_tensor = flat_frames[frame_offset:frame_offset + sample_count]
788
+ frame_offset += sample_count
789
+
790
+ video_metadata = VideoMetadata(
791
+ total_num_frames=sample_count,
792
+ fps=source_video_fps,
793
+ duration=duration,
794
+ video_backend="torchcodec",
795
+ height=torchcodec_metadata.height,
796
+ width=torchcodec_metadata.width,
797
+ frames_indices=None,
798
+ )
799
+ video_metadata.actual_timestamps = actual_timestamps
800
+
801
+ videos.append(video_tensor)
802
+ metadata.append(video_metadata)
803
+
804
+ return videos, metadata
805
+ finally:
806
+ del decoder
807
+
808
+
809
+ def _fetch_video_segment(
810
+ self,
811
+ video_path: str,
812
+ segment: List[float],
813
+ min_frames: Optional[int] = None,
814
+ max_frames: Optional[int] = None,
815
+ video_fps: Optional[float] = None,
816
+ ):
817
+ """
818
+ Fetch video frames for a specific segment.
819
+
820
+ Args:
821
+ video_path: Path to the video file
822
+ segment: [start, end] for a segment (left-closed, right-open) or [time] for a single frame
823
+ min_frames: Minimum frames for this segment (weighted). Defaults to self.min_frames. Must be >= 1.
824
+ max_frames: Maximum frames for this segment (weighted). Defaults to self.max_frames. Must be >= 1.
825
+ video_fps: Target frames per second for video sampling. If None, uses self.video_fps.
826
+
827
+ Returns:
828
+ Tuple of (video_tensor, video_metadata)
829
+ """
830
+ # Use provided min/max or fall back to defaults, ensure >= 1
831
+ min_frames = max(1, min_frames if min_frames is not None else self.min_frames)
832
+ max_frames = max(1, max_frames if max_frames is not None else self.max_frames)
833
+ # Use provided video_fps or fall back to self.video_fps
834
+ target_video_fps = video_fps if video_fps is not None else self.video_fps
835
+
836
+ video_path = clean_video_streams(video_path)
837
+ decoder = VideoDecoder(video_path, num_ffmpeg_threads=0)
838
+ try:
839
+ torchcodec_metadata = decoder.metadata
840
+
841
+ video_fps = torchcodec_metadata.average_fps
842
+
843
+ # Calculate duration
844
+ duration = None
845
+ if torchcodec_metadata.end_stream_seconds_from_content is not None and torchcodec_metadata.begin_stream_seconds_from_content is not None:
846
+ duration = torchcodec_metadata.end_stream_seconds_from_content - torchcodec_metadata.begin_stream_seconds_from_content
847
+ if duration is None or duration <= 0:
848
+ duration = torchcodec_metadata.duration_seconds
849
+
850
+ if len(segment) == 1:
851
+ # Single frame at specified time
852
+ actual_timestamps = self._clamp_timestamps_for_decoder([segment[0]], torchcodec_metadata)
853
+ frame_batch = decoder.get_frames_played_at(actual_timestamps)
854
+ video_tensor = frame_batch.data
855
+ sample_count = 1
856
+ else:
857
+ # Segment [start, end) - left-closed, right-open interval
858
+ start_time, end_time = segment
859
+ segment_duration = end_time - start_time
860
+
861
+ # Calculate number of frames to sample for this segment
862
+ target_frames = int(math.ceil(segment_duration * target_video_fps))
863
+ target_frames = max(target_frames, min_frames)
864
+ target_frames = min(target_frames, max_frames)
865
+
866
+ # Generate timestamps for uniform sampling within segment
867
+ if target_frames == 1:
868
+ actual_timestamps = [start_time] # Use start_time for single frame
869
+ else:
870
+ # Sample uniformly within [start, end), endpoint=False for left-closed right-open
871
+ actual_timestamps = np.linspace(start_time, end_time, target_frames, endpoint=False).tolist()
872
+
873
+ actual_timestamps = self._clamp_timestamps_for_decoder(actual_timestamps, torchcodec_metadata)
874
+
875
+ # Use multithreading for extraction
876
+ result = timestamp_decode_with_multithreading(actual_timestamps, self.num_extract_threads, video_path)
877
+ video_tensor = result["data"]
878
+ sample_count = len(actual_timestamps)
879
+
880
+ # Create VideoMetadata
881
+ video_metadata = VideoMetadata(
882
+ total_num_frames=sample_count,
883
+ fps=video_fps,
884
+ duration=duration,
885
+ video_backend="torchcodec",
886
+ height=torchcodec_metadata.height,
887
+ width=torchcodec_metadata.width,
888
+ frames_indices=None
889
+ )
890
+
891
+ # Store actual timestamps as a custom attribute for _calculate_timestamps to use
892
+ video_metadata.actual_timestamps = actual_timestamps
893
+
894
+ return video_tensor, video_metadata
895
+ finally:
896
+ del decoder
897
+
898
+ def fetch_videos(
899
+ self,
900
+ video_url_or_urls: Union[str, Dict[str, Any], List[Union[str, Dict[str, Any]]]],
901
+ sample_indices_fn=None,
902
+ video_fps: Optional[float] = None,
903
+ min_frames: Optional[int] = None,
904
+ max_frames: Optional[int] = None,
905
+ ):
906
+ """
907
+ Override fetch_videos to use torchcodec for frame extraction.
908
+
909
+ This method uses torchcodec with multithreading for efficient frame extraction.
910
+ Frame count is calculated by the calculate_num_frames method
911
+ (fps-based with min/max constraints).
912
+
913
+ Args:
914
+ video_url_or_urls: Can be one of:
915
+ - str: Single video path
916
+ - Dict: Video with segments {"video_path": str, "segments": List[List[float]]}
917
+ - List[Union[str, Dict]]: List of video paths or segment dicts
918
+ sample_indices_fn: (Not used) Kept for compatibility with base class signature.
919
+ video_fps: Target frames per second for video sampling. If None, uses self.video_fps.
920
+ min_frames: Minimum number of frames to sample. If None, uses self.min_frames.
921
+ max_frames: Maximum number of frames to sample. If None, uses self.max_frames.
922
+
923
+ Returns:
924
+ Tuple of (videos, metadata) where videos are torch.Tensors and metadata are VideoMetadata objects.
925
+ """
926
+ # Use provided values or fall back to self defaults
927
+ effective_video_fps = video_fps if video_fps is not None else self.video_fps
928
+ effective_min_frames = min_frames if min_frames is not None else self.min_frames
929
+ effective_max_frames = max_frames if max_frames is not None else self.max_frames
930
+ # Handle recursive calls for lists
931
+ if isinstance(video_url_or_urls, list):
932
+ all_videos = []
933
+ all_metadata = []
934
+ if len(video_url_or_urls) == 1:
935
+ per_video_max_frames = [effective_max_frames]
936
+ else:
937
+ per_video_max_frames = self._allocate_max_frames_for_multiple_videos(
938
+ video_url_or_urls,
939
+ effective_max_frames,
940
+ )
941
+ for x, allocated_max_frames in zip(video_url_or_urls, per_video_max_frames):
942
+ result = self.fetch_videos(
943
+ x,
944
+ video_fps=effective_video_fps,
945
+ min_frames=effective_min_frames,
946
+ max_frames=allocated_max_frames,
947
+ )
948
+ # Check if result is from segment expansion (returns lists) or single item
949
+ if isinstance(result[0], list):
950
+ all_videos.extend(result[0])
951
+ all_metadata.extend(result[1])
952
+ else:
953
+ all_videos.append(result[0])
954
+ all_metadata.append(result[1])
955
+ return all_videos, all_metadata
956
+
957
+ # Handle dict with segments - returns lists (one per segment)
958
+ if isinstance(video_url_or_urls, dict):
959
+ video_path = video_url_or_urls["video_path"]
960
+ segments = video_url_or_urls["segments"]
961
+
962
+ return self._fetch_video_segments_batched(
963
+ video_path,
964
+ segments,
965
+ min_frames=effective_min_frames,
966
+ max_frames=effective_max_frames,
967
+ video_fps=effective_video_fps,
968
+ )
969
+
970
+ # Single video path
971
+ video_path = video_url_or_urls
972
+
973
+ # Clean video streams first (remove extra streams if needed)
974
+ video_path = cached_clean_video_streams(video_path)
975
+
976
+ decoder = None
977
+ try:
978
+ # Create VideoDecoder only once for both metadata and frame extraction
979
+ decoder = VideoDecoder(video_path, num_ffmpeg_threads=0)
980
+ torchcodec_metadata = decoder.metadata
981
+
982
+ duration = None
983
+ if torchcodec_metadata.end_stream_seconds_from_content is not None and torchcodec_metadata.begin_stream_seconds_from_content is not None:
984
+ duration = torchcodec_metadata.end_stream_seconds_from_content - torchcodec_metadata.begin_stream_seconds_from_content
985
+
986
+ if duration is None or duration <= 0:
987
+ duration = torchcodec_metadata.duration_seconds
988
+
989
+ # Use num_frames_from_content for accurate frame count (consistent with extraction)
990
+ total_frames_in_video = torchcodec_metadata.num_frames_from_content
991
+
992
+ # Create VideoMetadata object for sample_frames method
993
+ temp_metadata = VideoMetadata(
994
+ total_num_frames=total_frames_in_video,
995
+ fps=torchcodec_metadata.average_fps,
996
+ duration=duration,
997
+ video_backend="torchcodec",
998
+ height=torchcodec_metadata.height,
999
+ width=torchcodec_metadata.width,
1000
+ frames_indices=None
1001
+ )
1002
+
1003
+ # Use calculate_num_frames method to get the number of frames to sample
1004
+ sample_frames_count = self.calculate_num_frames(
1005
+ temp_metadata,
1006
+ fps=effective_video_fps,
1007
+ min_frames=effective_min_frames,
1008
+ max_frames=effective_max_frames,
1009
+ )
1010
+
1011
+ # Ensure sample count is valid
1012
+ effective_sample_count = min(sample_frames_count, total_frames_in_video)
1013
+ if effective_sample_count == 0:
1014
+ raise ValueError(f"Cannot extract frames: video has 0 frames or specified frame count is 0")
1015
+
1016
+ # Generate uniform frame indices
1017
+ frame_indices = np.linspace(0, total_frames_in_video - 1, effective_sample_count).astype(np.int32)
1018
+ # Ensure indices are valid and remove duplicates
1019
+ frame_indices = np.unique(np.clip(frame_indices, 0, total_frames_in_video - 1))
1020
+
1021
+ # Extract frames using multithreading (decoder is created inside each thread for thread safety)
1022
+ result = decode_with_multithreading(frame_indices.tolist(), num_threads=self.num_extract_threads, video_path=video_path)
1023
+
1024
+ # Extract frame tensor (N, C, H, W)
1025
+ frames_tensor = result["data"]
1026
+
1027
+ # Create final VideoMetadata object
1028
+ video_metadata = VideoMetadata(
1029
+ total_num_frames=len(frame_indices),
1030
+ fps=torchcodec_metadata.average_fps,
1031
+ duration=duration,
1032
+ video_backend="torchcodec",
1033
+ height=torchcodec_metadata.height,
1034
+ width=torchcodec_metadata.width,
1035
+ frames_indices=frame_indices
1036
+ )
1037
+
1038
+ # Ensure frames are in (T, C, H, W) format
1039
+ if frames_tensor.dim() == 4: # (N, C, H, W)
1040
+ video_tensor = frames_tensor
1041
+ else:
1042
+ raise ValueError(f"Unexpected frame tensor shape: {frames_tensor.shape}")
1043
+
1044
+ return video_tensor, video_metadata
1045
+
1046
+ except Exception as e:
1047
+ logger.error(f"Error loading video {video_path}: {e}")
1048
+ traceback.print_exc()
1049
+ raise ValueError(f"Failed to load video {video_path}: {e}")
1050
+ finally:
1051
+ if decoder is not None:
1052
+ del decoder
1053
+
1054
+ def _preprocess(
1055
+ self,
1056
+ videos: list[torch.Tensor],
1057
+ do_convert_rgb: bool = True,
1058
+ do_resize: bool = True,
1059
+ size: Optional[SizeDict] = None,
1060
+ interpolation: PILImageResampling = PILImageResampling.BICUBIC,
1061
+ do_rescale: bool = True,
1062
+ rescale_factor: float = 1 / 255.0,
1063
+ do_normalize: bool = True,
1064
+ image_mean: Optional[Union[float, list[float]]] = None,
1065
+ image_std: Optional[Union[float, list[float]]] = None,
1066
+ patch_size: Optional[int] = None,
1067
+ temporal_patch_size: Optional[int] = None,
1068
+ merge_size: Optional[int] = None,
1069
+ return_tensors: Optional[Union[str, TensorType]] = None,
1070
+ **kwargs,
1071
+ ):
1072
+ grouped_videos, grouped_videos_index = group_videos_by_shape(videos)
1073
+ resized_videos_grouped = {}
1074
+
1075
+ video_max_pixels = getattr(self, "video_max_pixels", None)
1076
+ if video_max_pixels is not None:
1077
+ total_volume = sum(
1078
+ sv.shape[0] * sv.shape[1] * sv.shape[3] * sv.shape[4]
1079
+ for sv in grouped_videos.values()
1080
+ )
1081
+ else:
1082
+ total_volume = 0
1083
+
1084
+ for shape, stacked_videos in grouped_videos.items():
1085
+ B, T, C, H, W = stacked_videos.shape
1086
+ num_frames, height, width = T, H, W
1087
+ # Convert to RGB if needed (reuse from base class)
1088
+ if do_convert_rgb:
1089
+ stacked_videos = self.convert_to_rgb(stacked_videos)
1090
+ if do_resize:
1091
+ if video_max_pixels is not None and total_volume > 0:
1092
+ allocated_max_pixels = int(video_max_pixels * (T * H * W) / total_volume)
1093
+ else:
1094
+ allocated_max_pixels = size.longest_edge
1095
+ resized_height, resized_width = smart_resize(
1096
+ num_frames=num_frames,
1097
+ height=height,
1098
+ width=width,
1099
+ temporal_factor=temporal_patch_size,
1100
+ factor=patch_size * merge_size,
1101
+ min_pixels=size.shortest_edge,
1102
+ max_pixels=allocated_max_pixels,
1103
+ per_frame_min_pixels=size.shortest_edge,
1104
+ per_frame_max_pixels=size.longest_edge,
1105
+ )
1106
+ stacked_videos = stacked_videos.view(B * T, C, H, W)
1107
+ stacked_videos = self.resize(
1108
+ stacked_videos,
1109
+ size=SizeDict(height=resized_height, width=resized_width),
1110
+ interpolation=interpolation,
1111
+ )
1112
+ stacked_videos = stacked_videos.view(B, T, C, resized_height, resized_width)
1113
+ resized_videos_grouped[shape] = stacked_videos
1114
+ resized_videos = reorder_videos(resized_videos_grouped, grouped_videos_index)
1115
+
1116
+ # Group videos by size for further processing
1117
+ # Needed in case do_resize is False, or resize returns videos with different sizes
1118
+ grouped_videos, grouped_videos_index = group_videos_by_shape(resized_videos)
1119
+ processed_videos_grouped = {}
1120
+ processed_grids = {}
1121
+ for shape, stacked_videos in grouped_videos.items():
1122
+ resized_height, resized_width = get_image_size(stacked_videos[0], channel_dim=ChannelDimension.FIRST)
1123
+
1124
+ # Fused rescale and normalize
1125
+ stacked_videos = self.rescale_and_normalize(
1126
+ stacked_videos, do_rescale, rescale_factor, do_normalize, image_mean, image_std
1127
+ )
1128
+ patches = stacked_videos
1129
+
1130
+ # Check that videos have `num_frames` divisible by `temporal_patch_size`
1131
+ if patches.shape[1] % temporal_patch_size != 0:
1132
+ repeats = patches[:, -1:].repeat(1, temporal_patch_size - 1, 1, 1, 1)
1133
+ patches = torch.cat([patches, repeats], dim=1)
1134
+ batch_size, grid_t, channel = patches.shape[:3]
1135
+ grid_t = grid_t // temporal_patch_size
1136
+ grid_h, grid_w = resized_height // patch_size, resized_width // patch_size
1137
+
1138
+ patches = patches.view(
1139
+ batch_size,
1140
+ grid_t,
1141
+ temporal_patch_size,
1142
+ channel,
1143
+ grid_h // merge_size,
1144
+ merge_size,
1145
+ patch_size,
1146
+ grid_w // merge_size,
1147
+ merge_size,
1148
+ patch_size,
1149
+ )
1150
+ patches = patches.permute(0, 1, 4, 7, 5, 8, 3, 2, 6, 9)
1151
+ flatten_patches = patches.reshape(
1152
+ batch_size,
1153
+ grid_t * grid_h * grid_w,
1154
+ channel * temporal_patch_size * patch_size * patch_size,
1155
+ )
1156
+
1157
+ processed_videos_grouped[shape] = flatten_patches
1158
+ processed_grids[shape] = [[grid_t, grid_h, grid_w]] * batch_size
1159
+
1160
+ processed_videos = reorder_videos(processed_videos_grouped, grouped_videos_index)
1161
+ processed_grids = reorder_videos(processed_grids, grouped_videos_index)
1162
+ pixel_values_videos = torch.cat(processed_videos, dim=0)
1163
+ video_grid_thw = torch.tensor(processed_grids)
1164
+ data = {
1165
+ "pixel_values_videos": pixel_values_videos,
1166
+ "video_grid_thw": video_grid_thw,
1167
+ }
1168
+
1169
+ return BatchFeature(data=data, tensor_type=return_tensors)
1170
+
1171
+ def preprocess(
1172
+ self,
1173
+ videos: Union[str, Dict[str, Any], List[Union[str, Dict[str, Any]]]],
1174
+ **kwargs,
1175
+ ) -> BatchFeature:
1176
+ """
1177
+ Preprocess videos for the model.
1178
+
1179
+ This method overrides the base class to handle two video input formats:
1180
+ 1. String path: "path/to/video.mp4"
1181
+ 2. Dict with segments: {"video_path": "...", "segment": [[start, end], [time], ...]}
1182
+
1183
+ Args:
1184
+ videos: Video input(s) in one of the supported formats.
1185
+ **kwargs: Additional arguments passed to _preprocess.
1186
+
1187
+ Returns:
1188
+ BatchFeature with pixel_values_videos, video_grid_thw, and optionally video_metadata.
1189
+ """
1190
+ # Validate kwargs
1191
+ validate_kwargs(
1192
+ captured_kwargs=kwargs.keys(),
1193
+ valid_processor_keys=list(self.valid_kwargs.__annotations__.keys()) + ["return_tensors"],
1194
+ )
1195
+
1196
+ # Set default kwargs from self
1197
+ for kwarg_name in self.valid_kwargs.__annotations__:
1198
+ kwargs.setdefault(kwarg_name, getattr(self, kwarg_name, None))
1199
+
1200
+ # Pop kwargs that are handled separately
1201
+ return_tensors = kwargs.pop("return_tensors", None)
1202
+ return_metadata = kwargs.pop("return_metadata", False)
1203
+ input_data_format = kwargs.pop("input_data_format", None)
1204
+ device = kwargs.pop("device", None)
1205
+ kwargs.pop("video_metadata", None) # We generate our own metadata
1206
+ kwargs.pop("do_sample_frames", None) # We handle sampling ourselves
1207
+ kwargs.pop("data_format", None) # Not used
1208
+
1209
+ # Normalize input to list format
1210
+ if not isinstance(videos, list):
1211
+ videos = [videos]
1212
+
1213
+ # Get video processing params from kwargs (may be passed explicitly for per-batch configuration)
1214
+ video_fps = kwargs.pop("video_fps", None)
1215
+ min_frames = kwargs.pop("min_frames", None)
1216
+ max_frames = kwargs.pop("max_frames", None)
1217
+
1218
+ # Use fetch_videos to handle both string and dict formats
1219
+ video_tensors, video_metadata = self.fetch_videos(
1220
+ videos,
1221
+ video_fps=video_fps,
1222
+ min_frames=min_frames,
1223
+ max_frames=max_frames,
1224
+ )
1225
+
1226
+ # Prepare video tensors using _prepare_input_videos
1227
+ prepared_videos = self._prepare_input_videos(
1228
+ videos=video_tensors,
1229
+ input_data_format=input_data_format,
1230
+ device=device,
1231
+ )
1232
+
1233
+ # Process kwargs for _preprocess
1234
+ kwargs = self._further_process_kwargs(**kwargs)
1235
+ self._validate_preprocess_kwargs(**kwargs)
1236
+
1237
+ # Call _preprocess with prepared videos
1238
+ result = self._preprocess(videos=prepared_videos, return_tensors=return_tensors, **kwargs)
1239
+
1240
+ # Add metadata if requested
1241
+ if return_metadata:
1242
+ result["video_metadata"] = video_metadata
1243
+
1244
+ return result
1245
+
1246
+
1247
+ __all__ = ["MossVLVideoProcessor"]
1248
+
vocab.json ADDED
The diff for this file is too large to render. See raw diff