efwkjn commited on
Commit
9874200
·
verified ·
1 Parent(s): d87dc6a

Upload 6 files

Browse files
Files changed (6) hide show
  1. README.md +69 -0
  2. cohere_asr.py +1769 -0
  3. config.json +173 -0
  4. model.safetensors +3 -0
  5. tokenizer.json +0 -0
  6. train.py +520 -0
README.md ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ language:
3
+ - ja
4
+ pipeline_tag: automatic-speech-recognition
5
+ base_model:
6
+ - efwkjn/cohere-asr-ja
7
+ ---
8
+ Experimental single step block diffusion model for speculative decoding similar to [Orthrus](https://arxiv.org/abs/2605.12825)/[DFlash](https://arxiv.org/abs/2602.06036). Like Orthrus it conditions on the AR KV cache but like DFlash only the embedding layer is shared. Training and inference code is included based on pure pytorch/flex attention with torch compile.
9
+
10
+ |bsz=1 |transformers |nano-cohere-transcribe |diffusion=False |diffusion=True |avg accept |
11
+ |-------|----------------------:|----------------------:|----------------------:|----------------------:|----------:|
12
+ |fleurs | 1.00x| 2.35x| 2.97x| 5.28x| 8.92|
13
+ |jsut | 1.00x| 2.02x| 2.72x| 4.24x| 9.88|
14
+ |reazon | 1.00x| 1.89x| 2.59x| 3.82x| 8.45|
15
+
16
+ Notes
17
+ * Diffusion for fun, not very practical (increase batching instead)
18
+ * torch.compile involves more warmup time
19
+ * Pad inputs to static shapes for compile efficiency
20
+ * diffusion=False ~10% faster than nano if encoder isn't compiled
21
+ * Benchmark sequences short, average of jsut/reazon is below block size
22
+
23
+ ```python
24
+ from huggingface_hub import snapshot_download
25
+ model_dir = 'diff'
26
+ snapshot_download('efwkjn/cohere-asr-ja-diffusion', cache_dir=model_dir, local_dir=model_dir)
27
+ ```
28
+ ```python
29
+ import importlib
30
+ import subprocess
31
+
32
+ import numpy as np
33
+ import torch
34
+ from tokenizers import Tokenizer
35
+
36
+ cohere_asr = importlib.import_module(model_dir + '.cohere_asr')
37
+ file = 'audio.wav'
38
+ device = 'cuda'
39
+
40
+ cmd = [
41
+ 'ffmpeg',
42
+ '-threads', '1',
43
+ '-nostdin',
44
+ '-i', file,
45
+ '-f', 's16le',
46
+ '-c:a', 'pcm_s16le',
47
+ '-ar', '16000',
48
+ '-ac', '1',
49
+ '-'
50
+ ]
51
+ with subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL) as p:
52
+ audio = np.frombuffer(p.stdout.read(), dtype=np.int16).astype(np.float32) / 0x8000
53
+
54
+ fe = cohere_asr.CohereAsrFeatureExtractor(model_dir)
55
+ model = cohere_asr.CohereAsr.from_pretrained(model_dir, device)
56
+ tokenizer: Tokenizer = Tokenizer.from_file(model_dir + '/tokenizer.json')
57
+ prompt = tokenizer.encode(
58
+ '<|startofcontext|><|startoftranscript|><|emo:undefined|>'
59
+ '<|ja|><|ja|><|pnc|><|noitn|><|notimestamp|><|nodiarize|>',
60
+ add_special_tokens=False
61
+ ).ids
62
+
63
+ features, lengths = fe([audio[:480000]])
64
+ input_ids = torch.tensor(prompt, device=device)[None, :]
65
+ features = features.to(device, torch.bfloat16)
66
+ lengths = lengths.to(device)
67
+ ids = model.generate(input_ids, features, lengths, compile=False, diffusion=True)
68
+ print(tokenizer.decode_batch(ids.tolist())[0])
69
+ ```
cohere_asr.py ADDED
@@ -0,0 +1,1769 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import math
3
+ from pathlib import Path
4
+
5
+ import numpy as np
6
+ import torch
7
+ import torch.nn.functional as F
8
+ from safetensors import safe_open
9
+ from torch import nn
10
+ from torch.nn.attention.flex_attention import _DEFAULT_SPARSE_BLOCK_SIZE, BlockMask, flex_attention
11
+
12
+
13
+ class FilterbankFeatures(nn.Module):
14
+ '''Filterbank features extraction module.
15
+ Follows NeMo's FilterbankFeatures implementation.
16
+ '''
17
+
18
+ window: torch.Tensor
19
+ fb: torch.Tensor
20
+
21
+ def __init__(
22
+ self,
23
+ pretrained_model_or_path=None,
24
+ sample_rate=16000,
25
+ n_window_size=400,
26
+ n_window_stride=160,
27
+ window='hann',
28
+ normalize='per_feature',
29
+ n_fft=512,
30
+ preemph=0.97,
31
+ nfilt=128,
32
+ lowfreq=0,
33
+ highfreq=None,
34
+ log=True,
35
+ log_zero_guard_type='add',
36
+ log_zero_guard_value=2**-24,
37
+ dither=1e-5,
38
+ pad_to=0,
39
+ max_duration=35,
40
+ frame_splicing=1,
41
+ exact_pad=False,
42
+ pad_value=0,
43
+ mag_power=2.0,
44
+ use_grads=False,
45
+ nb_augmentation_prob=0.0,
46
+ nb_max_freq=4000,
47
+ mel_norm='slaney',
48
+ device='cpu',
49
+ ):
50
+ super().__init__()
51
+ if exact_pad and n_window_stride % 2 == 1:
52
+ raise NotImplementedError(f'{self} received exact_pad=True with odd hop length ({n_window_stride}).')
53
+
54
+ if (
55
+ n_window_size is None
56
+ or n_window_stride is None
57
+ or not isinstance(n_window_size, int)
58
+ or not isinstance(n_window_stride, int)
59
+ or n_window_size <= 0
60
+ or n_window_stride <= 0
61
+ ):
62
+ raise ValueError('n_window_size and n_window_stride must be positive ints.')
63
+
64
+ self.log_zero_guard_value = log_zero_guard_value
65
+ self.sample_rate = sample_rate
66
+ self.win_length = n_window_size
67
+ self.hop_length = n_window_stride
68
+ self.n_fft = n_fft or 2 ** math.ceil(math.log2(self.win_length))
69
+ self.stft_pad_amount = (self.n_fft - self.hop_length) // 2 if exact_pad else None
70
+ self.exact_pad = exact_pad
71
+ self.max_duration = max_duration
72
+
73
+ if pretrained_model_or_path:
74
+ safetensor_path = Path(pretrained_model_or_path) / 'model.safetensors'
75
+ if safetensor_path.exists():
76
+ try:
77
+ with safe_open(safetensor_path.as_posix(), 'pt') as file:
78
+ self.register_buffer('fb', file.get_tensor('preprocessor.featurizer.fb'))
79
+ self.register_buffer('window', file.get_tensor('preprocessor.featurizer.window'))
80
+ except:
81
+ pass
82
+
83
+ if not hasattr(self, 'window'):
84
+ torch_windows = {
85
+ 'hann': torch.hann_window,
86
+ 'hamming': torch.hamming_window,
87
+ 'blackman': torch.blackman_window,
88
+ 'bartlett': torch.bartlett_window,
89
+ 'none': None,
90
+ }
91
+ window_fn = torch_windows.get(window)
92
+ window_tensor = window_fn(self.win_length, periodic=False) if window_fn else None
93
+ self.register_buffer('window', window_tensor)
94
+
95
+ self.normalize = normalize
96
+ self.log = log
97
+ self.dither = dither
98
+ self.frame_splicing = frame_splicing
99
+ self.nfilt = nfilt
100
+ self.preemph = preemph
101
+ self.pad_to = pad_to
102
+ highfreq = highfreq or sample_rate / 2
103
+ self.pad_min_duration = 0.0
104
+ self.pad_direction = 'both'
105
+ self.pad_value = pad_value
106
+ self.mag_power = mag_power
107
+ self.nb_augmentation_prob = nb_augmentation_prob
108
+
109
+ if not hasattr(self, 'fb'):
110
+ self.register_buffer('fb', self._get_mel_filters(lowfreq, highfreq, mel_norm))
111
+
112
+ max_length = self.get_seq_len(torch.tensor(max_duration * sample_rate, dtype=torch.float))
113
+ max_pad = pad_to - (max_length % pad_to) if pad_to > 0 else 0
114
+ self.max_length = max_length + max_pad
115
+
116
+ if log_zero_guard_type not in ['add', 'clamp']:
117
+ raise ValueError('log_zero_guard_type must be `add` or `clamp`.')
118
+ self.log_zero_guard_type = log_zero_guard_type
119
+
120
+ self.use_grads = use_grads
121
+ if not use_grads:
122
+ self.forward = torch.no_grad()(self.forward)
123
+
124
+ if self.nb_augmentation_prob > 0.0:
125
+ if nb_max_freq >= sample_rate / 2:
126
+ self.nb_augmentation_prob = 0.0
127
+ else:
128
+ self._nb_max_fft_bin = int((nb_max_freq / sample_rate) * self.n_fft)
129
+
130
+ if self.window is None:
131
+ raise RuntimeError('Expected a window tensor for STFT feature extraction.')
132
+ if self.fb is None:
133
+ raise RuntimeError('Expected mel filterbank weights for feature extraction.')
134
+ self.window = self.window.to(dtype=torch.float32)
135
+ self.fb = self.fb.to(dtype=torch.float32)
136
+ self.generator = torch.Generator(device=device)
137
+ self.generator.manual_seed(0)
138
+
139
+ def _get_mel_filters(self, fmin: float, fmax: float, mel_norm: str):
140
+ assert mel_norm == 'slaney'
141
+ min_log_hertz = 1000.0
142
+ min_log_mel = 15.0
143
+ logstep = math.log(6.4) / 27.0
144
+ fftfreqs = torch.fft.rfftfreq(n=self.n_fft, d=1.0 / self.sample_rate, dtype=torch.float64)
145
+
146
+ def hz_to_mel(freq: float) -> float:
147
+ if freq < min_log_hertz:
148
+ return 3 * freq / 200.0
149
+ return min_log_mel + math.log(freq / min_log_hertz) * (1 / logstep)
150
+ mels = torch.linspace(hz_to_mel(fmin), hz_to_mel(fmax), self.nfilt + 2, dtype=torch.float64)
151
+ freqs = 200.0 / 3 * mels
152
+ log_t = mels >= min_log_mel
153
+ freqs[log_t] = min_log_hertz * torch.exp(logstep * (mels[log_t] - min_log_mel))
154
+
155
+ fdiff = torch.diff(freqs)
156
+ ramps = freqs[:, None] - fftfreqs[None, :]
157
+ lower = (-ramps[:-2, :] / fdiff[:-1, None]).float()
158
+ upper = (ramps[2:, :] / fdiff[1:, None]).float()
159
+ weights = torch.maximum(torch.minimum(lower, upper), torch.zeros(1))
160
+ enorm = 2.0 / (freqs[2: self.nfilt + 2] - freqs[:self.nfilt])
161
+ weights *= enorm[:, None]
162
+ return weights
163
+
164
+ @torch._dynamo.disable
165
+ def _apply_dither(self, x: torch.Tensor, seq_len_time: torch.Tensor) -> torch.Tensor:
166
+ '''Apply deterministic per-sample dither outside torch.compile.
167
+ Each sample is seeded by its valid waveform length so that dither noise
168
+ is batch-composition invariant (a sample's features depend only on its
169
+ own content, not on what else is in the batch).
170
+ '''
171
+ if self.dither <= 0:
172
+ return x
173
+ for i in range(x.shape[0]):
174
+ valid_samples = min(int(seq_len_time[i].item()), x.shape[1])
175
+ if valid_samples <= 0:
176
+ continue
177
+ self.generator.manual_seed(valid_samples)
178
+ noise = torch.randn(
179
+ (valid_samples,),
180
+ dtype=x.dtype,
181
+ device=x.device,
182
+ generator=self.generator,
183
+ )
184
+ x[i, :valid_samples] += self.dither * noise
185
+ return x
186
+
187
+ def log_zero_guard_value_fn(self, x: torch.Tensor) -> float:
188
+ if isinstance(self.log_zero_guard_value, str):
189
+ if self.log_zero_guard_value == 'tiny':
190
+ return torch.finfo(x.dtype).tiny
191
+ if self.log_zero_guard_value == 'eps':
192
+ return torch.finfo(x.dtype).eps
193
+ raise ValueError('log_zero_guard_value must be number, `tiny`, or `eps` when str.')
194
+ return self.log_zero_guard_value
195
+
196
+ def get_seq_len(self, seq_len: torch.Tensor) -> torch.Tensor:
197
+ pad_amount = self.stft_pad_amount * 2 if self.stft_pad_amount is not None else self.n_fft // 2 * 2
198
+ seq_len = torch.floor_divide((seq_len + pad_amount - self.n_fft), self.hop_length)
199
+ return seq_len.to(dtype=torch.long)
200
+
201
+ def splice_frames(self, x: torch.Tensor, frame_splicing: int) -> torch.Tensor:
202
+ seq = [x]
203
+ for n in range(1, frame_splicing):
204
+ seq.append(torch.cat([x[:, :, :n], x[:, :, n:]], dim=2))
205
+ return torch.cat(seq, dim=1)
206
+
207
+ def normalize_batch(self, x: torch.Tensor, seq_len: torch.Tensor, normalize_type: str) -> torch.Tensor:
208
+ if normalize_type != 'per_feature':
209
+ raise ValueError('Only per_feature normalization is supported.')
210
+ batch_size = x.shape[0]
211
+ max_time = x.shape[2]
212
+ time_steps = torch.arange(max_time, device=x.device).unsqueeze(0).expand(batch_size, max_time)
213
+ valid_mask = time_steps < seq_len.unsqueeze(1)
214
+ x_mean_num = torch.where(valid_mask.unsqueeze(1), x, 0.0).sum(dim=2)
215
+ x_mean_den = valid_mask.sum(dim=1)
216
+ x_mean = x_mean_num / x_mean_den.unsqueeze(1)
217
+ x_std = torch.sqrt(
218
+ torch.sum(
219
+ torch.where(valid_mask.unsqueeze(1), x - x_mean.unsqueeze(2), 0.0) ** 2,
220
+ dim=2,
221
+ )
222
+ / (x_mean_den.unsqueeze(1) - 1.0)
223
+ )
224
+ x_std = x_std.masked_fill(x_std.isnan(), 0.0)
225
+ x_std += 1e-5
226
+ return (x - x_mean.unsqueeze(2)) / x_std.unsqueeze(2), x_mean, x_std
227
+
228
+ def forward(self, x: torch.Tensor, seq_len: torch.Tensor, linear_spec: bool = False) -> tuple[torch.Tensor, torch.Tensor]:
229
+ if x.shape[1] < self.sample_rate * self.pad_min_duration:
230
+ pad_amount = int(self.sample_rate * self.pad_min_duration) - x.shape[1]
231
+ if self.pad_direction == 'right':
232
+ x = F.pad(x, (0, pad_amount), value=self.pad_value)
233
+ elif self.pad_direction == 'left':
234
+ x = F.pad(x, (pad_amount, 0), value=self.pad_value)
235
+ elif self.pad_direction == 'both':
236
+ left_pad = pad_amount // 2
237
+ right_pad = pad_amount - left_pad
238
+ x = F.pad(x, (left_pad, right_pad), value=self.pad_value)
239
+ else:
240
+ raise ValueError(f'Invalid pad_direction: {self.pad_direction}')
241
+ seq_len = torch.tensor([x.shape[1]], dtype=torch.float, device=x.device)
242
+
243
+ seq_len_time = seq_len
244
+ seq_len_unfixed = self.get_seq_len(seq_len)
245
+ seq_len = torch.where(seq_len == 0, torch.zeros_like(seq_len_unfixed), seq_len_unfixed)
246
+
247
+ if self.stft_pad_amount is not None:
248
+ x = F.pad(x.unsqueeze(1), (self.stft_pad_amount, self.stft_pad_amount), 'constant').squeeze(1)
249
+
250
+ x = self._apply_dither(x, seq_len_time)
251
+
252
+ if self.preemph is not None:
253
+ timemask = torch.arange(x.shape[1], device=x.device).unsqueeze(0) < seq_len_time.unsqueeze(1)
254
+ x = torch.cat((x[:, 0].unsqueeze(1), x[:, 1:] - self.preemph * x[:, :-1]), dim=1)
255
+ x = x.masked_fill(~timemask, 0.0)
256
+
257
+ x = torch.stft(
258
+ x,
259
+ n_fft=self.n_fft,
260
+ hop_length=self.hop_length,
261
+ win_length=self.win_length,
262
+ center=not self.exact_pad,
263
+ window=self.window,
264
+ return_complex=True,
265
+ pad_mode='constant',
266
+ )
267
+ x = x[:, :, :seq_len.max()]
268
+ guard = 0 if not self.use_grads else 1e-5
269
+ x = torch.sqrt(torch.view_as_real(x).pow(2).sum(-1) + guard)
270
+
271
+ if self.mag_power != 1.0:
272
+ x = x.pow(self.mag_power)
273
+ if linear_spec:
274
+ return x, seq_len
275
+
276
+ x = torch.matmul(self.fb, x)
277
+
278
+ if self.log:
279
+ if self.log_zero_guard_type == 'add':
280
+ x = torch.log(x + self.log_zero_guard_value_fn(x))
281
+ elif self.log_zero_guard_type == 'clamp':
282
+ x = torch.log(torch.clamp(x, min=self.log_zero_guard_value_fn(x)))
283
+ else:
284
+ raise ValueError('log_zero_guard_type was not understood')
285
+
286
+ if self.frame_splicing > 1:
287
+ x = self.splice_frames(x, self.frame_splicing)
288
+ if self.normalize:
289
+ x, _, _ = self.normalize_batch(x, seq_len, normalize_type=self.normalize)
290
+
291
+ max_len = x.size(-1)
292
+ mask = torch.arange(max_len, device=x.device)
293
+ mask = mask.repeat(x.size(0), 1) >= seq_len.unsqueeze(1)
294
+ x = x.masked_fill(mask.unsqueeze(1).to(device=x.device), self.pad_value)
295
+ del mask
296
+
297
+ if self.pad_to == 'max':
298
+ x = F.pad(x, (0, self.max_length - x.size(-1)), value=self.pad_value)
299
+ elif self.pad_to > 0:
300
+ pad_amt = x.size(-1) % self.pad_to
301
+ if pad_amt != 0:
302
+ x = F.pad(x, (0, self.pad_to - pad_amt), value=self.pad_value)
303
+ return x, seq_len
304
+
305
+
306
+ class CohereAsrFeatureExtractor(nn.Module):
307
+ def __init__(
308
+ self,
309
+ pretrained_model_or_path=None,
310
+ feature_size=128,
311
+ sampling_rate=16000,
312
+ padding_value=0.0,
313
+ max_duration=35,
314
+ n_window_size=400,
315
+ n_window_stride=160,
316
+ window='hann',
317
+ normalize='per_feature',
318
+ n_fft=512,
319
+ preemph=0.97,
320
+ lowfreq=0,
321
+ highfreq=None,
322
+ log=True,
323
+ log_zero_guard_type='add',
324
+ log_zero_guard_value=2**-24,
325
+ dither=1e-5,
326
+ pad_to=0,
327
+ frame_splicing=1,
328
+ exact_pad=False,
329
+ mag_power=2.0,
330
+ nb_augmentation_prob=0.0,
331
+ nb_max_freq=4000,
332
+ mel_norm='slaney',
333
+ device='cpu',
334
+ ):
335
+ super().__init__()
336
+ self.max_duration = max_duration
337
+ self.hop_length = n_window_stride
338
+ self._device = str(device)
339
+ self.filterbank = FilterbankFeatures(
340
+ pretrained_model_or_path=pretrained_model_or_path,
341
+ sample_rate=sampling_rate,
342
+ n_window_size=n_window_size,
343
+ n_window_stride=n_window_stride,
344
+ window=window,
345
+ normalize=normalize,
346
+ n_fft=n_fft,
347
+ preemph=preemph,
348
+ nfilt=feature_size,
349
+ lowfreq=lowfreq,
350
+ highfreq=highfreq,
351
+ log=log,
352
+ log_zero_guard_type=log_zero_guard_type,
353
+ log_zero_guard_value=log_zero_guard_value,
354
+ dither=dither,
355
+ pad_to=pad_to,
356
+ max_duration=max_duration,
357
+ frame_splicing=frame_splicing,
358
+ exact_pad=exact_pad,
359
+ pad_value=padding_value,
360
+ mag_power=mag_power,
361
+ nb_augmentation_prob=nb_augmentation_prob,
362
+ nb_max_freq=nb_max_freq,
363
+ mel_norm=mel_norm,
364
+ device=device,
365
+ )
366
+ self.filterbank.eval()
367
+ self.filterbank = self.filterbank.to(self._device)
368
+
369
+ def get_seq_len(self, seq_len: torch.Tensor) -> torch.Tensor:
370
+ return self.filterbank.get_seq_len(seq_len)
371
+
372
+ def __call__(self, raw_speech: list[np.ndarray], sampling_rate: int = None) -> tuple[torch.Tensor, torch.Tensor]:
373
+ '''Extract mel features from raw waveform input.'''
374
+ if sampling_rate is not None and int(sampling_rate) != int(self.filterbank.sampling_rate):
375
+ raise ValueError(f'Expected sampling_rate={self.filterbank.sampling_rate}, got {sampling_rate}')
376
+
377
+ if isinstance(raw_speech, np.ndarray):
378
+ if raw_speech.ndim == 1:
379
+ raw_speech = [raw_speech]
380
+ else:
381
+ raw_speech = [s for s in raw_speech]
382
+ elif isinstance(raw_speech, torch.Tensor):
383
+ if raw_speech.ndim == 1:
384
+ raw_speech = [raw_speech.detach().cpu().numpy()]
385
+ else:
386
+ raw_speech = [s.detach().cpu().numpy() for s in raw_speech]
387
+ elif not isinstance(raw_speech, (list, tuple)):
388
+ raise TypeError('raw_speech must be an array/tensor or list of arrays.')
389
+
390
+ normalized = []
391
+ for sample in raw_speech:
392
+ arr = np.asarray(sample, dtype=np.float32)
393
+ if arr.ndim != 1:
394
+ raise ValueError('Each audio sample must be 1D waveform.')
395
+ normalized.append(arr)
396
+
397
+ seq_len = torch.tensor([s.shape[0] for s in normalized], dtype=torch.long)
398
+ max_len = max(s.shape[0] for s in normalized)
399
+ padded = np.zeros((len(normalized), max_len), dtype=np.float32)
400
+ for i, s in enumerate(normalized):
401
+ padded[i, : s.shape[0]] = s
402
+
403
+ audio_tensor = torch.from_numpy(padded).to(self._device)
404
+ seq_len = seq_len.to(self._device)
405
+ with torch.no_grad():
406
+ input_features, length = self.filterbank(audio_tensor, seq_len)
407
+
408
+ return input_features, length
409
+
410
+
411
+ class MaskedConvSequential(nn.Sequential):
412
+ def forward(self, x: torch.Tensor, lengths: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor]:
413
+ # x: (batch, channels, time, features)
414
+ current_lengths = lengths.clone().float()
415
+ mask = self._create_mask(x, current_lengths.long())
416
+ for layer in self:
417
+ x = self.apply_channel_mask(x, mask)
418
+ x = layer(x)
419
+ if hasattr(layer, 'stride') and layer.stride != (1, 1):
420
+ current_lengths = self.calculate_conv_output_size(
421
+ current_lengths, layer.kernel_size[0], layer.stride[0], layer.padding
422
+ )
423
+ mask = self._create_mask(x, current_lengths.long())
424
+ x = self.apply_channel_mask(x, mask)
425
+ return x, current_lengths.long()
426
+
427
+ def _create_mask(self, tensor: torch.Tensor, lengths: torch.Tensor) -> torch.Tensor:
428
+ batch_size, _, time, features = tensor.shape
429
+ time_mask = torch.arange(time, device=tensor.device).expand(batch_size, time) < lengths.unsqueeze(1)
430
+ return time_mask.unsqueeze(-1).expand(batch_size, time, features).to(tensor.dtype)
431
+
432
+ def apply_channel_mask(self, tensor: torch.Tensor, mask: torch.Tensor) -> torch.Tensor:
433
+ batch_size, channels, time, features = tensor.shape
434
+ expanded_mask = mask.unsqueeze(1).expand(batch_size, channels, time, features)
435
+ return tensor * expanded_mask
436
+
437
+ def calculate_conv_output_size(
438
+ self,
439
+ input_size: torch.Tensor,
440
+ kernel_size: int,
441
+ stride: int,
442
+ padding: tuple[int, int],
443
+ ) -> torch.Tensor:
444
+ return (input_size + padding[0] + padding[1] - kernel_size) // stride + 1
445
+
446
+
447
+ class ConvSubsampling(nn.Module):
448
+ def __init__(self, config: dict):
449
+ super().__init__()
450
+ feat_in = int(config['feat_in'])
451
+ conv_channels = int(config['subsampling_conv_channels'])
452
+ self._conv_channels = conv_channels
453
+ feat_out = int(config['feat_out'])
454
+ if feat_out <= 0:
455
+ feat_out = int(config['d_model'])
456
+ subsampling_factor = int(config['subsampling_factor'])
457
+
458
+ self.conv = MaskedConvSequential(
459
+ nn.Conv2d(1, conv_channels, kernel_size=3, stride=2, padding=1),
460
+ nn.ReLU(),
461
+ nn.Conv2d(conv_channels, conv_channels, kernel_size=3, stride=2, padding=1, groups=conv_channels),
462
+ nn.Conv2d(conv_channels, conv_channels, kernel_size=1),
463
+ nn.ReLU(),
464
+ nn.Conv2d(conv_channels, conv_channels, kernel_size=3, stride=2, padding=1, groups=conv_channels),
465
+ nn.Conv2d(conv_channels, conv_channels, kernel_size=1),
466
+ nn.ReLU(),
467
+ )
468
+ self.out = nn.Linear(conv_channels * (feat_in // subsampling_factor), feat_out)
469
+
470
+ def forward(self, x: torch.Tensor, lengths: torch.Tensor):
471
+ # x: (B, feat_in, T) -> (B, 1, T, feat_in)
472
+ x = x.transpose(1, 2).unsqueeze(1)
473
+ x, lengths = self.conv(x, lengths)
474
+ b, c, t, f = x.size()
475
+ x = x.transpose(1, 2).reshape(b, t, -1)
476
+ x = self.out(x)
477
+ return x, lengths
478
+
479
+
480
+ class RelPositionalEncoding(nn.Module):
481
+ def __init__(self, d_model: int, max_len: int = 5000):
482
+ super().__init__()
483
+ self.d_model = d_model
484
+ self.max_len = max_len
485
+ positions = torch.arange(
486
+ max_len - 1, -max_len, -1, dtype=torch.float32
487
+ ).unsqueeze(1)
488
+ pe = self._create_pe(positions=positions, dtype=torch.float32)
489
+ self.register_buffer('pe', pe, persistent=False)
490
+
491
+ def _create_pe(self, positions: torch.Tensor, dtype: torch.dtype) -> torch.Tensor:
492
+ pos_length = positions.size(0)
493
+ pe = torch.zeros(pos_length, self.d_model, device=positions.device)
494
+ div_term = torch.exp(
495
+ torch.arange(0, self.d_model, 2, dtype=torch.float32, device=positions.device)
496
+ * -(math.log(10000.0) / self.d_model)
497
+ )
498
+ pe[:, 0::2] = torch.sin(positions * div_term)
499
+ pe[:, 1::2] = torch.cos(positions * div_term)
500
+ return pe.unsqueeze(0).to(dtype)
501
+
502
+ @torch._dynamo.disable
503
+ def _materialize_pe(self, length: int, device: torch.device, dtype: torch.dtype):
504
+ needed_size = 2 * length - 1
505
+ if hasattr(self, 'pe') and self.pe.device.type != 'meta' and self.pe.size(1) >= needed_size:
506
+ if self.pe.device != device:
507
+ self.pe = self.pe.to(device=device)
508
+ if self.pe.dtype != dtype:
509
+ self.pe = self.pe.to(dtype=dtype)
510
+ return
511
+ effective_length = max(length, self.max_len)
512
+ positions = torch.arange(
513
+ effective_length - 1, -effective_length, -1, dtype=torch.float32, device=device
514
+ ).unsqueeze(1)
515
+ pe = self._create_pe(positions=positions, dtype=dtype)
516
+ if hasattr(self, 'pe'):
517
+ self.pe = pe
518
+ else:
519
+ self.register_buffer('pe', pe, persistent=False)
520
+
521
+ def forward(self, x: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor]:
522
+ # center_pos would be the index of position 0
523
+ # negative positions would be used for right and
524
+ # positive for left tokens
525
+ # for input of length L, 2*L-1 positions are needed,
526
+ # positions from (L-1) to -(L-1)
527
+ input_len = x.size(1)
528
+ center_pos = self.pe.size(1) // 2 + 1
529
+ start_pos = center_pos - input_len
530
+ end_pos = center_pos + input_len - 1
531
+ pos_emb = self.pe[:, start_pos:end_pos]
532
+
533
+ return x, pos_emb
534
+
535
+
536
+ class ConformerFeedForward(nn.Module):
537
+ def __init__(self, d_model: int, d_ff: int, dropout: float):
538
+ super().__init__()
539
+ self.linear1 = nn.Linear(d_model, d_ff)
540
+ self.activation = nn.SiLU()
541
+ self.dropout = nn.Dropout(dropout)
542
+ self.linear2 = nn.Linear(d_ff, d_model)
543
+
544
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
545
+ x = self.linear1(x)
546
+ x = self.activation(x)
547
+ x = self.dropout(x)
548
+ x = self.linear2(x)
549
+ return x
550
+
551
+
552
+ class ConformerConvolution(nn.Module):
553
+ def __init__(self, d_model: int, kernel_size: int):
554
+ super().__init__()
555
+ self.pointwise_conv1 = nn.Conv1d(d_model, d_model * 2, kernel_size=1)
556
+ self.depthwise_conv = nn.Conv1d(
557
+ d_model, d_model, kernel_size=kernel_size, groups=d_model, padding=(kernel_size - 1) // 2
558
+ )
559
+ self.batch_norm = nn.BatchNorm1d(d_model)
560
+ self.activation = nn.SiLU()
561
+ self.pointwise_conv2 = nn.Conv1d(d_model, d_model, kernel_size=1)
562
+
563
+ def forward(self, x: torch.Tensor, pad_mask: torch.Tensor = None) -> torch.Tensor:
564
+ x = x.transpose(1, 2)
565
+ x = self.pointwise_conv1(x)
566
+ x = F.glu(x, dim=1)
567
+ if pad_mask is not None:
568
+ x = x.masked_fill(pad_mask.unsqueeze(1), 0.0)
569
+ x = self.depthwise_conv(x)
570
+ x = self.batch_norm(x)
571
+ x = self.activation(x)
572
+ x = self.pointwise_conv2(x)
573
+ return x.transpose(1, 2)
574
+
575
+
576
+ class RelPositionMultiHeadAttention(nn.Module):
577
+ def __init__(self, n_head: int, n_feat: int, dropout_rate: float):
578
+ super().__init__()
579
+ self.d_k = n_feat // n_head
580
+ self.h = n_head
581
+ self.linear_q = nn.Linear(n_feat, n_feat)
582
+ self.linear_k = nn.Linear(n_feat, n_feat)
583
+ self.linear_v = nn.Linear(n_feat, n_feat)
584
+ self.linear_pos = nn.Linear(n_feat, n_feat, bias=False)
585
+ self.linear_out = nn.Linear(n_feat, n_feat)
586
+ self.dropout = nn.Dropout(dropout_rate)
587
+ self.scaling = self.d_k**-0.5
588
+ self.pos_bias_u = nn.Parameter(torch.zeros(self.h, self.d_k))
589
+ self.pos_bias_v = nn.Parameter(torch.zeros(self.h, self.d_k))
590
+
591
+ def rel_shift(self, x: torch.Tensor) -> torch.Tensor:
592
+ '''Compute relative positional encoding.
593
+ Args:
594
+ x (torch.Tensor): (batch, nheads, time, 2*time-1)
595
+ '''
596
+ b, h, qlen, pos_len = x.size() # (b, h, t1, t2)
597
+ # need to add a column of zeros on the left side of
598
+ # last dimension to perform the relative shifting
599
+ x = F.pad(x, pad=(1, 0)) # (b, h, t1, t2+1)
600
+ x = x.view(b, h, -1, qlen) # (b, h, t2+1, t1)
601
+ # need to drop the first row
602
+ x = x[:, :, 1:].view(b, h, qlen, pos_len) # (b, h, t1, t2)
603
+ return x
604
+
605
+ def forward(
606
+ self,
607
+ x: torch.Tensor,
608
+ pos_emb: torch.Tensor,
609
+ mask: BlockMask | torch.Tensor = None,
610
+ ) -> torch.Tensor:
611
+ batch_size = x.size(0)
612
+ q = self.linear_q(x).view(batch_size, -1, self.h, self.d_k).transpose(1, 2)
613
+ k = self.linear_k(x).view(batch_size, -1, self.h, self.d_k).transpose(1, 2)
614
+ v = self.linear_v(x).view(batch_size, -1, self.h, self.d_k).transpose(1, 2)
615
+
616
+ # pos_emb might be shared across batch
617
+ if pos_emb.size(0) == 1 and batch_size > 1:
618
+ pos_emb = pos_emb.expand(batch_size, -1, -1)
619
+ p = self.linear_pos(pos_emb).view(batch_size, -1, self.h, self.d_k).transpose(1, 2)
620
+
621
+ q_with_u = q + self.pos_bias_u.unsqueeze(0).unsqueeze(2)
622
+ q_with_v = q + self.pos_bias_v.unsqueeze(0).unsqueeze(2)
623
+ matrix_bd = torch.matmul(q_with_v, p.transpose(-1, -2))
624
+
625
+ if isinstance(mask, BlockMask):
626
+ def score_mod(score, b, h, q_idx, kv_idx):
627
+ i = kv_idx - q_idx + q.size(2) - 1
628
+ return score + matrix_bd[b, h, q_idx, i] * self.scaling
629
+
630
+ x = torch.compile(flex_attention)(
631
+ q_with_u, k, v,
632
+ score_mod=score_mod,
633
+ block_mask=mask,
634
+ scale=self.scaling,
635
+ )
636
+
637
+ else:
638
+ matrix_bd = self.rel_shift(matrix_bd)
639
+ matrix_bd = matrix_bd[:, :, :, : k.size(-2)] * self.scaling
640
+
641
+ if mask is not None:
642
+ matrix_bd.masked_fill_(mask.unsqueeze(1), -1e9)
643
+
644
+ x = F.scaled_dot_product_attention(
645
+ q_with_u, k, v,
646
+ attn_mask=matrix_bd,
647
+ dropout_p=self.dropout.p if self.training else 0,
648
+ scale=self.scaling,
649
+ )
650
+
651
+ x = x.transpose(1, 2).contiguous().view(batch_size, -1, self.h * self.d_k)
652
+ return self.linear_out(x)
653
+
654
+
655
+ class ConformerLayer(nn.Module):
656
+ def __init__(self, d_model: int, d_ff: int, n_heads: int, conv_kernel_size: int, dropout: float):
657
+ super().__init__()
658
+ self.norm_feed_forward1 = nn.LayerNorm(d_model)
659
+ self.feed_forward1 = ConformerFeedForward(d_model, d_ff, dropout)
660
+ self.norm_self_att = nn.LayerNorm(d_model)
661
+ self.self_attn = RelPositionMultiHeadAttention(n_heads, d_model, dropout)
662
+ self.norm_conv = nn.LayerNorm(d_model)
663
+ self.conv = ConformerConvolution(d_model, conv_kernel_size)
664
+ self.norm_feed_forward2 = nn.LayerNorm(d_model)
665
+ self.feed_forward2 = ConformerFeedForward(d_model, d_ff, dropout)
666
+ self.norm_out = nn.LayerNorm(d_model)
667
+ self.dropout = nn.Dropout(dropout)
668
+
669
+ def forward(self, x: torch.Tensor, pos_emb: torch.Tensor, mask: torch.Tensor = None, pad_mask: torch.Tensor = None) -> torch.Tensor:
670
+ residual = x
671
+ x = self.norm_feed_forward1(x)
672
+ x = residual + 0.5 * self.dropout(self.feed_forward1(x))
673
+
674
+ residual = x
675
+ x = self.norm_self_att(x)
676
+ x = residual + self.dropout(self.self_attn(x, pos_emb, mask))
677
+
678
+ residual = x
679
+ x = self.norm_conv(x)
680
+ x = residual + self.dropout(self.conv(x, pad_mask=pad_mask))
681
+
682
+ residual = x
683
+ x = self.norm_feed_forward2(x)
684
+ x = residual + 0.5 * self.dropout(self.feed_forward2(x))
685
+
686
+ return self.norm_out(x)
687
+
688
+
689
+ class ConformerEncoder(nn.Module):
690
+ '''
691
+ Fast Conformer encoder.
692
+
693
+ Follows [Fast Conformer with Linearly Scalable Attention for Efficient Speech
694
+ Recognition](https://arxiv.org/abs/2305.05084).
695
+ '''
696
+
697
+ main_input_name = 'input_features'
698
+
699
+ def __init__(self, config: dict | str):
700
+ super().__init__()
701
+ if not isinstance(config, dict):
702
+ with open(config, 'r', encoding='utf-8') as file:
703
+ config = json.load(file)
704
+ enc_config = config['encoder']
705
+ self.d_model = enc_config['d_model']
706
+ d_ff = self.d_model * enc_config['ff_expansion_factor']
707
+ n_heads = enc_config['n_heads']
708
+ conv_kernel_size = enc_config['conv_kernel_size']
709
+ dropout = enc_config['dropout']
710
+ n_layers = enc_config['n_layers']
711
+ pos_emb_max_len = enc_config['pos_emb_max_len']
712
+
713
+ self.pre_encode = ConvSubsampling(enc_config)
714
+ self.pos_enc = RelPositionalEncoding(self.d_model, pos_emb_max_len)
715
+
716
+ self.layers = nn.ModuleList(
717
+ [ConformerLayer(self.d_model, d_ff, n_heads, conv_kernel_size, dropout) for _ in range(n_layers)]
718
+ )
719
+ self.encoder_decoder_proj = nn.Linear(self.d_model, config['transf_decoder']['config_dict']['hidden_size'])
720
+
721
+ @torch.no_grad()
722
+ def load(self, model: str):
723
+ with safe_open(model, 'pt') as file:
724
+ for name, param in self.named_parameters():
725
+ if name.startswith('encoder_decoder_proj.'):
726
+ key = name
727
+ else:
728
+ key = 'encoder.' + name
729
+ param.copy_(file.get_tensor(key), non_blocking=True)
730
+ return self
731
+
732
+ def _create_masks(
733
+ self,
734
+ padding_length: torch.Tensor,
735
+ max_audio_length: int,
736
+ device: torch.device,
737
+ block_size: int = _DEFAULT_SPARSE_BLOCK_SIZE,
738
+ ) -> tuple[torch.Tensor, BlockMask]:
739
+ padding_length = padding_length.int()
740
+ bsz = padding_length.shape[0]
741
+ pad_mask = torch.arange(0, max_audio_length, device=device).expand(bsz, -1) >= padding_length[:, None]
742
+
743
+ def mask_mod(b, h, q_idx, kv_idx):
744
+ return (q_idx < padding_length[b]) & (kv_idx < padding_length[b])
745
+
746
+ bsz = padding_length.size(0)
747
+ num_blocks = -(-max_audio_length // block_size)
748
+ arange = torch.arange(num_blocks, dtype=torch.int32, device=device)
749
+
750
+ full_blocks = (padding_length // block_size)[:, None]
751
+ full = arange < full_blocks
752
+ full_kv_num_blocks = torch.where(full, full_blocks, 0).view(bsz, 1, num_blocks)
753
+ full_kv_indices = arange.expand(bsz, 1, num_blocks, num_blocks).contiguous()
754
+
755
+ partial = (padding_length % block_size != 0)[:, None]
756
+ partial_blocks = -(-padding_length // block_size)[:, None]
757
+ mask = partial & (full_blocks == arange)
758
+ extra_block = full & partial
759
+ kv_num_blocks = torch.where(mask, partial_blocks, extra_block).view(bsz, 1, num_blocks)
760
+ kv_indices = torch.where(
761
+ extra_block.view(bsz, 1, num_blocks, 1),
762
+ partial_blocks.view(bsz, 1, 1, 1) - 1,
763
+ full_kv_indices,
764
+ )
765
+
766
+ att_mask = BlockMask.from_kv_blocks(
767
+ kv_num_blocks=kv_num_blocks,
768
+ kv_indices=kv_indices,
769
+ full_kv_num_blocks=full_kv_num_blocks,
770
+ full_kv_indices=full_kv_indices,
771
+ BLOCK_SIZE=(block_size, block_size),
772
+ mask_mod=mask_mod,
773
+ seq_lengths=(max_audio_length, max_audio_length),
774
+ compute_q_blocks=False,
775
+ )
776
+ return pad_mask, att_mask
777
+
778
+ def forward(self, input_features: torch.Tensor = None, length: torch.Tensor = None) -> tuple[torch.Tensor, torch.Tensor]:
779
+ if input_features is None:
780
+ raise ValueError('Expected `input_features` for encoder forward.')
781
+ if length is None:
782
+ length = torch.full(
783
+ (input_features.shape[0],),
784
+ input_features.shape[-1],
785
+ device=input_features.device,
786
+ dtype=torch.long,
787
+ )
788
+ x, length = self.pre_encode(input_features, length)
789
+ max_audio_length = x.size(1)
790
+ x, pos_emb = self.pos_enc(x)
791
+ pad_mask, att_mask = self._create_masks(
792
+ padding_length=length,
793
+ max_audio_length=max_audio_length,
794
+ device=x.device,
795
+ )
796
+ for layer in self.layers:
797
+ x = layer(x, pos_emb, mask=att_mask, pad_mask=pad_mask)
798
+ x = self.encoder_decoder_proj(x)
799
+ return x, length
800
+
801
+
802
+ class FixedPositionalEncoding(nn.Module):
803
+ def __init__(self, hidden_size: int, max_sequence_length: int = 512):
804
+ super().__init__()
805
+ self.hidden_size = hidden_size
806
+ self.max_sequence_length = max_sequence_length
807
+
808
+ pos_enc = torch.zeros(max_sequence_length, hidden_size)
809
+ position = torch.arange(0.0, max_sequence_length).unsqueeze(1)
810
+ coef = -math.log(10000.0) / hidden_size
811
+ div_term = torch.exp(coef * torch.arange(0.0, hidden_size, 2))
812
+ pos_enc[:, 0::2] = torch.sin(position * div_term)
813
+ pos_enc[:, 1::2] = torch.cos(position * div_term)
814
+ pos_enc.div_(math.sqrt(hidden_size))
815
+ self.register_buffer('pos_enc', pos_enc)
816
+
817
+ def forward(self, position_ids: torch.Tensor) -> torch.Tensor:
818
+ return torch.index_select(self.pos_enc, 0, position_ids.reshape(-1)).reshape(*position_ids.shape, -1)
819
+
820
+
821
+ class Cache(nn.Module):
822
+ def __init__(
823
+ self,
824
+ batch_size: int,
825
+ max_cache_len: int,
826
+ device: torch.device,
827
+ dtype: torch.dtype,
828
+ num_key_value_heads: int,
829
+ head_dim: int,
830
+ num_hidden_layers: int,
831
+ ):
832
+ super().__init__()
833
+ self.batch_size = batch_size
834
+ self.max_cache_len = max_cache_len
835
+ self.cur_cache_len = max_cache_len
836
+ self.device = device
837
+ self.dtype = dtype
838
+ self.layers = num_hidden_layers
839
+
840
+ cache_shape = batch_size, num_key_value_heads, max_cache_len, head_dim
841
+ self.key_cache: list[torch.Tensor] = []
842
+ self.value_cache: list[torch.Tensor] = []
843
+ for i in range(num_hidden_layers):
844
+ self.register_buffer(f'key_cache_{i}', torch.zeros(cache_shape, dtype=dtype, device=device), False)
845
+ self.register_buffer(f'value_cache_{i}', torch.zeros(cache_shape, dtype=dtype, device=device), False)
846
+ k = getattr(self, f'key_cache_{i}')
847
+ v = getattr(self, f'value_cache_{i}')
848
+ torch._dynamo.mark_static_address(k)
849
+ torch._dynamo.mark_static_address(v)
850
+ self.key_cache.append(k)
851
+ self.value_cache.append(v)
852
+
853
+ def update(
854
+ self,
855
+ layer_idx: int,
856
+ bsz: int,
857
+ key: torch.Tensor = None,
858
+ value: torch.Tensor = None,
859
+ positions: torch.Tensor = None,
860
+ ) -> tuple[torch.Tensor, torch.Tensor]:
861
+ k = self.key_cache[layer_idx][:bsz, :, :self.cur_cache_len, :]
862
+ v = self.value_cache[layer_idx][:bsz, :, :self.cur_cache_len, :]
863
+ if key is None: # cross decode
864
+ pass
865
+ elif positions is None: # prefill
866
+ l = key.shape[2]
867
+ k = k[:, :, :l, :].copy_(key)
868
+ v = v[:, :, :l, :].copy_(value)
869
+ else: # decode
870
+ k.index_copy_(2, positions, key)
871
+ v.index_copy_(2, positions, value)
872
+ return k, v
873
+
874
+ def reset(self):
875
+ for k, v in zip(self.key_cache, self.value_cache):
876
+ k.zero_()
877
+ v.zero_()
878
+
879
+ def reorder(self, indices: torch.Tensor, finished: torch.Tensor, l: int):
880
+ indices = indices[~finished]
881
+ for i in range(self.layers):
882
+ self.key_cache[i][~finished, :, :l, :] = self.key_cache[i][indices, :, :l, :]
883
+ self.value_cache[i][~finished, :, :l, :] = self.value_cache[i][indices, :, :l, :]
884
+
885
+
886
+ class EncoderDecoderCache(nn.Module):
887
+ def __init__(self, self_attention_cache: Cache, cross_attention_cache: Cache):
888
+ super().__init__()
889
+ self.self_attention_cache = self_attention_cache
890
+ self.cross_attention_cache = cross_attention_cache
891
+ self.is_updated = {}
892
+ for layer_idx in range(len(cross_attention_cache.key_cache)):
893
+ self.is_updated[layer_idx] = False
894
+
895
+ def reset(self):
896
+ self.self_attention_cache.reset()
897
+ self.cross_attention_cache.reset()
898
+ for layer_idx in self.is_updated:
899
+ self.is_updated[layer_idx] = False
900
+
901
+
902
+ class DecoderAttention(nn.Module):
903
+ def __init__(self, hidden_size: int, num_heads: int, layer_idx: int, has_kv: bool = True):
904
+ super().__init__()
905
+ self.hidden_size = hidden_size
906
+ self.num_heads = num_heads
907
+ self.layer_idx = layer_idx
908
+ self.head_dim = hidden_size // num_heads
909
+ self.scale = self.head_dim**-0.5
910
+ self.query_net = nn.Linear(hidden_size, hidden_size)
911
+ if has_kv:
912
+ self.key_net = nn.Linear(hidden_size, hidden_size)
913
+ self.value_net = nn.Linear(hidden_size, hidden_size)
914
+ self.out_projection = nn.Linear(hidden_size, hidden_size)
915
+
916
+ def _reshape(self, x: torch.Tensor) -> torch.Tensor:
917
+ b, t, _ = x.shape
918
+ return x.view(b, t, self.num_heads, self.head_dim).transpose(1, 2)
919
+
920
+ def forward(
921
+ self,
922
+ hidden_states: torch.Tensor,
923
+ context_states: torch.Tensor = None,
924
+ attention_mask: BlockMask | torch.Tensor = None,
925
+ past_key_values: EncoderDecoderCache = None,
926
+ positions: torch.Tensor = None,
927
+ diffusion: bool = False,
928
+ ) -> torch.Tensor:
929
+ bsz, tgt_len, _ = hidden_states.size()
930
+ query = self._reshape(self.query_net(hidden_states))
931
+ _flex_attention = torch.compile(flex_attention)
932
+
933
+ if context_states is not None:
934
+ enc_bsz = context_states.shape[0]
935
+ beam_size = bsz // enc_bsz
936
+ if past_key_values is not None and past_key_values.is_updated.get(self.layer_idx):
937
+ key, value = past_key_values.cross_attention_cache.update(self.layer_idx, enc_bsz)
938
+ else:
939
+ key = self._reshape(self.key_net(context_states))
940
+ value = self._reshape(self.value_net(context_states))
941
+ if past_key_values is not None:
942
+ key, value = past_key_values.cross_attention_cache.update(self.layer_idx, enc_bsz, key, value)
943
+ past_key_values.is_updated[self.layer_idx] = True
944
+
945
+ if beam_size != 1: # use gqa
946
+ query = query.transpose(1, 2)
947
+ query = query.view(enc_bsz, beam_size, tgt_len, self.num_heads, self.head_dim)
948
+ query = query.permute(0, 3, 1, 2, 4)
949
+ query = query.reshape(enc_bsz, self.num_heads * beam_size, tgt_len, self.head_dim)
950
+
951
+ kernel_options = {'BLOCK_M': 1} if tgt_len == 1 else None # incase decoding kernel not used
952
+ attn_output = _flex_attention(query, key, value, block_mask=attention_mask, scale=self.scale, enable_gqa=True, kernel_options=kernel_options)
953
+ attn_output = attn_output.view(enc_bsz, self.num_heads, beam_size, tgt_len, self.head_dim)
954
+ attn_output = attn_output.permute(0, 2, 3, 1, 4).reshape(bsz, tgt_len, self.hidden_size)
955
+ elif isinstance(attention_mask, torch.Tensor):
956
+ attn_output = F.scaled_dot_product_attention(query, key, value, attn_mask=attention_mask, scale=self.scale)
957
+ attn_output = attn_output.transpose(1, 2).reshape(bsz, tgt_len, self.hidden_size)
958
+ else:
959
+ attn_output = _flex_attention(query, key, value, block_mask=attention_mask, scale=self.scale)
960
+ attn_output = attn_output.transpose(1, 2).reshape(bsz, tgt_len, self.hidden_size)
961
+
962
+ else:
963
+ key = self._reshape(self.key_net(hidden_states))
964
+ value = self._reshape(self.value_net(hidden_states))
965
+ if past_key_values is not None:
966
+ key, value = past_key_values.self_attention_cache.update(self.layer_idx, bsz, key, value, positions)
967
+
968
+ if isinstance(attention_mask, BlockMask):
969
+ attn_output = _flex_attention(query, key, value, block_mask=attention_mask, scale=self.scale)
970
+ else:
971
+ attn_output = F.scaled_dot_product_attention(
972
+ query=query,
973
+ key=key,
974
+ value=value,
975
+ attn_mask=attention_mask,
976
+ scale=self.scale,
977
+ is_causal=attention_mask is None and not diffusion,
978
+ )
979
+ attn_output = attn_output.transpose(1, 2).reshape(bsz, tgt_len, self.hidden_size)
980
+
981
+ return self.out_projection(attn_output)
982
+
983
+
984
+ class DecoderFeedForward(nn.Module):
985
+ def __init__(self, hidden_size: int, inner_size: int, hidden_act: str = 'relu'):
986
+ super().__init__()
987
+ self.dense_in = nn.Linear(hidden_size, inner_size)
988
+ assert hidden_act == 'relu'
989
+ self.activation = nn.ReLU()
990
+ self.dense_out = nn.Linear(inner_size, hidden_size)
991
+
992
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
993
+ return self.dense_out(self.activation(self.dense_in(x)))
994
+
995
+
996
+ class TransformerDecoderLayer(nn.Module):
997
+ def __init__(self, hidden_size: int, inner_size: int, num_heads: int, layer_idx: int, hidden_act: str, diffusion: bool):
998
+ super().__init__()
999
+ self.layer_norm_1 = nn.LayerNorm(hidden_size)
1000
+ self.first_sub_layer = DecoderAttention(hidden_size, num_heads, layer_idx)
1001
+ self.layer_norm_2 = nn.LayerNorm(hidden_size)
1002
+ self.second_sub_layer = DecoderAttention(hidden_size, num_heads, layer_idx, has_kv=not diffusion)
1003
+ self.layer_norm_3 = nn.LayerNorm(hidden_size)
1004
+ self.third_sub_layer = DecoderFeedForward(hidden_size, inner_size, hidden_act=hidden_act)
1005
+
1006
+ def forward(
1007
+ self,
1008
+ hidden_states: torch.Tensor,
1009
+ encoder_hidden_states: torch.Tensor = None,
1010
+ self_attention_mask: BlockMask | torch.Tensor = None,
1011
+ cross_attention_mask: BlockMask | torch.Tensor = None,
1012
+ past_key_values: EncoderDecoderCache = None,
1013
+ positions: torch.Tensor = None,
1014
+ ) -> torch.Tensor:
1015
+ residual = hidden_states
1016
+ hidden_states = self.layer_norm_1(hidden_states)
1017
+ self_out = self.first_sub_layer(
1018
+ hidden_states,
1019
+ context_states=None,
1020
+ attention_mask=self_attention_mask,
1021
+ past_key_values=past_key_values,
1022
+ positions=positions,
1023
+ )
1024
+ hidden_states = residual + self_out
1025
+
1026
+ residual = hidden_states
1027
+ hidden_states = self.layer_norm_2(hidden_states)
1028
+ cross_out = self.second_sub_layer(
1029
+ hidden_states,
1030
+ context_states=encoder_hidden_states,
1031
+ attention_mask=cross_attention_mask,
1032
+ past_key_values=past_key_values,
1033
+ )
1034
+ hidden_states = residual + cross_out
1035
+
1036
+ residual = hidden_states
1037
+ hidden_states = self.layer_norm_3(hidden_states)
1038
+ hidden_states = residual + self.third_sub_layer(hidden_states)
1039
+ return hidden_states
1040
+
1041
+
1042
+ class TransformerDecoderEmbedding(nn.Module):
1043
+ def __init__(self, vocab_size: int, hidden_size: int, max_sequence_length: int, padding_idx: int = 2):
1044
+ super().__init__()
1045
+ self.token_embedding = nn.Embedding(vocab_size, hidden_size, padding_idx)
1046
+ self.position_embedding = FixedPositionalEncoding(hidden_size, max_sequence_length)
1047
+ self.layer_norm = nn.LayerNorm(hidden_size)
1048
+
1049
+ def forward(self, input_ids: torch.Tensor, positions: torch.Tensor) -> torch.Tensor:
1050
+ token_embeds = self.token_embedding(input_ids)
1051
+ if positions is None:
1052
+ pos_embeds = self.position_embedding.pos_enc[:input_ids.shape[-1]]
1053
+ else:
1054
+ pos_embeds = self.position_embedding(positions)
1055
+ return self.layer_norm(token_embeds + pos_embeds)
1056
+
1057
+
1058
+ class TransformerDecoderCore(nn.Module):
1059
+ def __init__(self, hidden_size: int, inner_size: int, num_heads: int, num_layers: int, hidden_act: str, diffusion: bool):
1060
+ super().__init__()
1061
+ self.layers = nn.ModuleList(
1062
+ [
1063
+ TransformerDecoderLayer(hidden_size, inner_size, num_heads, i, hidden_act, diffusion)
1064
+ for i in range(num_layers)
1065
+ ]
1066
+ )
1067
+ self.final_layer_norm = nn.LayerNorm(hidden_size)
1068
+
1069
+ def forward(
1070
+ self,
1071
+ hidden_states: torch.Tensor,
1072
+ encoder_hidden_states: torch.Tensor = None,
1073
+ self_attention_mask: BlockMask | torch.Tensor = None,
1074
+ cross_attention_mask: BlockMask | torch.Tensor = None,
1075
+ past_key_values: EncoderDecoderCache = None,
1076
+ positions: torch.Tensor = None,
1077
+ ) -> torch.Tensor:
1078
+ for layer in self.layers:
1079
+ hidden_states = layer(
1080
+ hidden_states,
1081
+ encoder_hidden_states=encoder_hidden_states,
1082
+ self_attention_mask=self_attention_mask,
1083
+ cross_attention_mask=cross_attention_mask,
1084
+ past_key_values=past_key_values,
1085
+ positions=positions,
1086
+ )
1087
+ return self.final_layer_norm(hidden_states)
1088
+
1089
+
1090
+ class TransformerDecoderWrapper(nn.Module):
1091
+ def __init__(self, config: str | dict):
1092
+ super().__init__()
1093
+ if not isinstance(config, dict):
1094
+ with open(config, 'r', encoding='utf-8') as file:
1095
+ config = json.load(file)
1096
+ dec_config = config['transf_decoder']['config_dict']
1097
+ hidden_size = dec_config['hidden_size']
1098
+ self._embedding = TransformerDecoderEmbedding(
1099
+ vocab_size=config['vocab_size'],
1100
+ hidden_size=hidden_size,
1101
+ max_sequence_length=dec_config['max_sequence_length'],
1102
+ padding_idx=2,
1103
+ )
1104
+ self._decoder = TransformerDecoderCore(
1105
+ hidden_size=hidden_size,
1106
+ inner_size=dec_config['inner_size'],
1107
+ num_heads=dec_config['num_attention_heads'],
1108
+ num_layers=dec_config['num_layers'],
1109
+ hidden_act=dec_config.get('hidden_act', 'relu'),
1110
+ diffusion=False,
1111
+ )
1112
+ self._lm_head = nn.Linear(hidden_size, config['vocab_size'])
1113
+ self._lm_head.weight = self._embedding.token_embedding.weight
1114
+
1115
+ @torch.no_grad()
1116
+ def load(self, model: str):
1117
+ with safe_open(model, 'pt') as file:
1118
+ for name, param in self.named_parameters():
1119
+ if name.startswith('_lm_head.'):
1120
+ key = 'log_softmax.mlp.layer0.' + name.removeprefix('_lm_head.')
1121
+ else:
1122
+ key = 'transf_decoder.' + name
1123
+ param.copy_(file.get_tensor(key), non_blocking=True)
1124
+ return self
1125
+
1126
+ def forward(
1127
+ self,
1128
+ input_ids: torch.Tensor,
1129
+ positions: torch.Tensor = None,
1130
+ encoder_hidden_states: BlockMask | torch.Tensor = None,
1131
+ self_attention_mask: BlockMask | torch.Tensor = None,
1132
+ cross_attention_mask: BlockMask | torch.Tensor = None,
1133
+ past_key_values: EncoderDecoderCache = None,
1134
+ ) -> torch.Tensor:
1135
+ hidden_states = self._embedding(input_ids, positions)
1136
+ hidden_states = self._decoder(
1137
+ hidden_states,
1138
+ encoder_hidden_states=encoder_hidden_states,
1139
+ self_attention_mask=self_attention_mask,
1140
+ cross_attention_mask=cross_attention_mask,
1141
+ past_key_values=past_key_values,
1142
+ positions=positions,
1143
+ )
1144
+ return self._lm_head(hidden_states)
1145
+
1146
+
1147
+ class CohereAsr(nn.Module):
1148
+ def __init__(self, config: dict | str, pad_id: int = 2, eot_id: int = 3):
1149
+ super().__init__()
1150
+ if not isinstance(config, dict):
1151
+ with open(config, 'r', encoding='utf-8') as file:
1152
+ config = json.load(file)
1153
+ self.encoder = ConformerEncoder(config)
1154
+ self.transf_decoder = TransformerDecoderWrapper(config)
1155
+ dec_config = config['transf_decoder']['config_dict']
1156
+ self.decoder_hidden_size = dec_config['hidden_size']
1157
+ self.diffusion = dec_config.get('diffusion', 0)
1158
+ if self.diffusion > 0:
1159
+ self.diff_decoder = TransformerDecoderCore(
1160
+ hidden_size=self.decoder_hidden_size,
1161
+ inner_size=dec_config['inner_size'],
1162
+ num_heads=dec_config['num_attention_heads'],
1163
+ num_layers=dec_config['num_layers'],
1164
+ hidden_act=dec_config.get('hidden_act', 'relu'),
1165
+ diffusion=True,
1166
+ )
1167
+
1168
+ self.pad_id = pad_id
1169
+ self.eot_id = eot_id
1170
+
1171
+ @torch.no_grad()
1172
+ def load(self, model: str):
1173
+ with safe_open(model, 'pt') as file:
1174
+ for name, param in self.named_parameters():
1175
+ if name.startswith('encoder.encoder_decoder_proj.'):
1176
+ key = name.removeprefix('encoder.')
1177
+ elif name.startswith('transf_decoder._lm_head.'):
1178
+ key = 'log_softmax.mlp.layer0.' + name.removeprefix('transf_decoder._lm_head.')
1179
+ else:
1180
+ key = name
1181
+ param.copy_(file.get_tensor(key), non_blocking=True)
1182
+ return self
1183
+
1184
+ @classmethod
1185
+ def from_pretrained(cls, path: Path, device: torch.device = 'cpu', dtype: torch.dtype = None):
1186
+ path = Path(path)
1187
+ with torch.device('meta'):
1188
+ model = cls(path/'config.json')
1189
+ state = {}
1190
+ with safe_open(path/'model.safetensors', 'pt', device) as file:
1191
+ for key in file.keys():
1192
+ if key.startswith('preprocessor'):
1193
+ continue
1194
+ elif key.startswith('encoder_decoder_proj.'):
1195
+ name = 'encoder.' + key
1196
+ elif key.startswith('log_softmax.mlp.layer0.'):
1197
+ name = 'transf_decoder._lm_head.' + key.removeprefix('log_softmax.mlp.layer0.')
1198
+ else:
1199
+ name = key
1200
+ state[name] = file.get_tensor(key).to(dtype)
1201
+ model.load_state_dict(state, assign=True)
1202
+ model.encoder.pos_enc._materialize_pe(model.encoder.pos_enc.max_len, device, state['encoder.pre_encode.out.weight'].dtype)
1203
+ model.transf_decoder._lm_head.weight = model.transf_decoder._embedding.token_embedding.weight
1204
+ return model.eval()
1205
+
1206
+ def create_block_masks(
1207
+ self,
1208
+ encoder_lengths: torch.Tensor,
1209
+ bsz: int,
1210
+ q_seq_len: int,
1211
+ kv_seq_len: int,
1212
+ device: torch.device,
1213
+ block_size: int = _DEFAULT_SPARSE_BLOCK_SIZE,
1214
+ ) -> tuple[BlockMask, BlockMask]:
1215
+ num_blocks = -(-q_seq_len // block_size)
1216
+ assert num_blocks == 1
1217
+
1218
+ def causal_mask(b, h, q_idx, kv_idx):
1219
+ return kv_idx <= q_idx
1220
+ kv_num_blocks = torch.ones((1, 1, 1), dtype=torch.int32, device=device)
1221
+ kv_indices = torch.zeros((1, 1, 1, 1), dtype=torch.int32, device=device)
1222
+ self_attn_mask = BlockMask.from_kv_blocks(
1223
+ kv_num_blocks=kv_num_blocks,
1224
+ kv_indices=kv_indices,
1225
+ full_kv_num_blocks=None,
1226
+ full_kv_indices=None,
1227
+ BLOCK_SIZE=(block_size, block_size),
1228
+ mask_mod=causal_mask,
1229
+ seq_lengths=(q_seq_len, q_seq_len),
1230
+ compute_q_blocks=False,
1231
+ )
1232
+ encoder_lengths = encoder_lengths.int()
1233
+
1234
+ def cross_mask(b, h, q_idx, kv_idx):
1235
+ return kv_idx < encoder_lengths[b]
1236
+ num_kv_blocks = -(-kv_seq_len // block_size)
1237
+ kv_num_blocks = (encoder_lengths % block_size != 0).int().view(bsz, 1, 1)
1238
+ full_kv_num_blocks = (encoder_lengths // block_size).view(bsz, 1, 1)
1239
+ kv_indices = full_kv_num_blocks.view(bsz, 1, 1, 1).expand(bsz, 1, 1, num_kv_blocks).contiguous()
1240
+ full_kv_indices = torch.arange(num_kv_blocks, dtype=torch.int32, device=device).expand(bsz, 1, 1, num_kv_blocks).contiguous()
1241
+ cross_attn_mask = BlockMask.from_kv_blocks(
1242
+ kv_num_blocks=kv_num_blocks,
1243
+ kv_indices=kv_indices,
1244
+ full_kv_num_blocks=full_kv_num_blocks,
1245
+ full_kv_indices=full_kv_indices,
1246
+ BLOCK_SIZE=(block_size, block_size),
1247
+ mask_mod=cross_mask,
1248
+ seq_lengths=(q_seq_len, kv_seq_len),
1249
+ compute_q_blocks=False,
1250
+ )
1251
+ return self_attn_mask, cross_attn_mask
1252
+
1253
+ def forward(
1254
+ self,
1255
+ input_ids: torch.Tensor,
1256
+ positions: torch.Tensor = None,
1257
+ input_features: torch.Tensor = None,
1258
+ encoder_hidden_states: torch.Tensor = None,
1259
+ lengths: torch.Tensor = None,
1260
+ self_attention_mask: BlockMask | torch.Tensor = None,
1261
+ cross_attention_mask: BlockMask | torch.Tensor = None,
1262
+ past_key_values: EncoderDecoderCache = None,
1263
+ diffusion: bool = False,
1264
+ ) -> torch.Tensor:
1265
+ if encoder_hidden_states is None:
1266
+ encoder_hidden_states, _ = self.encoder(input_features, lengths)
1267
+
1268
+ logits = self.transf_decoder(
1269
+ input_ids=input_ids,
1270
+ positions=positions,
1271
+ encoder_hidden_states=encoder_hidden_states,
1272
+ self_attention_mask=self_attention_mask,
1273
+ cross_attention_mask=cross_attention_mask,
1274
+ past_key_values=past_key_values,
1275
+ diffusion=diffusion,
1276
+ )
1277
+ return logits
1278
+
1279
+ def prepare_cache(
1280
+ self,
1281
+ bsz: int,
1282
+ max_len: int,
1283
+ kv_len: int,
1284
+ device: torch.device,
1285
+ beam_size: int = 1,
1286
+ ) -> EncoderDecoderCache:
1287
+ past_key_values = None
1288
+ if hasattr(self, '_cache'):
1289
+ past_key_values = self._cache
1290
+ if (past_key_values.self_attention_cache.batch_size >= bsz
1291
+ and past_key_values.self_attention_cache.max_cache_len >= max_len
1292
+ and past_key_values.cross_attention_cache.batch_size >= bsz
1293
+ and past_key_values.cross_attention_cache.max_cache_len >= kv_len):
1294
+ past_key_values.reset()
1295
+ past_key_values.self_attention_cache.cur_cache_len = max_len
1296
+ past_key_values.cross_attention_cache.cur_cache_len = kv_len
1297
+ else:
1298
+ past_key_values = None
1299
+
1300
+ if past_key_values is None:
1301
+ attn: DecoderAttention = self.transf_decoder._decoder.layers[0].first_sub_layer
1302
+ cache_kwargs = {
1303
+ 'batch_size': bsz * beam_size,
1304
+ 'max_cache_len': max_len,
1305
+ 'device': device,
1306
+ 'dtype': attn.query_net.weight.dtype,
1307
+ 'num_key_value_heads': attn.num_heads,
1308
+ 'head_dim': attn.head_dim,
1309
+ 'num_hidden_layers': len(self.transf_decoder._decoder.layers),
1310
+ }
1311
+ cross_kwargs = cache_kwargs | {'batch_size': bsz, 'max_cache_len': kv_len}
1312
+ past_key_values = EncoderDecoderCache(Cache(**cache_kwargs), Cache(**cross_kwargs))
1313
+ self._cache = past_key_values
1314
+ return past_key_values
1315
+
1316
+ def _sample(
1317
+ self,
1318
+ input_ids: torch.Tensor,
1319
+ encoder_hidden_states: torch.Tensor,
1320
+ encoder_lengths: torch.Tensor,
1321
+ sample: bool = False,
1322
+ topk: int = 0,
1323
+ temp: float = 1.0,
1324
+ max_len: int = 256,
1325
+ flex_attn: bool = True,
1326
+ block_size: int = _DEFAULT_SPARSE_BLOCK_SIZE,
1327
+ ) -> torch.Tensor:
1328
+ device = input_ids.device
1329
+ bsz, prompt_len = input_ids.shape
1330
+
1331
+ kv_len = encoder_hidden_states.shape[1]
1332
+ input_ids = F.pad(input_ids, (0, max_len - prompt_len), 'constant', self.pad_id)
1333
+ kv_seq_len = torch.zeros((), dtype=torch.int64, device=device)
1334
+ finished = input_ids[:, prompt_len-1] == self.pad_id
1335
+ done = torch.zeros((), dtype=torch.bool, pin_memory=True)
1336
+ event = torch.Event(device)
1337
+ past_key_values = self.prepare_cache(bsz, max_len, kv_len, device)
1338
+
1339
+ if flex_attn:
1340
+ self_attention_mask, cross_attention_mask = self.create_block_masks(
1341
+ encoder_lengths=encoder_lengths,
1342
+ bsz=bsz,
1343
+ q_seq_len=prompt_len,
1344
+ kv_seq_len=kv_len,
1345
+ device=device,
1346
+ block_size=block_size,
1347
+ )
1348
+ assert prompt_len <= block_size
1349
+ else:
1350
+ self_attention_mask = None
1351
+ mask = torch.arange(kv_len, device=device) < encoder_lengths[:, None]
1352
+ cross_attention_mask = mask[:, None, None, :]
1353
+
1354
+ for i in range(prompt_len, max_len):
1355
+ next_ids = input_ids[:, :prompt_len] if i == prompt_len else input_ids[:, i-1:i]
1356
+ logits: torch.Tensor = self.transf_decoder(
1357
+ input_ids=next_ids,
1358
+ positions=kv_seq_len if next_ids.shape[1] == 1 else None,
1359
+ encoder_hidden_states=encoder_hidden_states,
1360
+ self_attention_mask=self_attention_mask,
1361
+ cross_attention_mask=cross_attention_mask,
1362
+ past_key_values=past_key_values,
1363
+ )
1364
+ if sample:
1365
+ if temp != 1.0:
1366
+ logits.div_(temp)
1367
+ if topk != 0:
1368
+ indices_to_remove = logits < torch.topk(logits, topk)[0][..., -1, None]
1369
+ logits.masked_fill_(indices_to_remove, float('-inf'))
1370
+ probs = F.softmax(logits[:, -1, :], dim=1, dtype=torch.float32)
1371
+ new_tokens = torch.multinomial(probs, num_samples=1)[:, 0]
1372
+ else:
1373
+ new_tokens = torch.argmax(logits[:, -1, :], dim=1)
1374
+ new_tokens[finished] = self.pad_id
1375
+
1376
+ if i == prompt_len and flex_attn:
1377
+ def decode_mask(b, h, q_idx, kv_idx):
1378
+ return kv_idx <= kv_seq_len
1379
+ num_blocks = -(-max_len // block_size)
1380
+ kv_num_blocks = torch.ones((bsz, 1, 1), dtype=torch.int32, device=device)
1381
+ kv_indices = torch.zeros((bsz, 1, 1, num_blocks), dtype=torch.int32, device=device)
1382
+ full_kv_num_blocks = torch.zeros((bsz, 1, 1), dtype=torch.int32, device=device)
1383
+ full_kv_indices = torch.arange(num_blocks, dtype=torch.int32, device=device).expand(bsz, 1, 1, num_blocks).contiguous()
1384
+ self_attention_mask = BlockMask.from_kv_blocks(
1385
+ kv_num_blocks=kv_num_blocks,
1386
+ kv_indices=kv_indices,
1387
+ full_kv_num_blocks=full_kv_num_blocks,
1388
+ full_kv_indices=full_kv_indices,
1389
+ BLOCK_SIZE=(1, block_size),
1390
+ mask_mod=decode_mask,
1391
+ seq_lengths=(1, max_len),
1392
+ compute_q_blocks=False,
1393
+ )
1394
+ cross_attention_mask.seq_lengths = 1, kv_len
1395
+ cross_attention_mask.BLOCK_SIZE = 1, cross_attention_mask.BLOCK_SIZE[1]
1396
+ elif i == prompt_len:
1397
+ mask = torch.arange(max_len, device=device) <= prompt_len
1398
+ self_attention_mask = mask[None, None, None, :]
1399
+ else:
1400
+ event.synchronize()
1401
+ if done:
1402
+ break
1403
+
1404
+ finished.logical_or_(new_tokens == self.eot_id)
1405
+ done.copy_(finished.all(), non_blocking=True)
1406
+ event.record()
1407
+ kv_seq_len += next_ids.shape[1]
1408
+ input_ids.index_copy_(1, kv_seq_len, new_tokens[:, None])
1409
+
1410
+ if flex_attn:
1411
+ if (i - 1) % block_size == 0:
1412
+ self_attention_mask.kv_indices += 1
1413
+ self_attention_mask.full_kv_num_blocks += 1
1414
+ self_attention_mask.kv_num_blocks[finished] = 0
1415
+ self_attention_mask.full_kv_num_blocks[finished] = 0
1416
+ cross_attention_mask.kv_num_blocks[finished] = 0
1417
+ cross_attention_mask.full_kv_num_blocks[finished] = 0
1418
+ else:
1419
+ self_attention_mask[:, :, :, kv_seq_len] = True
1420
+
1421
+ return input_ids
1422
+
1423
+ def _beam_search(
1424
+ self,
1425
+ input_ids: torch.Tensor,
1426
+ encoder_hidden_states: torch.Tensor,
1427
+ encoder_lengths: torch.Tensor,
1428
+ beam_size: int = 5,
1429
+ max_len: int = 256,
1430
+ flex_attn: bool = True,
1431
+ block_size: int = _DEFAULT_SPARSE_BLOCK_SIZE,
1432
+ ) -> torch.Tensor:
1433
+ device = input_ids.device
1434
+ bsz, prompt_len = input_ids.shape
1435
+
1436
+ kv_len = encoder_hidden_states.shape[1]
1437
+ flat_size = bsz * beam_size
1438
+ kv_seq_len = torch.zeros((), dtype=torch.int64, device=device)
1439
+ done = torch.zeros((), dtype=torch.bool, pin_memory=True)
1440
+ event = torch.Event(device)
1441
+ past_key_values = self.prepare_cache(bsz, max_len, kv_len, device, beam_size)
1442
+ finish_ids = torch.tensor([self.pad_id, self.eot_id], device=device)
1443
+
1444
+ if flex_attn:
1445
+ self_attention_mask, cross_attention_mask = self.create_block_masks(
1446
+ encoder_lengths=encoder_lengths,
1447
+ bsz=bsz,
1448
+ q_seq_len=prompt_len,
1449
+ kv_seq_len=kv_len,
1450
+ device=device,
1451
+ block_size=block_size,
1452
+ )
1453
+ assert prompt_len <= block_size
1454
+ else:
1455
+ self_attention_mask = None
1456
+ mask = torch.arange(kv_len, device=device) < encoder_lengths[:, None]
1457
+ cross_attention_mask = mask[:, None, None, :]
1458
+
1459
+ for i in range(prompt_len, max_len):
1460
+ next_ids = input_ids if i == prompt_len else input_ids[:, -1:]
1461
+ logits: torch.Tensor = self.transf_decoder(
1462
+ input_ids=next_ids.contiguous(),
1463
+ positions=kv_seq_len if next_ids.shape[1] == 1 else None,
1464
+ encoder_hidden_states=encoder_hidden_states,
1465
+ self_attention_mask=self_attention_mask,
1466
+ cross_attention_mask=cross_attention_mask,
1467
+ past_key_values=past_key_values,
1468
+ )
1469
+ logprobs = F.log_softmax(logits[:, -1, :], dim=1, dtype=torch.float32)
1470
+
1471
+ if i == prompt_len:
1472
+ if flex_attn:
1473
+ def decode_mask(b, h, q_idx, kv_idx):
1474
+ return kv_idx <= kv_seq_len
1475
+ num_blocks = -(-max_len // block_size)
1476
+ kv_num_blocks = torch.ones((flat_size, 1, 1), dtype=torch.int32, device=device)
1477
+ kv_indices = torch.zeros((flat_size, 1, 1, num_blocks), dtype=torch.int32, device=device)
1478
+ full_kv_num_blocks = torch.zeros((flat_size, 1, 1), dtype=torch.int32, device=device)
1479
+ full_kv_indices = torch.arange(num_blocks, dtype=torch.int32, device=device).expand(flat_size, 1, 1, num_blocks).contiguous()
1480
+ self_attention_mask = BlockMask.from_kv_blocks(
1481
+ kv_num_blocks=kv_num_blocks,
1482
+ kv_indices=kv_indices,
1483
+ full_kv_num_blocks=full_kv_num_blocks,
1484
+ full_kv_indices=full_kv_indices,
1485
+ BLOCK_SIZE=(1, block_size),
1486
+ mask_mod=decode_mask,
1487
+ seq_lengths=(1, max_len),
1488
+ compute_q_blocks=False,
1489
+ )
1490
+ cross_attention_mask.seq_lengths = 1, kv_len
1491
+ cross_attention_mask.BLOCK_SIZE = 1, cross_attention_mask.BLOCK_SIZE[1]
1492
+ else:
1493
+ mask = torch.arange(max_len, device=device) <= prompt_len
1494
+ self_attention_mask = mask[None, None, None, :]
1495
+
1496
+ scores, new_tokens = torch.topk(logprobs, k=beam_size, dim=1)
1497
+ new_indices = torch.arange(bsz, device=device).repeat_interleave(beam_size, dim=0)
1498
+
1499
+ else:
1500
+ event.synchronize()
1501
+ if done:
1502
+ break
1503
+ vocab_size = logprobs.shape[1]
1504
+ logprobs[finished] = 0
1505
+ batch_logprobs = (logprobs + scores.view(-1, 1)).view(bsz, -1)
1506
+ scores, topk_indices = torch.topk(batch_logprobs, k=beam_size, dim=1)
1507
+ new_indices = topk_indices // vocab_size
1508
+ new_indices += torch.arange(0, flat_size, beam_size, device=device)[:, None]
1509
+ new_indices = new_indices.flatten()
1510
+ new_tokens = topk_indices % vocab_size
1511
+
1512
+ input_ids = input_ids[new_indices]
1513
+ finished = torch.isin(input_ids[:, -1].view(bsz, beam_size), finish_ids)
1514
+ finished[finished[:, 0]] = True
1515
+ new_tokens[finished] = self.pad_id
1516
+ input_ids = torch.cat((input_ids, new_tokens.view(-1, 1)), dim=1)
1517
+ finished = torch.isin(input_ids[:, -1], finish_ids)
1518
+ done.copy_(finished.all(), non_blocking=True)
1519
+ event.record()
1520
+ past_key_values.self_attention_cache.reorder(new_indices, finished, i)
1521
+ kv_seq_len += next_ids.shape[1]
1522
+
1523
+ if flex_attn:
1524
+ if (i - 1) % block_size == 0:
1525
+ self_attention_mask.kv_indices += 1
1526
+ self_attention_mask.full_kv_num_blocks += 1
1527
+ self_attention_mask.kv_num_blocks[finished] = 0
1528
+ self_attention_mask.full_kv_num_blocks[finished] = 0
1529
+ cross_finished = finished.view(bsz, beam_size).all(dim=1)
1530
+ cross_attention_mask.kv_num_blocks[cross_finished] = 0
1531
+ cross_attention_mask.full_kv_num_blocks[cross_finished] = 0
1532
+ else:
1533
+ self_attention_mask[:, :, :, kv_seq_len] = True
1534
+
1535
+ return input_ids.view(bsz, beam_size, -1)[:, 0, :]
1536
+
1537
+ def _spec_forward(
1538
+ self,
1539
+ input_ids: torch.LongTensor, # [b,1]
1540
+ encoder_hidden_states: torch.Tensor, # [b,t,d]
1541
+ cross_attention_mask: BlockMask,
1542
+ diff_attention_mask: BlockMask,
1543
+ self_attention_mask: BlockMask,
1544
+ past_key_values: EncoderDecoderCache,
1545
+ finished: torch.BoolTensor, # [b]
1546
+ kv_seq_len: torch.IntTensor, # []
1547
+ diff_len: int,
1548
+ ) -> tuple[torch.LongTensor, torch.IntTensor]:
1549
+ device = input_ids.device
1550
+ kv_len = encoder_hidden_states.shape[1]
1551
+ cross_attention_mask.seq_lengths = diff_len, kv_len
1552
+ cross_attention_mask.BLOCK_SIZE = diff_len, cross_attention_mask.BLOCK_SIZE[1]
1553
+
1554
+ positions = torch.arange(diff_len, device=device) + kv_seq_len
1555
+ diff_states = self.transf_decoder._embedding(
1556
+ input_ids=F.pad(input_ids, (0, diff_len - 1), 'constant', self.pad_id),
1557
+ positions=positions,
1558
+ )
1559
+ diff_states = self.diff_decoder(
1560
+ hidden_states=diff_states,
1561
+ encoder_hidden_states=encoder_hidden_states,
1562
+ self_attention_mask=diff_attention_mask,
1563
+ cross_attention_mask=cross_attention_mask,
1564
+ past_key_values=past_key_values,
1565
+ positions=positions,
1566
+ )
1567
+ diff_logits = self.transf_decoder._lm_head(diff_states)
1568
+ diff_tokens = torch.argmax(diff_logits, dim=2)
1569
+ diff_eot = (diff_tokens == self.eot_id).int()
1570
+ diff_pad = diff_eot.cumsum(dim=1) - diff_eot > 0
1571
+ diff_tokens[finished[:, None] | diff_pad] = self.pad_id
1572
+
1573
+ cross_attention_mask.seq_lengths = diff_len + 1, kv_len
1574
+ cross_attention_mask.BLOCK_SIZE = diff_len + 1, cross_attention_mask.BLOCK_SIZE[1]
1575
+ ar_logits = self.transf_decoder(
1576
+ input_ids=torch.cat((input_ids, diff_tokens), dim=1),
1577
+ positions=torch.arange(diff_len + 1, device=device) + kv_seq_len,
1578
+ encoder_hidden_states=encoder_hidden_states,
1579
+ self_attention_mask=self_attention_mask,
1580
+ cross_attention_mask=cross_attention_mask,
1581
+ past_key_values=past_key_values,
1582
+ )
1583
+ ar_tokens = torch.argmax(ar_logits, dim=2)
1584
+ ar_eot = (ar_tokens == self.eot_id).int()
1585
+ ar_pad = ar_eot.cumsum(dim=1) - ar_eot > 0
1586
+ ar_tokens[finished[:, None] | ar_pad] = self.pad_id
1587
+
1588
+ matches = (diff_tokens == ar_tokens[:, :-1]).int().cumprod(dim=1)
1589
+ match_len = matches.sum(dim=1).min() + 1
1590
+ return ar_tokens, match_len
1591
+
1592
+ def _speculate(
1593
+ self,
1594
+ input_ids: torch.Tensor,
1595
+ encoder_hidden_states: torch.Tensor,
1596
+ encoder_lengths: torch.Tensor,
1597
+ max_len: int = 256,
1598
+ block_size: int = _DEFAULT_SPARSE_BLOCK_SIZE,
1599
+ compile: bool = False,
1600
+ compile_options: dict = {},
1601
+ ) -> torch.Tensor:
1602
+ device = input_ids.device
1603
+ bsz, prompt_len = input_ids.shape
1604
+ _spec_forward = (torch.compile(self._spec_forward, **compile_options)
1605
+ if compile else self._spec_forward)
1606
+
1607
+ kv_len = encoder_hidden_states.shape[1]
1608
+ input_ids = F.pad(input_ids, (0, max_len - prompt_len), 'constant', self.pad_id)
1609
+ finished = input_ids[:, prompt_len-1] == self.pad_id
1610
+ diff_len = self.diffusion
1611
+ cache_len = max_len + diff_len
1612
+ past_key_values = self.prepare_cache(bsz, cache_len, kv_len, device)
1613
+
1614
+ self_attention_mask, cross_attention_mask = self.create_block_masks(
1615
+ encoder_lengths=encoder_lengths,
1616
+ bsz=bsz,
1617
+ q_seq_len=prompt_len,
1618
+ kv_seq_len=kv_len,
1619
+ device=device,
1620
+ block_size=block_size,
1621
+ )
1622
+ assert prompt_len + diff_len <= block_size
1623
+
1624
+ # prefill
1625
+ logits: torch.Tensor = self.transf_decoder(
1626
+ input_ids=input_ids[:, :prompt_len],
1627
+ positions=None,
1628
+ encoder_hidden_states=encoder_hidden_states,
1629
+ self_attention_mask=self_attention_mask,
1630
+ cross_attention_mask=cross_attention_mask,
1631
+ past_key_values=past_key_values,
1632
+ )
1633
+ new_tokens = torch.argmax(logits[:, -1, :], dim=1)
1634
+ finished.logical_or_(new_tokens == self.eot_id)
1635
+ kv_seq_len = torch.full((), prompt_len, dtype=torch.int64, device=device)
1636
+ input_ids[:, prompt_len] = new_tokens
1637
+
1638
+ # decode
1639
+ num_blocks = -(-cache_len // block_size)
1640
+
1641
+ def diff_mask(b, h, q_idx, kv_idx):
1642
+ return kv_idx <= kv_seq_len + diff_len
1643
+ kv_num_blocks = torch.ones((bsz, 1, 1), dtype=torch.int32, device=device)
1644
+ kv_indices = torch.arange(num_blocks, dtype=torch.int32, device=device).expand(bsz, 1, 1, num_blocks).contiguous()
1645
+ full_kv_num_blocks = torch.zeros((bsz, 1, 1), dtype=torch.int32, device=device)
1646
+ full_kv_indices = torch.arange(num_blocks, dtype=torch.int32, device=device).expand(bsz, 1, 1, num_blocks).contiguous()
1647
+ diff_attention_mask = BlockMask.from_kv_blocks(
1648
+ kv_num_blocks=kv_num_blocks,
1649
+ kv_indices=kv_indices,
1650
+ full_kv_num_blocks=full_kv_num_blocks,
1651
+ full_kv_indices=full_kv_indices,
1652
+ BLOCK_SIZE=(diff_len, block_size),
1653
+ mask_mod=diff_mask,
1654
+ seq_lengths=(diff_len, cache_len),
1655
+ compute_q_blocks=False,
1656
+ )
1657
+
1658
+ def decode_mask(b, h, q_idx, kv_idx):
1659
+ return kv_idx <= kv_seq_len + q_idx
1660
+ kv_num_blocks = torch.ones((bsz, 1, 1), dtype=torch.int32, device=device)
1661
+ kv_indices = torch.arange(num_blocks, dtype=torch.int32, device=device).expand(bsz, 1, 1, num_blocks).contiguous()
1662
+ self_attention_mask = BlockMask.from_kv_blocks(
1663
+ kv_num_blocks=kv_num_blocks,
1664
+ kv_indices=kv_indices,
1665
+ full_kv_num_blocks=None,
1666
+ full_kv_indices=None,
1667
+ BLOCK_SIZE=(diff_len + 1, block_size),
1668
+ mask_mod=decode_mask,
1669
+ seq_lengths=(diff_len + 1, cache_len),
1670
+ compute_q_blocks=False,
1671
+ )
1672
+
1673
+ i = prompt_len + 1
1674
+ while i < max_len:
1675
+ ar_tokens, match_len = _spec_forward(
1676
+ input_ids=input_ids[:, i-1:i],
1677
+ encoder_hidden_states=encoder_hidden_states,
1678
+ cross_attention_mask=cross_attention_mask,
1679
+ diff_attention_mask=diff_attention_mask,
1680
+ self_attention_mask=self_attention_mask,
1681
+ past_key_values=past_key_values,
1682
+ finished=finished,
1683
+ kv_seq_len=kv_seq_len,
1684
+ diff_len=diff_len,
1685
+ )
1686
+ new_len = min(match_len.item(), max_len - i)
1687
+ new_tokens = ar_tokens[:, :new_len]
1688
+ input_ids[:, i:i+new_len] = new_tokens
1689
+ finished.logical_or_(torch.any(new_tokens == self.eot_id, dim=1))
1690
+ if finished.all():
1691
+ break
1692
+
1693
+ diff_i = i + diff_len
1694
+ if diff_i // block_size < (diff_i + new_len) // block_size:
1695
+ diff_attention_mask.kv_indices += 1
1696
+ diff_attention_mask.full_kv_num_blocks += 1
1697
+ self_attention_mask.kv_num_blocks += 1
1698
+ diff_attention_mask.kv_num_blocks[finished] = 0
1699
+ diff_attention_mask.full_kv_num_blocks[finished] = 0
1700
+ self_attention_mask.kv_num_blocks[finished] = 0
1701
+ cross_attention_mask.kv_num_blocks[finished] = 0
1702
+ cross_attention_mask.full_kv_num_blocks[finished] = 0
1703
+ kv_seq_len += match_len
1704
+ i += new_len
1705
+
1706
+ return input_ids
1707
+
1708
+ @torch.no_grad()
1709
+ def generate(
1710
+ self,
1711
+ input_ids: torch.Tensor,
1712
+ input_features: torch.Tensor = None,
1713
+ lengths: torch.Tensor = None,
1714
+ encoder_hidden_states: torch.Tensor = None,
1715
+ sample: bool = False,
1716
+ topk: int = 0,
1717
+ temp: float = 1.0,
1718
+ beam_size: int = 1,
1719
+ max_len: int = 256,
1720
+ flex_attn: bool = True,
1721
+ block_size: int = _DEFAULT_SPARSE_BLOCK_SIZE,
1722
+ compile: bool = False,
1723
+ compile_options: dict = {'mode': 'reduce-overhead', 'fullgraph': True, 'dynamic': False},
1724
+ diffusion: bool = False,
1725
+ ) -> torch.Tensor:
1726
+ if compile:
1727
+ self.encoder.compile(**compile_options)
1728
+ self.transf_decoder.compile(**compile_options)
1729
+ if encoder_hidden_states is None:
1730
+ encoder_hidden_states, encoder_lengths = self.encoder(input_features, lengths)
1731
+ encoder_hidden_states = encoder_hidden_states.clone()
1732
+ else:
1733
+ encoder_lengths = lengths
1734
+
1735
+ if diffusion:
1736
+ if sample or beam_size != 1 or not flex_attn or not self.diffusion:
1737
+ raise NotImplementedError()
1738
+ return self._speculate(
1739
+ input_ids=input_ids,
1740
+ encoder_hidden_states=encoder_hidden_states,
1741
+ encoder_lengths=encoder_lengths,
1742
+ max_len=max_len,
1743
+ block_size=block_size,
1744
+ compile=compile,
1745
+ compile_options=compile_options,
1746
+ )
1747
+ if beam_size != 1:
1748
+ if sample:
1749
+ raise NotImplementedError()
1750
+ return self._beam_search(
1751
+ input_ids=input_ids,
1752
+ encoder_hidden_states=encoder_hidden_states,
1753
+ encoder_lengths=encoder_lengths,
1754
+ beam_size=beam_size,
1755
+ max_len=max_len,
1756
+ flex_attn=flex_attn,
1757
+ block_size=block_size,
1758
+ )
1759
+ return self._sample(
1760
+ input_ids=input_ids,
1761
+ encoder_hidden_states=encoder_hidden_states,
1762
+ encoder_lengths=encoder_lengths,
1763
+ sample=sample,
1764
+ topk=topk,
1765
+ temp=temp,
1766
+ max_len=max_len,
1767
+ flex_attn=flex_attn,
1768
+ block_size=block_size,
1769
+ )
config.json ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "CohereAsrForConditionalGeneration"
4
+ ],
5
+ "auto_map": {
6
+ "AutoConfig": "configuration_cohere_asr.CohereAsrConfig",
7
+ "AutoFeatureExtractor": "processing_cohere_asr.CohereAsrFeatureExtractor",
8
+ "AutoModel": "modeling_cohere_asr.CohereAsrModel",
9
+ "AutoModelForSpeechSeq2Seq": "modeling_cohere_asr.CohereAsrForConditionalGeneration",
10
+ "AutoProcessor": "processing_cohere_asr.CohereAsrProcessor",
11
+ "AutoTokenizer": "tokenization_cohere_asr.CohereAsrTokenizer"
12
+ },
13
+ "batch_size": 128,
14
+ "decoding": {
15
+ "beam": {
16
+ "beam_size": 1,
17
+ "len_pen": 0.0,
18
+ "max_generation_delta": 50
19
+ },
20
+ "return_best_hypothesis": true,
21
+ "strategy": "beam"
22
+ },
23
+ "encoder": {
24
+ "att_context_size": [
25
+ -1,
26
+ -1
27
+ ],
28
+ "causal_downsampling": false,
29
+ "conv_context_size": null,
30
+ "conv_kernel_size": 9,
31
+ "conv_norm_type": "batch_norm",
32
+ "d_model": 1280,
33
+ "dropout": 0,
34
+ "dropout_att": 0,
35
+ "dropout_emb": 0,
36
+ "dropout_pre_encoder": 0,
37
+ "feat_in": 128,
38
+ "feat_out": -1,
39
+ "ff_expansion_factor": 4,
40
+ "n_heads": 8,
41
+ "n_layers": 48,
42
+ "pos_emb_max_len": 5000,
43
+ "reduction": null,
44
+ "reduction_factor": 1,
45
+ "reduction_position": null,
46
+ "self_attention_model": "rel_pos",
47
+ "subsampling": "dw_striding",
48
+ "subsampling_conv_channels": 256,
49
+ "subsampling_factor": 8,
50
+ "untie_biases": true,
51
+ "xscaling": false
52
+ },
53
+ "head": {
54
+ "activation": "relu",
55
+ "dropout": 0,
56
+ "hidden_size": 1024,
57
+ "log_softmax": true,
58
+ "num_classes": 16384,
59
+ "num_layers": 1,
60
+ "use_transformer_init": true
61
+ },
62
+ "is_encoder_decoder": true,
63
+ "log_batch_stats": false,
64
+ "log_prediction": true,
65
+ "max_audio_clip_s": 35,
66
+ "max_seq_len": 1024,
67
+ "model_defaults": {
68
+ "asr_enc_hidden": 1280,
69
+ "lm_dec_hidden": 1024,
70
+ "lm_enc_hidden": 1024
71
+ },
72
+ "model_type": "cohere_asr",
73
+ "multitask_metrics_cfg": {
74
+ "log_predictions": true,
75
+ "metrics": {
76
+ "wer": {
77
+ "constraint": ".source_lang==.target_lang"
78
+ }
79
+ }
80
+ },
81
+ "overlap_chunk_second": 5,
82
+ "preprocessor": {
83
+ "dither": 1e-05,
84
+ "features": 128,
85
+ "frame_splicing": 1,
86
+ "log": true,
87
+ "n_fft": 512,
88
+ "normalize": "per_feature",
89
+ "pad_to": 0,
90
+ "pad_value": 0.0,
91
+ "sample_rate": 16000,
92
+ "window": "hann",
93
+ "window_size": 0.025,
94
+ "window_stride": 0.01
95
+ },
96
+ "prompt_defaults": [
97
+ {
98
+ "role": "user",
99
+ "slots": {
100
+ "decodercontext": "",
101
+ "diarize": "<|nodiarize|>",
102
+ "emotion": "<|emo:undefined|>",
103
+ "itn": "<|noitn|>",
104
+ "pnc": "<|pnc|>",
105
+ "source_lang": "<|en|>",
106
+ "target_lang": "<|en|>",
107
+ "timestamp": "<|notimestamp|>"
108
+ }
109
+ },
110
+ {
111
+ "role": "user_partial",
112
+ "slots": {
113
+ "decodercontext": ""
114
+ }
115
+ }
116
+ ],
117
+ "prompt_format": "cohere_asr",
118
+ "sample_rate": 16000,
119
+ "supported_languages": [
120
+ "en",
121
+ "fr",
122
+ "de",
123
+ "es",
124
+ "it",
125
+ "pt",
126
+ "nl",
127
+ "pl",
128
+ "el",
129
+ "ar",
130
+ "ja",
131
+ "zh",
132
+ "vi",
133
+ "ko"
134
+ ],
135
+ "transf_decoder": {
136
+ "config_dict": {
137
+ "attn_layer_dropout": 0,
138
+ "attn_score_dropout": 0,
139
+ "diffusion": 32,
140
+ "embedding_dropout": 0,
141
+ "ffn_dropout": 0,
142
+ "hidden_act": "relu",
143
+ "hidden_size": 1024,
144
+ "inner_size": 4096,
145
+ "learn_positional_encodings": false,
146
+ "lm_dec_hidden": 1280,
147
+ "max_sequence_length": 1024,
148
+ "num_attention_heads": 8,
149
+ "num_layers": 8,
150
+ "num_token_types": 0,
151
+ "pre_ln": true,
152
+ "vocab_size": "None"
153
+ },
154
+ "encoder": null,
155
+ "model_name": null,
156
+ "pre_ln_final_layer_norm": true,
157
+ "pretrained": false
158
+ },
159
+ "transf_encoder": {
160
+ "attn_layer_dropout": 0,
161
+ "attn_score_dropout": 0,
162
+ "ffn_dropout": 0,
163
+ "hidden_size": 1024,
164
+ "inner_size": 4096,
165
+ "mask_future": false,
166
+ "num_attention_heads": 8,
167
+ "num_layers": 0,
168
+ "pre_ln": true,
169
+ "pre_ln_final_layer_norm": true
170
+ },
171
+ "use_loss_mask_for_prompt": false,
172
+ "vocab_size": 16384
173
+ }
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4e683346a1a0c860342513dfb775add615b6e83375a5d73e2b4fa197e14d185c
3
+ size 4367048880
tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
train.py ADDED
@@ -0,0 +1,520 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import logging
3
+ import math
4
+ import os
5
+ import time
6
+ from functools import partial
7
+ from pathlib import Path
8
+
9
+ import torch
10
+ import torch.nn.functional as F
11
+ from huggingface_hub import HfApi
12
+ from safetensors import safe_open
13
+ from torch import nn
14
+ from torch.nn.attention.flex_attention import BlockMask, create_block_mask, flex_attention
15
+ from torch.utils.tensorboard import SummaryWriter
16
+ from tqdm.auto import tqdm
17
+
18
+ LOGGER = logging.getLogger(__name__)
19
+ HF_TOKEN = os.environ['HF_TOKEN']
20
+ API = HfApi(token=HF_TOKEN)
21
+
22
+
23
+ class FixedPositionalEncoding(nn.Module):
24
+ def __init__(self, hidden_size, max_sequence_length=512):
25
+ super().__init__()
26
+ self.hidden_size = hidden_size
27
+ self.max_sequence_length = max_sequence_length
28
+
29
+ pos_enc = torch.zeros(max_sequence_length, hidden_size)
30
+ position = torch.arange(0.0, max_sequence_length).unsqueeze(1)
31
+ coef = -math.log(10000.0) / hidden_size
32
+ div_term = torch.exp(coef * torch.arange(0.0, hidden_size, 2))
33
+ pos_enc[:, 0::2] = torch.sin(position * div_term)
34
+ pos_enc[:, 1::2] = torch.cos(position * div_term)
35
+ pos_enc.div_(math.sqrt(hidden_size))
36
+ self.register_buffer('pos_enc', pos_enc)
37
+
38
+ def forward(self, position_ids):
39
+ return torch.index_select(self.pos_enc, 0, position_ids.reshape(-1)).reshape(*position_ids.shape, -1)
40
+
41
+
42
+ class DecoderAttention(nn.Module):
43
+ def __init__(self, hidden_size, num_heads, layer_idx, kv=True):
44
+ super().__init__()
45
+ self.hidden_size = hidden_size
46
+ self.num_heads = num_heads
47
+ self.layer_idx = layer_idx
48
+ self.head_dim = hidden_size // num_heads
49
+ self.scale = self.head_dim**-0.5
50
+ self.query_net = nn.Linear(hidden_size, hidden_size)
51
+ if kv:
52
+ self.key_net = nn.Linear(hidden_size, hidden_size)
53
+ self.value_net = nn.Linear(hidden_size, hidden_size)
54
+ self.out_projection = nn.Linear(hidden_size, hidden_size)
55
+
56
+ def _reshape(self, x):
57
+ b, t, _ = x.shape
58
+ return x.view(b, t, self.num_heads, self.head_dim).transpose(1, 2)
59
+
60
+ def forward(
61
+ self,
62
+ hidden_states,
63
+ context_states=None,
64
+ attention_mask=None,
65
+ past_key_values=None,
66
+ diffusion=False,
67
+ ):
68
+ self_attn = context_states is None
69
+ name = 'self' if self_attn else 'cross'
70
+ if self_attn:
71
+ context_states = hidden_states
72
+ bsz, tgt_len, _ = hidden_states.size()
73
+ query = self._reshape(self.query_net(hidden_states))
74
+
75
+ if diffusion:
76
+ ar_key = past_key_values[f'{self.layer_idx}.{name}.key']
77
+ ar_value = past_key_values[f'{self.layer_idx}.{name}.value']
78
+ if self_attn:
79
+ diff_key = self._reshape(self.key_net(context_states))
80
+ diff_value = self._reshape(self.value_net(context_states))
81
+ key = torch.cat((ar_key, diff_key), dim=2)
82
+ value = torch.cat((ar_value, diff_value), dim=2)
83
+ else:
84
+ key = ar_key
85
+ value = ar_value
86
+ else:
87
+ key = self._reshape(self.key_net(context_states))
88
+ value = self._reshape(self.value_net(context_states))
89
+ past_key_values[f'{self.layer_idx}.{name}.key'] = key
90
+ past_key_values[f'{self.layer_idx}.{name}.value'] = value
91
+
92
+ attn_output = flex_attention(query, key, value, block_mask=attention_mask, scale=self.scale)
93
+ attn_output = attn_output.transpose(1, 2).reshape(bsz, tgt_len, self.hidden_size)
94
+ return self.out_projection(attn_output)
95
+
96
+
97
+ class DecoderFeedForward(nn.Module):
98
+ def __init__(self, hidden_size, inner_size, hidden_act='relu'):
99
+ super().__init__()
100
+ self.dense_in = nn.Linear(hidden_size, inner_size)
101
+ assert hidden_act == 'relu'
102
+ self.activation = nn.ReLU()
103
+ self.dense_out = nn.Linear(inner_size, hidden_size)
104
+
105
+ def forward(self, x):
106
+ return self.dense_out(self.activation(self.dense_in(x)))
107
+
108
+
109
+ class TransformerDecoderLayer(nn.Module):
110
+ def __init__(self, hidden_size, inner_size, num_heads, diffusion, layer_idx, hidden_act='relu'):
111
+ super().__init__()
112
+ self.layer_norm_1 = nn.LayerNorm(hidden_size)
113
+ self.first_sub_layer = DecoderAttention(hidden_size, num_heads, layer_idx=layer_idx)
114
+ self.layer_norm_2 = nn.LayerNorm(hidden_size)
115
+ self.second_sub_layer = DecoderAttention(hidden_size, num_heads, layer_idx=layer_idx, kv=not diffusion)
116
+ self.layer_norm_3 = nn.LayerNorm(hidden_size)
117
+ self.third_sub_layer = DecoderFeedForward(hidden_size, inner_size, hidden_act=hidden_act)
118
+
119
+ def forward(
120
+ self,
121
+ hidden_states,
122
+ encoder_hidden_states=None,
123
+ self_attention_mask=None,
124
+ cross_attention_mask=None,
125
+ past_key_values=None,
126
+ diffusion=False,
127
+ ):
128
+ residual = hidden_states
129
+ hidden_states = self.layer_norm_1(hidden_states)
130
+ self_out = self.first_sub_layer(
131
+ hidden_states,
132
+ context_states=None,
133
+ attention_mask=self_attention_mask,
134
+ past_key_values=past_key_values,
135
+ diffusion=diffusion,
136
+ )
137
+ hidden_states = residual + self_out
138
+
139
+ residual = hidden_states
140
+ hidden_states = self.layer_norm_2(hidden_states)
141
+ cross_out = self.second_sub_layer(
142
+ hidden_states,
143
+ context_states=encoder_hidden_states,
144
+ attention_mask=cross_attention_mask,
145
+ past_key_values=past_key_values,
146
+ diffusion=diffusion,
147
+ )
148
+ hidden_states = residual + cross_out
149
+
150
+ residual = hidden_states
151
+ hidden_states = self.layer_norm_3(hidden_states)
152
+ hidden_states = residual + self.third_sub_layer(hidden_states)
153
+ return hidden_states
154
+
155
+
156
+ class TransformerDecoderEmbedding(nn.Module):
157
+ def __init__(self, vocab_size, hidden_size, max_sequence_length, padding_idx=2):
158
+ super().__init__()
159
+ self.token_embedding = nn.Embedding(vocab_size, hidden_size, padding_idx)
160
+ self.position_embedding = FixedPositionalEncoding(hidden_size, max_sequence_length)
161
+ self.layer_norm = nn.LayerNorm(hidden_size)
162
+
163
+ def forward(self, input_ids, positions):
164
+ token_embeds = self.token_embedding(input_ids)
165
+ if positions is None:
166
+ pos_embeds = self.position_embedding.pos_enc[:input_ids.shape[-1]]
167
+ else:
168
+ pos_embeds = self.position_embedding(positions)
169
+ return self.layer_norm(token_embeds + pos_embeds)
170
+
171
+
172
+ class TransformerDecoderCore(nn.Module):
173
+ def __init__(self, hidden_size, inner_size, num_heads, num_layers, diffusion, hidden_act='relu'):
174
+ super().__init__()
175
+ self.layers = nn.ModuleList(
176
+ [
177
+ TransformerDecoderLayer(hidden_size, inner_size, num_heads, diffusion, layer_idx=i, hidden_act=hidden_act)
178
+ for i in range(num_layers)
179
+ ]
180
+ )
181
+ self.final_layer_norm = nn.LayerNorm(hidden_size)
182
+
183
+ def forward(
184
+ self,
185
+ hidden_states,
186
+ encoder_hidden_states=None,
187
+ self_attention_mask=None,
188
+ cross_attention_mask=None,
189
+ past_key_values=None,
190
+ diffusion=False
191
+ ):
192
+ for layer in self.layers:
193
+ hidden_states = layer(
194
+ hidden_states,
195
+ encoder_hidden_states=encoder_hidden_states,
196
+ self_attention_mask=self_attention_mask,
197
+ cross_attention_mask=cross_attention_mask,
198
+ past_key_values=past_key_values,
199
+ diffusion=diffusion,
200
+ )
201
+ return self.final_layer_norm(hidden_states)
202
+
203
+
204
+ class TransformerDecoderWrapper(nn.Module):
205
+ def __init__(self, config, diffusion=False):
206
+ super().__init__()
207
+ if not isinstance(config, dict):
208
+ with open(config, 'r', encoding='utf-8') as file:
209
+ config = json.load(file)
210
+ dec_config = config['transf_decoder']['config_dict']
211
+ hidden_size = dec_config['hidden_size']
212
+ self._embedding = TransformerDecoderEmbedding(
213
+ vocab_size=config['vocab_size'],
214
+ hidden_size=hidden_size,
215
+ max_sequence_length=dec_config['max_sequence_length'],
216
+ padding_idx=2,
217
+ )
218
+ self._decoder = TransformerDecoderCore(
219
+ hidden_size=hidden_size,
220
+ inner_size=dec_config['inner_size'],
221
+ num_heads=dec_config['num_attention_heads'],
222
+ num_layers=dec_config['num_layers'],
223
+ diffusion=diffusion,
224
+ hidden_act=dec_config.get('hidden_act', 'relu'),
225
+ )
226
+ self.diffusion = diffusion
227
+ self._lm_head = nn.Linear(hidden_size, config['vocab_size'])
228
+ self._lm_head.weight = self._embedding.token_embedding.weight
229
+
230
+ def load(self, model: str):
231
+ state = {}
232
+ with safe_open(model, 'pt') as file:
233
+ for key in file.keys():
234
+ if self.diffusion and ('.second_sub_layer.key_net.' in key or '.second_sub_layer.value_net.' in key):
235
+ continue
236
+ elif key.startswith('transf_decoder.'):
237
+ state[key.removeprefix('transf_decoder.')] = file.get_tensor(key)
238
+ elif key == 'log_softmax.mlp.layer0.bias':
239
+ state['_lm_head.bias'] = file.get_tensor(key)
240
+ elif key == 'log_softmax.mlp.layer0.weight':
241
+ state['_lm_head.weight'] = file.get_tensor(key)
242
+ self.load_state_dict(state)
243
+ return self
244
+
245
+ def forward(
246
+ self,
247
+ input_ids,
248
+ positions=None,
249
+ encoder_hidden_states=None,
250
+ self_attention_mask=None,
251
+ cross_attention_mask=None,
252
+ past_key_values=None,
253
+ diffusion=False
254
+ ):
255
+ hidden_states = self._embedding(input_ids, positions)
256
+ hidden_states = self._decoder(
257
+ hidden_states,
258
+ encoder_hidden_states=encoder_hidden_states,
259
+ self_attention_mask=self_attention_mask,
260
+ cross_attention_mask=cross_attention_mask,
261
+ past_key_values=past_key_values,
262
+ diffusion=diffusion,
263
+ )
264
+ return self._lm_head(hidden_states)
265
+
266
+
267
+ def cosine_schedule(step: int, *, warmup_steps: int, max_steps: int) -> float:
268
+ if step < warmup_steps:
269
+ return step / warmup_steps
270
+ progress = (step - warmup_steps) / (max_steps - warmup_steps)
271
+ return 0.5 * (1 + math.cos(math.pi * progress))
272
+
273
+
274
+ @torch.no_grad()
275
+ def load(model_id: str, hub_id: str, warmup_steps: int, max_steps: int, output_dir: Path) -> tuple[
276
+ int,
277
+ TransformerDecoderWrapper,
278
+ TransformerDecoderCore,
279
+ torch.optim.AdamW,
280
+ torch.optim.lr_scheduler.LambdaLR,
281
+ ]:
282
+ config = API.hf_hub_download(model_id, 'config.json')
283
+ teacher = TransformerDecoderWrapper(config).to(device='cuda', dtype=torch.bfloat16).eval()
284
+ student = TransformerDecoderWrapper(config, diffusion=True).to(device='cuda', dtype=torch.bfloat16)
285
+ model = API.hf_hub_download(model_id, 'model.safetensors')
286
+ teacher.load(model)
287
+ student.load(model)
288
+ student = student._decoder
289
+ teacher.requires_grad_(False)
290
+ cosine_lr = partial(cosine_schedule, warmup_steps=warmup_steps, max_steps=max_steps)
291
+
292
+ decay_params = []
293
+ no_decay_params = []
294
+ for param in student.parameters():
295
+ if param.ndim < 2:
296
+ no_decay_params.append(param)
297
+ else:
298
+ decay_params.append(param)
299
+ optimizer = torch.optim.AdamW([
300
+ {'params': decay_params, 'weight_decay': 0.01},
301
+ {'params': no_decay_params, 'weight_decay': 0.0},
302
+ ], lr=4e-3, betas=(0.9, 0.98), eps=1e-8)
303
+ scheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, cosine_lr)
304
+
305
+ cur_step = 0
306
+ checkpoints = [x.path for x in API.list_bucket_tree(hub_id) if x.path.endswith('.pt')]
307
+ checkpoints.sort(key=lambda x: int(x.split('.')[0]))
308
+ if checkpoints:
309
+ checkpoint = checkpoints[-1]
310
+ LOGGER.info('Checkpoint found %s', checkpoint)
311
+ API.download_bucket_files(hub_id, files=[(checkpoint, output_dir/checkpoint)])
312
+ state = torch.load(output_dir/checkpoint, weights_only=True)
313
+ cur_step = state['step']
314
+ student.load_state_dict(state['model'])
315
+ optimizer.load_state_dict(state['optimizer'])
316
+ scheduler.load_state_dict(state['scheduler'])
317
+ else:
318
+ LOGGER.info('Checkpoint not detected')
319
+
320
+ return cur_step, teacher, student, optimizer, scheduler
321
+
322
+
323
+ @torch.compile(mode='default', fullgraph=True, dynamic=False)
324
+ def forward(
325
+ teacher: TransformerDecoderWrapper,
326
+ student: TransformerDecoderCore,
327
+ encoder_states: torch.Tensor, # [b,t,d]
328
+ input_ids: torch.LongTensor, # [b,s]
329
+ indices: torch.LongTensor, # [b,u]
330
+ causal_attn_mask: BlockMask,
331
+ self_attn_mask: BlockMask,
332
+ cross_attn_mask: BlockMask,
333
+ bsz: int,
334
+ ar_len: int,
335
+ diff_len: int,
336
+ kv_len: int,
337
+ diff_block: int,
338
+ diff_blocks: int,
339
+ pad_id: int,
340
+ eot_id: int,
341
+ ) -> torch.Tensor:
342
+ past_key_values = {}
343
+ with torch.no_grad():
344
+ teacher_attn_mask = cross_attn_mask._adjust(ar_len, kv_len)
345
+ teacher_attn_mask.seq_lengths = ar_len, kv_len
346
+ ar_logits = teacher(
347
+ input_ids=input_ids,
348
+ positions=None,
349
+ encoder_hidden_states=encoder_states,
350
+ self_attention_mask=causal_attn_mask,
351
+ cross_attention_mask=teacher_attn_mask,
352
+ past_key_values=past_key_values,
353
+ diffusion=False,
354
+ )
355
+ ar_logprobs = torch.log_softmax(ar_logits, dim=2, dtype=torch.float32)
356
+
357
+ positions = (indices[:, :, None] + torch.arange(0, diff_block, device=input_ids.device)).view(bsz, diff_len)
358
+ valid = positions < ar_len
359
+ pad_mask = valid & (input_ids.gather(1, torch.where(valid, positions, 0)) > eot_id)
360
+ target = ar_logprobs.take_along_dim(torch.clamp_max(positions, ar_len-1)[:, :, None], dim=1)
361
+ del ar_logits, ar_logprobs
362
+ train_ids = input_ids.gather(1, indices)[:, :, None]
363
+ train_ids = F.pad(train_ids, (0, diff_block - 1), 'constant', pad_id).reshape(bsz, diff_len)
364
+ diff_states = teacher._embedding(train_ids, positions)
365
+
366
+ diff_states = student(
367
+ diff_states,
368
+ encoder_hidden_states=encoder_states,
369
+ self_attention_mask=self_attn_mask,
370
+ cross_attention_mask=cross_attn_mask,
371
+ past_key_values=past_key_values,
372
+ diffusion=True,
373
+ )
374
+ diff_logits = teacher._lm_head(diff_states)
375
+ diff_logprobs = torch.log_softmax(diff_logits, dim=2, dtype=torch.float32)
376
+
377
+ kld = (target.exp() * (target - diff_logprobs)).sum(dim=2) # [b,s]
378
+ weight = torch.exp(torch.arange(diff_block, dtype=torch.float32, device=kld.device) / -12)
379
+ kld.view(bsz, diff_blocks, diff_block).mul_(weight)
380
+ return (kld * pad_mask).sum() / pad_mask.sum()
381
+
382
+
383
+ def train_step(
384
+ encoder_states: torch.Tensor, # [b,t,d]
385
+ encoder_lengths: torch.LongTensor, # [b]
386
+ input_ids: torch.LongTensor, # [b,s]
387
+ teacher: TransformerDecoderWrapper,
388
+ student: TransformerDecoderCore,
389
+ optimizer: torch.optim.AdamW,
390
+ scheduler: torch.optim.lr_scheduler.LambdaLR,
391
+ ) -> dict[str, torch.Tensor]:
392
+ device = encoder_states.device
393
+ bsz = encoder_states.shape[0]
394
+ ar_len = input_ids.shape[1]
395
+ diff_len = 2048
396
+ kv_len = encoder_states.shape[1]
397
+ diff_block = 32
398
+ ar_blocks = ar_len // diff_block
399
+ diff_blocks = diff_len // diff_block
400
+ prompt_len = 9
401
+
402
+ pad_id = 2
403
+ eot_id = 3
404
+ specials = 254
405
+ input_lengths = (input_ids > eot_id).cumprod(dim=1).sum(dim=1)
406
+ weights = (input_ids > specials).bfloat16()
407
+ weights[:, prompt_len] = 1
408
+ indices = torch.multinomial(weights, diff_blocks).sort(dim=1).values
409
+ _create_block_mask = torch.compile(create_block_mask, fullgraph=True, dynamic=False)
410
+
411
+ def causal_mask(b, h, q_idx, kv_idx):
412
+ return kv_idx <= q_idx
413
+ causal_attn_mask = _create_block_mask(causal_mask, B=None, H=None, Q_LEN=ar_len, KV_LEN=ar_len, device=device)
414
+
415
+ def self_mask(b, h, q_idx, kv_idx):
416
+ block = q_idx // diff_block == kv_idx // diff_block - ar_blocks
417
+ idx = q_idx // diff_block
418
+ prefix = kv_idx < indices[b, idx]
419
+ return (block | prefix) & (idx < input_lengths[b])
420
+ self_attn_mask = _create_block_mask(self_mask, B=bsz, H=None, Q_LEN=diff_len, KV_LEN=ar_len+diff_len, device=device)
421
+
422
+ def cross_mask(b, h, q_idx, kv_idx):
423
+ return kv_idx < encoder_lengths[b]
424
+ cross_attn_mask = _create_block_mask(cross_mask, B=bsz, H=None, Q_LEN=diff_len, KV_LEN=kv_len, device=device)
425
+
426
+ optimizer.zero_grad()
427
+ loss = forward(
428
+ teacher=teacher,
429
+ student=student,
430
+ encoder_states=encoder_states,
431
+ input_ids=input_ids,
432
+ indices=indices,
433
+ causal_attn_mask=causal_attn_mask,
434
+ self_attn_mask=self_attn_mask,
435
+ cross_attn_mask=cross_attn_mask,
436
+ bsz=bsz,
437
+ ar_len=ar_len,
438
+ diff_len=diff_len,
439
+ kv_len=kv_len,
440
+ diff_block=diff_block,
441
+ diff_blocks=diff_blocks,
442
+ pad_id=pad_id,
443
+ eot_id=eot_id,
444
+ )
445
+ loss.backward()
446
+ grad_norm = nn.utils.clip_grad_norm_(student.parameters(), 1.0)
447
+ optimizer.step()
448
+ scheduler.step()
449
+
450
+ return {
451
+ 'train/loss': loss.detach().clone(),
452
+ 'train/grad_norm': grad_norm.detach().clone(),
453
+ 'train/learning_rate': scheduler.get_last_lr()[0],
454
+ }
455
+
456
+
457
+ def main():
458
+ model_id = 'efwkjn/cohere-asr-ja'
459
+ hub_id = 'efwkjn/checkpoints'
460
+ output_dir = Path('checkpoints')
461
+ summary_writer = SummaryWriter(log_dir=output_dir/'runs')
462
+ handler = logging.StreamHandler()
463
+ formatter = logging.Formatter('%(levelname)s: %(message)s')
464
+ handler.setFormatter(formatter)
465
+ LOGGER.addHandler(handler)
466
+ LOGGER.setLevel(logging.INFO)
467
+ API.create_bucket(hub_id, private=True, exist_ok=True)
468
+
469
+ max_steps = 2**17
470
+ warmup_steps = 2**13
471
+ save_steps = 2**10
472
+ logging_steps = 2**4
473
+
474
+ cur_step, teacher, student, optimizer, scheduler = load(model_id, hub_id, warmup_steps, max_steps, output_dir)
475
+ dataset = None
476
+ train_metrics: list[dict[str, torch.Tensor | float]] = []
477
+ time_start = time.perf_counter()
478
+
479
+ for batch in tqdm(dataset, initial=cur_step, total=max_steps):
480
+ cur_step += 1
481
+ metrics = train_step(
482
+ **batch,
483
+ teacher=teacher,
484
+ student=student,
485
+ optimizer=optimizer,
486
+ scheduler=scheduler,
487
+ )
488
+
489
+ if cur_step % logging_steps == 0:
490
+ metrics['step'] = cur_step
491
+ train_metrics.append(metrics)
492
+ if cur_step % (logging_steps * 16) == 0:
493
+ prev_metrics = train_metrics[-2]
494
+ s = ' | '.join(f'{k[6:]}: {v.item():.5f}' for k, v in prev_metrics.items()
495
+ if k.startswith('train/') and isinstance(v, torch.Tensor))
496
+ LOGGER.info(f'{prev_metrics["step"]}: {s}')
497
+
498
+ if cur_step % save_steps == 0:
499
+ train_time = time.perf_counter() - time_start
500
+ summary_writer.add_scalar('train/time', train_time, cur_step)
501
+ for m in train_metrics:
502
+ step = m.pop('step')
503
+ for k, v in m.items():
504
+ summary_writer.add_scalar(k, v, step)
505
+ summary_writer.flush()
506
+ train_metrics = []
507
+ time_start = time.perf_counter()
508
+
509
+ checkpoint = output_dir/f'{cur_step}.pt'
510
+ torch.save({
511
+ 'step': cur_step,
512
+ 'model': student.state_dict(),
513
+ 'optimizer': optimizer.state_dict(),
514
+ 'scheduler': scheduler.state_dict(),
515
+ }, checkpoint)
516
+ API.run_as_future(API.sync_bucket, str(output_dir), f'hf://buckets/{hub_id}', ignore_times=True)
517
+
518
+
519
+ if __name__ == '__main__':
520
+ main()