bigshanedogg commited on
Commit
fdaa98e
·
verified ·
1 Parent(s): 55d092e

Upload folder using huggingface_hub

Browse files
__pycache__/configuration_cosyvoice2.cpython-312.pyc ADDED
Binary file (2.63 kB). View file
 
__pycache__/configuration_hyperclovax.cpython-312.pyc ADDED
Binary file (11.4 kB). View file
 
__pycache__/configuration_mambamia.cpython-312.pyc ADDED
Binary file (2.19 kB). View file
 
__pycache__/configuration_tatok.cpython-312.pyc ADDED
Binary file (3.42 kB). View file
 
audio_processing_hyperclovax_omni.py CHANGED
@@ -1,10 +1,21 @@
1
- import torch
 
 
 
 
 
 
 
 
 
 
 
2
  import numpy as np
3
- from typing import List, Union, Optional
4
  from transformers import BatchFeature
5
- from transformers.processing_utils import AudioKwargs
6
  from transformers.feature_extraction_sequence_utils import SequenceFeatureExtractor
7
- from transformers.audio_utils import mel_filter_bank, spectrogram, window_function
8
 
9
 
10
  class HyperCLOVAXOmniAudioKwargs(AudioKwargs, total=False):
@@ -29,6 +40,13 @@ class HyperCLOVAXOmniAudioKwargs(AudioKwargs, total=False):
29
 
30
 
31
  class HyperCLOVAXOmniAudioProcessor(SequenceFeatureExtractor):
 
 
 
 
 
 
 
32
  model_input_names = ["audio_values", "audio_masks", "discrete_audio_values"]
33
 
34
  def __init__(
@@ -93,17 +111,21 @@ class HyperCLOVAXOmniAudioProcessor(SequenceFeatureExtractor):
93
  mel_scale="slaney",
94
  )
95
 
96
- def _extract_fbank_features(self, waveform_batch: np.ndarray, device: str = "cpu") -> np.ndarray:
97
- """Waveform 배치에서 log-mel spectrogram 특징을 추출합니다.
 
 
 
 
98
 
99
- WhisperFeatureExtractor._torch_extract_fbank_features와 동일한 로직입니다.
100
 
101
  Args:
102
- waveform_batch: (batch_size, n_samples) shape의 waveform 배열.
103
- device: 연산에 사용할 디바이스. 기본 "cpu".
104
 
105
  Returns:
106
- (batch_size, feature_size, num_frames) shape의 log-mel spectrogram.
107
  """
108
  waveform = torch.from_numpy(waveform_batch).to(device, torch.float32)
109
  window = torch.hann_window(self.n_fft, device=device)
@@ -135,20 +157,19 @@ class HyperCLOVAXOmniAudioProcessor(SequenceFeatureExtractor):
135
  chunks: List[np.ndarray],
136
  sampling_rate: int,
137
  ) -> dict:
138
- """오디오 청크 리스트를 패딩하고 mel-spectrogram 추출합니다.
139
 
140
- 청크를 n_samples 길이로 패딩한 , mel-spectrogram 추출하고
141
- attention mask 생성합니다. WhisperFeatureExtractor.__call__의
142
- 핵심 로직을 대체합니다.
143
 
144
  Args:
145
- chunks: 1D numpy array 리스트. 배열은 하나의 오디오 청크.
146
- sampling_rate: 오디오 샘플링 레이트.
147
 
148
  Returns:
149
- dict with:
150
- - "input_features": (num_chunks, feature_size, nb_max_frames) numpy 배열.
151
- - "attention_mask": (num_chunks, nb_max_frames) numpy 배열.
152
  """
153
  n_samples = self.chunk_length * sampling_rate
154
  nb_max_frames = n_samples // self.hop_length
@@ -160,7 +181,7 @@ class HyperCLOVAXOmniAudioProcessor(SequenceFeatureExtractor):
160
  chunk = np.asarray(chunk, dtype=np.float32)
161
  chunk_len = len(chunk)
162
 
163
- # 패딩 또는 트렁케이션
164
  if chunk_len < n_samples:
165
  padded = np.full(n_samples, self.padding_value, dtype=np.float32)
166
  padded[:chunk_len] = chunk
@@ -170,11 +191,10 @@ class HyperCLOVAXOmniAudioProcessor(SequenceFeatureExtractor):
170
 
171
  padded_waveforms.append(padded)
172
 
173
- # Attention mask (sample-level frame-level)
174
  sample_mask = np.zeros(n_samples, dtype=np.int32)
175
  sample_mask[:chunk_len] = 1
176
  frame_mask = sample_mask[:: self.hop_length]
177
- # nb_max_frames 길이로 맞춤
178
  if len(frame_mask) > nb_max_frames:
179
  frame_mask = frame_mask[:nb_max_frames]
180
  elif len(frame_mask) < nb_max_frames:
@@ -190,75 +210,32 @@ class HyperCLOVAXOmniAudioProcessor(SequenceFeatureExtractor):
190
  "attention_mask": attention_mask,
191
  }
192
 
193
- def get_num_audio_tokens(
194
- self,
195
- audio_masks: "torch.Tensor",
196
- discrete_audio_values: Optional["torch.Tensor"] = None,
197
- include_boundary_tokens: bool = False,
198
- chunk_unit: Optional[int] = None,
199
- sampling_rate: Optional[int] = None,
200
- ) -> tuple:
201
- """오디오 입력에 대한 (continuous, discrete) 토큰 수를 계산합니다.
202
 
203
  Args:
204
- audio_masks: continuous audio의 attention mask. (N,) 또는 (num_chunks, N).
205
- discrete_audio_values: discrete audio waveform. None이면 discrete 계산 생략.
206
- include_boundary_tokens: start/end 토큰 포함 여부.
207
- chunk_unit: discrete 처리 시 청크 단위 (초). None이면 self.chunk_unit 사용.
208
- sampling_rate: 샘플링 레이트. None이면 self.sampling_rate 사용.
209
 
210
  Returns:
211
- (num_continuous_tokens, num_discrete_tokens) 튜플.
212
- discrete 미사용 시 num_discrete_tokens는 0.
213
  """
214
- chunk_unit = chunk_unit if chunk_unit is not None else self.chunk_unit
215
- sampling_rate = sampling_rate if sampling_rate is not None else self.sampling_rate
216
-
217
- def _compute_continuous_tokens(audio_mask: "torch.Tensor") -> int:
218
- input_length = (int(audio_mask.sum()) - 1) // 2 + 1
219
- return (input_length - 2) // 2 + 1
220
-
221
- num_continuous_tokens, num_discrete_tokens = 0, 0
222
- if len(audio_masks.shape) == 1:
223
- num_continuous_tokens = _compute_continuous_tokens(audio_masks)
224
- else:
225
- num_continuous_tokens = sum(_compute_continuous_tokens(m) for m in audio_masks)
226
- if include_boundary_tokens:
227
- num_continuous_tokens += 2 # audio_start_token, audio_end_token
228
 
229
- if (
230
- self.use_discrete_audio_token
231
- and discrete_audio_values is not None
232
- ):
233
- audio_length = len(discrete_audio_values)
234
- chunk_size = chunk_unit * sampling_rate
235
- for _start in range(0, audio_length, chunk_size):
236
- _end = min(_start + chunk_size, audio_length)
237
- _chunked_length = _end - _start
238
- mel_len = _chunked_length // 160
239
- after_conv1 = (mel_len + 2 * 1 - 1 * (3 - 1) - 1) // 2 + 1
240
- code_len = (after_conv1 + 2 * 1 - 1 * (3 - 1) - 1) // 2 + 1
241
- num_discrete_tokens += code_len
242
- if include_boundary_tokens:
243
- num_discrete_tokens += 2 # discrete_audio_start_token, discrete_audio_end_token
244
 
245
- return (num_continuous_tokens, num_discrete_tokens)
246
 
247
- def _get_feature_lengths(
248
- self,
249
- audio_masks: torch.Tensor,
250
- ):
251
- return (audio_masks.sum(-1) - 1) // 2 + 1
252
 
253
- def _get_attention_mask(
254
- self,
255
- audio_values: torch.Tensor,
256
- audio_masks: torch.Tensor,
257
- ):
258
  feature_lengths = self._get_feature_lengths(audio_masks=audio_masks)
259
- max_seq_len = (self.nb_max_frames - 2) // 2 + 1
260
  padding_mask = torch.arange(max_seq_len) >= feature_lengths.unsqueeze(1)
261
- attention_mask = padding_mask[:, None, None, :].expand(len(audio_values), 1, max_seq_len, max_seq_len)
262
  attention_mask = attention_mask.masked_fill(attention_mask, float("-inf"))
263
  return attention_mask
264
 
@@ -268,35 +245,32 @@ class HyperCLOVAXOmniAudioProcessor(SequenceFeatureExtractor):
268
  sampling_rate: Optional[int] = None,
269
  chunk_length: Optional[int] = None,
270
  ) -> dict:
271
- """오디오 클립들에 대한 continuous audio 전처리를 수행합니다.
272
 
273
- 오디오 클립을 chunk_length(초) 단위로 분할한 mel-spectrogram
274
- 특징을 추출하고, attention mask 기반으로 토큰 수를 계산합니다.
275
 
276
  Args:
277
- audio_clips: 오디오 클립 리스트.
278
- 클립은 1D numpy array (mono, float32).
279
- sampling_rate: 오디오 샘플링 레이트. None이면 self.sampling_rate 사용.
280
- chunk_length: 오디오를 분할할 단위 (초). None이면 self.chunk_length 사용.
281
 
282
  Returns:
283
- dict with:
284
- - "audio_values": (num_total_chunks, feature_size, nb_max_frames) 텐서.
285
- - "audio_masks": (num_total_chunks, nb_max_frames) 텐서.
286
- - "num_audio_tokens": (N,) 텐서. 클립별 continuous 토큰 .
 
287
  """
288
  sampling_rate = sampling_rate if sampling_rate is not None else self.sampling_rate
289
  chunk_length = chunk_length if chunk_length is not None else self.chunk_length
290
 
291
  if len(audio_clips) == 0:
292
- _audio_values = torch.zeros(0, self.feature_size, self.nb_max_frames)
293
- _audio_masks = torch.zeros(0, self.nb_max_frames)
294
  max_seq_len = (self.nb_max_frames - 2) // 2 + 1
295
- _audio_attention_mask = torch.zeros(0, 1, max_seq_len, max_seq_len)
296
  return {
297
- "audio_values": _audio_values,
298
- "_audio_attention_mask": _audio_attention_mask,
299
- "audio_masks": _audio_masks,
300
  "num_audio_tokens": torch.tensor([], dtype=torch.long),
301
  }
302
 
@@ -311,21 +285,19 @@ class HyperCLOVAXOmniAudioProcessor(SequenceFeatureExtractor):
311
 
312
  _audio_value = result["input_features"]
313
  _audio_mask = result["attention_mask"]
314
-
315
- input_lengths = int(_audio_mask.sum())
316
- input_lengths = (input_lengths - 1) // 2 + 1
317
- output_lengths = (input_lengths - 2) // 2 + 1
318
 
319
  _audio_values.append(torch.Tensor(_audio_value))
320
  _audio_masks.append(torch.Tensor(_audio_mask))
321
- _num_audio_tokens.append(output_lengths)
322
 
323
  _audio_values = torch.cat(_audio_values, dim=0)
324
  _audio_masks = torch.cat(_audio_masks, dim=0)
325
- _audio_attention_mask = self._get_attention_mask(
326
- audio_values=_audio_values,
327
- audio_masks=_audio_masks,
328
- )
329
  return {
330
  "audio_values": _audio_values,
331
  "audio_masks": _audio_masks,
@@ -340,23 +312,21 @@ class HyperCLOVAXOmniAudioProcessor(SequenceFeatureExtractor):
340
  chunk_unit: Optional[int] = None,
341
  min_chunk_size: Optional[int] = None,
342
  ) -> dict:
343
- """오디오 클립들에 대한 discrete audio 전처리를 수행합니다.
344
 
345
- 오디오 클립의 길이를 검증한 뒤, conv 레이어 기반으로
346
- discrete token 수를 계산합니다. 오디오 원본 waveform
347
- 패딩하여 텐서로 반환합니다.
348
 
349
  Args:
350
- audio_clips: 오디오 클립 리스트.
351
- 클립은 1D numpy array (mono, float32).
352
- sampling_rate: 오디오 샘플링 레이트. None이면 self.sampling_rate 사용.
353
- chunk_unit: 오디오를 분할할 단위 (초). None이면 self.chunk_unit 사용.
354
- min_chunk_size: 최소 오디오 길이 (샘플 수). None이면 self.min_chunk_size 사용.
355
 
356
  Returns:
357
- dict with:
358
- - "discrete_audio_values": (N, max_audio_len) 텐서. 패딩된 waveform.
359
- - "num_discrete_audio_tokens": (N,) 텐서. 클립별 discrete 토큰 .
360
  """
361
  sampling_rate = sampling_rate if sampling_rate is not None else self.sampling_rate
362
  chunk_unit = chunk_unit if chunk_unit is not None else self.chunk_unit
@@ -419,26 +389,29 @@ class HyperCLOVAXOmniAudioProcessor(SequenceFeatureExtractor):
419
  min_chunk_size: Optional[int] = None,
420
  **kwargs,
421
  ) -> BatchFeature:
422
- """오디오 클립들에 대한 전처리를 수행합니다.
423
 
424
- 오디오 클립 리스트에 대해 continuous audio 처리를 수행하고,
425
- use_discrete_audio_token이 True인 경우 discrete audio 처리도 추가로
426
- 수행합니다.
427
 
428
  Args:
429
- audios: 오디오 클립 리스트. 원소는 1D numpy array.
430
- sampling_rate: 오디오 샘플링 레이트. None이면 self.sampling_rate 사용.
431
- chunk_length: continuous 처리 오디오 분할 단위 (초). None이면 기본값 사용.
432
- chunk_unit: discrete 처리 시 오디오 분할 단위 (초). None이면 self.chunk_unit 사용.
433
- min_chunk_size: discrete 처리 최소 오디오 길이 (샘플 수). None이면 self.min_chunk_size 사용.
 
 
 
434
 
435
  Returns:
436
  BatchFeature with:
437
- - audio_values: (num_total_chunks, feature_size, nb_max_frames) 텐서.
438
- - audio_masks: (num_total_chunks, nb_max_frames) 텐서.
439
- - num_audio_tokens: (N,) 텐서. 클립별 continuous 토큰 .
440
- - discrete_audio_values (optional): (N, max_audio_len) 텐서.
441
- - num_discrete_audio_tokens (optional): (N,) 텐서. 클립별 discrete 토큰 수.
 
442
  """
