Upload 6 files
Browse files- README.md +69 -0
- cohere_asr.py +1769 -0
- config.json +173 -0
- model.safetensors +3 -0
- tokenizer.json +0 -0
- 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()
|