443
  continuous_result = self._preprocess_continuous_audio(
444
  audios,
@@ -464,3 +437,60 @@ class HyperCLOVAXOmniAudioProcessor(SequenceFeatureExtractor):
464
  data["num_discrete_audio_tokens"] = discrete_result["num_discrete_audio_tokens"]
465
 
466
  return BatchFeature(data=data, tensor_type="pt")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ HyperCLOVAX Omni Audio Processor
3
+
4
+ Implements Whisper-compatible audio feature extraction:
5
+ - Log-mel spectrogram extraction from waveform
6
+ - Chunked processing for long audio clips
7
+ - Attention mask generation for padded sequences
8
+ - Discrete audio token count calculation (conv-based)
9
+ """
10
+
11
+ from typing import List, Optional
12
+
13
  import numpy as np
14
+ import torch
15
  from transformers import BatchFeature
16
+ from transformers.audio_utils import mel_filter_bank
17
  from transformers.feature_extraction_sequence_utils import SequenceFeatureExtractor
18
+ from transformers.processing_utils import AudioKwargs
19
 
20
 
21
  class HyperCLOVAXOmniAudioKwargs(AudioKwargs, total=False):
 
40
 
41
 
42
  class HyperCLOVAXOmniAudioProcessor(SequenceFeatureExtractor):
43
+ """Audio processor for HyperCLOVAX Omni.
44
+
45
+ Extracts Whisper-compatible log-mel spectrogram features and computes
46
+ attention masks for the audio encoder. Also supports discrete audio
47
+ token count calculation.
48
+ """
49
+
50
  model_input_names = ["audio_values", "audio_masks", "discrete_audio_values"]
51
 
52
  def __init__(
 
111
  mel_scale="slaney",
112
  )
113
 
114
+ def _extract_fbank_features(
115
+ self,
116
+ waveform_batch: np.ndarray,
117
+ device: str = "cpu",
118
+ ) -> np.ndarray:
119
+ """Extract log-mel spectrogram features from a waveform batch.
120
 
121
+ Follows the same logic as WhisperFeatureExtractor._torch_extract_fbank_features.
122
 
123
  Args:
124
+ waveform_batch: Waveform array of shape (batch_size, n_samples).
125
+ device: Device for computation. Defaults to "cpu".
126
 
127
  Returns:
128
+ Log-mel spectrogram of shape (batch_size, feature_size, num_frames).
129
  """
130
  waveform = torch.from_numpy(waveform_batch).to(device, torch.float32)
131
  window = torch.hann_window(self.n_fft, device=device)
 
157
  chunks: List[np.ndarray],
158
  sampling_rate: int,
159
  ) -> dict:
160
+ """Pad audio chunks and extract mel-spectrogram features.
161
 
162
+ Each chunk is padded to n_samples length, then mel-spectrogram is
163
+ extracted and an attention mask is generated.
 
164
 
165
  Args:
166
+ chunks: List of 1D numpy arrays, each representing an audio chunk.
167
+ sampling_rate: Audio sampling rate.
168
 
169
  Returns:
170
+ Dictionary with:
171
+ - "input_features": Array of shape (num_chunks, feature_size, nb_max_frames).
172
+ - "attention_mask": Array of shape (num_chunks, nb_max_frames).
173
  """
174
  n_samples = self.chunk_length * sampling_rate
175
  nb_max_frames = n_samples // self.hop_length
 
181
  chunk = np.asarray(chunk, dtype=np.float32)
182
  chunk_len = len(chunk)
183
 
184
+ # Pad or truncate
185
  if chunk_len < n_samples:
186
  padded = np.full(n_samples, self.padding_value, dtype=np.float32)
187
  padded[:chunk_len] = chunk
 
191
 
192
  padded_waveforms.append(padded)
193
 
194
+ # Attention mask (sample-level -> frame-level)
195
  sample_mask = np.zeros(n_samples, dtype=np.int32)
196
  sample_mask[:chunk_len] = 1
197
  frame_mask = sample_mask[:: self.hop_length]
 
198
  if len(frame_mask) > nb_max_frames:
199
  frame_mask = frame_mask[:nb_max_frames]
200
  elif len(frame_mask) < nb_max_frames:
 
210
  "attention_mask": attention_mask,
211
  }
212
 
213
+ def _get_feature_lengths(self, audio_masks: torch.Tensor) -> torch.Tensor:
214
+ """Compute feature lengths after conv downsampling.
 
 
 
 
 
 
 
215
 
216
  Args:
217
+ audio_masks: Attention mask of shape (batch, nb_max_frames).
 
 
 
 
218
 
219
  Returns:
220
+ Feature lengths tensor of shape (batch,).
 
221
  """
222
+ return (audio_masks.sum(-1) - 1) // 2 + 1
 
 
 
 
 
 
 
 
 
 
 
 
 
223
 
224
+ def _get_attention_mask(self, audio_masks: torch.Tensor) -> torch.Tensor:
225
+ """Generate attention mask for the audio encoder.
 
 
 
 
 
 
 
 
 
 
 
 
 
226
 
227
+ Creates a causal-style mask where padded positions are filled with -inf.
228
 
229
+ Args:
230
+ audio_masks: Attention mask of shape (batch, nb_max_frames).
 
 
 
231
 
232
+ Returns:
233
+ Attention mask of shape (batch, 1, max_seq_len, max_seq_len).
234
+ """
 
 
235
  feature_lengths = self._get_feature_lengths(audio_masks=audio_masks)
236
+ max_seq_len = (self.nb_max_frames - 2) // 2 + 1
237
  padding_mask = torch.arange(max_seq_len) >= feature_lengths.unsqueeze(1)
238
+ attention_mask = padding_mask[:, None, None, :].expand(padding_mask.shape[0], 1, max_seq_len, max_seq_len)
239
  attention_mask = attention_mask.masked_fill(attention_mask, float("-inf"))
240
  return attention_mask
241
 
 
245
  sampling_rate: Optional[int] = None,
246
  chunk_length: Optional[int] = None,
247
  ) -> dict:
248
+ """Preprocess audio clips for continuous audio features.
249
 
250
+ Splits each audio clip into chunks of chunk_length seconds, extracts
251
+ mel-spectrogram features, and computes token counts from attention masks.
252
 
253
  Args:
254
+ audio_clips: List of audio clips, each a 1D numpy array (mono, float32).
255
+ sampling_rate: Audio sampling rate. Defaults to self.sampling_rate.
256
+ chunk_length: Chunk duration in seconds. Defaults to self.chunk_length.
 
257
 
258
  Returns:
259
+ Dictionary with:
260
+ - "audio_values": Tensor of shape (num_total_chunks, feature_size, nb_max_frames).
261
+ - "audio_masks": Tensor of shape (num_total_chunks, nb_max_frames).
262
+ - "audio_attention_mask": Tensor of shape (num_total_chunks, max_seq_len, max_seq_len).
263
+ - "num_audio_tokens": Tensor of shape (N,) with per-clip continuous token counts.
264
  """
265
  sampling_rate = sampling_rate if sampling_rate is not None else self.sampling_rate
266
  chunk_length = chunk_length if chunk_length is not None else self.chunk_length
267
 
268
  if len(audio_clips) == 0:
 
 
269
  max_seq_len = (self.nb_max_frames - 2) // 2 + 1
 
270
  return {
271
+ "audio_values": torch.zeros(0, self.feature_size, self.nb_max_frames),
272
+ "audio_masks": torch.zeros(0, self.nb_max_frames),
273
+ "audio_attention_mask": torch.zeros(0, max_seq_len, max_seq_len),
274
  "num_audio_tokens": torch.tensor([], dtype=torch.long),
275
  }
276
 
 
285
 
286
  _audio_value = result["input_features"]
287
  _audio_mask = result["attention_mask"]
288
+ _num_audio_token = 0
289
+ for _mask in _audio_mask:
290
+ _input_length = (_mask.shape[-1] - 1) // 2 + 1
291
+ _num_audio_token += (_input_length - 2) // 2 + 1
292
 
293
  _audio_values.append(torch.Tensor(_audio_value))
294
  _audio_masks.append(torch.Tensor(_audio_mask))
295
+ _num_audio_tokens.append(_num_audio_token)
296
 
297
  _audio_values = torch.cat(_audio_values, dim=0)
298
  _audio_masks = torch.cat(_audio_masks, dim=0)
299
+ _audio_attention_mask = self._get_attention_mask(audio_masks=_audio_masks)
300
+
 
 
301
  return {
302
  "audio_values": _audio_values,
303
  "audio_masks": _audio_masks,
 
312
  chunk_unit: Optional[int] = None,
313
  min_chunk_size: Optional[int] = None,
314
  ) -> dict:
315
+ """Preprocess audio clips for discrete audio tokens.
316
 
317
+ Validates each audio clip and computes the number of discrete tokens
318
+ based on conv layer downsampling. Returns padded waveform tensors.
 
319
 
320
  Args:
321
+ audio_clips: List of audio clips, each a 1D numpy array (mono, float32).
322
+ sampling_rate: Audio sampling rate. Defaults to self.sampling_rate.
323
+ chunk_unit: Chunk duration in seconds for long audio. Defaults to self.chunk_unit.
324
+ min_chunk_size: Minimum audio length in samples. Defaults to self.min_chunk_size.
 
325
 
326
  Returns:
327
+ Dictionary with:
328
+ - "discrete_audio_values": Tensor of shape (N, max_audio_len).
329
+ - "num_discrete_audio_tokens": Tensor of shape (N,) with per-clip discrete token counts.
330
  """
331
  sampling_rate = sampling_rate if sampling_rate is not None else self.sampling_rate
332
  chunk_unit = chunk_unit if chunk_unit is not None else self.chunk_unit
 
389
  min_chunk_size: Optional[int] = None,
390
  **kwargs,
391
  ) -> BatchFeature:
392
+ """Preprocess a list of audio clips.
393
 
394
+ Performs continuous audio processing on all clips. If use_discrete_audio_token
395
+ is enabled, discrete audio processing is also performed.
 
396
 
397
  Args:
398
+ audios: List of audio clips, each a 1D numpy array.
399
+ sampling_rate: Audio sampling rate. Defaults to self.sampling_rate.
400
+ chunk_length: Chunk duration in seconds for continuous processing.
401
+ Defaults to self.chunk_length.
402
+ chunk_unit: Chunk duration in seconds for discrete processing.
403
+ Defaults to self.chunk_unit.
404
+ min_chunk_size: Minimum audio length in samples for discrete processing.
405
+ Defaults to self.min_chunk_size.
406
 
407
  Returns:
408
  BatchFeature with:
409
+ - audio_values: Tensor of shape (num_total_chunks, feature_size, nb_max_frames).
410
+ - audio_masks: Tensor of shape (num_total_chunks, nb_max_frames).
411
+ - audio_attention_mask: Tensor of shape (num_total_chunks, max_seq_len, max_seq_len).
412
+ - num_audio_tokens: Tensor of shape (N,) with per-clip continuous token counts.
413
+ - discrete_audio_values (optional): Tensor of shape (N, max_audio_len).
414
+ - num_discrete_audio_tokens (optional): Tensor of shape (N,) with per-clip discrete token counts.
415
  """
416
  continuous_result = self._preprocess_continuous_audio(
417
  audios,
 
437
  data["num_discrete_audio_tokens"] = discrete_result["num_discrete_audio_tokens"]
438
 
439
  return BatchFeature(data=data, tensor_type="pt")
440
+
441
+ def get_num_audio_tokens(
442
+ self,
443
+ audio_masks: torch.Tensor,
444
+ discrete_audio_values: Optional[torch.Tensor] = None,
445
+ include_boundary_tokens: bool = False,
446
+ chunk_unit: Optional[int] = None,
447
+ sampling_rate: Optional[int] = None,
448
+ return_tuple: Optional[bool] = None,
449
+ ) -> int:
450
+ """Compute the number of audio tokens for the given input.
451
+
452
+ Args:
453
+ audio_masks: Attention mask for continuous audio. Shape (N,) or (num_chunks, N).
454
+ discrete_audio_values: Discrete audio waveform. None to skip discrete computation.
455
+ include_boundary_tokens: Whether to include start/end boundary tokens.
456
+ chunk_unit: Chunk duration in seconds for discrete processing.
457
+ Defaults to self.chunk_unit.
458
+ sampling_rate: Audio sampling rate. Defaults to self.sampling_rate.
459
+ return_tuple: If True, return (continuous, discrete) tuple.
460
+ Otherwise return the sum.
461
+
462
+ Returns:
463
+ Token count as int, or (continuous, discrete) tuple if return_tuple is True.
464
+ """
465
+ chunk_unit = chunk_unit if chunk_unit is not None else self.chunk_unit
466
+ sampling_rate = sampling_rate if sampling_rate is not None else self.sampling_rate
467
+
468
+ def _compute_continuous_tokens(audio_mask: torch.Tensor) -> int:
469
+ input_length = (audio_mask.shape[-1] - 1) // 2 + 1
470
+ return (input_length - 2) // 2 + 1
471
+
472
+ num_continuous_tokens, num_discrete_tokens = 0, 0
473
+ if len(audio_masks.shape) == 1:
474
+ num_continuous_tokens = _compute_continuous_tokens(audio_masks)
475
+ else:
476
+ num_continuous_tokens = sum(_compute_continuous_tokens(m) for m in audio_masks)
477
+ if include_boundary_tokens:
478
+ num_continuous_tokens += 2
479
+
480
+ if self.use_discrete_audio_token and discrete_audio_values is not None:
481
+ audio_length = len(discrete_audio_values)
482
+ chunk_size = chunk_unit * sampling_rate
483
+ for _start in range(0, audio_length, chunk_size):
484
+ _end = min(_start + chunk_size, audio_length)
485
+ _chunked_length = _end - _start
486
+ mel_len = _chunked_length // 160
487
+ after_conv1 = (mel_len + 2 * 1 - 1 * (3 - 1) - 1) // 2 + 1
488
+ code_len = (after_conv1 + 2 * 1 - 1 * (3 - 1) - 1) // 2 + 1
489
+ num_discrete_tokens += code_len
490
+ if include_boundary_tokens:
491
+ num_discrete_tokens += 2
492
+
493
+ if return_tuple:
494
+ return (num_continuous_tokens, num_discrete_tokens)
495
+ else:
496
+ return num_continuous_tokens + num_discrete_tokens
chat_template.jinja CHANGED
@@ -78,7 +78,7 @@
78
  {%- set image_id = 'image_%02d' % ns_img.count %}
79
  {%- set ns_img.count = ns_img.count + 1 %}
80
  {{- '<|mime_start|>{"id": "' + image_id + '", "type": "image/jpeg", "filename": "' + content.get('filename', "a.jpg") + '"}<|mime_end|>\n' }}
81
- {{- '<|discrete_image_start|><|DISCRETE_IMAGE_PAD|><|discrete_image_end|>'}}
82
  {{- '<|image_start|><|IMAGE_PAD|><|image_end|>' }}
83
  {%- elif content['type'] == 'video' or 'video' in content or 'video_url' in content %}
84
  {%- set video_id = 'video_%02d' % ns_vid.count %}
@@ -91,7 +91,7 @@
91
  {%- set ns_aud.count = ns_aud.count + 1 %}
92
  {{- '<|mime_start|>{"id": "' + audio_id + '", "type": "audio/wav", "filename": "' + content.get('filename', "a.wav") + '"}<|mime_end|>\n' }}
93
  {{- '<|audio_aux_start|>다음 중 audio_duration은 오디오 길이 정보입니다. 참고하여 답변하세요. {"audio_duration": ' + (content.get('audio_duration') | tojson if content.get('audio_duration') else '<|audio_duration|>') + '}<|audio_aux_end|>\n'}}
94
- {{- '<|discrete_audio_start|><|DISCRETE_AUDIO_PAD|><|discrete_audio_end|>'}}
95
  {{- '<|audio_start|><|AUDIO_PAD|><|audio_end|>'}}
96
  {%- elif content['type'] == 'text' %}
97
  {{- content['text'] }}
 
78
  {%- set image_id = 'image_%02d' % ns_img.count %}
79
  {%- set ns_img.count = ns_img.count + 1 %}
80
  {{- '<|mime_start|>{"id": "' + image_id + '", "type": "image/jpeg", "filename": "' + content.get('filename', "a.jpg") + '"}<|mime_end|>\n' }}
81
+ {{- '<|discrete_image_start|><|DISCRETE_IMAGE_PAD|><|discrete_image_end|>\n'}}
82
  {{- '<|image_start|><|IMAGE_PAD|><|image_end|>' }}
83
  {%- elif content['type'] == 'video' or 'video' in content or 'video_url' in content %}
84
  {%- set video_id = 'video_%02d' % ns_vid.count %}
 
91
  {%- set ns_aud.count = ns_aud.count + 1 %}
92
  {{- '<|mime_start|>{"id": "' + audio_id + '", "type": "audio/wav", "filename": "' + content.get('filename', "a.wav") + '"}<|mime_end|>\n' }}
93
  {{- '<|audio_aux_start|>다음 중 audio_duration은 오디오 길이 정보입니다. 참고하여 답변하세요. {"audio_duration": ' + (content.get('audio_duration') | tojson if content.get('audio_duration') else '<|audio_duration|>') + '}<|audio_aux_end|>\n'}}
94
+ {{- '<|discrete_audio_start|><|DISCRETE_AUDIO_PAD|><|discrete_audio_end|>\n'}}
95
  {{- '<|audio_start|><|AUDIO_PAD|><|audio_end|>'}}
96
  {%- elif content['type'] == 'text' %}
97
  {{- content['text'] }}
config.json CHANGED
@@ -4,89 +4,28 @@
4
  "HyperCLOVAXOmniForCausalLM"
5
  ],
6
  "audio_config": {
7
- "_name_or_path": "",
8
  "activation_dropout": 0.0,
9
  "activation_function": "gelu",
10
- "add_cross_attention": false,
11
  "architectures": [
12
  "Qwen2AudioEncoder"
13
  ],
14
  "attention_dropout": 0.0,
15
- "bad_words_ids": null,
16
- "begin_suppress_tokens": null,
17
- "bos_token_id": null,
18
- "chunk_size_feed_forward": 0,
19
- "cross_attention_hidden_size": null,
20
  "d_model": 1280,
21
- "decoder_start_token_id": null,
22
- "diversity_penalty": 0.0,
23
- "do_sample": false,
24
  "dropout": 0.0,
25
- "early_stopping": false,
26
  "encoder_attention_heads": 20,
27
  "encoder_ffn_dim": 5120,
28
  "encoder_layerdrop": 0.0,
29
  "encoder_layers": 32,
30
- "encoder_no_repeat_ngram_size": 0,
31
- "eos_token_id": null,
32
- "exponential_decay_length_penalty": null,
33
- "finetuning_task": null,
34
- "forced_bos_token_id": null,
35
- "forced_eos_token_id": null,
36
- "id2label": {
37
- "0": "LABEL_0",
38
- "1": "LABEL_1"
39
- },
40
  "init_std": 0.02,
41
  "initializer_range": 0.02,
42
- "is_decoder": false,
43
- "is_encoder_decoder": false,
44
- "label2id": {
45
- "LABEL_0": 0,
46
- "LABEL_1": 1
47
- },
48
- "length_penalty": 1.0,
49
- "max_length": 20,
50
  "max_source_positions": 1500,
51
- "min_length": 0,
52
  "model_type": "qwen2_audio_encoder",
53
- "no_repeat_ngram_size": 0,
54
- "num_beam_groups": 1,
55
- "num_beams": 1,
56
  "num_hidden_layers": 32,
57
  "num_mel_bins": 128,
58
- "num_return_sequences": 1,
59
- "output_attentions": false,
60
- "output_hidden_states": false,
61
- "output_scores": false,
62
- "pad_token_id": null,
63
- "prefix": null,
64
- "problem_type": null,
65
- "pruned_heads": {},
66
- "remove_invalid_values": false,
67
- "repetition_penalty": 1.0,
68
- "return_dict": true,
69
- "return_dict_in_generate": false,
70
- "scale_embedding": false,
71
- "sep_token_id": null,
72
- "suppress_tokens": null,
73
- "task_specific_params": null,
74
- "temperature": 1.0,
75
- "tf_legacy_loss": false,
76
- "tie_encoder_decoder": false,
77
- "tie_word_embeddings": true,
78
- "tokenizer_class": null,
79
- "top_k": 50,
80
- "top_p": 1.0,
81
- "torch_dtype": "float32",
82
- "torchscript": false,
83
- "typical_p": 1.0,
84
- "use_bfloat16": false
85
  },
86
  "audio_end_token_id": 128257,
87
- "audio_model_name_or_path": null,
88
  "audio_projector_type": "mlp",
89
- "audio_start_id": 128071,
90
  "audio_start_token_id": 128256,
91
  "audio_token_id": 128071,
92
  "auto_map": {
@@ -95,8 +34,6 @@
95
  "AutoModelForSequenceClassification": "modeling_hyperclovax_omni.HyperCLOVAXOmniForSequenceClassification"
96
  },
97
  "discrete_audio_config": {
98
- "_name_or_path": "",
99
- "add_cross_attention": false,
100
  "architectures": [
101
  "CosyvoiceEncoder"
102
  ],
@@ -104,34 +41,6 @@
104
  "AutoConfig": "configuration_cosyvoice2.CosyVoice2Config",
105
  "AutoModel": "modeling_cosyvoice2.CosyVoice2Model"
106
  },
107
- "bad_words_ids": null,
108
- "begin_suppress_tokens": null,
109
- "bos_token_id": null,
110
- "chunk_size_feed_forward": 0,
111
- "cross_attention_hidden_size": null,
112
- "decoder_start_token_id": null,
113
- "diversity_penalty": 0.0,
114
- "do_sample": false,
115
- "early_stopping": false,
116
- "encoder_no_repeat_ngram_size": 0,
117
- "eos_token_id": null,
118
- "exponential_decay_length_penalty": null,
119
- "finetuning_task": null,
120
- "forced_bos_token_id": null,
121
- "forced_eos_token_id": null,
122
- "id2label": {
123
- "0": "LABEL_0",
124
- "1": "LABEL_1"
125
- },
126
- "is_decoder": false,
127
- "is_encoder_decoder": false,
128
- "label2id": {
129
- "LABEL_0": 0,
130
- "LABEL_1": 1
131
- },
132
- "length_penalty": 1.0,
133
- "max_length": 20,
134
- "min_length": 0,
135
  "model_type": "cosyvoice2",
136
  "n_audio_ctx": 1500,
137
  "n_audio_head": 20,
@@ -139,39 +48,9 @@
139
  "n_audio_state": 1280,
140
  "n_codebook_size": 6561,
141
  "n_mels": 128,
142
- "no_repeat_ngram_size": 0,
143
- "num_beam_groups": 1,
144
- "num_beams": 1,
145
- "num_return_sequences": 1,
146
- "output_attentions": false,
147
- "output_hidden_states": false,
148
- "output_scores": false,
149
- "pad_token_id": null,
150
- "prefix": null,
151
- "problem_type": null,
152
- "pruned_heads": {},
153
- "remove_invalid_values": false,
154
- "repetition_penalty": 1.0,
155
- "return_dict": true,
156
- "return_dict_in_generate": false,
157
- "sep_token_id": null,
158
- "suppress_tokens": null,
159
- "task_specific_params": null,
160
- "temperature": 1.0,
161
- "tf_legacy_loss": false,
162
- "tie_encoder_decoder": false,
163
- "tie_word_embeddings": true,
164
- "tokenizer_class": null,
165
- "top_k": 50,
166
- "top_p": 1.0,
167
- "torch_dtype": "float32",
168
- "torchscript": false,
169
- "typical_p": 1.0,
170
- "use_bfloat16": false,
171
  "use_sdpa": true
172
  },
173
  "discrete_audio_end_token_id": 128073,
174
- "discrete_audio_model_name_or_path": null,
175
  "discrete_audio_start_token_id": 128072,
176
  "discrete_audio_token_id": 128074,
177
  "discrete_audio_unit_0_id": 128606,
@@ -180,9 +59,6 @@
180
  "discrete_image_token_id": 128069,
181
  "discrete_image_unit_0_id": 135168,
182
  "discrete_vision_config": {
183
- "_name_or_path": "",
184
-
185
- "add_cross_attention": false,
186
  "architectures": [
187
  "TextAlignedTokenizer"
188
  ],
@@ -190,9 +66,6 @@
190
  "AutoConfig": "configuration_tatok.TATokConfig",
191
  "AutoModel": "modeling_tatok.TATokModel"
192
  },
193
- "bad_words_ids": null,
194
- "begin_suppress_tokens": null,
195
- "bos_token_id": null,
196
  "bottleneck": {
197
  "args": {
198
  "bottleneck_dim": 1536,
@@ -217,85 +90,21 @@
217
  "name": "bottleneck"
218
  },
219
  "bottleneck_token_num": 729,
220
- "chunk_size_feed_forward": 0,
221
- "ckpt_path": "google/siglip2-so400m-patch14-384",
222
- "cross_attention_hidden_size": null,
223
  "decoder_depth": 3,
224
- "decoder_start_token_id": null,
225
- "diversity_penalty": 0.0,
226
- "do_sample": false,
227
- "early_stopping": false,
228
- "encoder_no_repeat_ngram_size": 0,
229
- "eos_token_id": null,
230
- "exponential_decay_length_penalty": null,
231
- "finetuning_task": null,
232
- "forced_bos_token_id": null,
233
- "forced_eos_token_id": null,
234
- "id2label": {
235
- "0": "LABEL_0",
236
- "1": "LABEL_1"
237
- },
238
  "input_size": 384,
239
  "input_type": "indices",
240
- "is_decoder": false,
241
- "is_encoder_decoder": false,
242
- "label2id": {
243
- "LABEL_0": 0,
244
- "LABEL_1": 1
245
- },
246
- "length_penalty": 1.0,
247
- "max_length": 20,
248
- "min_length": 0,
249
  "model_type": "tatok",
250
- "no_repeat_ngram_size": 0,
251
- "num_beam_groups": 1,
252
- "num_beams": 1,
253
- "num_return_sequences": 1,
254
- "output_attentions": false,
255
- "output_hidden_states": false,
256
- "output_scores": false,
257
- "pad_token_id": null,
258
  "pool_scale": 1,
259
- "prefix": null,
260
- "problem_type": null,
261
- "pruned_heads": {},
262
  "rand_scale": true,
263
- "remove_invalid_values": false,
264
- "repetition_penalty": 1.0,
265
- "return_dict": true,
266
- "return_dict_in_generate": false,
267
  "select_layer_id": -2,
268
- "sep_token_id": null,
269
- "suppress_tokens": null,
270
- "task_specific_params": null,
271
- "teacher": "google/siglip2-so400m-patch14-384",
272
- "temperature": 1.0,
273
- "tf_legacy_loss": false,
274
- "tie_encoder_decoder": false,
275
- "tie_word_embeddings": true,
276
- "tokenizer_class": null,
277
- "top_k": 50,
278
- "top_p": 1.0,
279
- "torch_dtype": "float32",
280
- "torchscript": false,
281
- "typical_p": 1.0,
282
- "use_bfloat16": false
283
  },
284
- "discrete_vision_model_name_or_path": null,
285
- "end_token_id": 128001,
286
  "eos_token_id": 128001,
287
- "freeze_audio_projector": true,
288
- "freeze_before_sampler": false,
289
- "freeze_decoder": false,
290
- "freeze_encoder": true,
291
- "freeze_mm_projector": false,
292
- "freeze_video_audio_compressor": false,
293
  "hidden_size": 4096,
294
  "ignore_index": -100,
295
  "image_end_token_id": 128058,
296
  "image_start_token_id": 128059,
297
  "image_token_id": 128062,
298
- "img_start_id": 128062,
299
  "is_safetensor_save": true,
300
  "max_num_grids": -1,
301
  "mm_projector_type": "linear",
@@ -305,95 +114,35 @@
305
  "possible_resolutions": [],
306
  "proj_pos_emb": true,
307
  "proj_prenorm": false,
308
- "q_former_model_name_or_path": null,
309
- "skip_ve_mlp_infer": true,
310
  "text_config": {
311
- "_name_or_path": "",
312
- "add_cross_attention": false,
313
  "architectures": [
314
  "LlamaForCausalLM"
315
  ],
316
  "attention_bias": false,
317
  "attention_dropout": 0.0,
318
- "bad_words_ids": null,
319
- "begin_suppress_tokens": null,
320
  "bos_token_id": 128000,
321
- "chunk_size_feed_forward": 0,
322
- "cross_attention_hidden_size": null,
323
- "decoder_start_token_id": null,
324
- "diversity_penalty": 0.0,
325
- "do_sample": false,
326
- "early_stopping": false,
327
- "encoder_no_repeat_ngram_size": 0,
328
  "eos_token_id": 128001,
329
- "exponential_decay_length_penalty": null,
330
- "finetuning_task": null,
331
- "forced_bos_token_id": null,
332
- "forced_eos_token_id": null,
333
  "head_dim": 128,
334
  "hidden_act": "silu",
335
  "hidden_size": 4096,
336
- "id2label": {
337
- "0": "LABEL_0",
338
- "1": "LABEL_1"
339
- },
340
  "initializer_range": 0.02,
341
  "intermediate_size": 12288,
342
- "is_decoder": false,
343
- "is_encoder_decoder": false,
344
- "label2id": {
345
- "LABEL_0": 0,
346
- "LABEL_1": 1
347
- },
348
- "length_penalty": 1.0,
349
  "logits_scaling": 1.0,
350
- "max_length": 20,
351
  "max_position_embeddings": 8192,
352
- "min_length": 0,
353
  "mlp_bias": false,
354
  "model_type": "llama",
355
- "no_repeat_ngram_size": 0,
356
  "num_attention_heads": 32,
357
- "num_beam_groups": 1,
358
- "num_beams": 1,
359
  "num_hidden_layers": 36,
360
  "num_key_value_heads": 8,
361
- "num_return_sequences": 1,
362
- "output_attentions": false,
363
- "output_hidden_states": false,
364
- "output_scores": false,
365
- "pad_token_id": null,
366
- "prefix": null,
367
  "pretraining_tp": 1,
368
- "problem_type": null,
369
- "pruned_heads": {},
370
- "remove_invalid_values": false,
371
- "repetition_penalty": 1.0,
372
- "return_dict": true,
373
- "return_dict_in_generate": false,
374
  "rms_norm_eps": 1e-06,
375
  "rope_scaling": null,
376
  "rope_theta": 5000000,
377
- "sep_token_id": null,
378
- "suppress_tokens": null,
379
- "task_specific_params": null,
380
- "temperature": 1.0,
381
- "tf_legacy_loss": false,
382
- "tie_encoder_decoder": false,
383
  "tie_word_embeddings": false,
384
- "tokenizer_class": null,
385
- "top_k": 50,
386
- "top_p": 1.0,
387
- "torch_dtype": "float32",
388
- "torchscript": false,
389
- "typical_p": 1.0,
390
- "use_bfloat16": false,
391
  "use_cache": true,
392
  "vocab_size": 200704
393
  },
394
- "text_model_name_or_path": "",
395
  "torch_dtype": "float32",
396
- "transformers_version": "4.52.4",
397
  "unpad": false,
398
  "use_1x1_grid": false,
399
  "use_components": {
@@ -403,112 +152,34 @@
403
  "use_discrete_audio": true,
404
  "use_discrete_vision": true
405
  },
406
- "use_nth_layer": -2,
407
  "video_audio_compressor_config": {
408
- "_name_or_path": "",
409
- "add_cross_attention": false,
410
  "architectures": null,
411
  "auto_map": {
412
  "AutoConfig": "configuration_mambamia.MambaMiaVideoAudioCompressorConfig",
413
  "AutoModel": "modeling_mambamia.MambaMiaVideoAudioCompressor"
414
  },
415
- "bad_words_ids": null,
416
- "begin_suppress_tokens": null,
417
- "bos_token_id": null,
418
  "chunk_size": 25,
419
- "chunk_size_feed_forward": 0,
420
- "cross_attention_hidden_size": null,
421
- "decoder_start_token_id": null,
422
- "diversity_penalty": 0.0,
423
- "do_sample": false,
424
- "early_stopping": false,
425
- "encoder_no_repeat_ngram_size": 0,
426
- "eos_token_id": null,
427
- "exponential_decay_length_penalty": null,
428
- "finetuning_task": null,
429
- "forced_bos_token_id": null,
430
- "forced_eos_token_id": null,
431
  "hidden_size": 3072,
432
- "id2label": {
433
- "0": "LABEL_0",
434
- "1": "LABEL_1"
435
- },
436
  "input_size": 4096,
437
- "is_decoder": false,
438
- "is_encoder_decoder": false,
439
- "label2id": {
440
- "LABEL_0": 0,
441
- "LABEL_1": 1
442
- },
443
- "length_penalty": 1.0,
444
- "max_length": 20,
445
- "min_length": 0,
446
  "model_type": "mambamia_videoaudio_compressor",
447
- "no_repeat_ngram_size": 0,
448
- "num_beam_groups": 1,
449
- "num_beams": 1,
450
  "num_hidden_layers": 1,
451
- "num_return_sequences": 1,
452
- "output_attentions": false,
453
- "output_hidden_states": false,
454
- "output_scores": false,
455
- "output_size": 4096,
456
- "pad_token_id": null,
457
- "prefix": null,
458
- "problem_type": null,
459
- "pruned_heads": {},
460
- "remove_invalid_values": false,
461
- "repetition_penalty": 1.0,
462
- "return_dict": true,
463
- "return_dict_in_generate": false,
464
- "sep_token_id": null,
465
- "suppress_tokens": null,
466
- "task_specific_params": null,
467
- "temperature": 1.0,
468
- "tf_legacy_loss": false,
469
- "tie_encoder_decoder": false,
470
- "tie_word_embeddings": true,
471
- "tokenizer_class": null,
472
- "top_k": 50,
473
- "top_p": 1.0,
474
- "torch_dtype": null,
475
- "torchscript": false,
476
- "typical_p": 1.0,
477
- "use_bfloat16": false
478
  },
479
  "video_audio_compressor_type": "mambamia",
480
- "video_audio_start_id": 128070,
481
  "video_audio_token_id": 128070,
482
  "video_end_token_id": 128061,
483
  "video_first_last_frames_slows": null,
484
  "video_num_queries_fast": null,
485
  "video_num_queries_slow": null,
486
- "video_start_id": 128063,
487
  "video_start_token_id": 128060,
488
  "video_token_id": 128063,
489
  "vision_config": {
490
- "_name_or_path": "",
491
- "add_cross_attention": false,
492
  "anyres": false,
493
  "architectures": [
494
  "Qwen2_5_VisionTransformerPretrainedModel"
495
  ],
496
- "bad_words_ids": null,
497
- "begin_suppress_tokens": null,
498
- "bos_token_id": null,
499
- "chunk_size_feed_forward": 0,
500
- "cross_attention_hidden_size": null,
501
- "decoder_start_token_id": null,
502
  "depth": 32,
503
- "diversity_penalty": 0.0,
504
- "do_sample": false,
505
- "early_stopping": false,
506
- "encoder_no_repeat_ngram_size": 0,
507
- "eos_token_id": null,
508
- "exponential_decay_length_penalty": null,
509
- "finetuning_task": null,
510
- "forced_bos_token_id": null,
511
- "forced_eos_token_id": null,
512
  "fullatt_block_indexes": [
513
  7,
514
  15,
@@ -517,63 +188,20 @@
517
  ],
518
  "hidden_act": "silu",
519
  "hidden_size": 1280,
520
- "id2label": {
521
- "0": "LABEL_0",
522
- "1": "LABEL_1"
523
- },
524
  "in_channels": 3,
525
  "in_chans": 3,
526
  "initializer_range": 0.02,
527
  "intermediate_size": 3456,
528
- "is_decoder": false,
529
- "is_encoder_decoder": false,
530
- "label2id": {
531
- "LABEL_0": 0,
532
- "LABEL_1": 1
533
- },
534
- "length_penalty": 1.0,
535
- "max_length": 20,
536
  "max_num_grids": -1,
537
- "min_length": 0,
538
  "model_type": "qwen2_5_vl_visual",
539
- "no_repeat_ngram_size": 0,
540
- "num_beam_groups": 1,
541
- "num_beams": 1,
542
  "num_heads": 16,
543
- "num_return_sequences": 1,
544
  "out_hidden_size": 5120,
545
- "output_attentions": false,
546
- "output_hidden_states": false,
547
- "output_scores": false,
548
- "pad_token_id": null,
549
  "patch_size": 14,
550
- "prefix": null,
551
- "problem_type": null,
552
- "pruned_heads": {},
553
- "remove_invalid_values": false,
554
- "repetition_penalty": 1.0,
555
- "return_dict": true,
556
- "return_dict_in_generate": false,
557
- "sep_token_id": null,
558
  "spatial_merge_size": 2,
559
  "spatial_patch_size": 14,
560
- "suppress_tokens": null,
561
- "task_specific_params": null,
562
- "temperature": 1.0,
563
  "temporal_patch_size": 2,
564
- "tf_legacy_loss": false,
565
- "tie_encoder_decoder": false,
566
- "tie_word_embeddings": true,
567
- "tokenizer_class": null,
568
  "tokens_per_second": 2,
569
- "top_k": 50,
570
- "top_p": 1.0,
571
- "torch_dtype": "float32",
572
- "torchscript": false,
573
- "typical_p": 1.0,
574
- "use_bfloat16": false,
575
  "window_size": 112
576
  },
577
- "vision_input_chunk_size": null,
578
- "vision_model_name_or_path": null
579
  }
 
4
  "HyperCLOVAXOmniForCausalLM"
5
  ],
6
  "audio_config": {
 
7
  "activation_dropout": 0.0,
8
  "activation_function": "gelu",
 
9
  "architectures": [
10
  "Qwen2AudioEncoder"
11
  ],
12
  "attention_dropout": 0.0,
 
 
 
 
 
13
  "d_model": 1280,
 
 
 
14
  "dropout": 0.0,
 
15
  "encoder_attention_heads": 20,
16
  "encoder_ffn_dim": 5120,
17
  "encoder_layerdrop": 0.0,
18
  "encoder_layers": 32,
 
 
 
 
 
 
 
 
 
 
19
  "init_std": 0.02,
20
  "initializer_range": 0.02,
 
 
 
 
 
 
 
 
21
  "max_source_positions": 1500,
 
22
  "model_type": "qwen2_audio_encoder",
 
 
 
23
  "num_hidden_layers": 32,
24
  "num_mel_bins": 128,
25
+ "scale_embedding": false
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  },
27
  "audio_end_token_id": 128257,
 
28
  "audio_projector_type": "mlp",
 
29
  "audio_start_token_id": 128256,
30
  "audio_token_id": 128071,
31
  "auto_map": {
 
34
  "AutoModelForSequenceClassification": "modeling_hyperclovax_omni.HyperCLOVAXOmniForSequenceClassification"
35
  },
36
  "discrete_audio_config": {
 
 
37
  "architectures": [
38
  "CosyvoiceEncoder"
39
  ],
 
41
  "AutoConfig": "configuration_cosyvoice2.CosyVoice2Config",
42
  "AutoModel": "modeling_cosyvoice2.CosyVoice2Model"
43
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  "model_type": "cosyvoice2",
45
  "n_audio_ctx": 1500,
46
  "n_audio_head": 20,
 
48
  "n_audio_state": 1280,
49
  "n_codebook_size": 6561,
50
  "n_mels": 128,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  "use_sdpa": true
52
  },
53
  "discrete_audio_end_token_id": 128073,
 
54
  "discrete_audio_start_token_id": 128072,
55
  "discrete_audio_token_id": 128074,
56
  "discrete_audio_unit_0_id": 128606,
 
59
  "discrete_image_token_id": 128069,
60
  "discrete_image_unit_0_id": 135168,
61
  "discrete_vision_config": {
 
 
 
62
  "architectures": [
63
  "TextAlignedTokenizer"
64
  ],
 
66
  "AutoConfig": "configuration_tatok.TATokConfig",
67
  "AutoModel": "modeling_tatok.TATokModel"
68
  },
 
 
 
69
  "bottleneck": {
70
  "args": {
71
  "bottleneck_dim": 1536,
 
90
  "name": "bottleneck"
91
  },
92
  "bottleneck_token_num": 729,
 
 
 
93
  "decoder_depth": 3,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  "input_size": 384,
95
  "input_type": "indices",
 
 
 
 
 
 
 
 
 
96
  "model_type": "tatok",
 
 
 
 
 
 
 
 
97
  "pool_scale": 1,
 
 
 
98
  "rand_scale": true,
 
 
 
 
99
  "select_layer_id": -2,
100
+ "teacher": "google/siglip2-so400m-patch14-384"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  },
 
 
102
  "eos_token_id": 128001,
 
 
 
 
 
 
103
  "hidden_size": 4096,
104
  "ignore_index": -100,
105
  "image_end_token_id": 128058,
106
  "image_start_token_id": 128059,
107
  "image_token_id": 128062,
 
108
  "is_safetensor_save": true,
109
  "max_num_grids": -1,
110
  "mm_projector_type": "linear",
 
114
  "possible_resolutions": [],
115
  "proj_pos_emb": true,
116
  "proj_prenorm": false,
 
 
117
  "text_config": {
 
 
118
  "architectures": [
119
  "LlamaForCausalLM"
120
  ],
121
  "attention_bias": false,
122
  "attention_dropout": 0.0,
 
 
123
  "bos_token_id": 128000,
 
 
 
 
 
 
 
124
  "eos_token_id": 128001,
 
 
 
 
125
  "head_dim": 128,
126
  "hidden_act": "silu",
127
  "hidden_size": 4096,
 
 
 
 
128
  "initializer_range": 0.02,
129
  "intermediate_size": 12288,
 
 
 
 
 
 
 
130
  "logits_scaling": 1.0,
 
131
  "max_position_embeddings": 8192,
 
132
  "mlp_bias": false,
133
  "model_type": "llama",
 
134
  "num_attention_heads": 32,
 
 
135
  "num_hidden_layers": 36,
136
  "num_key_value_heads": 8,
 
 
 
 
 
 
137
  "pretraining_tp": 1,
 
 
 
 
 
 
138
  "rms_norm_eps": 1e-06,
139
  "rope_scaling": null,
140
  "rope_theta": 5000000,
 
 
 
 
 
 
141
  "tie_word_embeddings": false,
 
 
 
 
 
 
 
142
  "use_cache": true,
143
  "vocab_size": 200704
144
  },
 
145
  "torch_dtype": "float32",
 
146
  "unpad": false,
147
  "use_1x1_grid": false,
148
  "use_components": {
 
152
  "use_discrete_audio": true,
153
  "use_discrete_vision": true
154
  },
155
+ "vision_feature_layer": -2,
156
  "video_audio_compressor_config": {
 
 
157
  "architectures": null,
158
  "auto_map": {
159
  "AutoConfig": "configuration_mambamia.MambaMiaVideoAudioCompressorConfig",
160
  "AutoModel": "modeling_mambamia.MambaMiaVideoAudioCompressor"
161
  },
 
 
 
162
  "chunk_size": 25,
 
 
 
 
 
 
 
 
 
 
 
 
163
  "hidden_size": 3072,
 
 
 
 
164
  "input_size": 4096,
 
 
 
 
 
 
 
 
 
165
  "model_type": "mambamia_videoaudio_compressor",
 
 
 
166
  "num_hidden_layers": 1,
167
+ "output_size": 4096
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
  },
169
  "video_audio_compressor_type": "mambamia",
 
170
  "video_audio_token_id": 128070,
171
  "video_end_token_id": 128061,
172
  "video_first_last_frames_slows": null,
173
  "video_num_queries_fast": null,
174
  "video_num_queries_slow": null,
 
175
  "video_start_token_id": 128060,
176
  "video_token_id": 128063,
177
  "vision_config": {
 
 
178
  "anyres": false,
179
  "architectures": [
180
  "Qwen2_5_VisionTransformerPretrainedModel"
181
  ],
 
 
 
 
 
 
182
  "depth": 32,
 
 
 
 
 
 
 
 
 
183
  "fullatt_block_indexes": [
184
  7,
185
  15,
 
188
  ],
189
  "hidden_act": "silu",
190
  "hidden_size": 1280,
 
 
 
 
191
  "in_channels": 3,
192
  "in_chans": 3,
193
  "initializer_range": 0.02,
194
  "intermediate_size": 3456,
 
 
 
 
 
 
 
 
195
  "max_num_grids": -1,
 
196
  "model_type": "qwen2_5_vl_visual",
 
 
 
197
  "num_heads": 16,
 
198
  "out_hidden_size": 5120,
 
 
 
 
199
  "patch_size": 14,
 
 
 
 
 
 
 
 
200
  "spatial_merge_size": 2,
201
  "spatial_patch_size": 14,
 
 
 
202
  "temporal_patch_size": 2,
 
 
 
 
203
  "tokens_per_second": 2,
 
 
 
 
 
 
204
  "window_size": 112
205
  },
206
+ "vision_input_chunk_size": null
 
207
  }
configuration_cosyvoice2.py CHANGED
@@ -1,107 +1,70 @@
1
- import transformers
2
- from transformers import AutoConfig, AutoModel
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  from transformers.configuration_utils import PretrainedConfig
4
 
5
- # CosyVoice (CosyvoiceEncoder) Config
6
  class CosyVoice2Config(PretrainedConfig):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  model_type = "cosyvoice2"
8
 
9
  def __init__(
10
  self,
11
- n_mels=128,
12
- n_audio_ctx=1500,
13
- n_audio_state=1280,
14
- n_audio_head=20,
15
- n_audio_layer=6,
16
- n_codebook_size=6561, # 3**8
17
- use_sdpa=True,
18
- model_name_or_path=None,
19
  **kwargs,
20
  ):
21
- # Extract our custom attributes from kwargs first (when coming from config.json)
22
- # Priority: explicit argument (if not default) > kwargs value > default value
23
- kwargs_n_mels = kwargs.pop("n_mels", 128)
24
- kwargs_n_audio_ctx = kwargs.pop("n_audio_ctx", 1500)
25
- kwargs_n_audio_state = kwargs.pop("n_audio_state", 1280)
26
- kwargs_n_audio_head = kwargs.pop("n_audio_head", 20)
27
- kwargs_n_audio_layer = kwargs.pop("n_audio_layer", 6)
28
- kwargs_n_codebook_size = kwargs.pop("n_codebook_size", 6561)
29
- kwargs_use_sdpa = kwargs.pop("use_sdpa", True)
30
- kwargs_model_name_or_path = kwargs.pop("model_name_or_path", None)
31
-
32
- # Apply precedence rules
33
- self.n_mels = n_mels if n_mels != 128 else kwargs_n_mels
34
- self.n_audio_ctx = n_audio_ctx if n_audio_ctx != 1500 else kwargs_n_audio_ctx
35
- self.n_audio_state = n_audio_state if n_audio_state != 1280 else kwargs_n_audio_state
36
- self.n_audio_head = n_audio_head if n_audio_head != 20 else kwargs_n_audio_head
37
- self.n_audio_layer = n_audio_layer if n_audio_layer != 6 else kwargs_n_audio_layer
38
- self.n_codebook_size = n_codebook_size if n_codebook_size != 6561 else kwargs_n_codebook_size
39
- self.use_sdpa = use_sdpa if use_sdpa is not True else kwargs_use_sdpa
40
- self.model_name_or_path = model_name_or_path if model_name_or_path is not None else kwargs_model_name_or_path
41
 
42
- # Default values for standard transformers config attributes
43
- # These will be merged with kwargs so they appear even when not in config.json
44
- default_transformers_config = {
45
- "_name_or_path": None,
46
- "add_cross_attention": False,
47
- "architectures": ["CosyvoiceEncoder"],
48
- "bad_words_ids": None,
49
- "begin_suppress_tokens": None,
50
- "bos_token_id": None,
51
- "chunk_size_feed_forward": 0,
52
- "cross_attention_hidden_size": None,
53
- "decoder_start_token_id": None,
54
- "diversity_penalty": 0.0,
55
- "do_sample": False,
56
- "early_stopping": False,
57
- "encoder_no_repeat_ngram_size": 0,
58
- "eos_token_id": None,
59
- "exponential_decay_length_penalty": None,
60
- "finetuning_task": None,
61
- "forced_bos_token_id": None,
62
- "forced_eos_token_id": None,
63
- "id2label": {"0": "LABEL_0", "1": "LABEL_1"},
64
- "is_decoder": False,
65
- "is_encoder_decoder": False,
66
- "label2id": {"LABEL_0": 0, "LABEL_1": 1},
67
- "length_penalty": 1.0,
68
- "max_length": 20,
69
- "min_length": 0,
70
- "no_repeat_ngram_size": 0,
71
- "num_beam_groups": 1,
72
- "num_beams": 1,
73
- "num_return_sequences": 1,
74
- "output_attentions": False,
75
- "output_hidden_states": False,
76
- "output_scores": False,
77
- "pad_token_id": None,
78
- "prefix": None,
79
- "problem_type": None,
80
- "pruned_heads": {},
81
- "remove_invalid_values": False,
82
- "repetition_penalty": 1.0,
83
- "return_dict": True,
84
- "return_dict_in_generate": False,
85
- "sep_token_id": None,
86
- "suppress_tokens": None,
87
- "task_specific_params": None,
88
- "temperature": 1.0,
89
- "tf_legacy_loss": False,
90
- "tie_encoder_decoder": False,
91
- "tie_word_embeddings": True,
92
- "tokenizer_class": None,
93
- "top_k": 50,
94
- "top_p": 1.0,
95
- "torch_dtype": "float32",
96
- "torchscript": False,
97
- "typical_p": 1.0,
98
- "use_bfloat16": False,
99
- }
100
 
101
- # Merge defaults with kwargs (kwargs values take precedence)
102
- merged_kwargs = {**default_transformers_config, **kwargs}
103
 
104
- # Pass merged kwargs to parent (these are standard transformers config attributes)
105
- super().__init__(**merged_kwargs)
106
-
107
  __all__ = ["CosyVoice2Config"]
 
1
+ # coding=utf-8
2
+ # Copyright 2024 NAVER Cloud Corp. 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
+ """CosyVoice2 audio encoder configuration"""
16
+
17
+ from transformers import AutoConfig
18
  from transformers.configuration_utils import PretrainedConfig
19
 
20
+
21
  class CosyVoice2Config(PretrainedConfig):
22
+ r"""
23
+ This is the configuration class to store the configuration of a CosyVoice2 audio encoder model.
24
+
25
+ Configuration objects inherit from [`PretrainedConfig`] and can be used to control the model outputs. Read the
26
+ documentation from [`PretrainedConfig`] for more information.
27
+
28
+ Args:
29
+ n_mels (`int`, *optional*, defaults to 128):
30
+ Number of mel frequency bins for the input spectrogram.
31
+ n_audio_ctx (`int`, *optional*, defaults to 1500):
32
+ Maximum audio context length.
33
+ n_audio_state (`int`, *optional*, defaults to 1280):
34
+ Dimensionality of the encoder hidden states.
35
+ n_audio_head (`int`, *optional*, defaults to 20):
36
+ Number of attention heads in the encoder.
37
+ n_audio_layer (`int`, *optional*, defaults to 6):
38
+ Number of encoder layers.
39
+ n_codebook_size (`int`, *optional*, defaults to 6561):
40
+ Size of the codebook (3^8).
41
+ use_sdpa (`bool`, *optional*, defaults to `True`):
42
+ Whether to use Scaled Dot-Product Attention.
43
+ """
44
+
45
  model_type = "cosyvoice2"
46
 
47
  def __init__(
48
  self,
49
+ n_mels: int = 128,
50
+ n_audio_ctx: int = 1500,
51
+ n_audio_state: int = 1280,
52
+ n_audio_head: int = 20,
53
+ n_audio_layer: int = 6,
54
+ n_codebook_size: int = 6561, # 3**8
55
+ use_sdpa: bool = True,
 
56
  **kwargs,
57
  ):
58
+ super().__init__(**kwargs)
59
+ self.n_mels = n_mels
60
+ self.n_audio_ctx = n_audio_ctx
61
+ self.n_audio_state = n_audio_state
62
+ self.n_audio_head = n_audio_head
63
+ self.n_audio_layer = n_audio_layer
64
+ self.n_codebook_size = n_codebook_size
65
+ self.use_sdpa = use_sdpa
 
 
 
 
 
 
 
 
 
 
 
 
66
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
 
68
+ AutoConfig.register("cosyvoice2", CosyVoice2Config)
 
69
 
 
 
 
70
  __all__ = ["CosyVoice2Config"]
configuration_hyperclovax.py CHANGED
@@ -1,10 +1,5 @@
1
  # coding=utf-8
2
- # Copyright 2022 EleutherAI and the HuggingFace Inc. team. All rights reserved.
3
- #
4
- # This code is based on EleutherAI's GPT-NeoX library and the GPT-NeoX
5
- # and OPT implementations in this library. It has been modified from its
6
- # original forms to accommodate minor architectural differences compared
7
- # to GPT-NeoX and OPT used by the Meta AI team that trained the model.
8
  #
9
  # Licensed under the Apache License, Version 2.0 (the "License");
10
  # you may not use this file except in compliance with the License.
@@ -17,27 +12,26 @@
17
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
  # See the License for the specific language governing permissions and
19
  # limitations under the License.
20
- """LLaMA model configuration"""
 
 
21
 
22
- import transformers
23
- from transformers import AutoConfig, AutoModel, AutoModelForCausalLM
24
  from transformers.configuration_utils import PretrainedConfig
25
 
26
 
27
  class HyperCLOVAXConfig(PretrainedConfig):
28
  r"""
29
- This is the configuration class to store the configuration of a [`LlamaModel`]. It is used to instantiate an LLaMA
30
- model according to the specified arguments, defining the model architecture. Instantiating a configuration with the
31
- defaults will yield a similar configuration to that of the LLaMA-7B.
32
 
33
  Configuration objects inherit from [`PretrainedConfig`] and can be used to control the model outputs. Read the
34
  documentation from [`PretrainedConfig`] for more information.
35
 
36
-
37
  Args:
38
  vocab_size (`int`, *optional*, defaults to 32000):
39
- Vocabulary size of the LLaMA model. Defines the number of different tokens that can be represented by the
40
- `inputs_ids` passed when calling [`LlamaModel`]
41
  hidden_size (`int`, *optional*, defaults to 4096):
42
  Dimension of the hidden representations.
43
  intermediate_size (`int`, *optional*, defaults to 11008):
@@ -57,8 +51,7 @@ class HyperCLOVAXConfig(PretrainedConfig):
57
  hidden_act (`str` or `function`, *optional*, defaults to `"silu"`):
58
  The non-linear activation function (function or string) in the decoder.
59
  max_position_embeddings (`int`, *optional*, defaults to 2048):
60
- The maximum sequence length that this model might ever be used with. Llama 1 supports up to 2048 tokens,
61
- Llama 2 up to 4096, CodeLlama up to 16384.
62
  initializer_range (`float`, *optional*, defaults to 0.02):
63
  The standard deviation of the truncated_normal_initializer for initializing all weight matrices.
64
  rms_norm_eps (`float`, *optional*, defaults to 1e-06):
@@ -78,7 +71,7 @@ class HyperCLOVAXConfig(PretrainedConfig):
78
  understand more about it. This value is necessary to ensure exact reproducibility of the pretraining
79
  results. Please refer to [this issue](https://github.com/pytorch/pytorch/issues/76232).
80
  tie_word_embeddings (`bool`, *optional*, defaults to `False`):
81
- Whether to tie weight embeddings
82
  rope_theta (`float`, *optional*, defaults to 10000.0):
83
  The base period of the RoPE embeddings.
84
  rope_scaling (`Dict`, *optional*):
@@ -125,19 +118,23 @@ class HyperCLOVAXConfig(PretrainedConfig):
125
  mlp_bias (`bool`, *optional*, defaults to `False`):
126
  Whether to use a bias in up_proj, down_proj and gate_proj layers in the MLP layers.
127
  head_dim (`int`, *optional*):
128
- The attention head dimension. If None, it will default to hidden_size // num_heads
 
 
 
 
 
 
 
 
 
 
129
 
130
  ```python
131
- >>> from transformers import LlamaModel, LlamaConfig
132
 
133
- >>> # Initializing a LLaMA llama-7b style configuration
134
- >>> configuration = LlamaConfig()
135
-
136
- >>> # Initializing a model from the llama-7b style configuration
137
- >>> model = LlamaModel(configuration)
138
-
139
- >>> # Accessing the model configuration
140
- >>> configuration = model.config
141
  ```"""
142
 
143
  model_type = "hyperclovax"
@@ -145,40 +142,42 @@ class HyperCLOVAXConfig(PretrainedConfig):
145
 
146
  def __init__(
147
  self,
148
- vocab_size=32000,
149
- hidden_size=4096,
150
- intermediate_size=11008,
151
- num_hidden_layers=32,
152
- num_attention_heads=32,
153
- num_key_value_heads=None,
154
- hidden_act="silu",
155
- max_position_embeddings=2048,
156
- initializer_range=0.02,
157
- rms_norm_eps=1e-6,
158
- use_cache=True,
159
- pad_token_id=None,
160
- bos_token_id=1,
161
- eos_token_id=2,
162
- pretraining_tp=1,
163
- tie_word_embeddings=False,
164
- rope_theta=10000.0,
165
- rope_scaling=None,
166
- attention_bias=False,
167
- attention_dropout=0.0,
168
- mlp_bias=False,
169
- head_dim=None,
170
- embedding_multiplier=1.0, # mup
171
- logits_scaling=1.0, # mup
172
- attention_multiplier=1.0, # mup
173
- residual_multiplier=1.0, # mup
174
- use_post_norm=False, # post-norm
175
- auto_map={
176
- "AutoConfig": "configuration_hyperclovax.HyperCLOVAXConfig",
177
- "AutoModel": "modeling_hyperclovax.HyperCLOVAXModel",
178
- "AutoModelForCausalLM": "modeling_hyperclovax.HyperCLOVAXForCausalLM",
179
- },
180
  **kwargs,
181
  ):
 
 
 
 
 
 
 
182
  self.vocab_size = vocab_size
183
  self.max_position_embeddings = max_position_embeddings
184
  self.hidden_size = hidden_size
@@ -202,11 +201,9 @@ class HyperCLOVAXConfig(PretrainedConfig):
202
  self.attention_dropout = attention_dropout
203
  self.mlp_bias = mlp_bias
204
  self.head_dim = head_dim if head_dim is not None else self.hidden_size // self.num_attention_heads
205
- # Validate the correctness of rotary position embeddings parameters
206
- # BC: if there is a 'type' field, copy it it to 'rope_type'.
207
  if self.rope_scaling is not None and "type" in self.rope_scaling:
208
  self.rope_scaling["rope_type"] = self.rope_scaling["type"]
209
- # rope_config_validation(self)
210
 
211
  # mup
212
  self.embedding_multiplier = embedding_multiplier
@@ -217,13 +214,7 @@ class HyperCLOVAXConfig(PretrainedConfig):
217
  # post-norm (dual-norm)
218
  self.use_post_norm = use_post_norm
219
 
220
- super().__init__(
221
- pad_token_id=pad_token_id,
222
- bos_token_id=bos_token_id,
223
- eos_token_id=eos_token_id,
224
- tie_word_embeddings=tie_word_embeddings,
225
- auto_map=auto_map,
226
- **kwargs,
227
- )
228
-
229
  __all__ = ["HyperCLOVAXConfig"]
 
1
  # coding=utf-8
2
+ # Copyright 2024 NAVER Cloud Corp. 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.
 
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
+ """HyperCLOVAX model configuration"""
16
+
17
+ from typing import Optional
18
 
19
+ from transformers import AutoConfig
 
20
  from transformers.configuration_utils import PretrainedConfig
21
 
22
 
23
  class HyperCLOVAXConfig(PretrainedConfig):
24
  r"""
25
+ This is the configuration class to store the configuration of a [`HyperCLOVAXModel`]. It is used to instantiate a
26
+ HyperCLOVAX model according to the specified arguments, defining the model architecture.
 
27
 
28
  Configuration objects inherit from [`PretrainedConfig`] and can be used to control the model outputs. Read the
29
  documentation from [`PretrainedConfig`] for more information.
30
 
 
31
  Args:
32
  vocab_size (`int`, *optional*, defaults to 32000):
33
+ Vocabulary size of the HyperCLOVAX model. Defines the number of different tokens that can be represented
34
+ by the `inputs_ids` passed when calling [`HyperCLOVAXModel`].
35
  hidden_size (`int`, *optional*, defaults to 4096):
36
  Dimension of the hidden representations.
37
  intermediate_size (`int`, *optional*, defaults to 11008):
 
51
  hidden_act (`str` or `function`, *optional*, defaults to `"silu"`):
52
  The non-linear activation function (function or string) in the decoder.
53
  max_position_embeddings (`int`, *optional*, defaults to 2048):
54
+ The maximum sequence length that this model might ever be used with.
 
55
  initializer_range (`float`, *optional*, defaults to 0.02):
56
  The standard deviation of the truncated_normal_initializer for initializing all weight matrices.
57
  rms_norm_eps (`float`, *optional*, defaults to 1e-06):
 
71
  understand more about it. This value is necessary to ensure exact reproducibility of the pretraining
72
  results. Please refer to [this issue](https://github.com/pytorch/pytorch/issues/76232).
73
  tie_word_embeddings (`bool`, *optional*, defaults to `False`):
74
+ Whether to tie weight embeddings.
75
  rope_theta (`float`, *optional*, defaults to 10000.0):
76
  The base period of the RoPE embeddings.
77
  rope_scaling (`Dict`, *optional*):
 
118
  mlp_bias (`bool`, *optional*, defaults to `False`):
119
  Whether to use a bias in up_proj, down_proj and gate_proj layers in the MLP layers.
120
  head_dim (`int`, *optional*):
121
+ The attention head dimension. If None, it will default to hidden_size // num_heads.
122
+ embedding_multiplier (`float`, *optional*, defaults to 1.0):
123
+ Multiplier for the embedding layer output, used for muP (maximal update parametrization).
124
+ logits_scaling (`float`, *optional*, defaults to 1.0):
125
+ Scaling factor for the logits, used for muP.
126
+ attention_multiplier (`float`, *optional*, defaults to 1.0):
127
+ Multiplier for the attention scores, used for muP.
128
+ residual_multiplier (`float`, *optional*, defaults to 1.0):
129
+ Multiplier for the residual connections, used for muP.
130
+ use_post_norm (`bool`, *optional*, defaults to `False`):
131
+ Whether to apply post-normalization (dual-norm) in addition to pre-normalization.
132
 
133
  ```python
134
+ >>> from configuration_hyperclovax import HyperCLOVAXConfig
135
 
136
+ >>> # Initializing a HyperCLOVAX configuration
137
+ >>> configuration = HyperCLOVAXConfig()
 
 
 
 
 
 
138
  ```"""
139
 
140
  model_type = "hyperclovax"
 
142
 
143
  def __init__(
144
  self,
145
+ vocab_size: int = 32000,
146
+ hidden_size: int = 4096,
147
+ intermediate_size: int = 11008,
148
+ num_hidden_layers: int = 32,
149
+ num_attention_heads: int = 32,
150
+ num_key_value_heads: Optional[int] = None,
151
+ hidden_act: str = "silu",
152
+ max_position_embeddings: int = 2048,
153
+ initializer_range: float = 0.02,
154
+ rms_norm_eps: float = 1e-6,
155
+ use_cache: bool = True,
156
+ pad_token_id: Optional[int] = None,
157
+ bos_token_id: int = 1,
158
+ eos_token_id: int = 2,
159
+ pretraining_tp: int = 1,
160
+ tie_word_embeddings: bool = False,
161
+ rope_theta: float = 10000.0,
162
+ rope_scaling: Optional[dict] = None,
163
+ attention_bias: bool = False,
164
+ attention_dropout: float = 0.0,
165
+ mlp_bias: bool = False,
166
+ head_dim: Optional[int] = None,
167
+ embedding_multiplier: float = 1.0,
168
+ logits_scaling: float = 1.0,
169
+ attention_multiplier: float = 1.0,
170
+ residual_multiplier: float = 1.0,
171
+ use_post_norm: bool = False,
 
 
 
 
 
172
  **kwargs,
173
  ):
174
+ super().__init__(
175
+ pad_token_id=pad_token_id,
176
+ bos_token_id=bos_token_id,
177
+ eos_token_id=eos_token_id,
178
+ tie_word_embeddings=tie_word_embeddings,
179
+ **kwargs,
180
+ )
181
  self.vocab_size = vocab_size
182
  self.max_position_embeddings = max_position_embeddings
183
  self.hidden_size = hidden_size
 
201
  self.attention_dropout = attention_dropout
202
  self.mlp_bias = mlp_bias
203
  self.head_dim = head_dim if head_dim is not None else self.hidden_size // self.num_attention_heads
204
+ # BC: if there is a 'type' field, copy it to 'rope_type'.
 
205
  if self.rope_scaling is not None and "type" in self.rope_scaling:
206
  self.rope_scaling["rope_type"] = self.rope_scaling["type"]
 
207
 
208
  # mup
209
  self.embedding_multiplier = embedding_multiplier
 
214
  # post-norm (dual-norm)
215
  self.use_post_norm = use_post_norm
216
 
217
+
218
+ AutoConfig.register("hyperclovax", HyperCLOVAXConfig)
219
+
 
 
 
 
 
 
220
  __all__ = ["HyperCLOVAXConfig"]
configuration_hyperclovax_omni.py CHANGED
@@ -1,35 +1,134 @@
1
- import os
2
- import transformers
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  from transformers import (
4
- AutoConfig, AutoModel, AutoModelForCausalLM,
5
- CLIPVisionConfig, LlamaConfig,
6
- PretrainedConfig, SiglipVisionConfig,
7
- Qwen2AudioEncoderConfig, WhisperConfig,
 
 
 
8
  )
9
- from transformers.models.qwen2_5_vl.modeling_qwen2_5_vl import Qwen2_5_VLVisionConfig
10
 
11
  from .configuration_cosyvoice2 import CosyVoice2Config
12
  from .configuration_hyperclovax import HyperCLOVAXConfig
13
  from .configuration_mambamia import MambaMiaVideoAudioCompressorConfig
14
  from .configuration_tatok import TATokConfig
15
 
 
16
  class HyperCLOVAXOmniConfig(PretrainedConfig):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  model_type = "hyperclovax_omni"
18
  keys_to_ignore_at_inference = ["past_key_values"]
19
 
20
- _sub_config_attrs = [
21
- "text_config",
22
- "vision_config",
23
- "audio_config",
24
- "discrete_vision_config",
25
- "discrete_audio_config",
26
- "video_audio_compressor_config",
27
- ]
28
 
29
  @classmethod
30
- def from_pretrained(cls, pretrained_model_name_or_path, **kwargs):
31
  config = super().from_pretrained(pretrained_model_name_or_path, **kwargs)
32
- for attr in cls._sub_config_attrs:
 
 
33
  sub_config = getattr(config, attr, None)
34
  if sub_config is not None and hasattr(sub_config, "_name_or_path"):
35
  sub_config._name_or_path = config._name_or_path
@@ -37,56 +136,35 @@ class HyperCLOVAXOmniConfig(PretrainedConfig):
37
 
38
  def __init__(
39
  self,
40
- text_config=None,
41
- vision_config=None,
42
- discrete_vision_config=None,
43
- audio_config=None,
44
- discrete_audio_config=None,
45
- text_model_name_or_path=None,
46
- vision_model_name_or_path=None,
47
- discrete_vision_model_name_or_path=None,
48
- audio_model_name_or_path=None,
49
- discrete_audio_model_name_or_path=None,
50
- q_former_model_name_or_path=None,
51
- mm_projector_type="mlp",
52
- audio_projector_type="mlp",
53
- video_audio_compressor_type=None,
54
- video_audio_compressor_config=None,
55
- use_nth_layer=-2,
56
- img_start_id=128062, # <|IMAGE_PAD|> # /mnt/ddn/vuvlm/outputs/251001_spd_hcx4b_stage2_c1_withmmpt_exp3/checkpoint-1500 수동 수정해서 맞춘 상황.
57
- discrete_image_start_id=128250, # <|DISCRETE_AUDIO_PAD|>
58
- discrete_image_unit_0_id=135166, # <|vision00000|>
59
- video_start_id=128063, # <|VIDEO_PAD|>
60
- video_audio_start_id=None, # <|VIDEO_AUDIO_PAD|> - will be set dynamically
61
- audio_start_id=128253, # <|AUDIO_PAD|>
62
- discrete_audio_start_id=128250, # <|DISCRETE_AUDIO_PAD|>
63
- discrete_audio_unit_0_id=128604, # <|audio0000|>
64
- freeze_encoder=False,
65
- freeze_decoder=False,
66
- freeze_mm_projector=False,
67
- freeze_audio_projector=False,
68
- freeze_video_audio_compressor=False,
69
- anyres=False,
70
- unpad=False,
71
- max_num_grids=-1,
72
- num_queries_vis_abstractor=-1,
73
- video_num_queries_fast=None,
74
- video_num_queries_slow=None,
75
- video_first_last_frames_slows=None,
76
- video_max_num_frames=None,
77
- ignore_index=-100,
78
- proj_pos_emb=True,
79
- proj_prenorm=False,
80
- use_1x1_grid=False,
81
- possible_resolutions=[],
82
  **kwargs,
83
  ):
 
84
  # text_config
85
- if (
86
- text_config is None
87
- and text_model_name_or_path is not None
88
- ):
89
- text_config = AutoConfig.from_pretrained(text_model_name_or_path, trust_remote_code=True)
90
  if isinstance(text_config, dict):
91
  if text_config["model_type"] == "hyperclovax":
92
  text_config = HyperCLOVAXConfig(**text_config)
@@ -94,13 +172,13 @@ class HyperCLOVAXOmniConfig(PretrainedConfig):
94
  text_config = LlamaConfig(**text_config)
95
  else:
96
  raise ValueError(f'Invalid text_config type: {text_config["model_type"]}')
97
- if text_config is not None: # for deepspeed zero to allocate dynamic memory
98
- self.hidden_size = text_config.hidden_size if hasattr(text_config, "hidden_size") else text_config.n_embd
 
 
99
  self.text_config = text_config
100
-
101
  # audio_config
102
- if audio_config is None and audio_model_name_or_path is not None:
103
- audio_config = AutoConfig.from_pretrained(audio_model_name_or_path)
104
  if isinstance(audio_config, dict):
105
  if audio_config["model_type"] == "qwen2_audio_encoder":
106
  audio_config = Qwen2AudioEncoderConfig(**audio_config)
@@ -109,26 +187,13 @@ class HyperCLOVAXOmniConfig(PretrainedConfig):
109
  else:
110
  raise ValueError(f'Invalid audio_config type: {audio_config["model_type"]}')
111
  self.audio_config = audio_config
112
-
113
  # discrete_audio_config
114
- if discrete_audio_config is None and discrete_audio_model_name_or_path is not None:
115
- discrete_audio_config = {
116
- "model_type": "cosyvoice2",
117
- "model_name_or_path": discrete_audio_model_name_or_path,
118
- }
119
- if (
120
- isinstance(CosyVoice2Config, type)
121
- and isinstance(discrete_audio_config, dict)
122
- ):
123
  discrete_audio_config = CosyVoice2Config.from_dict(discrete_audio_config)
124
  self.discrete_audio_config = discrete_audio_config
125
-
126
  # vision_config
127
- if vision_config is None and vision_model_name_or_path is not None:
128
- vision_config = AutoConfig.from_pretrained(
129
- vision_model_name_or_path,
130
- trust_remote_code=True,
131
- )
132
  if isinstance(vision_config, dict):
133
  if vision_config["model_type"] == "clip_vision_model":
134
  vision_config = CLIPVisionConfig(**vision_config)
@@ -139,16 +204,8 @@ class HyperCLOVAXOmniConfig(PretrainedConfig):
139
  else:
140
  raise ValueError(f'Invalid vision_config type: {vision_config["model_type"]}')
141
  self.vision_config = vision_config
142
-
143
  # discrete_vision_config
144
- if (
145
- discrete_vision_config is None
146
- and discrete_vision_model_name_or_path is not None
147
- ):
148
- discrete_vision_config = {
149
- "model_type": "tatok",
150
- "model_name_or_path": discrete_vision_model_name_or_path,
151
- }
152
  if isinstance(discrete_vision_config, dict):
153
  discrete_vision_config = TATokConfig.from_dict(discrete_vision_config)
154
  self.discrete_vision_config = discrete_vision_config
@@ -159,21 +216,10 @@ class HyperCLOVAXOmniConfig(PretrainedConfig):
159
  self.video_audio_compressor_config = video_audio_compressor_config
160
 
161
  # add VLM configs
162
- self.text_model_name_or_path = text_model_name_or_path
163
- self.vision_model_name_or_path = vision_model_name_or_path
164
- self.discrete_vision_model_name_or_path = discrete_vision_model_name_or_path
165
- self.audio_model_name_or_path = audio_model_name_or_path
166
- self.discrete_audio_model_name_or_path = discrete_audio_model_name_or_path
167
- self.q_former_model_name_or_path = q_former_model_name_or_path
168
  self.mm_projector_type = mm_projector_type
169
  self.audio_projector_type = audio_projector_type
170
  self.video_audio_compressor_type = video_audio_compressor_type
171
- self.use_nth_layer = use_nth_layer
172
- self.freeze_encoder = freeze_encoder
173
- self.freeze_decoder = freeze_decoder
174
- self.freeze_mm_projector = freeze_mm_projector
175
- self.freeze_audio_projector = freeze_audio_projector
176
- self.freeze_video_audio_compressor = freeze_video_audio_compressor
177
  self.anyres = anyres
178
  self.unpad = unpad
179
  self.max_num_grids = max_num_grids
@@ -183,39 +229,20 @@ class HyperCLOVAXOmniConfig(PretrainedConfig):
183
  self.video_first_last_frames_slows = video_first_last_frames_slows
184
  self.video_max_num_frames = video_max_num_frames
185
 
186
- self.img_start_id = img_start_id
187
- self.image_token_id = img_start_id
188
-
189
- self.discrete_image_start_id = discrete_image_start_id
190
- self.discrete_image_token_id = discrete_image_start_id
191
  self.discrete_image_unit_0_id = discrete_image_unit_0_id
192
-
193
- self.video_start_id = video_start_id
194
- self.video_token_id = video_start_id
195
-
196
- self.video_audio_start_id = video_audio_start_id
197
- self.video_audio_token_id = video_audio_start_id
198
-
199
- self.audio_start_id = audio_start_id
200
- self.audio_token_id = audio_start_id
201
-
202
- self.discrete_audio_start_id = discrete_audio_start_id
203
- self.discrete_audio_token_id = discrete_audio_start_id
204
  self.discrete_audio_unit_0_id = discrete_audio_unit_0_id
205
 
206
  self.ignore_index = ignore_index
207
  self.proj_pos_emb = proj_pos_emb
208
  self.proj_prenorm = proj_prenorm
209
  self.use_1x1_grid = use_1x1_grid
210
- self.possible_resolutions = possible_resolutions
211
-
212
- super().__init__(**kwargs)
213
-
214
  # needed for HCXVisionForSequenceClassification
215
- if self.text_config is not None:
216
  self.pad_token_id = self.text_config.pad_token_id
217
-
218
- from transformers.models.qwen2_5_vl.modeling_qwen2_5_vl import Qwen2_5_VLVisionConfig
219
 
220
 
221
- __all__ = ["CosyVoice2Config", "HyperCLOVAXConfig", "HyperCLOVAXOmniConfig", "MambaMiaVideoAudioCompressorConfig", "TATokConfig", "Qwen2_5_VLVisionConfig", ]
 
 
 
1
+ # coding=utf-8
2
+ # Copyright 2024 NAVER Cloud Corp. 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
+ """HyperCLOVAX-Omni multimodal model configuration"""
16
+
17
+ from typing import Dict, List, Optional, Union
18
+
19
  from transformers import (
20
+ AutoConfig,
21
+ CLIPVisionConfig,
22
+ LlamaConfig,
23
+ PretrainedConfig,
24
+ Qwen2AudioEncoderConfig,
25
+ SiglipVisionConfig,
26
+ WhisperConfig,
27
  )
28
+ from transformers.models.qwen2_5_vl.configuration_qwen2_5_vl import Qwen2_5_VLVisionConfig
29
 
30
  from .configuration_cosyvoice2 import CosyVoice2Config
31
  from .configuration_hyperclovax import HyperCLOVAXConfig
32
  from .configuration_mambamia import MambaMiaVideoAudioCompressorConfig
33
  from .configuration_tatok import TATokConfig
34
 
35
+
36
  class HyperCLOVAXOmniConfig(PretrainedConfig):
37
+ r"""
38
+ This is the configuration class to store the configuration of a [`HyperCLOVAXOmniForCausalLM`]. It is used to
39
+ instantiate a HyperCLOVAX-Omni multimodal model according to the specified arguments, defining the model
40
+ architecture including text, vision, and audio components.
41
+
42
+ Configuration objects inherit from [`PretrainedConfig`] and can be used to control the model outputs. Read the
43
+ documentation from [`PretrainedConfig`] for more information.
44
+
45
+ Args:
46
+ text_config (`dict` or [`PretrainedConfig`], *optional*):
47
+ Configuration for the text backbone model. Accepts a `HyperCLOVAXConfig` or `LlamaConfig`.
48
+ vision_config (`dict` or [`PretrainedConfig`], *optional*):
49
+ Configuration for the continuous vision encoder (e.g., CLIP, SigLIP, Qwen2.5-VL).
50
+ discrete_vision_config (`dict` or [`PretrainedConfig`], *optional*):
51
+ Configuration for the discrete vision tokenizer (TATok).
52
+ audio_config (`dict` or [`PretrainedConfig`], *optional*):
53
+ Configuration for the continuous audio encoder (e.g., Qwen2AudioEncoder, Whisper).
54
+ discrete_audio_config (`dict` or [`PretrainedConfig`], *optional*):
55
+ Configuration for the discrete audio encoder (CosyVoice2).
56
+ text_model_name_or_path (`str`, *optional*):
57
+ Path or identifier of a pretrained text model to load config from.
58
+ vision_model_name_or_path (`str`, *optional*):
59
+ Path or identifier of a pretrained vision model to load config from.
60
+ discrete_vision_model_name_or_path (`str`, *optional*):
61
+ Path or identifier of a pretrained discrete vision model to load config from.
62
+ audio_model_name_or_path (`str`, *optional*):
63
+ Path or identifier of a pretrained audio model to load config from.
64
+ discrete_audio_model_name_or_path (`str`, *optional*):
65
+ Path or identifier of a pretrained discrete audio model to load config from.
66
+ mm_projector_type (`str`, *optional*, defaults to `"mlp"`):
67
+ Type of the multimodal projector for vision features.
68
+ audio_projector_type (`str`, *optional*, defaults to `"mlp"`):
69
+ Type of the projector for audio features.
70
+ video_audio_compressor_type (`str`, *optional*):
71
+ Type of the video-audio compressor (e.g., `"mambamia"`).
72
+ video_audio_compressor_config (`dict` or [`PretrainedConfig`], *optional*):
73
+ Configuration for the video-audio compressor module.
74
+ vision_feature_layer (`int`, *optional*, defaults to -2):
75
+ Index of the vision encoder layer to extract features from.
76
+ discrete_image_unit_0_id (`int`, *optional*, defaults to 135166):
77
+ Token id for `<|vision00000|>`, the first discrete vision unit token.
78
+ discrete_audio_unit_0_id (`int`, *optional*, defaults to 128604):
79
+ Token id for `<|audio0000|>`, the first discrete audio unit token.
80
+ anyres (`bool`, *optional*, defaults to `False`):
81
+ Whether to use any-resolution image processing.
82
+ unpad (`bool`, *optional*, defaults to `False`):
83
+ Whether to remove padding from image features.
84
+ max_num_grids (`int`, *optional*, defaults to -1):
85
+ Maximum number of grids for any-resolution processing. -1 means no limit.
86
+ num_queries_vis_abstractor (`int`, *optional*, defaults to -1):
87
+ Number of query tokens for the visual abstractor. -1 means disabled.
88
+ video_num_queries_fast (`int`, *optional*):
89
+ Number of query tokens for fast video frames.
90
+ video_num_queries_slow (`int`, *optional*):
91
+ Number of query tokens for slow video frames.
92
+ video_first_last_frames_slows (`int`, *optional*):
93
+ Number of first/last frames to process as slow frames.
94
+ video_max_num_frames (`int`, *optional*):
95
+ Maximum number of video frames to process.
96
+ ignore_index (`int`, *optional*, defaults to -100):
97
+ The index to ignore in loss computation.
98
+ proj_pos_emb (`bool`, *optional*, defaults to `True`):
99
+ Whether to use positional embeddings in the projector.
100
+ proj_prenorm (`bool`, *optional*, defaults to `False`):
101
+ Whether to apply pre-normalization in the projector.
102
+ use_1x1_grid (`bool`, *optional*, defaults to `False`):
103
+ Whether to use 1x1 grid for single-image processing.
104
+ possible_resolutions (`List[List[int]]`, *optional*):
105
+ List of possible resolutions `[height, width]` for any-resolution processing.
106
+
107
+ ```python
108
+ >>> from configuration_hyperclovax_omni import HyperCLOVAXOmniConfig
109
+
110
+ >>> # Initializing a HyperCLOVAX-Omni configuration
111
+ >>> configuration = HyperCLOVAXOmniConfig()
112
+ ```
113
+ """
114
  model_type = "hyperclovax_omni"
115
  keys_to_ignore_at_inference = ["past_key_values"]
116
 
117
+ sub_configs = {
118
+ "text_config": AutoConfig,
119
+ "vision_config": AutoConfig,
120
+ "audio_config": AutoConfig,
121
+ "discrete_vision_config": AutoConfig,
122
+ "discrete_audio_config": AutoConfig,
123
+ "video_audio_compressor_config": AutoConfig,
124
+ }
125
 
126
  @classmethod
127
+ def from_pretrained(cls, pretrained_model_name_or_path: str, **kwargs) -> "HyperCLOVAXOmniConfig":
128
  config = super().from_pretrained(pretrained_model_name_or_path, **kwargs)
129
+ # Propagate _name_or_path to sub-configs so that AutoModel.from_config()
130
+ # can resolve dynamic module references (auto_map) from the checkpoint directory.
131
+ for attr in cls.sub_configs:
132
  sub_config = getattr(config, attr, None)
133
  if sub_config is not None and hasattr(sub_config, "_name_or_path"):
134
  sub_config._name_or_path = config._name_or_path
 
136
 
137
  def __init__(
138
  self,
139
+ text_config: Optional[Union[Dict, PretrainedConfig]] = None,
140
+ vision_config: Optional[Union[Dict, PretrainedConfig]] = None,
141
+ discrete_vision_config: Optional[Union[Dict, PretrainedConfig]] = None,
142
+ audio_config: Optional[Union[Dict, PretrainedConfig]] = None,
143
+ discrete_audio_config: Optional[Union[Dict, PretrainedConfig]] = None,
144
+ mm_projector_type: str = "mlp",
145
+ audio_projector_type: str = "mlp",
146
+ video_audio_compressor_type: Optional[str] = None,
147
+ video_audio_compressor_config: Optional[Union[Dict, PretrainedConfig]] = None,
148
+ vision_feature_layer: int = -2,
149
+ discrete_image_unit_0_id: int = 135166, # <|vision00000|>
150
+ discrete_audio_unit_0_id: int = 128604, # <|audio0000|>
151
+ anyres: bool = False,
152
+ unpad: bool = False,
153
+ max_num_grids: int = -1,
154
+ num_queries_vis_abstractor: int = -1,
155
+ video_num_queries_fast: Optional[int] = None,
156
+ video_num_queries_slow: Optional[int] = None,
157
+ video_first_last_frames_slows: Optional[int] = None,
158
+ video_max_num_frames: Optional[int] = None,
159
+ ignore_index: int = -100,
160
+ proj_pos_emb: bool = True,
161
+ proj_prenorm: bool = False,
162
+ use_1x1_grid: bool = False,
163
+ possible_resolutions: Optional[List[List[int]]] = None,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
  **kwargs,
165
  ):
166
+ super().__init__(**kwargs)
167
  # text_config
 
 
 
 
 
168
  if isinstance(text_config, dict):
169
  if text_config["model_type"] == "hyperclovax":
170
  text_config = HyperCLOVAXConfig(**text_config)
 
172
  text_config = LlamaConfig(**text_config)
173
  else:
174
  raise ValueError(f'Invalid text_config type: {text_config["model_type"]}')
175
+ if text_config is not None:
176
+ self.hidden_size = text_config.hidden_size
177
+ else:
178
+ self.hidden_size = kwargs.get("hidden_size", 4096)
179
  self.text_config = text_config
180
+
181
  # audio_config
 
 
182
  if isinstance(audio_config, dict):
183
  if audio_config["model_type"] == "qwen2_audio_encoder":
184
  audio_config = Qwen2AudioEncoderConfig(**audio_config)
 
187
  else:
188
  raise ValueError(f'Invalid audio_config type: {audio_config["model_type"]}')
189
  self.audio_config = audio_config
190
+
191
  # discrete_audio_config
192
+ if isinstance(discrete_audio_config, dict):
 
 
 
 
 
 
 
 
193
  discrete_audio_config = CosyVoice2Config.from_dict(discrete_audio_config)
194
  self.discrete_audio_config = discrete_audio_config
195
+
196
  # vision_config
 
 
 
 
 
197
  if isinstance(vision_config, dict):
198
  if vision_config["model_type"] == "clip_vision_model":
199
  vision_config = CLIPVisionConfig(**vision_config)
 
204
  else:
205
  raise ValueError(f'Invalid vision_config type: {vision_config["model_type"]}')
206
  self.vision_config = vision_config
207
+
208
  # discrete_vision_config
 
 
 
 
 
 
 
 
209
  if isinstance(discrete_vision_config, dict):
210
  discrete_vision_config = TATokConfig.from_dict(discrete_vision_config)
211
  self.discrete_vision_config = discrete_vision_config
 
216
  self.video_audio_compressor_config = video_audio_compressor_config
217
 
218
  # add VLM configs
 
 
 
 
 
 
219
  self.mm_projector_type = mm_projector_type
220
  self.audio_projector_type = audio_projector_type
221
  self.video_audio_compressor_type = video_audio_compressor_type
222
+ self.vision_feature_layer = vision_feature_layer
 
 
 
 
 
223
  self.anyres = anyres
224
  self.unpad = unpad
225
  self.max_num_grids = max_num_grids
 
229
  self.video_first_last_frames_slows = video_first_last_frames_slows
230
  self.video_max_num_frames = video_max_num_frames
231
 
 
 
 
 
 
232
  self.discrete_image_unit_0_id = discrete_image_unit_0_id
 
 
 
 
 
 
 
 
 
 
 
 
233
  self.discrete_audio_unit_0_id = discrete_audio_unit_0_id
234
 
235
  self.ignore_index = ignore_index
236
  self.proj_pos_emb = proj_pos_emb
237
  self.proj_prenorm = proj_prenorm
238
  self.use_1x1_grid = use_1x1_grid
239
+ self.possible_resolutions = possible_resolutions if possible_resolutions is not None else []
240
+
 
 
241
  # needed for HCXVisionForSequenceClassification
242
+ if self.text_config is not None:
243
  self.pad_token_id = self.text_config.pad_token_id
 
 
244
 
245
 
246
+ AutoConfig.register("hyperclovax_omni", HyperCLOVAXOmniConfig)
247
+
248
+ __all__ = ["HyperCLOVAXOmniConfig"]
configuration_mambamia.py CHANGED
@@ -1,19 +1,41 @@
1
- import transformers
2
- from transformers import AutoConfig, AutoModel
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  from transformers.configuration_utils import PretrainedConfig
4
 
5
 
6
- # MambaMia VideoAudio Compressor Config
7
  class MambaMiaVideoAudioCompressorConfig(PretrainedConfig):
8
- """
9
- Configuration for MambaMiaVideoAudioCompressor.
 
 
 
10
 
11
  Args:
12
- input_size: Input embedding dimension (e.g., 1280 for Whisper)
13
- output_size: Output embedding dimension (e.g., 2048 for LLM)
14
- chunk_size: Number of tokens per chunk (default: 25, i.e., 1 second at 25Hz)
15
- num_hidden_layers: Number of MambaMia2 layers (default: 1)
16
- hidden_size: Internal hidden size (default: 3072, must be divisible by 24)
 
 
 
 
 
17
  """
18
 
19
  model_type = "mambamia_videoaudio_compressor"
@@ -33,6 +55,8 @@ class MambaMiaVideoAudioCompressorConfig(PretrainedConfig):
33
  self.chunk_size = chunk_size
34
  self.num_hidden_layers = num_hidden_layers
35
  self.hidden_size = hidden_size
36
-
37
-
 
 
38
  __all__ = ["MambaMiaVideoAudioCompressorConfig"]
 
1
+ # coding=utf-8
2
+ # Copyright 2024 NAVER Cloud Corp. 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
+ """MambaMia video-audio compressor configuration"""
16
+
17
+ from transformers import AutoConfig
18
  from transformers.configuration_utils import PretrainedConfig
19
 
20
 
 
21
  class MambaMiaVideoAudioCompressorConfig(PretrainedConfig):
22
+ r"""
23
+ This is the configuration class to store the configuration of a MambaMia video-audio compressor.
24
+
25
+ Configuration objects inherit from [`PretrainedConfig`] and can be used to control the model outputs. Read the
26
+ documentation from [`PretrainedConfig`] for more information.
27
 
28
  Args:
29
+ input_size (`int`, *optional*, defaults to 1280):
30
+ Input embedding dimension (e.g., 1280 for Whisper encoder output).
31
+ output_size (`int`, *optional*, defaults to 2048):
32
+ Output embedding dimension (e.g., 2048 for LLM hidden size).
33
+ chunk_size (`int`, *optional*, defaults to 25):
34
+ Number of tokens per chunk (i.e., 1 second at 25Hz).
35
+ num_hidden_layers (`int`, *optional*, defaults to 1):
36
+ Number of MambaMia2 layers.
37
+ hidden_size (`int`, *optional*, defaults to 3072):
38
+ Internal hidden size. Must be divisible by 24.
39
  """
40
 
41
  model_type = "mambamia_videoaudio_compressor"
 
55
  self.chunk_size = chunk_size
56
  self.num_hidden_layers = num_hidden_layers
57
  self.hidden_size = hidden_size
58
+
59
+
60
+ AutoConfig.register("mambamia_videoaudio_compressor", MambaMiaVideoAudioCompressorConfig)
61
+
62
  __all__ = ["MambaMiaVideoAudioCompressorConfig"]
configuration_tatok.py CHANGED
@@ -1,13 +1,57 @@
1
- import transformers
2
- from transformers import AutoConfig, AutoModel
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  from transformers.configuration_utils import PretrainedConfig
4
 
5
 
6
- # TATok (TextAlignedTokenizer) Config
7
  class TATokConfig(PretrainedConfig):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  model_type = "tatok"
9
 
10
- default_tatok_bottleneck = {
11
  "name": "bottleneck",
12
  "args": {
13
  "bottleneck_dim": 1536,
@@ -33,125 +77,29 @@ class TATokConfig(PretrainedConfig):
33
 
34
  def __init__(
35
  self,
36
- bottleneck=None,
37
- bottleneck_token_num=729,
38
- input_size=384,
39
- teacher="google/siglip2-so400m-patch14-384",
40
- input_type="indices",
41
- pool_scale=1,
42
- decoder_depth=3,
43
- select_layer_id=-2,
44
- model_name_or_path=None,
45
  **kwargs,
46
  ):
47
- # Extract our custom attributes from kwargs first
48
- # This handles the case when config.json contains these values
49
- # Priority: explicit argument (if not default) > kwargs value > default value
50
- kwargs_bottleneck = kwargs.pop("bottleneck", None)
51
- kwargs_bottleneck_token_num = kwargs.pop("bottleneck_token_num", 729)
52
- kwargs_input_size = kwargs.pop("input_size", 384)
53
- kwargs_teacher = kwargs.pop("teacher", "google/siglip2-so400m-patch14-384")
54
- kwargs_input_type = kwargs.pop("input_type", "indices")
55
- kwargs_pool_scale = kwargs.pop("pool_scale", 1)
56
- kwargs_decoder_depth = kwargs.pop("decoder_depth", 3)
57
- kwargs_select_layer_id = kwargs.pop("select_layer_id", -2)
58
- kwargs_model_name_or_path = kwargs.pop("model_name_or_path", None)
59
-
60
- # Also handle ckpt_path which might be in kwargs from config.json
61
- ckpt_path = kwargs.pop("ckpt_path", None)
62
- if ckpt_path is not None:
63
- kwargs_teacher = ckpt_path
64
- # Store ckpt_path to include in merged_kwargs later
65
- stored_ckpt_path = ckpt_path
66
- else:
67
- stored_ckpt_path = None
68
-
69
- # Use explicit arguments if they differ from defaults, otherwise use kwargs values.
70
- # For bottleneck, if everything is None, fall back to the full default hierarchical config.
71
- if bottleneck is not None:
72
- self.bottleneck = bottleneck
73
- elif kwargs_bottleneck is not None:
74
- self.bottleneck = kwargs_bottleneck
75
- else:
76
- self.bottleneck = self.default_tatok_bottleneck
77
-
78
- self.bottleneck_token_num = bottleneck_token_num if bottleneck_token_num != 729 else kwargs_bottleneck_token_num
79
- self.input_size = input_size if input_size != 384 else kwargs_input_size
80
- self.teacher = teacher if teacher != "google/siglip2-so400m-patch14-384" else kwargs_teacher
81
- self.input_type = input_type if input_type != "indices" else kwargs_input_type
82
- self.pool_scale = pool_scale if pool_scale != 1 else kwargs_pool_scale
83
- self.decoder_depth = decoder_depth if decoder_depth != 3 else kwargs_decoder_depth
84
- self.select_layer_id = select_layer_id if select_layer_id != -2 else kwargs_select_layer_id
85
- self.model_name_or_path = model_name_or_path if model_name_or_path is not None else kwargs_model_name_or_path
86
-
87
- # Set default values for standard transformers config attributes
88
- # These will be merged with kwargs so they appear even when not in config.json
89
- default_transformers_config = {
90
- "_name_or_path": None,
91
- "add_cross_attention": False,
92
- "architectures": ["TextAlignedTokenizer"],
93
- "bad_words_ids": None,
94
- "begin_suppress_tokens": None,
95
- "bos_token_id": None,
96
- "chunk_size_feed_forward": 0,
97
- "cross_attention_hidden_size": None,
98
- "decoder_start_token_id": None,
99
- "diversity_penalty": 0.0,
100
- "do_sample": False,
101
- "early_stopping": False,
102
- "encoder_no_repeat_ngram_size": 0,
103
- "eos_token_id": None,
104
- "exponential_decay_length_penalty": None,
105
- "finetuning_task": None,
106
- "forced_bos_token_id": None,
107
- "forced_eos_token_id": None,
108
- "id2label": {"0": "LABEL_0", "1": "LABEL_1"},
109
- "is_decoder": False,
110
- "is_encoder_decoder": False,
111
- "label2id": {"LABEL_0": 0, "LABEL_1": 1},
112
- "length_penalty": 1.0,
113
- "max_length": 20,
114
- "min_length": 0,
115
- "no_repeat_ngram_size": 0,
116
- "num_beam_groups": 1,
117
- "num_beams": 1,
118
- "num_return_sequences": 1,
119
- "output_attentions": False,
120
- "output_hidden_states": False,
121
- "output_scores": False,
122
- "pad_token_id": None,
123
- "prefix": None,
124
- "problem_type": None,
125
- "pruned_heads": {},
126
- "rand_scale": True,
127
- "remove_invalid_values": False,
128
- "repetition_penalty": 1.0,
129
- "return_dict": True,
130
- "return_dict_in_generate": False,
131
- "sep_token_id": None,
132
- "suppress_tokens": None,
133
- "task_specific_params": None,
134
- "temperature": 1.0,
135
- "tf_legacy_loss": False,
136
- "tie_encoder_decoder": False,
137
- "tie_word_embeddings": True,
138
- "tokenizer_class": None,
139
- "top_k": 50,
140
- "top_p": 1.0,
141
- "torch_dtype": "float32",
142
- "torchscript": False,
143
- "typical_p": 1.0,
144
- "use_bfloat16": False,
145
- }
146
 
147
- # Merge defaults with kwargs (kwargs values take precedence)
148
- merged_kwargs = {**default_transformers_config, **kwargs}
149
 
150
- # Add ckpt_path back if it was in the original kwargs
151
- if stored_ckpt_path is not None:
152
- merged_kwargs["ckpt_path"] = stored_ckpt_path
153
 
154
- # Pass merged kwargs to parent (these are standard transformers config attributes)
155
- super().__init__(**merged_kwargs)
156
-
157
  __all__ = ["TATokConfig"]
 
1
+ # coding=utf-8
2
+ # Copyright 2024 NAVER Cloud Corp. 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
+ """TATok (Text-Aligned Tokenizer) configuration"""
16
+
17
+ import copy
18
+ from typing import Optional
19
+
20
+ from transformers import AutoConfig
21
  from transformers.configuration_utils import PretrainedConfig
22
 
23
 
 
24
  class TATokConfig(PretrainedConfig):
25
+ r"""
26
+ This is the configuration class to store the configuration of a TATok (Text-Aligned Tokenizer) model.
27
+
28
+ Configuration objects inherit from [`PretrainedConfig`] and can be used to control the model outputs. Read the
29
+ documentation from [`PretrainedConfig`] for more information.
30
+
31
+ Args:
32
+ bottleneck (`dict`, *optional*):
33
+ Configuration dict for the bottleneck layer. If not provided, uses `TATokConfig._default_bottleneck`.
34
+ bottleneck_token_num (`int`, *optional*, defaults to 729):
35
+ Number of bottleneck tokens.
36
+ input_size (`int`, *optional*, defaults to 384):
37
+ Input image size.
38
+ teacher (`str`, *optional*, defaults to `"google/siglip2-so400m-patch14-384"`):
39
+ Name or path of the teacher model.
40
+ input_type (`str`, *optional*, defaults to `"indices"`):
41
+ Type of input representation.
42
+ pool_scale (`int`, *optional*, defaults to 1):
43
+ Pooling scale factor.
44
+ decoder_depth (`int`, *optional*, defaults to 3):
45
+ Number of decoder layers.
46
+ select_layer_id (`int`, *optional*, defaults to -2):
47
+ Index of the teacher layer to select features from.
48
+ rand_scale (`bool`, *optional*, defaults to `True`):
49
+ Whether to use random scaling during training.
50
+ """
51
+
52
  model_type = "tatok"
53
 
54
+ _default_bottleneck = {
55
  "name": "bottleneck",
56
  "args": {
57
  "bottleneck_dim": 1536,
 
77
 
78
  def __init__(
79
  self,
80
+ bottleneck: Optional[dict] = None,
81
+ bottleneck_token_num: int = 729,
82
+ input_size: int = 384,
83
+ teacher: str = "google/siglip2-so400m-patch14-384",
84
+ input_type: str = "indices",
85
+ pool_scale: int = 1,
86
+ decoder_depth: int = 3,
87
+ select_layer_id: int = -2,
88
+ rand_scale: bool = True,
89
  **kwargs,
90
  ):
91
+ super().__init__(**kwargs)
92
+ self.bottleneck = bottleneck if bottleneck is not None else copy.deepcopy(self._default_bottleneck)
93
+ self.bottleneck_token_num = bottleneck_token_num
94
+ self.input_size = input_size
95
+ self.teacher = teacher
96
+ self.input_type = input_type
97
+ self.pool_scale = pool_scale
98
+ self.decoder_depth = decoder_depth
99
+ self.select_layer_id = select_layer_id
100
+ self.rand_scale = rand_scale
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
 
 
 
102
 
103
+ AutoConfig.register("tatok", TATokConfig)
 
 
104
 
 
 
 
105
  __all__ = ["TATokConfig"]
image_processing_hyperclovax_omni.py CHANGED
@@ -1,19 +1,19 @@
1
  """
2
- HyperCLOVAXOmni Image Processor (Fast)
3
 
4
- Qwen VL 스타일의 동적 해상도 이미지 처리를 구현합니다:
5
- - Smart resize: 이미지를 min_pixels와 max_pixels 범위 내로 조정
6
- - Vision token calculation: merge_size를 사용한 토큰 축소
7
- - Discrete image processing: 별도의 discrete vision token 처리
8
 
9
- BaseImageProcessorFast 기반으로 torchvision resize를 사용하여
10
- Track A (Qwen2VLImageProcessorFast)와 bit-perfect 일치를 달성합니다.
11
  """
12
 
13
- import os
14
  import math
 
 
 
15
  import torch
16
- from typing import Dict, List, Optional, Union, Tuple
17
  from torchvision.transforms.v2 import functional as F
18
  from transformers.image_processing_utils import BatchFeature
19
  from transformers.image_processing_utils_fast import (
@@ -32,29 +32,31 @@ from transformers.image_utils import (
32
  from transformers.processing_utils import ImagesKwargs, Unpack
33
  from transformers.utils import TensorType, logging
34
 
35
-
36
  logger = logging.get_logger(__name__)
37
 
38
 
39
  def smart_resize(
40
- height: int, width: int, factor: int = 28, min_pixels: int = 56 * 56, max_pixels: int = 14 * 14 * 4 * 1280
41
- ):
42
- """
43
- Qwen VL 스타일 스마트 리사이즈
44
-
45
- 이미지 크기를 다음 조건을 만족하도록 조정:
46
- 1. 양쪽 차원이 factor로 나누어떨어짐
47
- 2. 총 픽셀 수가 min_pixels와 max_pixels 사이
 
 
 
48
 
49
  Args:
50
- height: 원본 이미지 높이
51
- width: 원본 이미지 너비
52
- factor: 라운딩 단위 (기본: 28 = patch_size * merge_size)
53
- min_pixels: 최소 픽셀 (기본: 3136)
54
- max_pixels: 최대 픽셀 (기본: 1003520)
55
 
56
  Returns:
57
- (new_height, new_width) 튜플
58
  """
59
  if max(height, width) / min(height, width) > 200:
60
  raise ValueError(
@@ -73,18 +75,22 @@ def smart_resize(
73
  return h_bar, w_bar
74
 
75
 
76
- def calculate_qwen_num_patches(height: int, width: int, patch_size: int = 14, merge_size: int = 2):
77
- """
78
- Calculate number of vision tokens using Qwen VL method
 
 
 
 
79
 
80
  Args:
81
- height: Image height (should be divisible by patch_size * merge_size)
82
- width: Image width (should be divisible by patch_size * merge_size)
83
- patch_size: ViT patch size (default: 14)
84
- merge_size: Merge size for token reduction (default: 2)
85
 
86
  Returns:
87
- Number of vision tokens
88
  """
89
  grid_h = height // patch_size
90
  grid_w = width // patch_size
@@ -98,14 +104,6 @@ class HyperCLOVAXOmniFastImageProcessorKwargs(DefaultFastImageProcessorKwargs, t
98
  patch_size: Optional[int]
99
  temporal_patch_size: Optional[int]
100
  merge_size: Optional[int]
101
-
102
-
103
- class HyperCLOVAXOmniImagesKwargs(ImagesKwargs, total=False):
104
- min_pixels: Optional[int]
105
- max_pixels: Optional[int]
106
- patch_size: Optional[int]
107
- temporal_patch_size: Optional[int]
108
- merge_size: Optional[int]
109
  # Token parameters
110
  image_token: Optional[str]
111
  image_start_token: Optional[str]
@@ -123,19 +121,15 @@ class HyperCLOVAXOmniImagesKwargs(ImagesKwargs, total=False):
123
 
124
 
125
  class HyperCLOVAXOmniImageProcessor(BaseImageProcessorFast):
126
- """
127
- Fast image processor for HyperCLOVAXOmni that follows Qwen VL's image processing logic.
128
 
129
- Uses torchvision-based resize (BaseImageProcessorFast) for bit-perfect alignment
130
- with Qwen2VLImageProcessorFast.
131
-
132
- This processor implements Qwen VL's dynamic resolution approach:
133
- 1. Smart resize: adjusts image size to be within min_pixels and max_pixels
134
- 2. Vision token calculation: uses merge_size for token reduction
135
- 3. Discrete image processing: separate processing for discrete vision tokens
136
  """
137
 
138
- # Class-level defaults (Qwen2VLImageProcessorFast pattern)
139
  resample = PILImageResampling.BICUBIC
140
  image_mean = OPENAI_CLIP_MEAN
141
  image_std = OPENAI_CLIP_STD
@@ -154,7 +148,7 @@ class HyperCLOVAXOmniImageProcessor(BaseImageProcessorFast):
154
  valid_kwargs = HyperCLOVAXOmniFastImageProcessorKwargs
155
 
156
  def __init__(self, **kwargs):
157
- # Handle size min_pixels/max_pixels (Qwen2VL pattern)
158
  size = kwargs.pop("size", None)
159
  min_pixels = kwargs.pop("min_pixels", None)
160
  max_pixels = kwargs.pop("max_pixels", None)
@@ -192,7 +186,7 @@ class HyperCLOVAXOmniImageProcessor(BaseImageProcessorFast):
192
  if self.max_pixels is None:
193
  self.max_pixels = self.size["longest_edge"]
194
 
195
- # Build ratio token mapping from discrete_image_ratios
196
  ratios = self.discrete_image_ratios if self.discrete_image_ratios is not None else []
197
  self.discrete_image_ratio_tokens = {
198
  f"{r[0]}:{r[1]}": f"<|vision_ratio_{r[0]}:{r[1]}|>"
@@ -206,7 +200,7 @@ class HyperCLOVAXOmniImageProcessor(BaseImageProcessorFast):
206
  max_pixels: Optional[int] = None,
207
  **kwargs,
208
  ) -> dict:
209
- """size min_pixels/max_pixels 상호 연동"""
210
  if min_pixels is not None and max_pixels is not None:
211
  size = {"shortest_edge": min_pixels, "longest_edge": max_pixels}
212
  elif size is not None:
@@ -219,12 +213,41 @@ class HyperCLOVAXOmniImageProcessor(BaseImageProcessorFast):
219
 
220
  return super()._further_process_kwargs(size=size, min_pixels=min_pixels, max_pixels=max_pixels, **kwargs)
221
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
222
  def _preprocess_continuous_image(
223
  self,
224
  images: list,
225
  do_resize: bool,
226
  size: SizeDict,
227
- interpolation: Optional["F.InterpolationMode"],
228
  do_rescale: bool,
229
  rescale_factor: float,
230
  do_normalize: bool,
@@ -235,29 +258,30 @@ class HyperCLOVAXOmniImageProcessor(BaseImageProcessorFast):
235
  merge_size: int,
236
  disable_grouping: Optional[bool],
237
  ) -> dict:
238
- """이미지에 대한 continuous image 전처리를 수행합니다.
239
 
240
- Qwen2VL 패턴에 따라 smart resize rescale+normalize patchify를 수행합니다.
241
 
242
  Args:
243
- images: 전처리할 이미지 텐서 리스트.
244
- do_resize: 리사이즈 수행 여부.
245
- size: min_pixels/max_pixels를 포함하는 SizeDict.
246
- interpolation: 보간 방법.
247
- do_rescale: rescale 수행 여부.
248
- rescale_factor: rescale 계수.
249
- do_normalize: normalize 수행 여부.
250
- image_mean: 정규화 평균.
251
- image_std: 정규화 표준편차.
252
- patch_size: ViT 패치 크기.
253
- temporal_patch_size: 시간 패치 크기.
254
- merge_size: 토큰 축소를 위한 merge 크기.
255
- disable_grouping: 그룹화 비활성화 여부.
256
 
257
  Returns:
258
- dict with:
259
- - "pixel_values": (N, num_patches, patch_dim) 텐서.
260
- - "image_grid_thw": (N, 3) 텐서.
 
261
  """
262
  # 1. Group & smart resize
263
  grouped_images, grouped_images_index = group_images_by_shape(images, disable_grouping=disable_grouping)
@@ -279,7 +303,7 @@ class HyperCLOVAXOmniImageProcessor(BaseImageProcessorFast):
279
  resized_images_grouped[shape] = stacked_images
280
  resized_images = reorder_images(resized_images_grouped, grouped_images_index)
281
 
282
- # 2. Group again fused rescale+normalize patchify
283
  grouped_images, grouped_images_index = group_images_by_shape(resized_images, disable_grouping=disable_grouping)
284
  processed_images_grouped = {}
285
  processed_grids = {}
@@ -303,7 +327,7 @@ class HyperCLOVAXOmniImageProcessor(BaseImageProcessorFast):
303
  grid_t = grid_t // temporal_patch_size
304
  grid_h, grid_w = resized_height // patch_size, resized_width // patch_size
305
 
306
- # Patchify: reshape permute flatten
307
  patches = patches.view(
308
  batch_size,
309
  grid_t, temporal_patch_size,
@@ -338,22 +362,23 @@ class HyperCLOVAXOmniImageProcessor(BaseImageProcessorFast):
338
  self,
339
  images: list,
340
  original_sizes: List[Tuple[int, int]],
341
- interpolation: Optional["F.InterpolationMode"],
342
  ) -> dict:
343
- """이미지에 대한 discrete image 전처리를 수행합니다.
344
 
345
- 이미지를 고정 크기(discrete_image_size) 리사이즈하고,
346
- 원본 비율에 가장 가까운 ratio token을 찾습니다.
347
 
348
  Args:
349
- images: 전처리할 이미지 텐서 리스트.
350
- original_sizes: 이미지의 원본 (height, width) 튜플 리스트.
351
- interpolation: 보간 방법.
352
 
353
  Returns:
354
- dict with:
355
- - "discrete_pixel_values": (N, C, discrete_image_size, discrete_image_size) 텐서.
356
- - "discrete_image_ratios": (N, 2) 텐서.
 
357
  """
358
  discrete_pixel_values_list = []
359
  discrete_image_ratios_list = []
@@ -393,7 +418,7 @@ class HyperCLOVAXOmniImageProcessor(BaseImageProcessorFast):
393
  images: list,
394
  do_resize: bool,
395
  size: SizeDict,
396
- interpolation: Optional["F.InterpolationMode"],
397
  do_rescale: bool,
398
  rescale_factor: float,
399
  do_normalize: bool,
@@ -405,12 +430,36 @@ class HyperCLOVAXOmniImageProcessor(BaseImageProcessorFast):
405
  disable_grouping: Optional[bool],
406
  return_tensors: Optional[Union[str, TensorType]],
407
  **kwargs,
408
- ):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
409
  # Record original sizes for discrete processing before any transforms
410
  if self.use_discrete_image_token:
411
  original_sizes = [(img.shape[-2], img.shape[-1]) for img in images]
412
 
413
- # --- Continuous processing ---
414
  continuous_result = self._preprocess_continuous_image(
415
  images,
416
  do_resize=do_resize,
@@ -428,7 +477,7 @@ class HyperCLOVAXOmniImageProcessor(BaseImageProcessorFast):
428
  )
429
  data = continuous_result
430
 
431
- # --- Discrete processing ---
432
  if self.use_discrete_image_token:
433
  discrete_result = self._preprocess_discrete_image(
434
  images,
@@ -439,39 +488,35 @@ class HyperCLOVAXOmniImageProcessor(BaseImageProcessorFast):
439
 
440
  return BatchFeature(data=data, tensor_type=return_tensors)
441
 
442
- def _find_best_ratio_token(
443
- self,
444
- original_size: List[int],
445
- discrete_image_ratios: Optional[List[List[int]]] = None,
446
- ):
447
- """Find the best ratio token based on original_size"""
448
- discrete_image_ratios = discrete_image_ratios if discrete_image_ratios is not None else self.discrete_image_ratios
449
-
450
- if not discrete_image_ratios:
451
- return (1, 1)
452
-
453
- h, w = original_size
454
- if h == 0 or w == 0:
455
- return (1, 1)
456
-
457
- ratios = [i / j for i, j in discrete_image_ratios]
458
- diffs = [abs(w / h - r) for r in ratios]
459
- best_size_idx = diffs.index(min(diffs))
460
-
461
- return discrete_image_ratios[best_size_idx]
462
-
463
  def get_num_image_tokens(
464
  self,
465
  image_width: Optional[int] = None,
466
  image_height: Optional[int] = None,
467
- pixel_values: Optional["torch.Tensor"] = None,
468
  include_boundary_tokens: bool = False,
469
  min_pixels: Optional[int] = None,
470
  max_pixels: Optional[int] = None,
471
  patch_size: Optional[int] = None,
472
  merge_size: Optional[int] = None,
 
473
  ) -> int:
474
- """이미지 입력에 대한 토큰 수를 계산합니다."""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
475
  patch_size = patch_size if patch_size is not None else self.patch_size
476
  merge_size = merge_size if merge_size is not None else self.merge_size
477
  min_pixels = min_pixels if min_pixels is not None else self.min_pixels
@@ -483,7 +528,7 @@ class HyperCLOVAXOmniImageProcessor(BaseImageProcessorFast):
483
  resized_height, resized_width = smart_resize(
484
  image_height, image_width, factor=factor, min_pixels=min_pixels, max_pixels=max_pixels
485
  )
486
- num_patches = calculate_qwen_num_patches(resized_height, resized_width, patch_size, merge_size)
487
  num_continuous_tokens = num_patches // (merge_size ** 2)
488
  elif len(pixel_values.shape) == 2:
489
  num_continuous_tokens = pixel_values.shape[0] // (merge_size ** 2)
@@ -492,23 +537,31 @@ class HyperCLOVAXOmniImageProcessor(BaseImageProcessorFast):
492
  pv.shape[0] // (merge_size ** 2) for pv in pixel_values
493
  )
494
  if include_boundary_tokens:
495
- num_continuous_tokens += 2 # <|image_start_token, <|image_end_token
496
 
497
  if self.use_discrete_image_token:
498
  discrete_token_size = self.discrete_token_size
499
- num_discrete_tokens = discrete_token_size ** 2 # 729
500
- # num_discrete_tokens += discrete_token_size # vision_eol
501
- # num_discrete_tokens += 1 # vision_eof
502
  if include_boundary_tokens:
503
- num_discrete_tokens += 2 # <|discrete_image_start_token|>, <|discrete_image_end_token|>
504
 
505
- return (num_continuous_tokens, num_discrete_tokens)
 
 
 
506
 
507
  def save_pretrained(
508
  self,
509
  save_directory: Union[str, os.PathLike],
510
  *args,
511
  **kwargs,
512
- ):
 
 
 
 
 
 
 
513
  self.register_for_auto_class()
514
  super().save_pretrained(save_directory, *args, **kwargs)
 
1
  """
2
+ HyperCLOVAX Omni Image Processor (Fast)
3
 
4
+ Implements dynamic resolution image processing:
5
+ - Smart resize: adjusts image to fit within min_pixels and max_pixels
6
+ - Vision token calculation: token reduction using merge_size
7
+ - Discrete image processing: separate processing for discrete vision tokens
8
 
9
+ Based on BaseImageProcessorFast with torchvision resize.
 
10
  """
11
 
 
12
  import math
13
+ import os
14
+ from typing import List, Optional, Tuple, Union
15
+
16
  import torch
 
17
  from torchvision.transforms.v2 import functional as F
18
  from transformers.image_processing_utils import BatchFeature
19
  from transformers.image_processing_utils_fast import (
 
32
  from transformers.processing_utils import ImagesKwargs, Unpack
33
  from transformers.utils import TensorType, logging
34
 
 
35
  logger = logging.get_logger(__name__)
36
 
37
 
38
  def smart_resize(
39
+ height: int,
40
+ width: int,
41
+ factor: int = 28,
42
+ min_pixels: int = 56 * 56,
43
+ max_pixels: int = 14 * 14 * 4 * 1280,
44
+ ) -> Tuple[int, int]:
45
+ """Smart resize for dynamic resolution.
46
+
47
+ Adjusts image dimensions to satisfy:
48
+ 1. Both dimensions are divisible by factor.
49
+ 2. Total pixel count is between min_pixels and max_pixels.
50
 
51
  Args:
52
+ height: Original image height.
53
+ width: Original image width.
54
+ factor: Rounding unit (default: 28 = patch_size * merge_size).
55
+ min_pixels: Minimum pixel count (default: 3136).
56
+ max_pixels: Maximum pixel count (default: 1003520).
57
 
58
  Returns:
59
+ Tuple of (new_height, new_width).
60
  """
61
  if max(height, width) / min(height, width) > 200:
62
  raise ValueError(
 
75
  return h_bar, w_bar
76
 
77
 
78
+ def calculate_num_patches(
79
+ height: int,
80
+ width: int,
81
+ patch_size: int = 14,
82
+ merge_size: int = 2,
83
+ ) -> int:
84
+ """Calculate the number of vision tokens.
85
 
86
  Args:
87
+ height: Image height (should be divisible by patch_size * merge_size).
88
+ width: Image width (should be divisible by patch_size * merge_size).
89
+ patch_size: ViT patch size (default: 14).
90
+ merge_size: Merge size for token reduction (default: 2).
91
 
92
  Returns:
93
+ Number of vision tokens.
94
  """
95
  grid_h = height // patch_size
96
  grid_w = width // patch_size
 
104
  patch_size: Optional[int]
105
  temporal_patch_size: Optional[int]
106
  merge_size: Optional[int]
 
 
 
 
 
 
 
 
107
  # Token parameters
108
  image_token: Optional[str]
109
  image_start_token: Optional[str]
 
121
 
122
 
123
  class HyperCLOVAXOmniImageProcessor(BaseImageProcessorFast):
124
+ """Fast image processor for HyperCLOVAX Omni.
 
125
 
126
+ Uses torchvision-based resize for dynamic resolution processing:
127
+ 1. Smart resize: adjusts image size to be within min_pixels and max_pixels.
128
+ 2. Vision token calculation: uses merge_size for token reduction.
129
+ 3. Discrete image processing: separate processing for discrete vision tokens.
 
 
 
130
  """
131
 
132
+ # Class-level defaults
133
  resample = PILImageResampling.BICUBIC
134
  image_mean = OPENAI_CLIP_MEAN
135
  image_std = OPENAI_CLIP_STD
 
148
  valid_kwargs = HyperCLOVAXOmniFastImageProcessorKwargs
149
 
150
  def __init__(self, **kwargs):
151
+ # Handle size <-> min_pixels/max_pixels
152
  size = kwargs.pop("size", None)
153
  min_pixels = kwargs.pop("min_pixels", None)
154
  max_pixels = kwargs.pop("max_pixels", None)
 
186
  if self.max_pixels is None:
187
  self.max_pixels = self.size["longest_edge"]
188
 
189
+ # Build ratio -> token mapping from discrete_image_ratios
190
  ratios = self.discrete_image_ratios if self.discrete_image_ratios is not None else []
191
  self.discrete_image_ratio_tokens = {
192
  f"{r[0]}:{r[1]}": f"<|vision_ratio_{r[0]}:{r[1]}|>"
 
200
  max_pixels: Optional[int] = None,
201
  **kwargs,
202
  ) -> dict:
203
+ """Synchronize size <-> min_pixels/max_pixels."""
204
  if min_pixels is not None and max_pixels is not None:
205
  size = {"shortest_edge": min_pixels, "longest_edge": max_pixels}
206
  elif size is not None:
 
213
 
214
  return super()._further_process_kwargs(size=size, min_pixels=min_pixels, max_pixels=max_pixels, **kwargs)
215
 
216
+ def _find_best_ratio_token(
217
+ self,
218
+ original_size: List[int],
219
+ discrete_image_ratios: Optional[List[List[int]]] = None,
220
+ ) -> Tuple[int, int]:
221
+ """Find the best ratio token based on the original image aspect ratio.
222
+
223
+ Args:
224
+ original_size: Original [height, width] of the image.
225
+ discrete_image_ratios: List of [h, w] ratio pairs. Defaults to self.discrete_image_ratios.
226
+
227
+ Returns:
228
+ Best matching (h_ratio, w_ratio) tuple.
229
+ """
230
+ discrete_image_ratios = discrete_image_ratios if discrete_image_ratios is not None else self.discrete_image_ratios
231
+
232
+ if not discrete_image_ratios:
233
+ return (1, 1)
234
+
235
+ h, w = original_size
236
+ if h == 0 or w == 0:
237
+ return (1, 1)
238
+
239
+ ratios = [i / j for i, j in discrete_image_ratios]
240
+ diffs = [abs(w / h - r) for r in ratios]
241
+ best_size_idx = diffs.index(min(diffs))
242
+
243
+ return discrete_image_ratios[best_size_idx]
244
+
245
  def _preprocess_continuous_image(
246
  self,
247
  images: list,
248
  do_resize: bool,
249
  size: SizeDict,
250
+ interpolation: Optional[F.InterpolationMode],
251
  do_rescale: bool,
252
  rescale_factor: float,
253
  do_normalize: bool,
 
258
  merge_size: int,
259
  disable_grouping: Optional[bool],
260
  ) -> dict:
261
+ """Preprocess images for continuous vision features.
262
 
263
+ Performs smart resize -> rescale+normalize -> patchify.
264
 
265
  Args:
266
+ images: List of image tensors to preprocess.
267
+ do_resize: Whether to perform resizing.
268
+ size: SizeDict containing min_pixels/max_pixels.
269
+ interpolation: Interpolation method.
270
+ do_rescale: Whether to perform rescaling.
271
+ rescale_factor: Rescale factor.
272
+ do_normalize: Whether to perform normalization.
273
+ image_mean: Normalization mean.
274
+ image_std: Normalization standard deviation.
275
+ patch_size: ViT patch size.
276
+ temporal_patch_size: Temporal patch size.
277
+ merge_size: Token reduction merge size.
278
+ disable_grouping: Whether to disable image grouping.
279
 
280
  Returns:
281
+ Dictionary with:
282
+ - "pixel_values": Tensor of shape (N, num_patches, patch_dim).
283
+ - "image_grid_thw": Tensor of shape (N, 3).
284
+ - "num_image_tokens": Tensor of shape (N,) with per-image token counts.
285
  """
286
  # 1. Group & smart resize
287
  grouped_images, grouped_images_index = group_images_by_shape(images, disable_grouping=disable_grouping)
 
303
  resized_images_grouped[shape] = stacked_images
304
  resized_images = reorder_images(resized_images_grouped, grouped_images_index)
305
 
306
+ # 2. Group again -> fused rescale+normalize -> patchify
307
  grouped_images, grouped_images_index = group_images_by_shape(resized_images, disable_grouping=disable_grouping)
308
  processed_images_grouped = {}
309
  processed_grids = {}
 
327
  grid_t = grid_t // temporal_patch_size
328
  grid_h, grid_w = resized_height // patch_size, resized_width // patch_size
329
 
330
+ # Patchify: reshape -> permute -> flatten
331
  patches = patches.view(
332
  batch_size,
333
  grid_t, temporal_patch_size,
 
362
  self,
363
  images: list,
364
  original_sizes: List[Tuple[int, int]],
365
+ interpolation: Optional[F.InterpolationMode],
366
  ) -> dict:
367
+ """Preprocess images for discrete vision tokens.
368
 
369
+ Resizes each image to a fixed size (discrete_image_size) and finds
370
+ the closest aspect ratio token.
371
 
372
  Args:
373
+ images: List of image tensors to preprocess.
374
+ original_sizes: List of (height, width) tuples for each image.
375
+ interpolation: Interpolation method.
376
 
377
  Returns:
378
+ Dictionary with:
379
+ - "discrete_pixel_values": Tensor of shape (N, C, discrete_image_size, discrete_image_size).
380
+ - "discrete_image_ratios": Tensor of shape (N, 2).
381
+ - "num_discrete_image_tokens": Tensor of shape (N,) with per-image discrete token counts.
382
  """
383
  discrete_pixel_values_list = []
384
  discrete_image_ratios_list = []
 
418
  images: list,
419
  do_resize: bool,
420
  size: SizeDict,
421
+ interpolation: Optional[F.InterpolationMode],
422
  do_rescale: bool,
423
  rescale_factor: float,
424
  do_normalize: bool,
 
430
  disable_grouping: Optional[bool],
431
  return_tensors: Optional[Union[str, TensorType]],
432
  **kwargs,
433
+ ) -> BatchFeature:
434
+ """Main preprocessing entry point called by BaseImageProcessorFast.
435
+
436
+ Performs continuous image processing and optionally discrete image processing.
437
+
438
+ Args:
439
+ images: List of image tensors.
440
+ do_resize: Whether to perform resizing.
441
+ size: SizeDict containing min_pixels/max_pixels.
442
+ interpolation: Interpolation method.
443
+ do_rescale: Whether to perform rescaling.
444
+ rescale_factor: Rescale factor.
445
+ do_normalize: Whether to perform normalization.
446
+ image_mean: Normalization mean.
447
+ image_std: Normalization standard deviation.
448
+ patch_size: ViT patch size.
449
+ temporal_patch_size: Temporal patch size.
450
+ merge_size: Token reduction merge size.
451
+ disable_grouping: Whether to disable image grouping.
452
+ return_tensors: Desired tensor type for outputs.
453
+
454
+ Returns:
455
+ BatchFeature containing pixel_values, image_grid_thw, and optionally
456
+ discrete processing results.
457
+ """
458
  # Record original sizes for discrete processing before any transforms
459
  if self.use_discrete_image_token:
460
  original_sizes = [(img.shape[-2], img.shape[-1]) for img in images]
461
 
462
+ # Continuous processing
463
  continuous_result = self._preprocess_continuous_image(
464
  images,
465
  do_resize=do_resize,
 
477
  )
478
  data = continuous_result
479
 
480
+ # Discrete processing
481
  if self.use_discrete_image_token:
482
  discrete_result = self._preprocess_discrete_image(
483
  images,
 
488
 
489
  return BatchFeature(data=data, tensor_type=return_tensors)
490
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
491
  def get_num_image_tokens(
492
  self,
493
  image_width: Optional[int] = None,
494
  image_height: Optional[int] = None,
495
+ pixel_values: Optional[torch.Tensor] = None,
496
  include_boundary_tokens: bool = False,
497
  min_pixels: Optional[int] = None,
498
  max_pixels: Optional[int] = None,
499
  patch_size: Optional[int] = None,
500
  merge_size: Optional[int] = None,
501
+ return_tuple: Optional[bool] = None,
502
  ) -> int:
503
+ """Compute the number of image tokens for the given input.
504
+
505
+ Args:
506
+ image_width: Image width (used when pixel_values is None).
507
+ image_height: Image height (used when pixel_values is None).
508
+ pixel_values: Pre-computed pixel values tensor.
509
+ include_boundary_tokens: Whether to include start/end boundary tokens.
510
+ min_pixels: Minimum pixel count. Defaults to self.min_pixels.
511
+ max_pixels: Maximum pixel count. Defaults to self.max_pixels.
512
+ patch_size: ViT patch size. Defaults to self.patch_size.
513
+ merge_size: Token reduction merge size. Defaults to self.merge_size.
514
+ return_tuple: If True, return (continuous, discrete) tuple.
515
+ Otherwise return the sum.
516
+
517
+ Returns:
518
+ Token count as int, or (continuous, discrete) tuple if return_tuple is True.
519
+ """
520
  patch_size = patch_size if patch_size is not None else self.patch_size
521
  merge_size = merge_size if merge_size is not None else self.merge_size
522
  min_pixels = min_pixels if min_pixels is not None else self.min_pixels
 
528
  resized_height, resized_width = smart_resize(
529
  image_height, image_width, factor=factor, min_pixels=min_pixels, max_pixels=max_pixels
530
  )
531
+ num_patches = calculate_num_patches(resized_height, resized_width, patch_size, merge_size)
532
  num_continuous_tokens = num_patches // (merge_size ** 2)
533
  elif len(pixel_values.shape) == 2:
534
  num_continuous_tokens = pixel_values.shape[0] // (merge_size ** 2)
 
537
  pv.shape[0] // (merge_size ** 2) for pv in pixel_values
538
  )
539
  if include_boundary_tokens:
540
+ num_continuous_tokens += 2
541
 
542
  if self.use_discrete_image_token:
543
  discrete_token_size = self.discrete_token_size
544
+ num_discrete_tokens = discrete_token_size ** 2
 
 
545
  if include_boundary_tokens:
546
+ num_discrete_tokens += 2
547
 
548
+ if return_tuple:
549
+ return (num_continuous_tokens, num_discrete_tokens)
550
+ else:
551
+ return num_continuous_tokens + num_discrete_tokens
552
 
553
  def save_pretrained(
554
  self,
555
  save_directory: Union[str, os.PathLike],
556
  *args,
557
  **kwargs,
558
+ ) -> None:
559
+ """Save the processor to a directory.
560
+
561
+ Registers for auto class before saving.
562
+
563
+ Args:
564
+ save_directory: Directory path to save the processor.
565
+ """
566
  self.register_for_auto_class()
567
  super().save_pretrained(save_directory, *args, **kwargs)
modeling_hyperclovax_omni.py CHANGED
@@ -154,10 +154,6 @@ class HyperCLOVAXOmniModel(HyperCLOVAXOmniPreTrainedModel):
154
  else:
155
  self.config.possible_resolutions = config.possible_resolutions
156
 
157
- if without_llm:
158
- # if vision_config.vision_module_type not in ["officialllava", "cream2"]:
159
- # service에서, "vision_model_name_or_path" 의 경로가 vuclip_name2save_path 에 있는 default경로가 아니라, custom한 경로를 따라가야함.
160
- vision_config.vison_pretrained_name_or_path = config.vision_model_name_or_path
161
  with no_init_weights():
162
  if self.is_qwen_visual and is_ampere_or_newer():
163
  vision_config._attn_implementation = "flash_attention_2"
@@ -302,7 +298,7 @@ class HyperCLOVAXOmniModel(HyperCLOVAXOmniPreTrainedModel):
302
  hidden_features=input_hidden_size, # TODO: llava 처럼 hidden_size 를 input_hidden_size 가 아니라 LLM embedding size 로 바꿔주기
303
  out_features=text_config.hidden_size,
304
  )
305
- self.use_nth_layer = config.use_nth_layer
306
  self.model_parallel = False
307
  self.device_map = None
308
  self.vision_model_use_no_grad = None
@@ -346,7 +342,7 @@ class HyperCLOVAXOmniModel(HyperCLOVAXOmniPreTrainedModel):
346
  ) -> Union[Tuple, CausalLMOutputWithPast]:
347
  """
348
  :param input_ids: torch.int64 : torch.size([batchsize, variable)]) : SystemPrompt with Question text token indices for tokenizer.
349
- In positions where images are inputted, the value is replaced by config.img_start_id, which is a vocabulary index used to indicate the start of image data.
350
  :param pixel_values: List of List of 4D tensor (torch.float32)
351
  Each outer list corresponds to a batch and contains inner lists, each holding tensors for images in a sample. The structure accounts for samples with multiple images.
352
  :param past_key_values: None
@@ -511,7 +507,7 @@ class HyperCLOVAXOmniModel(HyperCLOVAXOmniPreTrainedModel):
511
  ):
512
  """
513
  :param input_ids: torch.int64 : torch.size([batchsize, variable)]) : SystemPrompt with Question text token indices for tokenizer.
514
- In positions where images are inputted, the value is replaced by config.img_start_id, which is a vocabulary index used to indicate the start of image data.
515
  In cases where a sample contains no images, a single dummy image is included.
516
  :param pixel_values: List of List of 4D tensor (torch.float32)
517
  Each outer list corresponds to a batch and contains inner lists, each holding tensors for images in a sample. The structure accounts for samples with multiple images.
@@ -537,7 +533,7 @@ class HyperCLOVAXOmniModel(HyperCLOVAXOmniPreTrainedModel):
537
  else:
538
  if self.is_qwen_visual:
539
  inputs_embeds = self.get_input_embeddings()(input_ids)
540
- context_vision_model = torch.no_grad() if self.config.freeze_encoder else contextlib.nullcontext()
541
 
542
  if pixel_values is not None:
543
  with context_vision_model:
@@ -545,11 +541,11 @@ class HyperCLOVAXOmniModel(HyperCLOVAXOmniPreTrainedModel):
545
  image_features = self.mm_projector(image_features)
546
 
547
  if img_start_ids_list is None:
548
- image_cnts = (input_ids == self.config.img_start_id).sum(dim=1).tolist()
549
  else:
550
  image_cnts = [len(img_start_ids) for img_start_ids in img_start_ids_list]
551
 
552
- mask = input_ids.eq(self.config.img_start_id)
553
  positions = mask.nonzero(as_tuple=False)
554
 
555
  batch_idx = positions[:, 0]
@@ -564,8 +560,8 @@ class HyperCLOVAXOmniModel(HyperCLOVAXOmniPreTrainedModel):
564
  video_features = self.vision_model(pixel_values_videos, grid_thw=video_grid_thw)
565
  video_features = self.mm_projector(video_features)
566
 
567
- video_cnts = (input_ids == self.config.video_start_id).sum(dim=1).tolist()
568
- mask = input_ids.eq(self.config.video_start_id)
569
  positions = mask.nonzero(as_tuple=False)
570
 
571
  batch_idx = positions[:, 0]
@@ -674,8 +670,8 @@ class HyperCLOVAXOmniModel(HyperCLOVAXOmniPreTrainedModel):
674
  if current_chunk_size == 0:
675
  chunk = dummy
676
 
677
- # vision 모델에 chunk를 통과시킴 (use_nth_layer에 따라 처리)
678
- if self.use_nth_layer == -1:
679
  # 마지막 레이어의 후처리인 post_layernorm을 Identity로 대체
680
  self.vision_model.vision_model.post_layernorm = nn.Identity()
681
  with context_vision_model:
@@ -684,7 +680,7 @@ class HyperCLOVAXOmniModel(HyperCLOVAXOmniPreTrainedModel):
684
  else:
685
  with context_vision_model:
686
  outs = self.vision_model(chunk, output_hidden_states=True)
687
- outs = outs.hidden_states[self.use_nth_layer][:, visual_token_idx:]
688
  if self.vision_model_use_no_grad:
689
  outs = outs.detach().requires_grad_(True)
690
  if not is_adaptive_anyres:
@@ -728,7 +724,7 @@ class HyperCLOVAXOmniModel(HyperCLOVAXOmniPreTrainedModel):
728
  image_forward_outs = torch.cat(image_forward_outs, dim=0).to(image_forward_outs[0].dtype)
729
 
730
  if img_start_ids_list is None:
731
- image_cnts = (input_ids == self.config.img_start_id).sum(dim=1).tolist()
732
  else:
733
  image_cnts = [len(img_start_ids) for img_start_ids in img_start_ids_list]
734
 
@@ -781,13 +777,13 @@ class HyperCLOVAXOmniModel(HyperCLOVAXOmniPreTrainedModel):
781
  image_feature_dtype = image_features[0][0].dtype
782
 
783
  if img_start_ids_list is None:
784
- image_cnts = (input_ids == self.config.img_start_id).sum(dim=1).tolist()
785
  else:
786
  image_cnts = [len(img_start_ids) for img_start_ids in img_start_ids_list]
787
 
788
  if non_vision_query_lengths is None:
789
  non_vision_query_lengths = self.determine_non_vision_query_lengths(
790
- input_ids, self.config.text_config.pad_token_id, self.config.img_start_id
791
  )
792
 
793
  if vision_query_lengths is None:
@@ -832,7 +828,7 @@ class HyperCLOVAXOmniModel(HyperCLOVAXOmniPreTrainedModel):
832
  ] # batch_idx sample 의 첫번째 이미지 (dummy 이미지)
833
  else:
834
  if img_start_ids_list is None:
835
- img_start_ids = (sample == self.config.img_start_id).nonzero()
836
  else:
837
  img_start_ids = img_start_ids_list[batch_idx]
838
  assert len(img_start_ids) == image_cnts[batch_idx] == len(image_features[batch_idx])
@@ -1171,7 +1167,7 @@ class HyperCLOVAXOmniForCausalLM(HyperCLOVAXOmniPreTrainedModel, GenerationMixin
1171
  ) -> Union[Tuple, CausalLMOutputWithPast]:
1172
  """
1173
  :param input_ids: torch.int64 : torch.size([batchsize, variable)]) : SystemPrompt with Question text token indices for tokenizer.
1174
- In positions where images are inputted, the value is replaced by config.img_start_id, which is a vocabulary index used to indicate the start of image data.
1175
  :param pixel_values: List of List of 4D tensor (torch.float32)
1176
  Each outer list corresponds to a batch and contains inner lists, each holding tensors for images in a sample. The structure accounts for samples with multiple images.
1177
  :param past_key_values: None
@@ -1272,7 +1268,7 @@ class HyperCLOVAXOmniForCausalLM(HyperCLOVAXOmniPreTrainedModel, GenerationMixin
1272
  ):
1273
  """
1274
  :param input_ids: torch.int64 : torch.size([batchsize, variable)]) : SystemPrompt with Question text token indices for tokenizer.
1275
- In positions where images are inputted, the value is replaced by config.img_start_id, which is a vocabulary index used to indicate the start of image data.
1276
  In cases where a sample contains no images, a single dummy image is included.
1277
  :param pixel_values: List of List of 4D tensor (torch.float32)
1278
  Each outer list corresponds to a batch and contains inner lists, each holding tensors for images in a sample. The structure accounts for samples with multiple images.
 
154
  else:
155
  self.config.possible_resolutions = config.possible_resolutions
156
 
 
 
 
 
157
  with no_init_weights():
158
  if self.is_qwen_visual and is_ampere_or_newer():
159
  vision_config._attn_implementation = "flash_attention_2"
 
298
  hidden_features=input_hidden_size, # TODO: llava 처럼 hidden_size 를 input_hidden_size 가 아니라 LLM embedding size 로 바꿔주기
299
  out_features=text_config.hidden_size,
300
  )
301
+ self.vision_feature_layer = config.vision_feature_layer
302
  self.model_parallel = False
303
  self.device_map = None
304
  self.vision_model_use_no_grad = None
 
342
  ) -> Union[Tuple, CausalLMOutputWithPast]:
343
  """
344
  :param input_ids: torch.int64 : torch.size([batchsize, variable)]) : SystemPrompt with Question text token indices for tokenizer.
345
+ In positions where images are inputted, the value is replaced by config.image_token_id, which is a vocabulary index used to indicate the start of image data.
346
  :param pixel_values: List of List of 4D tensor (torch.float32)
347
  Each outer list corresponds to a batch and contains inner lists, each holding tensors for images in a sample. The structure accounts for samples with multiple images.
348
  :param past_key_values: None
 
507
  ):
508
  """
509
  :param input_ids: torch.int64 : torch.size([batchsize, variable)]) : SystemPrompt with Question text token indices for tokenizer.
510
+ In positions where images are inputted, the value is replaced by config.image_token_id, which is a vocabulary index used to indicate the start of image data.
511
  In cases where a sample contains no images, a single dummy image is included.
512
  :param pixel_values: List of List of 4D tensor (torch.float32)
513
  Each outer list corresponds to a batch and contains inner lists, each holding tensors for images in a sample. The structure accounts for samples with multiple images.
 
533
  else:
534
  if self.is_qwen_visual:
535
  inputs_embeds = self.get_input_embeddings()(input_ids)
536
+ context_vision_model = contextlib.nullcontext()
537
 
538
  if pixel_values is not None:
539
  with context_vision_model:
 
541
  image_features = self.mm_projector(image_features)
542
 
543
  if img_start_ids_list is None:
544
+ image_cnts = (input_ids == self.config.image_token_id).sum(dim=1).tolist()
545
  else:
546
  image_cnts = [len(img_start_ids) for img_start_ids in img_start_ids_list]
547
 
548
+ mask = input_ids.eq(self.config.image_token_id)
549
  positions = mask.nonzero(as_tuple=False)
550
 
551
  batch_idx = positions[:, 0]
 
560
  video_features = self.vision_model(pixel_values_videos, grid_thw=video_grid_thw)
561
  video_features = self.mm_projector(video_features)
562
 
563
+ video_cnts = (input_ids == self.config.video_token_id).sum(dim=1).tolist()
564
+ mask = input_ids.eq(self.config.video_token_id)
565
  positions = mask.nonzero(as_tuple=False)
566
 
567
  batch_idx = positions[:, 0]
 
670
  if current_chunk_size == 0:
671
  chunk = dummy
672
 
673
+ # vision 모델에 chunk를 통과시킴 (vision_feature_layer에 따라 처리)
674
+ if self.vision_feature_layer == -1:
675
  # 마지막 레이어의 후처리인 post_layernorm을 Identity로 대체
676
  self.vision_model.vision_model.post_layernorm = nn.Identity()
677
  with context_vision_model:
 
680
  else:
681
  with context_vision_model:
682
  outs = self.vision_model(chunk, output_hidden_states=True)
683
+ outs = outs.hidden_states[self.vision_feature_layer][:, visual_token_idx:]
684
  if self.vision_model_use_no_grad:
685
  outs = outs.detach().requires_grad_(True)
686
  if not is_adaptive_anyres:
 
724
  image_forward_outs = torch.cat(image_forward_outs, dim=0).to(image_forward_outs[0].dtype)
725
 
726
  if img_start_ids_list is None:
727
+ image_cnts = (input_ids == self.config.image_token_id).sum(dim=1).tolist()
728
  else:
729
  image_cnts = [len(img_start_ids) for img_start_ids in img_start_ids_list]
730
 
 
777
  image_feature_dtype = image_features[0][0].dtype
778
 
779
  if img_start_ids_list is None:
780
+ image_cnts = (input_ids == self.config.image_token_id).sum(dim=1).tolist()
781
  else:
782
  image_cnts = [len(img_start_ids) for img_start_ids in img_start_ids_list]
783
 
784
  if non_vision_query_lengths is None:
785
  non_vision_query_lengths = self.determine_non_vision_query_lengths(
786
+ input_ids, self.config.text_config.pad_token_id, self.config.image_token_id
787
  )
788
 
789
  if vision_query_lengths is None:
 
828
  ] # batch_idx sample 의 첫번째 이미지 (dummy 이미지)
829
  else:
830
  if img_start_ids_list is None:
831
+ img_start_ids = (sample == self.config.image_token_id).nonzero()
832
  else:
833
  img_start_ids = img_start_ids_list[batch_idx]
834
  assert len(img_start_ids) == image_cnts[batch_idx] == len(image_features[batch_idx])
 
1167
  ) -> Union[Tuple, CausalLMOutputWithPast]:
1168
  """
1169
  :param input_ids: torch.int64 : torch.size([batchsize, variable)]) : SystemPrompt with Question text token indices for tokenizer.
1170
+ In positions where images are inputted, the value is replaced by config.image_token_id, which is a vocabulary index used to indicate the start of image data.
1171
  :param pixel_values: List of List of 4D tensor (torch.float32)
1172
  Each outer list corresponds to a batch and contains inner lists, each holding tensors for images in a sample. The structure accounts for samples with multiple images.
1173
  :param past_key_values: None
 
1268
  ):
1269
  """
1270
  :param input_ids: torch.int64 : torch.size([batchsize, variable)]) : SystemPrompt with Question text token indices for tokenizer.
1271
+ In positions where images are inputted, the value is replaced by config.image_token_id, which is a vocabulary index used to indicate the start of image data.
1272
  In cases where a sample contains no images, a single dummy image is included.
1273
  :param pixel_values: List of List of 4D tensor (torch.float32)
1274
  Each outer list corresponds to a batch and contains inner lists, each holding tensors for images in a sample. The structure accounts for samples with multiple images.
preprocessor_config.json CHANGED
@@ -78,7 +78,7 @@
78
  "video_do_resize": true,
79
  "video_end_token": "<|video_end|>",
80
  "video_max_frames": 120,
81
- "video_max_pixels": 602112,
82
  "video_mean": [
83
  0.48145466,
84
  0.4578275,
 
78
  "video_do_resize": true,
79
  "video_end_token": "<|video_end|>",
80
  "video_max_frames": 120,
81
+ "video_max_pixels": 12845056,
82
  "video_mean": [
83
  0.48145466,
84
  0.4578275,
processing_hyperclovax_omni.py CHANGED
@@ -833,24 +833,7 @@ class HyperCLOVAXOmniProcessor(ProcessorMixin):
833
  and self.image_processor.use_discrete_image_token
834
  ):
835
  data.update(discrete_image_inputs)
836
-
837
- # _tensorable_data, _untensorable_data = dict(), dict()
838
- # for _k, _v in data.items():
839
- # if _v is None:
840
- # continue
841
- # if isinstance(_v, list) and any(x is None for x in _v):
842
- # continue
843
- # if _k in [
844
- # "discrete_image_ratios",
845
- # "num_audio_tokens",
846
- # "num_discrete_audio_tokens",
847
- # ]:
848
- # _untensorable_data[_k] = _v
849
- # else:
850
- # _tensorable_data[_k] = _v
851
-
852
- # model_inputs = BatchFeature(data=_tensorable_data, tensor_type=return_tensors)
853
- # model_inputs.update(_untensorable_data)
854
  model_inputs = BatchFeature(data=data, tensor_type=return_tensors)
855
  return model_inputs
856
 
@@ -860,143 +843,159 @@ class HyperCLOVAXOmniProcessor(ProcessorMixin):
860
  ):
861
  audio_placeholder = ""
862
  if self.audio_processor.use_discrete_audio_token:
863
- audio_placeholder += f'{self.audio_processor.discrete_audio_start_token}{self.audio_processor.discrete_audio_token}{self.audio_processor.discrete_audio_end_token}'
864
  audio_placeholder += f'{self.audio_processor.audio_start_token}{self.audio_processor.audio_token}{self.audio_processor.audio_end_token}'
865
  if tokenize:
866
  audio_placeholder = self.tokenizer.encode(audio_placeholder)
867
  return audio_placeholder
868
 
869
- def get_image_placeholder(
870
- self,
871
- tokenize: bool = False,
872
- ):
873
- image_placeholder = ""
874
- if self.image_processor.use_discrete_audio_token:
875
- image_placeholder += f'{self.image_processor.discrete_image_start_token}{self.image_processor.discrete_image_token}{self.image_processor.discrete_image_end_token}'
876
- image_placeholder += f'{self.image_processor.image_start_token}{self.image_processor.image_token}{self.image_processor.image_end_token}'
877
- if tokenize:
878
- image_placeholder = self.tokenizer.encode(image_placeholder)
879
- return image_placeholder
880
-
881
- def get_video_placeholder(
882
- self,
883
- tokenize: bool = False,
884
- ):
885
- video_placeholder = f'{self.video_processor.video_start_token}{self.video_processor.video_token}{self.video_processor.video_end_token}'
886
- if tokenize:
887
- video_placeholder = self.tokenizer.encode(video_placeholder)
888
- return video_placeholder
889
-
890
  def get_audio_token_replacement(
891
  self,
892
  num_audio_tokens: int,
 
893
  include_boundary_tokens: Optional[bool] = False,
894
  tokenize: Optional[bool] = False,
 
895
  ):
 
 
896
  if (
897
  isinstance(num_audio_tokens, (list, tuple))
898
  or (isinstance(num_audio_tokens, torch.Tensor) and num_audio_tokens.dim() >= 1)
899
  ):
900
  num_audio_tokens = num_audio_tokens[0]
901
-
902
- replacement = self.audio_processor.audio_token * num_audio_tokens
903
  if include_boundary_tokens:
904
- replacement = f"{self.audio_processor.audio_start_token}{replacement}{self.audio_processor.audio_end_token}"
905
- if tokenize:
906
- replacement = self.tokenizer.encode(replacement)
907
- return replacement
908
-
909
- def get_discrete_audio_token_replacement(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
910
  self,
911
- num_discrete_audio_tokens: int,
912
- include_boundary_tokens: Optional[bool] = False,
913
- tokenize: Optional[bool] = False,
914
  ):
915
- if (
916
- isinstance(num_discrete_audio_tokens, (list, tuple))
917
- or (isinstance(num_discrete_audio_tokens, torch.Tensor) and num_discrete_audio_tokens.dim() >= 1)
918
- ):
919
- num_discrete_audio_tokens = num_discrete_audio_tokens[0]
920
-
921
- replacement = self.audio_processor.discrete_audio_token * num_discrete_audio_tokens
922
- if include_boundary_tokens:
923
- replacement = f"{self.audio_processor.discrete_audio_start_token}{replacement}{self.audio_processor.discrete_audio_end_token}"
924
  if tokenize:
925
- replacement = self.tokenizer.encode(replacement)
926
- return replacement
927
 
928
  def get_image_token_replacement(
929
  self,
930
  num_image_tokens: int,
 
931
  include_boundary_tokens: Optional[bool] = False,
932
  tokenize: Optional[bool] = False,
 
933
  ):
 
 
934
  if (
935
  isinstance(num_image_tokens, (list, tuple))
936
  or (isinstance(num_image_tokens, torch.Tensor) and num_image_tokens.dim() >= 1)
937
  ):
938
  num_image_tokens = num_image_tokens[0]
939
-
940
  discrete_token_size = self.image_processor.discrete_token_size
941
- replacement = self.image_processor.image_token * num_image_tokens
942
  if include_boundary_tokens:
943
- replacement = f"{self.image_processor.image_start_token}{replacement}{self.image_processor.image_end_token}"
944
- if tokenize:
945
- replacement = self.tokenizer.encode(replacement)
946
- return replacement
947
-
948
- def get_discrete_image_token_replacement(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
949
  self,
950
- discrete_image_ratio: Optional[List[int]] = None,
951
- include_boundary_tokens: Optional[bool] = False,
952
- tokenize: Optional[bool] = False,
953
  ):
954
- if (
955
- discrete_image_ratio
956
- and len(discrete_image_ratio) == 1
957
- and (
958
- isinstance(discrete_image_ratio, (list, tuple))
959
- or (isinstance(discrete_image_ratio, torch.Tensor) and discrete_image_ratio.dim() >= 2)
960
- )
961
- ): # [[16, 9]], or torch.Tensor([[16, 9]])
962
- discrete_image_ratio = discrete_image_ratio[0]
963
-
964
- row_str = self.image_processor.discrete_image_token * self.image_processor.discrete_token_size
965
- # row_str += self.image_processor.vision_eol_token
966
- replacement = row_str * self.image_processor.discrete_token_size
967
- if discrete_image_ratio:
968
- if isinstance(discrete_image_ratio, (list, tuple)):
969
- ratio_key = f"{int(discrete_image_ratio[0])}:{int(discrete_image_ratio[1])}"
970
- elif isinstance(discrete_image_ratio, torch.Tensor):
971
- ratio_key = f"{discrete_image_ratio[0].item()}:{discrete_image_ratio[1].item()}"
972
- discrete_image_ratio_token = self.image_processor.discrete_image_ratio_tokens[ratio_key]
973
- replacement = f"{discrete_image_ratio_token}{replacement}"
974
- # replacement = f"{replacement}{self.image_processor.vision_eof_token}"
975
- if include_boundary_tokens:
976
- replacement = f"{self.image_processor.discrete_image_start_token}{replacement}{self.image_processor.discrete_image_end_token}"
977
  if tokenize:
978
- replacement = self.tokenizer.encode(replacement)
979
- return replacement
980
 
981
  def get_video_token_replacement(
982
  self,
983
  num_video_tokens: int,
984
  include_boundary_tokens: Optional[bool] = False,
985
  tokenize: Optional[bool] = False,
 
986
  ):
 
 
987
  if (
988
  isinstance(num_video_tokens, (list, tuple))
989
  or (isinstance(num_video_tokens, torch.Tensor) and num_video_tokens.dim() >= 1)
990
  ):
991
  num_video_tokens = num_video_tokens[0]
992
-
993
  merge_length = self.video_processor.video_merge_size**2
994
- replacement = self.video_processor.video_token * int(num_video_tokens)
995
  if include_boundary_tokens:
996
- replacement = f"{self.video_processor.video_start_token}{replacement}{self.video_processor.video_end_token}"
997
- if tokenize:
998
- replacement = self.tokenizer.encode(replacement)
999
- return replacement
 
 
 
 
 
 
 
 
1000
 
1001
  def _interleave_video_audio_tokens(
1002
  self,
 
833
  and self.image_processor.use_discrete_image_token
834
  ):
835
  data.update(discrete_image_inputs)
836
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
837
  model_inputs = BatchFeature(data=data, tensor_type=return_tensors)
838
  return model_inputs
839
 
 
843
  ):
844
  audio_placeholder = ""
845
  if self.audio_processor.use_discrete_audio_token:
846
+ audio_placeholder += f'{self.audio_processor.discrete_audio_start_token}{self.audio_processor.discrete_audio_token}{self.audio_processor.discrete_audio_end_token}\n'
847
  audio_placeholder += f'{self.audio_processor.audio_start_token}{self.audio_processor.audio_token}{self.audio_processor.audio_end_token}'
848
  if tokenize:
849
  audio_placeholder = self.tokenizer.encode(audio_placeholder)
850
  return audio_placeholder
851
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
852
  def get_audio_token_replacement(
853
  self,
854
  num_audio_tokens: int,
855
+ num_discrete_audio_tokens: Optional[int] = None,
856
  include_boundary_tokens: Optional[bool] = False,
857
  tokenize: Optional[bool] = False,
858
+ return_tuple: Optional[bool] = None,
859
  ):
860
+ conitnuous_replacement, discrete_replacement = "", ""
861
+
862
  if (
863
  isinstance(num_audio_tokens, (list, tuple))
864
  or (isinstance(num_audio_tokens, torch.Tensor) and num_audio_tokens.dim() >= 1)
865
  ):
866
  num_audio_tokens = num_audio_tokens[0]
867
+ conitnuous_replacement = self.audio_processor.audio_token * num_audio_tokens
 
868
  if include_boundary_tokens:
869
+ conitnuous_replacement = f"{self.audio_processor.audio_start_token}{conitnuous_replacement}{self.audio_processor.audio_end_token}"
870
+
871
+ if self.audio_processor.use_discrete_audio_token:
872
+ if (
873
+ isinstance(num_discrete_audio_tokens, (list, tuple))
874
+ or (isinstance(num_discrete_audio_tokens, torch.Tensor) and num_discrete_audio_tokens.dim() >= 1)
875
+ ):
876
+ num_discrete_audio_tokens = num_discrete_audio_tokens[0]
877
+ discrete_replacement = self.audio_processor.discrete_audio_token * num_discrete_audio_tokens
878
+ if include_boundary_tokens:
879
+ discrete_replacement = f"{self.audio_processor.discrete_audio_start_token}{discrete_replacement}{self.audio_processor.discrete_audio_end_token}"
880
+ discrete_replacement = f'{discrete_replacement}\n'
881
+
882
+ if return_tuple:
883
+ if tokenize:
884
+ conitnuous_replacement = self.tokenizer.encode(conitnuous_replacement)
885
+ discrete_replacement = self.tokenizer.encode(discrete_replacement)
886
+ return (conitnuous_replacement, discrete_replacement)
887
+ else:
888
+ replacement = f'{discrete_replacement}{conitnuous_replacement}'
889
+ if tokenize:
890
+ replacement = self.tokenizer.encode(replacement)
891
+ return replacement
892
+
893
+ def get_image_placeholder(
894
  self,
895
+ tokenize: bool = False,
 
 
896
  ):
897
+ image_placeholder = ""
898
+ if self.image_processor.use_discrete_audio_token:
899
+ image_placeholder += f'{self.image_processor.discrete_image_start_token}{self.image_processor.discrete_image_token}{self.image_processor.discrete_image_end_token}\n'
900
+ image_placeholder += f'{self.image_processor.image_start_token}{self.image_processor.image_token}{self.image_processor.image_end_token}'
 
 
 
 
 
901
  if tokenize:
902
+ image_placeholder = self.tokenizer.encode(image_placeholder)
903
+ return image_placeholder
904
 
905
  def get_image_token_replacement(
906
  self,
907
  num_image_tokens: int,
908
+ discrete_image_ratio: Optional[List[int]] = None,
909
  include_boundary_tokens: Optional[bool] = False,
910
  tokenize: Optional[bool] = False,
911
+ return_tuple: Optional[bool] = None,
912
  ):
913
+ conitnuous_replacement, discrete_replacement = "", ""
914
+
915
  if (
916
  isinstance(num_image_tokens, (list, tuple))
917
  or (isinstance(num_image_tokens, torch.Tensor) and num_image_tokens.dim() >= 1)
918
  ):
919
  num_image_tokens = num_image_tokens[0]
 
920
  discrete_token_size = self.image_processor.discrete_token_size
921
+ continuous_replacement = self.image_processor.image_token * num_image_tokens
922
  if include_boundary_tokens:
923
+ continuous_replacement = f"{self.image_processor.image_start_token}{continuous_replacement}{self.image_processor.image_end_token}"
924
+
925
+ if self.image_processor.use_discrete_image_token:
926
+ if (
927
+ discrete_image_ratio
928
+ and len(discrete_image_ratio) == 1
929
+ and (
930
+ isinstance(discrete_image_ratio, (list, tuple))
931
+ or (isinstance(discrete_image_ratio, torch.Tensor) and discrete_image_ratio.dim() >= 2)
932
+ )
933
+ ): # [[16, 9]], or torch.Tensor([[16, 9]])
934
+ discrete_image_ratio = discrete_image_ratio[0]
935
+ row_str = self.image_processor.discrete_image_token * self.image_processor.discrete_token_size
936
+ # row_str += self.image_processor.vision_eol_token
937
+ discrete_replacement = row_str * self.image_processor.discrete_token_size
938
+ if discrete_image_ratio:
939
+ if isinstance(discrete_image_ratio, (list, tuple)):
940
+ ratio_key = f"{int(discrete_image_ratio[0])}:{int(discrete_image_ratio[1])}"
941
+ elif isinstance(discrete_image_ratio, torch.Tensor):
942
+ ratio_key = f"{discrete_image_ratio[0].item()}:{discrete_image_ratio[1].item()}"
943
+ discrete_image_ratio_token = self.image_processor.discrete_image_ratio_tokens[ratio_key]
944
+ discrete_replacement = f"{discrete_image_ratio_token}{discrete_replacement}"
945
+ # discrete_replacement = f"{discrete_replacement}{self.image_processor.vision_eof_token}"
946
+ if include_boundary_tokens:
947
+ discrete_replacement = f"{self.image_processor.discrete_image_start_token}{discrete_replacement}{self.image_processor.discrete_image_end_token}"
948
+ discrete_replacement = f'{discrete_replacement}\n'
949
+
950
+ if return_tuple:
951
+ if tokenize:
952
+ conitnuous_replacement = self.tokenizer.encode(conitnuous_replacement)
953
+ discrete_replacement = self.tokenizer.encode(discrete_replacement)
954
+ return (conitnuous_replacement, discrete_replacement)
955
+ else:
956
+ replacement = f'{discrete_replacement}{conitnuous_replacement}'
957
+ if tokenize:
958
+ replacement = self.tokenizer.encode(replacement)
959
+ return replacement
960
+
961
+ def get_video_placeholder(
962
  self,
963
+ tokenize: bool = False,
 
 
964
  ):
965
+ video_placeholder = f'{self.video_processor.video_start_token}{self.video_processor.video_token}{self.video_processor.video_end_token}'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
966
  if tokenize:
967
+ video_placeholder = self.tokenizer.encode(video_placeholder)
968
+ return video_placeholder
969
 
970
  def get_video_token_replacement(
971
  self,
972
  num_video_tokens: int,
973
  include_boundary_tokens: Optional[bool] = False,
974
  tokenize: Optional[bool] = False,
975
+ return_tuple: Optional[bool] = None,
976
  ):
977
+ conitnuous_replacement, discrete_replacement = "", ""
978
+
979
  if (
980
  isinstance(num_video_tokens, (list, tuple))
981
  or (isinstance(num_video_tokens, torch.Tensor) and num_video_tokens.dim() >= 1)
982
  ):
983
  num_video_tokens = num_video_tokens[0]
 
984
  merge_length = self.video_processor.video_merge_size**2
985
+ conitnuous_replacement = self.video_processor.video_token * int(num_video_tokens)
986
  if include_boundary_tokens:
987
+ conitnuous_replacement = f"{self.video_processor.video_start_token}{conitnuous_replacement}{self.video_processor.video_end_token}"
988
+
989
+ if return_tuple:
990
+ if tokenize:
991
+ conitnuous_replacement = self.tokenizer.encode(conitnuous_replacement)
992
+ discrete_replacement = self.tokenizer.encode(discrete_replacement)
993
+ return (conitnuous_replacement, discrete_replacement)
994
+ else:
995
+ replacement = f'{discrete_replacement}{conitnuous_replacement}'
996
+ if tokenize:
997
+ replacement = self.tokenizer.encode(replacement)
998
+ return replacement
999
 
1000
  def _interleave_video_audio_tokens(
1001
  self,
tokenizer.json CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:666f303c324b9b2e2e8f13950cd44a18896a6fc1a70aae70583a77663d0ebe31
3
- size 23621510
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:25be15af870991ef21ee479f5ca5f72ab4160e51e6e6a6131b65505ec32b63c4
3
+ size 23621753
tokenizer_config.json CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:8e6c389295385be8eaa613b30db4a988065eac05eb1351b427dd385a6bc4cea5
3
- size 13220218
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7fa862c7a52c316ae1c3e81d74f36688d970eb56a367957473bf185eff64a259
3
+ size 13220251
video_processing_hyperclovax_omni.py CHANGED
@@ -1,46 +1,61 @@
1
  """
2
- HyperCLOVAXOmni Video Processor
3
 
4
- Qwen2VL 스타일의 동적 해상도 비디오 처리를 구현합니다:
5
- - Smart resize: 비디오 프레임을 min_pixels와 max_pixels 범위 내로 조정
6
- - Temporal patch: temporal_patch_size 단위로 프레임 그룹핑
7
- - Patch flattening: merge_size를 사용한 토큰 축소
8
 
9
- BaseVideoProcessor 기반으로 torchvision resize를 사용하여
10
- Track A (Qwen2VLVideoProcessor)와 bit-perfect 일치를 달성합니다.
11
-
12
- 입력 준비(numpy→torch), kwargs 해석, resample→interpolation 변환 등은
13
- BaseVideoProcessor.preprocess()와 동일한 흐름을 따릅니다.
14
- _preprocess_continuous_video는 Qwen2VLVideoProcessor._preprocess와
15
- 동일한 시그니처·로직을 사용합니다.
16
  """
17
 
18
  import math
 
 
19
  import numpy as np
20
  import torch
21
- from typing import Dict, List, Optional, Union
22
-
23
  from transformers.image_processing_utils import BatchFeature
 
24
  from transformers.image_transforms import to_channel_dimension_format
25
  from transformers.image_utils import (
26
  OPENAI_CLIP_MEAN,
27
  OPENAI_CLIP_STD,
28
- PILImageResampling,
29
  ChannelDimension,
30
- get_image_size,
31
  SizeDict,
 
32
  )
 
33
  from transformers.utils import TensorType, logging
34
  from transformers.video_processing_utils import BaseVideoProcessor
35
  from transformers.video_utils import group_videos_by_shape, reorder_videos
36
- from transformers.processing_utils import VideosKwargs
37
 
38
  logger = logging.get_logger(__name__)
39
 
40
 
41
  def smart_resize(
42
- height: int, width: int, factor: int = 28, min_pixels: int = 56 * 56, max_pixels: int = 14 * 14 * 4 * 1280
43
- ):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  if max(height, width) / min(height, width) > 200:
45
  raise ValueError(
46
  f"absolute aspect ratio must be smaller than 200, got {max(height, width) / min(height, width)}"
@@ -82,11 +97,10 @@ class HyperCLOVAXOmniVideosKwargs(VideosKwargs, total=False):
82
 
83
 
84
  class HyperCLOVAXOmniVideoProcessor(BaseVideoProcessor):
85
- """
86
- Video processor for HyperCLOVAXOmni that follows Qwen2VL's video processing logic.
87
 
88
- BaseVideoProcessor 기반으로 torchvision resize rescale_and_normalize 사용하여
89
- Qwen2VLVideoProcessor와 bit-perfect 일치를 달성합니다.
90
  """
91
 
92
  model_input_names = ["pixel_values_videos", "video_grid_thw"]
@@ -117,7 +131,7 @@ class HyperCLOVAXOmniVideoProcessor(BaseVideoProcessor):
117
  vision_eof_token: str = "<|vision_eof|>",
118
  **kwargs,
119
  ):
120
- # Qwen2VLVideoProcessor와 동일하게 size dict 구성하여 super().__init__에 전달
121
  size = {"shortest_edge": video_min_pixels, "longest_edge": video_max_pixels}
122
 
123
  super().__init__(
@@ -149,10 +163,10 @@ class HyperCLOVAXOmniVideoProcessor(BaseVideoProcessor):
149
 
150
  def _preprocess_continuous_video(
151
  self,
152
- videos: List["torch.Tensor"],
153
  do_resize: bool,
154
  size: SizeDict,
155
- interpolation: "torch.nn.functional.InterpolationMode",
156
  do_rescale: bool,
157
  rescale_factor: float,
158
  do_normalize: bool,
@@ -161,33 +175,31 @@ class HyperCLOVAXOmniVideoProcessor(BaseVideoProcessor):
161
  patch_size: int,
162
  temporal_patch_size: int,
163
  merge_size: int,
164
- ) -> Dict:
165
- """단일 비디오에 대한 continuous vision 전처리를 수행합니다.
166
 
167
- Qwen2VLVideoProcessor._preprocess와 동일한 시그니처·로직:
168
- group_videos_by_shape → self.resize (torchvision) → self.rescale_and_normalize → patchify
169
 
170
  Args:
171
- videos: channel-first torch 텐서 리스트. 원소는 (num_frames, C, H, W).
172
- do_resize: 리사이즈 수행 여부.
173
- size: SizeDict with shortest_edge / longest_edge (smart_resize min/max pixels).
174
  interpolation: torchvision InterpolationMode.
175
- do_rescale: rescale 수행 여부.
176
- rescale_factor: rescale 배율.
177
- do_normalize: 정규화 수행 여부.
178
- image_mean: 정규화 평균 (tuple).
179
- image_std: 정규화 표준편차 (tuple).
180
- patch_size: ViT patch 크기.
181
- temporal_patch_size: 시간 patch 크기.
182
- merge_size: token merge 크기.
183
 
184
  Returns:
185
- dict with:
186
- - "pixel_values_videos": (grid_t * grid_h * grid_w, feat_dim) 텐서.
187
- - "video_grid_thw": [grid_t, grid_h, grid_w] 리스트.
188
- - "num_video_tokens": continuous 토큰 (int).
189
  """
190
- # --- Qwen2VLVideoProcessor._preprocess와 동일한 흐름 ---
191
  grouped_videos, grouped_videos_index = group_videos_by_shape(videos)
192
 
193
  resized_videos_grouped = {}
@@ -258,11 +270,15 @@ class HyperCLOVAXOmniVideoProcessor(BaseVideoProcessor):
258
  "num_video_tokens": num_video_tokens,
259
  }
260
 
261
- def _preprocess_discrete_video(
262
- self,
263
- video: "torch.Tensor",
264
- ) -> Dict:
265
- """단일 비디오에 대한 discrete vision 전처리 (현재 미구현)."""
 
 
 
 
266
  return {}
267
 
268
  def preprocess(
@@ -271,28 +287,29 @@ class HyperCLOVAXOmniVideoProcessor(BaseVideoProcessor):
271
  return_tensors: Optional[Union[str, TensorType]] = None,
272
  **kwargs,
273
  ) -> BatchFeature:
274
- """비디오 배치에 대한 전처리를 수행합니다.
275
 
276
- BaseVideoProcessor.preprocess()와 동일한 흐름:
277
- 1. numpy channel-first torch 변환 (_prepare_input_videos 패턴)
278
- 2. kwargs 해석 resampleinterpolation, mean/std→tuple 변환 (_further_process_kwargs 패턴)
279
- 3. _preprocess_continuous_video 호출 (Qwen2VL._preprocess 시그니처)
280
 
281
  Args:
282
- videos: 비디오 입력. 다음 형태 중 하나:
283
- - np.ndarray: 단일 비디오 (num_frames, H, W, C).
284
- - List[np.ndarray]: 배치된 비디오들, 원소는 4D.
 
285
 
286
  Returns:
287
  BatchFeature with:
288
- - pixel_values_videos: (total_patches, feat_dim) 텐서.
289
- - video_grid_thw: (num_videos, 3) 텐서.
290
- - num_video_tokens: (num_videos,) 텐서.
291
  """
292
  if isinstance(videos, np.ndarray) and videos.ndim == 4:
293
  videos = [videos]
294
 
295
- # --- 1. kwargs 해석: self 속성에서 기본값 채우기 ---
296
  do_resize = kwargs.pop("do_resize", kwargs.pop("video_do_resize", None))
297
  if do_resize is None:
298
  do_resize = self.do_resize
@@ -337,7 +354,7 @@ class HyperCLOVAXOmniVideoProcessor(BaseVideoProcessor):
337
  if merge_size is None:
338
  merge_size = self.video_merge_size
339
 
340
- # size dict: Qwen2VLVideoProcessor와 동일하게 shortest_edge/longest_edge 사용
341
  min_pixels = kwargs.pop("min_pixels", kwargs.pop("video_min_pixels", None))
342
  if min_pixels is None:
343
  min_pixels = self.size["shortest_edge"]
@@ -348,8 +365,7 @@ class HyperCLOVAXOmniVideoProcessor(BaseVideoProcessor):
348
 
349
  size = SizeDict(shortest_edge=min_pixels, longest_edge=max_pixels)
350
 
351
- # --- 2. _further_process_kwargs 패턴: resampleinterpolation, mean/std→tuple ---
352
- from transformers.image_processing_utils_fast import pil_torch_interpolation_mapping
353
  if isinstance(resample, (PILImageResampling, int)):
354
  interpolation = pil_torch_interpolation_mapping[resample]
355
  else:
@@ -360,18 +376,17 @@ class HyperCLOVAXOmniVideoProcessor(BaseVideoProcessor):
360
  if isinstance(image_std, list):
361
  image_std = tuple(image_std)
362
 
363
- # --- 3. 비디오별 처리 ---
364
  pixel_values_list = []
365
  grid_thw_list = []
366
  num_video_tokens_list = []
367
 
368
  for video in videos:
369
- # _prepare_input_videos 패턴: numpy(NHWC) channel-first torch(NCHW)
370
  if isinstance(video, np.ndarray):
371
  video = to_channel_dimension_format(video, ChannelDimension.FIRST)
372
  video = torch.from_numpy(video).contiguous()
373
 
374
- # convert_to_rgb: BaseVideoProcessor.convert_to_rgb (torchvision 기반)
375
  if do_convert_rgb:
376
  video = self.convert_to_rgb(video)
377
 
@@ -406,15 +421,34 @@ class HyperCLOVAXOmniVideoProcessor(BaseVideoProcessor):
406
  image_width: Optional[int] = None,
407
  image_height: Optional[int] = None,
408
  num_frames: Optional[int] = None,
409
- pixel_values_videos: Optional["torch.Tensor"] = None,
410
  include_boundary_tokens: bool = False,
411
  patch_size: Optional[int] = None,
412
  temporal_patch_size: Optional[int] = None,
413
  merge_size: Optional[int] = None,
414
  min_pixels: Optional[int] = None,
415
  max_pixels: Optional[int] = None,
416
- ) -> tuple:
417
- """비디오 입력에 대한 (continuous, discrete) 토큰 수를 계산합니다."""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
418
  patch_size = patch_size if patch_size is not None else self.video_patch_size
419
  temporal_patch_size = temporal_patch_size if temporal_patch_size is not None else self.video_temporal_patch_size
420
  merge_size = merge_size if merge_size is not None else self.video_merge_size
@@ -440,4 +474,7 @@ class HyperCLOVAXOmniVideoProcessor(BaseVideoProcessor):
440
  if include_boundary_tokens:
441
  num_continuous_tokens += 2
442
 
443
- return (num_continuous_tokens, num_discrete_tokens)
 
 
 
 
1
  """
2
+ HyperCLOVAX Omni Video Processor
3
 
4
+ Implements dynamic resolution video processing:
5
+ - Smart resize: adjusts video frames to fit within min_pixels and max_pixels
6
+ - Temporal patch: frame grouping by temporal_patch_size
7
+ - Patch flattening: token reduction using merge_size
8
 
9
+ Based on BaseVideoProcessor with torchvision resize.
 
 
 
 
 
 
10
  """
11
 
12
  import math
13
+ from typing import Dict, List, Optional, Tuple, Union
14
+
15
  import numpy as np
16
  import torch
17
+ from torchvision.transforms.v2 import functional as F
 
18
  from transformers.image_processing_utils import BatchFeature
19
+ from transformers.image_processing_utils_fast import pil_torch_interpolation_mapping
20
  from transformers.image_transforms import to_channel_dimension_format
21
  from transformers.image_utils import (
22
  OPENAI_CLIP_MEAN,
23
  OPENAI_CLIP_STD,
 
24
  ChannelDimension,
25
+ PILImageResampling,
26
  SizeDict,
27
+ get_image_size,
28
  )
29
+ from transformers.processing_utils import VideosKwargs
30
  from transformers.utils import TensorType, logging
31
  from transformers.video_processing_utils import BaseVideoProcessor
32
  from transformers.video_utils import group_videos_by_shape, reorder_videos
 
33
 
34
  logger = logging.get_logger(__name__)
35
 
36
 
37
  def smart_resize(
38
+ height: int,
39
+ width: int,
40
+ factor: int = 28,
41
+ min_pixels: int = 56 * 56,
42
+ max_pixels: int = 14 * 14 * 4 * 1280,
43
+ ) -> Tuple[int, int]:
44
+ """Smart resize for dynamic resolution.
45
+
46
+ Adjusts dimensions so that both sides are divisible by factor
47
+ and total pixel count is between min_pixels and max_pixels.
48
+
49
+ Args:
50
+ height: Original height.
51
+ width: Original width.
52
+ factor: Rounding unit (default: 28 = patch_size * merge_size).
53
+ min_pixels: Minimum pixel count.
54
+ max_pixels: Maximum pixel count.
55
+
56
+ Returns:
57
+ Tuple of (new_height, new_width).
58
+ """
59
  if max(height, width) / min(height, width) > 200:
60
  raise ValueError(
61
  f"absolute aspect ratio must be smaller than 200, got {max(height, width) / min(height, width)}"
 
97
 
98
 
99
  class HyperCLOVAXOmniVideoProcessor(BaseVideoProcessor):
100
+ """Video processor for HyperCLOVAX Omni.
 
101
 
102
+ Uses torchvision resize and rescale_and_normalize for
103
+ dynamic resolution video processing.
104
  """
105
 
106
  model_input_names = ["pixel_values_videos", "video_grid_thw"]
 
131
  vision_eof_token: str = "<|vision_eof|>",
132
  **kwargs,
133
  ):
134
+ # Construct size dict (shortest_edge/longest_edge)
135
  size = {"shortest_edge": video_min_pixels, "longest_edge": video_max_pixels}
136
 
137
  super().__init__(
 
163
 
164
  def _preprocess_continuous_video(
165
  self,
166
+ videos: List[torch.Tensor],
167
  do_resize: bool,
168
  size: SizeDict,
169
+ interpolation: F.InterpolationMode,
170
  do_rescale: bool,
171
  rescale_factor: float,
172
  do_normalize: bool,
 
175
  patch_size: int,
176
  temporal_patch_size: int,
177
  merge_size: int,
178
+ ) -> dict:
179
+ """Preprocess a single video for continuous vision features.
180
 
181
+ Performs group_videos_by_shape -> resize (torchvision) -> rescale_and_normalize -> patchify.
 
182
 
183
  Args:
184
+ videos: List of channel-first torch tensors, each of shape (num_frames, C, H, W).
185
+ do_resize: Whether to perform resizing.
186
+ size: SizeDict with shortest_edge/longest_edge (smart_resize min/max pixels).
187
  interpolation: torchvision InterpolationMode.
188
+ do_rescale: Whether to perform rescaling.
189
+ rescale_factor: Rescale factor.
190
+ do_normalize: Whether to perform normalization.
191
+ image_mean: Normalization mean (tuple).
192
+ image_std: Normalization standard deviation (tuple).
193
+ patch_size: ViT patch size.
194
+ temporal_patch_size: Temporal patch size.
195
+ merge_size: Token merge size.
196
 
197
  Returns:
198
+ Dictionary with:
199
+ - "pixel_values_videos": Tensor of shape (grid_t * grid_h * grid_w, feat_dim).
200
+ - "video_grid_thw": List of [grid_t, grid_h, grid_w].
201
+ - "num_video_tokens": Number of continuous tokens (int).
202
  """
 
203
  grouped_videos, grouped_videos_index = group_videos_by_shape(videos)
204
 
205
  resized_videos_grouped = {}
 
270
  "num_video_tokens": num_video_tokens,
271
  }
272
 
273
+ def _preprocess_discrete_video(self, video: torch.Tensor) -> dict:
274
+ """Preprocess a single video for discrete vision tokens (not yet implemented).
275
+
276
+ Args:
277
+ video: Video tensor.
278
+
279
+ Returns:
280
+ Empty dictionary.
281
+ """
282
  return {}
283
 
284
  def preprocess(
 
287
  return_tensors: Optional[Union[str, TensorType]] = None,
288
  **kwargs,
289
  ) -> BatchFeature:
290
+ """Preprocess a batch of videos.
291
 
292
+ Follows the same flow as BaseVideoProcessor.preprocess():
293
+ 1. numpy (NHWC) -> channel-first torch (NCHW) conversion
294
+ 2. kwargs resolution and resample -> interpolation, mean/std -> tuple conversion
295
+ 3. _preprocess_continuous_video call per video
296
 
297
  Args:
298
+ videos: Video input. Either:
299
+ - np.ndarray: Single video of shape (num_frames, H, W, C).
300
+ - List[np.ndarray]: Batch of videos, each 4D.
301
+ return_tensors: Desired tensor type for outputs.
302
 
303
  Returns:
304
  BatchFeature with:
305
+ - pixel_values_videos: Tensor of shape (total_patches, feat_dim).
306
+ - video_grid_thw: Tensor of shape (num_videos, 3).
307
+ - num_video_tokens: Tensor of shape (num_videos,).
308
  """
309
  if isinstance(videos, np.ndarray) and videos.ndim == 4:
310
  videos = [videos]
311
 
312
+ # 1. Resolve kwargs from self attributes
313
  do_resize = kwargs.pop("do_resize", kwargs.pop("video_do_resize", None))
314
  if do_resize is None:
315
  do_resize = self.do_resize
 
354
  if merge_size is None:
355
  merge_size = self.video_merge_size
356
 
357
+ # Size dict (shortest_edge/longest_edge)
358
  min_pixels = kwargs.pop("min_pixels", kwargs.pop("video_min_pixels", None))
359
  if min_pixels is None:
360
  min_pixels = self.size["shortest_edge"]
 
365
 
366
  size = SizeDict(shortest_edge=min_pixels, longest_edge=max_pixels)
367
 
368
+ # 2. Convert resample -> interpolation, mean/std -> tuple
 
369
  if isinstance(resample, (PILImageResampling, int)):
370
  interpolation = pil_torch_interpolation_mapping[resample]
371
  else:
 
376
  if isinstance(image_std, list):
377
  image_std = tuple(image_std)
378
 
379
+ # 3. Per-video processing
380
  pixel_values_list = []
381
  grid_thw_list = []
382
  num_video_tokens_list = []
383
 
384
  for video in videos:
385
+ # numpy (NHWC) -> channel-first torch (NCHW)
386
  if isinstance(video, np.ndarray):
387
  video = to_channel_dimension_format(video, ChannelDimension.FIRST)
388
  video = torch.from_numpy(video).contiguous()
389
 
 
390
  if do_convert_rgb:
391
  video = self.convert_to_rgb(video)
392
 
 
421
  image_width: Optional[int] = None,
422
  image_height: Optional[int] = None,
423
  num_frames: Optional[int] = None,
424
+ pixel_values_videos: Optional[torch.Tensor] = None,
425
  include_boundary_tokens: bool = False,
426
  patch_size: Optional[int] = None,
427
  temporal_patch_size: Optional[int] = None,
428
  merge_size: Optional[int] = None,
429
  min_pixels: Optional[int] = None,
430
  max_pixels: Optional[int] = None,
431
+ return_tuple: Optional[bool] = None,
432
+ ) -> int:
433
+ """Compute the number of video tokens for the given input.
434
+
435
+ Args:
436
+ image_width: Frame width (used when pixel_values_videos is None).
437
+ image_height: Frame height (used when pixel_values_videos is None).
438
+ num_frames: Number of frames (used when pixel_values_videos is None).
439
+ pixel_values_videos: Pre-computed pixel values tensor.
440
+ include_boundary_tokens: Whether to include start/end boundary tokens.
441
+ patch_size: ViT patch size. Defaults to self.video_patch_size.
442
+ temporal_patch_size: Temporal patch size. Defaults to self.video_temporal_patch_size.
443
+ merge_size: Token reduction merge size. Defaults to self.video_merge_size.
444
+ min_pixels: Minimum pixel count. Defaults to self.size["shortest_edge"].
445
+ max_pixels: Maximum pixel count. Defaults to self.size["longest_edge"].
446
+ return_tuple: If True, return (continuous, discrete) tuple.
447
+ Otherwise return the sum.
448
+
449
+ Returns:
450
+ Token count as int, or (continuous, discrete) tuple if return_tuple is True.
451
+ """
452
  patch_size = patch_size if patch_size is not None else self.video_patch_size
453
  temporal_patch_size = temporal_patch_size if temporal_patch_size is not None else self.video_temporal_patch_size
454
  merge_size = merge_size if merge_size is not None else self.video_merge_size
 
474
  if include_boundary_tokens:
475
  num_continuous_tokens += 2
476
 
477
+ if return_tuple:
478
+ return (num_continuous_tokens, num_discrete_tokens)
479
+ else:
480
+ return num_continuous_tokens + num_discrete_tokens