Text Generation
Transformers
Safetensors
Upper Grand Valley Dani
evo2
DNA
language-model
StripedHyena2
Evo2
custom_code
Instructions to use Taykhoom/Evo2-7B-8K with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use Taykhoom/Evo2-7B-8K with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="Taykhoom/Evo2-7B-8K", trust_remote_code=True)# Load model directly from transformers import AutoModelForCausalLM model = AutoModelForCausalLM.from_pretrained("Taykhoom/Evo2-7B-8K", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use Taykhoom/Evo2-7B-8K with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "Taykhoom/Evo2-7B-8K" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "Taykhoom/Evo2-7B-8K", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker
docker model run hf.co/Taykhoom/Evo2-7B-8K
- SGLang
How to use Taykhoom/Evo2-7B-8K with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "Taykhoom/Evo2-7B-8K" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "Taykhoom/Evo2-7B-8K", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "Taykhoom/Evo2-7B-8K" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "Taykhoom/Evo2-7B-8K", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }' - Docker Model Runner
How to use Taykhoom/Evo2-7B-8K with Docker Model Runner:
docker model run hf.co/Taykhoom/Evo2-7B-8K
Commit ·
e2b4020
0
Parent(s):
Add model_max_length=8192 and max_seqlen=8192 (training context); note StripedHyena extension in README
Browse files- .gitattributes +35 -0
- README.md +247 -0
- attention.py +261 -0
- cache.py +141 -0
- config.json +108 -0
- configuration_evo2.py +197 -0
- engine.py +327 -0
- generation_config.json +5 -0
- hyena.py +517 -0
- layers.py +252 -0
- model-00001-of-00003.safetensors +3 -0
- model-00002-of-00003.safetensors +3 -0
- model-00003-of-00003.safetensors +3 -0
- model.safetensors.index.json +352 -0
- modeling_evo2.py +425 -0
- rotary.py +201 -0
- special_tokens_map.json +1 -0
- tokenization_evo2.py +119 -0
- tokenizer_config.json +12 -0
.gitattributes
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
*.7z filter=lfs diff=lfs merge=lfs -text
|
| 2 |
+
*.arrow filter=lfs diff=lfs merge=lfs -text
|
| 3 |
+
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 4 |
+
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
| 5 |
+
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
| 6 |
+
*.ftz filter=lfs diff=lfs merge=lfs -text
|
| 7 |
+
*.gz filter=lfs diff=lfs merge=lfs -text
|
| 8 |
+
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 9 |
+
*.joblib filter=lfs diff=lfs merge=lfs -text
|
| 10 |
+
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
| 11 |
+
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
| 12 |
+
*.model filter=lfs diff=lfs merge=lfs -text
|
| 13 |
+
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
| 14 |
+
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 15 |
+
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 16 |
+
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 17 |
+
*.ot filter=lfs diff=lfs merge=lfs -text
|
| 18 |
+
*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 19 |
+
*.pb filter=lfs diff=lfs merge=lfs -text
|
| 20 |
+
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 21 |
+
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 22 |
+
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 23 |
+
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 24 |
+
*.rar filter=lfs diff=lfs merge=lfs -text
|
| 25 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 26 |
+
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
| 27 |
+
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
| 28 |
+
*.tar filter=lfs diff=lfs merge=lfs -text
|
| 29 |
+
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 30 |
+
*.tgz filter=lfs diff=lfs merge=lfs -text
|
| 31 |
+
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 32 |
+
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 33 |
+
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
+
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
+
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
README.md
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
language:
|
| 3 |
+
- dna
|
| 4 |
+
library_name: transformers
|
| 5 |
+
tags:
|
| 6 |
+
- DNA
|
| 7 |
+
- language-model
|
| 8 |
+
- StripedHyena2
|
| 9 |
+
- Evo2
|
| 10 |
+
license: apache-2.0
|
| 11 |
+
---
|
| 12 |
+
|
| 13 |
+
# Evo2-7B-8K
|
| 14 |
+
|
| 15 |
+
A clean, minimal HuggingFace port of [Evo 2 7B base](https://huggingface.co/arcinstitute/evo2_7b_base), the 8K-context StripedHyena2 DNA foundation model. Provides native support for layer-by-layer hidden state extraction, attention-weight extraction, and a runtime-switchable attention backend.
|
| 16 |
+
|
| 17 |
+
> **No Transformer Engine required.** This variant runs in pure bf16 on any
|
| 18 |
+
> CUDA-capable GPU (no FP8 / TE dependency).
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
## Why this port?
|
| 23 |
+
|
| 24 |
+
[arcinstitute/evo2_7b_base](https://huggingface.co/arcinstitute/evo2_7b_base) ships a `.pt` checkpoint that requires the [evo2](https://github.com/ArcInstitute/evo2) and [vortex](https://github.com/Zymrael/vortex) Python packages just to instantiate the model. Even with both installed, common pain points remain:
|
| 25 |
+
|
| 26 |
+
1. **Not a HuggingFace model.** No `from_pretrained`, no `AutoModel`, no `AutoModelForCausalLM` - the original ships a thin Python wrapper around a custom `nn.Module`.
|
| 27 |
+
2. **No way to extract attention weights.** The reference uses flash-attn unconditionally and discards the `(B, H, T, T)` attention matrix; there is no official path to read it back.
|
| 28 |
+
3. **`evo2` + `vortex` packages mandatory** even for inference.
|
| 29 |
+
|
| 30 |
+
This repo fixes all three. The math is **bit-exact** with the vortex reference (`max_abs_diff = 0.000e+00` at every layer; see [Parity Verification](#parity-verification)). Loads with `from_pretrained` and `trust_remote_code=True` - no `evo2` / `vortex` install needed.
|
| 31 |
+
|
| 32 |
+
## Architecture
|
| 33 |
+
|
| 34 |
+
| Parameter | Value |
|
| 35 |
+
|---|---|
|
| 36 |
+
| Total parameters | ~6.5B |
|
| 37 |
+
| Architecture | StripedHyena 2 (interleaved Hyena cascade + MHA blocks) |
|
| 38 |
+
| Layers | 32 |
|
| 39 |
+
| Attention heads | 32 |
|
| 40 |
+
| Embedding dimension | 4096 |
|
| 41 |
+
| Inner MLP size | 11 008 |
|
| 42 |
+
| Vocabulary size | 512 (UTF-8 byte-level) |
|
| 43 |
+
| Attention block indices | 3, 10, 17, 24, 31 (5 blocks total) |
|
| 44 |
+
| Hyena block indices | all others (27 blocks: hcs / hcm / hcl pattern) |
|
| 45 |
+
| Positional encoding | RoPE (base = 10 000) |
|
| 46 |
+
| Max sequence length | 8 192 (training context; StripedHyena supports extension beyond this with adjusted FFT buffers) |
|
| 47 |
+
| Training dtype | bfloat16 (Hyena modal-form `log_poles` / `residues` and rotary `inv_freq` kept in fp32) |
|
| 48 |
+
| FP8 input projections | no |
|
| 49 |
+
| Weight format | `model.safetensors` (6.5B params, 3 files) |
|
| 50 |
+
|
| 51 |
+
## Pretraining
|
| 52 |
+
|
| 53 |
+
- **Objective:** causal byte-level next-token prediction.
|
| 54 |
+
- **Data:** [OpenGenome2](https://huggingface.co/datasets/arcinstitute/opengenome2), 8.8 trillion tokens spanning all domains of life.
|
| 55 |
+
- **Source checkpoint:** `arcinstitute/evo2_7b_base` ([evo2_7b_base.pt](https://huggingface.co/arcinstitute/evo2_7b_base/blob/main/evo2_7b_base.pt)).
|
| 56 |
+
|
| 57 |
+
## Parity Verification
|
| 58 |
+
|
| 59 |
+
Hidden-state representations verified **bit-exact** (`max_abs_diff = 0.000e+00`) to the vortex reference at every block output, using `attn_implementation="sdpa"` in bf16 (the same backend vortex's `SelfAttention` calls when `use_flash_attn=False`). Logits from `Evo2ForCausalLM` were also verified bit-exact (top-1 agreement: 128/128 positions on a 128-byte ACGT input). Verified on H100 with PyTorch 2.7 / CUDA 12.
|
| 60 |
+
|
| 61 |
+
Two non-obvious correctness fixes were required versus a naive port (see Implementation Notes for details):
|
| 62 |
+
|
| 63 |
+
1. **`inv_freq` recomputation.** `from_pretrained(dtype=bf16)` casts buffers to bf16, which loses ~7 bits of mantissa in the rotary `inv_freq = 1 / base^(2i/dim)`. Our `to_bfloat16_except_poles_residues()` recomputes `inv_freq` in fp32 from `self.base` to match vortex's `to_bfloat16_except_pr_lc(to_float32=True)`.
|
| 64 |
+
2. **SDPA backend used for parity.** Vortex's reference `SelfAttention` (`use_flash_attn=False`) calls `F.scaled_dot_product_attention`, not a textbook softmax loop. Parity is measured with `attn_implementation="sdpa"` on our side. Using `"eager"` (textbook einsum + softmax) is mathematically equivalent but not bit-exact in bf16; using `"flash_attention_2"` (the recommended runtime backend) is also not bit-exact but agrees within bf16 noise.
|
| 65 |
+
|
| 66 |
+
## Related Models
|
| 67 |
+
|
| 68 |
+
See the full Evo 2 collection on the [Arc Institute HF org](https://huggingface.co/arcinstitute) for the original weights, or the [`Taykhoom/Evo2-*` collection](https://huggingface.co/collections/Taykhoom/evo2-6a24b06c05955a295025a006) for our minimal HF ports.
|
| 69 |
+
|
| 70 |
+
| Model | Size | Context | Notes |
|
| 71 |
+
|---|---|---|---|
|
| 72 |
+
| [Taykhoom/Evo2-1B-8K](https://huggingface.co/Taykhoom/Evo2-1B-8K) | 1B | 8 192 | |
|
| 73 |
+
| **[Taykhoom/Evo2-7B-8K](https://huggingface.co/Taykhoom/Evo2-7B-8K)** | 7B | 8 192 | <- this model |
|
| 74 |
+
| [Taykhoom/Evo2-7B-262K](https://huggingface.co/Taykhoom/Evo2-7B-262K) | 7B | 262 144 | |
|
| 75 |
+
| [Taykhoom/Evo2-7B-1M](https://huggingface.co/Taykhoom/Evo2-7B-1M) | 7B | 1 048 576 | |
|
| 76 |
+
| [Taykhoom/Evo2-20B-1M](https://huggingface.co/Taykhoom/Evo2-20B-1M) | 20B | 1 048 576 | |
|
| 77 |
+
| [Taykhoom/Evo2-40B-8K](https://huggingface.co/Taykhoom/Evo2-40B-8K) | 40B | 8 192 | |
|
| 78 |
+
| [Taykhoom/Evo2-40B-1M](https://huggingface.co/Taykhoom/Evo2-40B-1M) | 40B | 1 048 576 | |
|
| 79 |
+
|
| 80 |
+
## Usage
|
| 81 |
+
|
| 82 |
+
> **Note on dtype.** Evo 2 was trained in bfloat16, with the Hyena `log_poles` / `residues` (modal-form filter parameters) and the rotary `inv_freq` kept in fp32 for numerical stability. Passing `dtype=...` to `from_pretrained` only affects the initial load precision - `Evo2Model.__init__` and `Evo2ForCausalLM.__init__` always call `to_bfloat16_except_poles_residues()`, so the model runs in bf16 with these fp32 invariants regardless. This is intentional: bf16 is the trained precision, and the fp32 islands are required for stability.
|
| 83 |
+
|
| 84 |
+
> **Note on attention backend.** By HuggingFace convention this model defaults to `attn_implementation="sdpa"` (`F.scaled_dot_product_attention`) since SDPA needs only `torch` and runs on any GPU. The original Arc Institute Evo 2 inference path uses **flash_attention_2**, which is faster on long sequences but requires a separate `flash-attn` install. All usage examples below opt in to `flash_attention_2` explicitly because most real users will want it. Drop the kwarg (or pass `"sdpa"` / `"eager"`) if you don't have `flash-attn` installed.
|
| 85 |
+
|
| 86 |
+
### Embedding generation (no LM head)
|
| 87 |
+
|
| 88 |
+
```python
|
| 89 |
+
import torch
|
| 90 |
+
from transformers import AutoTokenizer, AutoModel
|
| 91 |
+
|
| 92 |
+
tokenizer = AutoTokenizer.from_pretrained("Taykhoom/Evo2-7B-8K", trust_remote_code=True)
|
| 93 |
+
model = AutoModel.from_pretrained(
|
| 94 |
+
"Taykhoom/Evo2-7B-8K",
|
| 95 |
+
trust_remote_code=True,
|
| 96 |
+
attn_implementation="flash_attention_2", # or "sdpa" (default) or "eager"
|
| 97 |
+
).cuda().eval()
|
| 98 |
+
|
| 99 |
+
seqs = ["ACGTACGTACGT", "GGGTTTAAACCC"]
|
| 100 |
+
inputs = tokenizer(seqs, return_tensors="pt", padding=True).to(model.device)
|
| 101 |
+
|
| 102 |
+
with torch.no_grad():
|
| 103 |
+
out = model(**inputs, output_hidden_states=True)
|
| 104 |
+
|
| 105 |
+
last_hidden = out.last_hidden_state # (B, T, 4096)
|
| 106 |
+
all_layers = out.hidden_states # tuple of (B, T, 4096), len = 34
|
| 107 |
+
middle_layer = all_layers[16] # input to block 16 (= output of block 15)
|
| 108 |
+
```
|
| 109 |
+
|
| 110 |
+
### Recommended embedding: pre-norm of the middle block
|
| 111 |
+
|
| 112 |
+
The Evo 2 paper reports that intermediate representations work better than the final layer for downstream tasks - specifically the **pre-norm of a middle block**. For this variant the middle block is `blocks[16]`, so the recommended embedding is `blocks[16].pre_norm(hidden_states[16])`:
|
| 113 |
+
|
| 114 |
+
```python
|
| 115 |
+
import torch
|
| 116 |
+
from transformers import AutoTokenizer, AutoModel
|
| 117 |
+
|
| 118 |
+
tokenizer = AutoTokenizer.from_pretrained("Taykhoom/Evo2-7B-8K", trust_remote_code=True)
|
| 119 |
+
model = AutoModel.from_pretrained(
|
| 120 |
+
"Taykhoom/Evo2-7B-8K",
|
| 121 |
+
trust_remote_code=True,
|
| 122 |
+
attn_implementation="flash_attention_2",
|
| 123 |
+
).cuda().eval()
|
| 124 |
+
|
| 125 |
+
inputs = tokenizer(["ACGTACGTACGT"], return_tensors="pt").to(model.device)
|
| 126 |
+
with torch.no_grad():
|
| 127 |
+
out = model(**inputs, output_hidden_states=True)
|
| 128 |
+
pre_norm_middle = model.backbone.blocks[16].pre_norm(
|
| 129 |
+
out.hidden_states[16]
|
| 130 |
+
) # (B, T, 4096)
|
| 131 |
+
```
|
| 132 |
+
|
| 133 |
+
HF has no built-in API for sub-block intermediates like pre-norm outputs (only block outputs via `output_hidden_states`). The pattern above applies the block's `pre_norm` submodule directly to the corresponding `hidden_states` entry; this gives a bit-identical result to registering a forward hook on `backbone.blocks[i].pre_norm` and is simpler than using PyTorch hooks. Note that it does require running the full forward pass and then re-applying `pre_norm`, so a forward hook is more efficient if you only need this single intermediate.
|
| 134 |
+
|
| 135 |
+
### LM logits
|
| 136 |
+
|
| 137 |
+
```python
|
| 138 |
+
import torch
|
| 139 |
+
from transformers import AutoTokenizer, AutoModelForCausalLM
|
| 140 |
+
|
| 141 |
+
tokenizer = AutoTokenizer.from_pretrained("Taykhoom/Evo2-7B-8K", trust_remote_code=True)
|
| 142 |
+
model = AutoModelForCausalLM.from_pretrained(
|
| 143 |
+
"Taykhoom/Evo2-7B-8K", trust_remote_code=True,
|
| 144 |
+
attn_implementation="flash_attention_2",
|
| 145 |
+
).cuda().eval()
|
| 146 |
+
|
| 147 |
+
inputs = tokenizer(["ACGT"], return_tensors="pt").to(model.device)
|
| 148 |
+
with torch.no_grad():
|
| 149 |
+
logits = model(**inputs).logits # (1, T, 512)
|
| 150 |
+
```
|
| 151 |
+
|
| 152 |
+
### Generation
|
| 153 |
+
|
| 154 |
+
```python
|
| 155 |
+
import torch
|
| 156 |
+
from transformers import AutoTokenizer, AutoModelForCausalLM
|
| 157 |
+
|
| 158 |
+
tokenizer = AutoTokenizer.from_pretrained("Taykhoom/Evo2-7B-8K", trust_remote_code=True)
|
| 159 |
+
model = AutoModelForCausalLM.from_pretrained(
|
| 160 |
+
"Taykhoom/Evo2-7B-8K", trust_remote_code=True,
|
| 161 |
+
attn_implementation="flash_attention_2",
|
| 162 |
+
).cuda().eval()
|
| 163 |
+
|
| 164 |
+
inputs = tokenizer(["ACGT"], return_tensors="pt").to(model.device)
|
| 165 |
+
out = model.generate(**inputs, max_new_tokens=128, do_sample=True, top_k=4, temperature=1.0)
|
| 166 |
+
print(tokenizer.decode(out[0]))
|
| 167 |
+
```
|
| 168 |
+
|
| 169 |
+
`generation_config.json` ships with `eos_token_id = 0` (the EOD byte) and `pad_token_id = 1` so `model.generate()` stops naturally at the trained end-of-document token.
|
| 170 |
+
|
| 171 |
+
### Attention weights
|
| 172 |
+
|
| 173 |
+
```python
|
| 174 |
+
import torch
|
| 175 |
+
from transformers import AutoTokenizer, AutoModel
|
| 176 |
+
|
| 177 |
+
tokenizer = AutoTokenizer.from_pretrained("Taykhoom/Evo2-7B-8K", trust_remote_code=True)
|
| 178 |
+
model = AutoModel.from_pretrained(
|
| 179 |
+
"Taykhoom/Evo2-7B-8K",
|
| 180 |
+
trust_remote_code=True,
|
| 181 |
+
attn_implementation="eager", # required for output_attentions to populate
|
| 182 |
+
).cuda().eval()
|
| 183 |
+
|
| 184 |
+
inputs = tokenizer(["ACGTACGT"], return_tensors="pt").to(model.device)
|
| 185 |
+
with torch.no_grad():
|
| 186 |
+
out = model(**inputs, output_attentions=True)
|
| 187 |
+
|
| 188 |
+
# out.attentions is a tuple of length 32. Entries at indices not in
|
| 189 |
+
# [3, 10, 17, 24, 31] are None (Hyena blocks have no attention matrix).
|
| 190 |
+
# The 5 attention block(s) at those indices return a (B, num_heads, T, T) tensor.
|
| 191 |
+
attn_block_3 = out.attentions[3]
|
| 192 |
+
```
|
| 193 |
+
|
| 194 |
+
### Multi-GPU loading (optional)
|
| 195 |
+
|
| 196 |
+
For sharding across multiple GPUs (required for 40B, optional for smaller
|
| 197 |
+
variants), install [accelerate](https://github.com/huggingface/accelerate)
|
| 198 |
+
and pass `device_map="auto"`:
|
| 199 |
+
|
| 200 |
+
```python
|
| 201 |
+
from transformers import AutoModelForCausalLM
|
| 202 |
+
# pip install accelerate
|
| 203 |
+
model = AutoModelForCausalLM.from_pretrained(
|
| 204 |
+
"Taykhoom/Evo2-7B-8K", trust_remote_code=True,
|
| 205 |
+
device_map="auto", # accelerate will shard across all visible GPUs
|
| 206 |
+
)
|
| 207 |
+
```
|
| 208 |
+
|
| 209 |
+
### Fine-tuning
|
| 210 |
+
|
| 211 |
+
This HuggingFace port has **not** been tested for fine-tuning - it's verified only for inference parity. For fine-tuning, follow the original Arc Institute guidance and use either [Savanna](https://github.com/Zymrael/savanna) (the framework Evo 2 was pretrained in) or [Nvidia BioNeMo](https://github.com/NVIDIA/bionemo-framework), which provides an official [Evo 2 fine-tuning recipe](https://github.com/NVIDIA-BioNeMo/bionemo-framework/tree/main/bionemo-recipes/recipes/evo2_megatron#fine-tuning-from-an-existing-checkpoint).
|
| 212 |
+
|
| 213 |
+
## Implementation Notes
|
| 214 |
+
|
| 215 |
+
- **`inv_freq` kept in fp32 (critical for parity).** HF's `from_pretrained(dtype=bf16)` casts all buffers, including the rotary `inv_freq`, to bf16. The geometric series `inv_freq[i] = 1 / base^(2i/dim)` loses ~7 bits of mantissa in bf16, which shifts the cos/sin tables by ~5e-2 per cell at higher positions and contributes ~3e-2 of Q/K noise per attention layer. Our `to_bfloat16_except_poles_residues()` (called in each `__init__`) recomputes `inv_freq` in fp32 from the stored `self.base` and invalidates the cos/sin cache, mirroring vortex's `to_bfloat16_except_pr_lc(to_float32=True)`.
|
| 216 |
+
- **`log_poles` / `residues` kept in fp32 (critical for stability).** The Hyena cascade long (hcl) blocks parameterize an IIR filter via `log_poles` and `residues`; bf16 quantisation makes the recurrence numerically unstable. Both are stored as fp32 in the safetensors and restored to fp32 by `force_dtype()` after load.
|
| 217 |
+
- **`attn_implementation` switching (`attention.py`).** Three backends, selected via the standard HF `attn_implementation` kwarg to `from_pretrained` (default chosen by HF auto-detection - typically `"sdpa"`):
|
| 218 |
+
- `"sdpa"`: calls `F.scaled_dot_product_attention`. Bit-exact with vortex's reference path (when vortex uses `use_flash_attn=False`).
|
| 219 |
+
- `"flash_attention_2"`: calls `flash_attn.flash_attn_qkvpacked_func`. Matches the original Arc Institute inference path; faster on long sequences; requires `flash-attn` installed.
|
| 220 |
+
- `"eager"`: textbook einsum + softmax(QK^T) + einsum. Slowest, used internally when `output_attentions=True` so the attention matrix is materialized.
|
| 221 |
+
- **Block dispatch (`hyena.py`).** StripedHyena 2 has 4 block types, dispatched by `layer_idx` membership in four config lists: `attn_layer_idxs` (MHA + RoPE), `hcl_layer_idxs` (modal-form IIR via FFT), `hcm_layer_idxs` (medium FIR cascade, inner length 128), `hcs_layer_idxs` (short FIR cascade, inner length 7). The disjoint union must equal `range(num_layers)`.
|
| 222 |
+
- **`TELinear` with pure-PyTorch fallback (`layers.py`).** Hyena cascade blocks use a TransformerEngine-backed input projection (3x hidden_size output) that supports FP8 quantisation. When TE is not installed, a `TELinear` fallback class with the same state_dict layout (`weight`, `bias`) is used - checkpoints are cross-loadable.
|
| 223 |
+
- **Custom cache (`cache.py`).** `Evo2Cache` wraps four block-type-specific dataclasses: `InferenceParams` for MHA KV cache, `HyenaCascadeIIRInferenceParams` for hcl, and two `HyenaCascadeFIRInferenceParams` for hcm / hcs. Passed through `model.generate()` as `past_key_values` (we set `_supports_cache_class = False` so HF treats it as an opaque dict rather than wrapping it in a `DynamicCache`).
|
| 224 |
+
- **Tokenizer (`tokenization_evo2.py`).** Byte-level UTF-8, vocab_size = 512. Pad token = byte `\x01`. EOS = byte `\x00` (set as `eos_token_id` in `generation_config.json`). Tokenizer does not add EOS at encoding time - matches the original Evo 2 inference pipeline.
|
| 225 |
+
- **Dependencies.** `torch`, `transformers`, `numpy`, `safetensors`, `huggingface_hub`. `accelerate` is optional but recommended if you want to load with `device_map="auto"` for multi-GPU sharding. `flash_attn` is optional (only needed if you pass `attn_implementation="flash_attention_2"`).
|
| 226 |
+
|
| 227 |
+
## Citation
|
| 228 |
+
|
| 229 |
+
```bibtex
|
| 230 |
+
@article{brixi2026_evo2,
|
| 231 |
+
title = {Genome modelling and design across all domains of life with {Evo} 2},
|
| 232 |
+
author = {Brixi, Garyk and Durrant, Matthew G. and Ku, Jerome and Naghipourfar, Mohsen and Poli, Michael and Sun, Gwanggyu and Brockman, Greg and Chang, Daniel and Fanton, Alison and Gonzalez, Gabriel A. and King, Samuel H. and Li, David B. and Merchant, Aditi T. and Nguyen, Eric and Ricci-Tam, Chiara and Romero, David W. and Schmok, Jonathan C. and Taghibakhshi, Ali and Vorontsov, Anton and Yang, Brandon and Deng, Myra and Gorton, Liv and Nguyen, Nam and Wang, Nicholas K. and Pearce, Michael T. and Simon, Elana and Adams, Etowah and Amador, Zachary J. and Ashley, Euan A. and Baccus, Stephen A. and Dai, Haoyu and Dillmann, Steven and Ermon, Stefano and Guo, Daniel and Herschl, Michael H. and Ilango, Rajesh and Janik, Ken and Lu, Amy X. and Mehta, Reshma and Mofrad, Mohammad R. K. and Ng, Madelena Y. and Pannu, Jaspreet and {R{\'e}}, Christopher and St. John, John and Sullivan, Jeremy and Tey, Joseph and Viggiano, Ben and Zhu, Kevin and Zynda, Greg and Balsam, Daniel and Collison, Patrick and Costa, Anthony B. and Hernandez-Boussard, Tina and Ho, Eric and Liu, Ming-Yu and McGrath, Thomas and Powell, Kimberly and Pinglay, Sudarshan and Burke, Dave P. and Goodarzi, Hani and Hsu, Patrick D. and Hie, Brian L.},
|
| 233 |
+
journal = {Nature},
|
| 234 |
+
year = {2026},
|
| 235 |
+
doi = {10.1038/s41586-026-10176-5}
|
| 236 |
+
}
|
| 237 |
+
```
|
| 238 |
+
|
| 239 |
+
## Credits
|
| 240 |
+
|
| 241 |
+
Original Evo 2 model and code by Brixi et al. ([arcinstitute/evo2](https://github.com/arcinstitute/evo2), [Zymrael/vortex](https://github.com/Zymrael/vortex)). Source checkpoint: [arcinstitute/evo2_7b_base](https://huggingface.co/arcinstitute/evo2_7b_base).
|
| 242 |
+
|
| 243 |
+
The HuggingFace conversion code in this repo was authored primarily by [Claude](https://claude.ai/code) and reviewed manually by Taykhoom Dalal.
|
| 244 |
+
|
| 245 |
+
## License
|
| 246 |
+
|
| 247 |
+
Apache 2.0, following the original Evo 2 release.
|
attention.py
ADDED
|
@@ -0,0 +1,261 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Multi-head attention for Evo2.
|
| 2 |
+
|
| 3 |
+
Causal self-attention with RoPE. Three backends dispatchable via the standard
|
| 4 |
+
HF attn_implementation kwarg:
|
| 5 |
+
|
| 6 |
+
* "eager" -- pure F.softmax(QK^T)V; returns weights on demand
|
| 7 |
+
* "sdpa" -- F.scaled_dot_product_attention; no weights
|
| 8 |
+
* "flash_attention_2" -- flash_attn.flash_attn_qkvpacked_func; no weights
|
| 9 |
+
|
| 10 |
+
Constructor signature is a strict subset of vortex's MHA so the
|
| 11 |
+
AttentionBlock instantiation site only changes the attn_implementation kwarg.
|
| 12 |
+
KV cache (used by Evo2 generation) goes through an SDPA path that handles
|
| 13 |
+
arbitrary sequence lengths.
|
| 14 |
+
"""
|
| 15 |
+
|
| 16 |
+
from __future__ import annotations
|
| 17 |
+
|
| 18 |
+
import math
|
| 19 |
+
|
| 20 |
+
import torch
|
| 21 |
+
import torch.nn as nn
|
| 22 |
+
import torch.nn.functional as F
|
| 23 |
+
|
| 24 |
+
from .rotary import RotaryEmbedding
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
def _flash_attn_required():
|
| 28 |
+
try:
|
| 29 |
+
from flash_attn import flash_attn_qkvpacked_func # noqa: F401
|
| 30 |
+
except ImportError as exc:
|
| 31 |
+
raise ImportError(
|
| 32 |
+
"attn_implementation='flash_attention_2' requires the flash-attn "
|
| 33 |
+
"package. Install with `pip install flash-attn --no-build-isolation`."
|
| 34 |
+
) from exc
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
def _update_kv_cache(kv: torch.Tensor, inference_params, layer_idx: int) -> torch.Tensor:
|
| 38 |
+
num_heads, head_dim = kv.shape[-2:]
|
| 39 |
+
if layer_idx not in inference_params.key_value_memory_dict:
|
| 40 |
+
kv_cache = torch.empty(
|
| 41 |
+
inference_params.max_batch_size,
|
| 42 |
+
inference_params.max_seqlen,
|
| 43 |
+
2,
|
| 44 |
+
num_heads,
|
| 45 |
+
head_dim,
|
| 46 |
+
dtype=kv.dtype,
|
| 47 |
+
device=kv.device,
|
| 48 |
+
)
|
| 49 |
+
inference_params.key_value_memory_dict[layer_idx] = kv_cache
|
| 50 |
+
else:
|
| 51 |
+
kv_cache = inference_params.key_value_memory_dict[layer_idx]
|
| 52 |
+
batch_start = inference_params.batch_size_offset
|
| 53 |
+
batch_end = batch_start + kv.shape[0]
|
| 54 |
+
sequence_start = inference_params.seqlen_offset
|
| 55 |
+
sequence_end = sequence_start + kv.shape[1]
|
| 56 |
+
kv_cache[batch_start:batch_end, sequence_start:sequence_end, ...] = kv
|
| 57 |
+
return kv_cache[batch_start:batch_end, :sequence_end, ...]
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
class MHA(nn.Module):
|
| 61 |
+
"""Multi-head self-attention with backend-dispatch."""
|
| 62 |
+
|
| 63 |
+
def __init__(
|
| 64 |
+
self,
|
| 65 |
+
embed_dim: int,
|
| 66 |
+
num_heads: int,
|
| 67 |
+
num_heads_kv: int | None = None,
|
| 68 |
+
cross_attn: bool = False,
|
| 69 |
+
qkv_proj_bias: bool = True,
|
| 70 |
+
out_proj_bias: bool = True,
|
| 71 |
+
dropout: float = 0.0,
|
| 72 |
+
softmax_scale: float | None = None,
|
| 73 |
+
causal: bool = False,
|
| 74 |
+
layer_idx: int | None = None,
|
| 75 |
+
rotary_emb_dim: int = 0,
|
| 76 |
+
rotary_emb_base: float = 10000.0,
|
| 77 |
+
rotary_emb_scale_base: float | None = None,
|
| 78 |
+
rotary_emb_interleaved: bool = False,
|
| 79 |
+
use_flash_attn: bool = False, # legacy kwarg kept for ctor compat
|
| 80 |
+
attn_implementation: str = "eager",
|
| 81 |
+
device=None,
|
| 82 |
+
dtype=None,
|
| 83 |
+
) -> None:
|
| 84 |
+
super().__init__()
|
| 85 |
+
if cross_attn:
|
| 86 |
+
raise NotImplementedError("Cross-attention is not supported.")
|
| 87 |
+
|
| 88 |
+
factory_kwargs = {"device": device, "dtype": dtype}
|
| 89 |
+
self.embed_dim = embed_dim
|
| 90 |
+
self.num_heads = num_heads
|
| 91 |
+
self.num_heads_kv = num_heads_kv if num_heads_kv is not None else num_heads
|
| 92 |
+
if self.embed_dim % num_heads != 0:
|
| 93 |
+
raise ValueError("embed_dim must be divisible by num_heads")
|
| 94 |
+
if self.num_heads % self.num_heads_kv != 0:
|
| 95 |
+
raise ValueError("num_heads must be divisible by num_heads_kv")
|
| 96 |
+
self.head_dim = self.embed_dim // num_heads
|
| 97 |
+
self.causal = causal
|
| 98 |
+
self.softmax_scale = softmax_scale
|
| 99 |
+
self.layer_idx = layer_idx
|
| 100 |
+
self.rotary_emb_dim = rotary_emb_dim
|
| 101 |
+
self.attn_implementation = attn_implementation
|
| 102 |
+
self.dropout_p = dropout
|
| 103 |
+
self.cross_attn = cross_attn
|
| 104 |
+
|
| 105 |
+
if self.rotary_emb_dim > 0:
|
| 106 |
+
self.rotary_emb = RotaryEmbedding(
|
| 107 |
+
self.rotary_emb_dim,
|
| 108 |
+
base=rotary_emb_base,
|
| 109 |
+
interleaved=rotary_emb_interleaved,
|
| 110 |
+
scale_base=rotary_emb_scale_base,
|
| 111 |
+
device=device,
|
| 112 |
+
)
|
| 113 |
+
|
| 114 |
+
qkv_dim = self.head_dim * (self.num_heads + 2 * self.num_heads_kv)
|
| 115 |
+
self.Wqkv = nn.Linear(embed_dim, qkv_dim, bias=qkv_proj_bias, **factory_kwargs)
|
| 116 |
+
self.out_proj = nn.Linear(embed_dim, embed_dim, bias=out_proj_bias, **factory_kwargs)
|
| 117 |
+
|
| 118 |
+
def allocate_inference_cache(self, batch_size, max_seqlen, dtype=None):
|
| 119 |
+
dtype = self.out_proj.weight.dtype if dtype is None else dtype
|
| 120 |
+
device = self.out_proj.weight.device
|
| 121 |
+
return torch.empty(
|
| 122 |
+
batch_size, max_seqlen, 2, self.num_heads_kv, self.head_dim,
|
| 123 |
+
dtype=dtype, device=device,
|
| 124 |
+
)
|
| 125 |
+
|
| 126 |
+
def _project_qkv(self, x: torch.Tensor) -> torch.Tensor:
|
| 127 |
+
qkv = self.Wqkv(x)
|
| 128 |
+
if self.num_heads_kv == self.num_heads:
|
| 129 |
+
return qkv.view(*qkv.shape[:-1], 3, self.num_heads, self.head_dim)
|
| 130 |
+
q = qkv[..., : self.num_heads * self.head_dim]
|
| 131 |
+
kv = qkv[..., self.num_heads * self.head_dim:]
|
| 132 |
+
q = q.view(*q.shape[:-1], self.num_heads, self.head_dim)
|
| 133 |
+
kv = kv.view(*kv.shape[:-1], 2, self.num_heads_kv, self.head_dim)
|
| 134 |
+
return q, kv
|
| 135 |
+
|
| 136 |
+
def _forward_eager(
|
| 137 |
+
self,
|
| 138 |
+
qkv: torch.Tensor,
|
| 139 |
+
output_attentions: bool,
|
| 140 |
+
) -> tuple[torch.Tensor, torch.Tensor | None]:
|
| 141 |
+
"""Bit-identical port of flash_attn.modules.mha.SelfAttention.forward.
|
| 142 |
+
|
| 143 |
+
Key choices that must match vortex (which delegates to this class
|
| 144 |
+
when use_flash_attn=False):
|
| 145 |
+
|
| 146 |
+
* einsum (not matmul) for QK^T and PV: bf16 matmul vs bf16 einsum
|
| 147 |
+
use different accumulator orders, ~3e-2 per attention layer.
|
| 148 |
+
* -10000.0 causal mask (not -inf): vortex uses a finite mask value.
|
| 149 |
+
* softmax(scores, dim=-1, dtype=v.dtype) (not F.softmax(.float())):
|
| 150 |
+
PyTorch promotes to fp32 internally then casts to v.dtype.
|
| 151 |
+
Explicit .float() then .to(v.dtype) cast rounds differently.
|
| 152 |
+
* scale applied to K (k * scale), not Q. Same math, different
|
| 153 |
+
bf16 multiply target.
|
| 154 |
+
"""
|
| 155 |
+
q, k, v = qkv.unbind(dim=2) # each (B, T, H, D)
|
| 156 |
+
softmax_scale = (
|
| 157 |
+
self.softmax_scale if self.softmax_scale is not None
|
| 158 |
+
else 1.0 / math.sqrt(self.head_dim)
|
| 159 |
+
)
|
| 160 |
+
scores = torch.einsum("bthd,bshd->bhts", q, k * softmax_scale)
|
| 161 |
+
T = q.shape[1]
|
| 162 |
+
if self.causal:
|
| 163 |
+
causal_mask = torch.triu(
|
| 164 |
+
torch.full((T, T), -10000.0, device=scores.device), 1
|
| 165 |
+
)
|
| 166 |
+
scores = scores + causal_mask.to(dtype=scores.dtype)
|
| 167 |
+
attention = torch.softmax(scores, dim=-1, dtype=v.dtype)
|
| 168 |
+
if self.training and self.dropout_p > 0:
|
| 169 |
+
attention = F.dropout(attention, p=self.dropout_p)
|
| 170 |
+
out = torch.einsum("bhts,bshd->bthd", attention, v)
|
| 171 |
+
return out, (attention if output_attentions else None)
|
| 172 |
+
|
| 173 |
+
def _forward_sdpa(self, qkv: torch.Tensor) -> torch.Tensor:
|
| 174 |
+
q, k, v = qkv.unbind(dim=2)
|
| 175 |
+
q = q.permute(0, 2, 1, 3)
|
| 176 |
+
k = k.permute(0, 2, 1, 3)
|
| 177 |
+
v = v.permute(0, 2, 1, 3)
|
| 178 |
+
scale = self.softmax_scale if self.softmax_scale is not None else None
|
| 179 |
+
out = F.scaled_dot_product_attention(
|
| 180 |
+
q, k, v,
|
| 181 |
+
attn_mask=None,
|
| 182 |
+
dropout_p=self.dropout_p if self.training else 0.0,
|
| 183 |
+
is_causal=self.causal,
|
| 184 |
+
scale=scale,
|
| 185 |
+
)
|
| 186 |
+
return out.permute(0, 2, 1, 3)
|
| 187 |
+
|
| 188 |
+
def _forward_flash(self, qkv: torch.Tensor) -> torch.Tensor:
|
| 189 |
+
_flash_attn_required()
|
| 190 |
+
from flash_attn import flash_attn_qkvpacked_func
|
| 191 |
+
out = flash_attn_qkvpacked_func(
|
| 192 |
+
qkv,
|
| 193 |
+
dropout_p=self.dropout_p if self.training else 0.0,
|
| 194 |
+
softmax_scale=self.softmax_scale,
|
| 195 |
+
causal=self.causal,
|
| 196 |
+
)
|
| 197 |
+
return out
|
| 198 |
+
|
| 199 |
+
def _forward_with_cache(
|
| 200 |
+
self,
|
| 201 |
+
qkv: torch.Tensor,
|
| 202 |
+
inference_params,
|
| 203 |
+
) -> torch.Tensor:
|
| 204 |
+
if self.rotary_emb_dim > 0:
|
| 205 |
+
qkv = self.rotary_emb(
|
| 206 |
+
qkv,
|
| 207 |
+
seqlen_offset=inference_params.seqlen_offset,
|
| 208 |
+
max_seqlen=inference_params.max_seqlen,
|
| 209 |
+
)
|
| 210 |
+
q, k, v = qkv.unbind(dim=2)
|
| 211 |
+
kv = torch.stack((k, v), dim=2)
|
| 212 |
+
kv = _update_kv_cache(kv, inference_params, self.layer_idx)
|
| 213 |
+
k_full, v_full = kv.unbind(dim=2)
|
| 214 |
+
|
| 215 |
+
q = q.permute(0, 2, 1, 3)
|
| 216 |
+
k_full = k_full.permute(0, 2, 1, 3)
|
| 217 |
+
v_full = v_full.permute(0, 2, 1, 3)
|
| 218 |
+
scale = self.softmax_scale if self.softmax_scale is not None else None
|
| 219 |
+
is_causal = self.causal and q.shape[-2] == k_full.shape[-2]
|
| 220 |
+
out = F.scaled_dot_product_attention(
|
| 221 |
+
q, k_full, v_full, is_causal=is_causal, scale=scale,
|
| 222 |
+
)
|
| 223 |
+
return out.permute(0, 2, 1, 3)
|
| 224 |
+
|
| 225 |
+
def forward(
|
| 226 |
+
self,
|
| 227 |
+
x: torch.Tensor,
|
| 228 |
+
inference_params=None,
|
| 229 |
+
output_attentions: bool = False,
|
| 230 |
+
**_unused,
|
| 231 |
+
) -> tuple[torch.Tensor, torch.Tensor | None]:
|
| 232 |
+
if self.num_heads_kv != self.num_heads:
|
| 233 |
+
raise NotImplementedError("GQA is not exercised by Evo2.")
|
| 234 |
+
|
| 235 |
+
qkv = self._project_qkv(x)
|
| 236 |
+
|
| 237 |
+
if inference_params is not None:
|
| 238 |
+
out_btd = self._forward_with_cache(qkv, inference_params)
|
| 239 |
+
attn_weights = None
|
| 240 |
+
else:
|
| 241 |
+
if self.rotary_emb_dim > 0:
|
| 242 |
+
qkv = self.rotary_emb(qkv, seqlen_offset=0, max_seqlen=qkv.shape[1])
|
| 243 |
+
|
| 244 |
+
backend = self.attn_implementation
|
| 245 |
+
if output_attentions and backend != "eager":
|
| 246 |
+
backend = "eager"
|
| 247 |
+
|
| 248 |
+
if backend == "eager":
|
| 249 |
+
out_btd, attn_weights = self._forward_eager(qkv, output_attentions=output_attentions)
|
| 250 |
+
elif backend == "sdpa":
|
| 251 |
+
out_btd = self._forward_sdpa(qkv)
|
| 252 |
+
attn_weights = None
|
| 253 |
+
elif backend == "flash_attention_2":
|
| 254 |
+
out_btd = self._forward_flash(qkv)
|
| 255 |
+
attn_weights = None
|
| 256 |
+
else:
|
| 257 |
+
raise ValueError(f"Unknown attn_implementation: {backend!r}")
|
| 258 |
+
|
| 259 |
+
B, T, H, D = out_btd.shape
|
| 260 |
+
out_flat = out_btd.reshape(B, T, H * D)
|
| 261 |
+
return self.out_proj(out_flat), attn_weights
|
cache.py
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Inference-time caches for Evo2 blocks.
|
| 2 |
+
|
| 3 |
+
StripedHyena2 has four block types with different caching needs:
|
| 4 |
+
|
| 5 |
+
* `attn` blocks -> InferenceParams (standard KV cache)
|
| 6 |
+
* `hcl` blocks -> HyenaCascadeIIRInferenceParams (FIR window + IIR state)
|
| 7 |
+
* `hcm` blocks -> HyenaCascadeFIRInferenceParams (outer FIR + inner FIR)
|
| 8 |
+
* `hcs` blocks -> HyenaCascadeFIRInferenceParams (outer FIR + inner FIR)
|
| 9 |
+
|
| 10 |
+
Layer outputs of these caches are wrapped together inside an HF Cache subclass
|
| 11 |
+
(`Evo2Cache`) so model.generate() can drive autoregressive decoding without
|
| 12 |
+
the user having to instantiate four separate caches by hand.
|
| 13 |
+
"""
|
| 14 |
+
|
| 15 |
+
from __future__ import annotations
|
| 16 |
+
|
| 17 |
+
from dataclasses import dataclass, field
|
| 18 |
+
from typing import Optional
|
| 19 |
+
|
| 20 |
+
import torch
|
| 21 |
+
from torch import Tensor
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
@dataclass
|
| 25 |
+
class InferenceParams:
|
| 26 |
+
"""Standard KV cache for attention blocks."""
|
| 27 |
+
|
| 28 |
+
max_seqlen: int
|
| 29 |
+
max_batch_size: int
|
| 30 |
+
seqlen_offset: int = 0
|
| 31 |
+
batch_size_offset: int = 0
|
| 32 |
+
key_value_memory_dict: dict = field(default_factory=dict)
|
| 33 |
+
lengths_per_sample: Optional[Tensor] = None
|
| 34 |
+
|
| 35 |
+
def reset(self, max_seqlen, max_batch_size):
|
| 36 |
+
self.max_seqlen = max_seqlen
|
| 37 |
+
self.max_batch_size = max_batch_size
|
| 38 |
+
self.seqlen_offset = 0
|
| 39 |
+
if self.lengths_per_sample is not None:
|
| 40 |
+
self.lengths_per_sample.zero_()
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
@dataclass
|
| 44 |
+
class HyenaCascadeIIRInferenceParams:
|
| 45 |
+
"""Cache for `hcl` blocks: short FIR window + IIR modal state."""
|
| 46 |
+
|
| 47 |
+
fir_filter_length: int = 3
|
| 48 |
+
state_dim: int = 16
|
| 49 |
+
seqlen_offset: int = 0
|
| 50 |
+
fir_state_dict: dict = field(default_factory=dict)
|
| 51 |
+
state_dict: dict = field(default_factory=dict)
|
| 52 |
+
|
| 53 |
+
def reset(self):
|
| 54 |
+
self.seqlen_offset = 0
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
@dataclass
|
| 58 |
+
class HyenaCascadeFIRInferenceParams:
|
| 59 |
+
"""Cache for `hcm` and `hcs` blocks: outer short FIR + inner FIR cascade."""
|
| 60 |
+
|
| 61 |
+
fir_filter_length: int = 3
|
| 62 |
+
fir_inner_filter_length: int = 4
|
| 63 |
+
seqlen_offset: int = 0
|
| 64 |
+
fir_inner_state_dict: dict = field(default_factory=dict)
|
| 65 |
+
fir_state_dict: dict = field(default_factory=dict)
|
| 66 |
+
state_dict: dict = field(default_factory=dict)
|
| 67 |
+
|
| 68 |
+
def reset(self):
|
| 69 |
+
self.seqlen_offset = 0
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
class Evo2Cache:
|
| 73 |
+
"""Container for per-block-type inference params.
|
| 74 |
+
|
| 75 |
+
Not a transformers.Cache subclass (the new Cache API requires per-layer
|
| 76 |
+
dataclasses, which doesn't fit StripedHyena 2's 4 block-type-specific
|
| 77 |
+
state structures). Instead we set Evo2PreTrainedModel._supports_cache_class
|
| 78 |
+
= False so HF's generate() treats this as an opaque past_key_values dict.
|
| 79 |
+
"""
|
| 80 |
+
|
| 81 |
+
is_compileable = False
|
| 82 |
+
|
| 83 |
+
def __init__(
|
| 84 |
+
self,
|
| 85 |
+
max_seqlen: int,
|
| 86 |
+
max_batch_size: int,
|
| 87 |
+
short_filter_length: int,
|
| 88 |
+
hcm_filter_length: int,
|
| 89 |
+
hcs_filter_length: int,
|
| 90 |
+
state_size: int,
|
| 91 |
+
):
|
| 92 |
+
self.mha = InferenceParams(
|
| 93 |
+
max_seqlen=max_seqlen,
|
| 94 |
+
max_batch_size=max_batch_size,
|
| 95 |
+
)
|
| 96 |
+
self.hcl = HyenaCascadeIIRInferenceParams(
|
| 97 |
+
fir_filter_length=short_filter_length,
|
| 98 |
+
state_dim=state_size,
|
| 99 |
+
)
|
| 100 |
+
self.hcm = HyenaCascadeFIRInferenceParams(
|
| 101 |
+
fir_filter_length=short_filter_length,
|
| 102 |
+
fir_inner_filter_length=hcm_filter_length,
|
| 103 |
+
)
|
| 104 |
+
self.hcs = HyenaCascadeFIRInferenceParams(
|
| 105 |
+
fir_filter_length=short_filter_length,
|
| 106 |
+
fir_inner_filter_length=hcs_filter_length,
|
| 107 |
+
)
|
| 108 |
+
|
| 109 |
+
@property
|
| 110 |
+
def seqlen_offset(self) -> int:
|
| 111 |
+
return self.mha.seqlen_offset
|
| 112 |
+
|
| 113 |
+
def get_seq_length(self, layer_idx: int = 0) -> int:
|
| 114 |
+
return self.mha.seqlen_offset
|
| 115 |
+
|
| 116 |
+
def get_max_cache_shape(self) -> int:
|
| 117 |
+
return self.mha.max_seqlen
|
| 118 |
+
|
| 119 |
+
def get_max_length(self) -> int:
|
| 120 |
+
return self.mha.max_seqlen
|
| 121 |
+
|
| 122 |
+
def advance(self, n: int = 1) -> None:
|
| 123 |
+
self.mha.seqlen_offset += n
|
| 124 |
+
self.hcl.seqlen_offset += n
|
| 125 |
+
self.hcm.seqlen_offset += n
|
| 126 |
+
self.hcs.seqlen_offset += n
|
| 127 |
+
|
| 128 |
+
def set_offset(self, offset: int) -> None:
|
| 129 |
+
self.mha.seqlen_offset = offset
|
| 130 |
+
self.hcl.seqlen_offset = offset
|
| 131 |
+
self.hcm.seqlen_offset = offset
|
| 132 |
+
self.hcs.seqlen_offset = offset
|
| 133 |
+
|
| 134 |
+
def reset(self) -> None:
|
| 135 |
+
self.mha.reset(self.mha.max_seqlen, self.mha.max_batch_size)
|
| 136 |
+
self.hcl.reset()
|
| 137 |
+
self.hcm.reset()
|
| 138 |
+
self.hcs.reset()
|
| 139 |
+
|
| 140 |
+
def by_block_name(self, name: str):
|
| 141 |
+
return getattr(self, name)
|
config.json
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"architectures": [
|
| 3 |
+
"Evo2ForCausalLM"
|
| 4 |
+
],
|
| 5 |
+
"attn_block_dtype": "bfloat16",
|
| 6 |
+
"attn_layer_idxs": [
|
| 7 |
+
3,
|
| 8 |
+
10,
|
| 9 |
+
17,
|
| 10 |
+
24,
|
| 11 |
+
31
|
| 12 |
+
],
|
| 13 |
+
"auto_map": {
|
| 14 |
+
"AutoConfig": "configuration_evo2.Evo2Config",
|
| 15 |
+
"AutoModel": "modeling_evo2.Evo2Model",
|
| 16 |
+
"AutoModelForCausalLM": "modeling_evo2.Evo2ForCausalLM"
|
| 17 |
+
},
|
| 18 |
+
"column_split": true,
|
| 19 |
+
"column_split_hyena": false,
|
| 20 |
+
"dtype": "bfloat16",
|
| 21 |
+
"eps": 1e-06,
|
| 22 |
+
"evo2_style_activations": true,
|
| 23 |
+
"final_norm": true,
|
| 24 |
+
"hcl_filter_groups": 4096,
|
| 25 |
+
"hcl_layer_idxs": [
|
| 26 |
+
2,
|
| 27 |
+
6,
|
| 28 |
+
9,
|
| 29 |
+
13,
|
| 30 |
+
16,
|
| 31 |
+
20,
|
| 32 |
+
23,
|
| 33 |
+
27,
|
| 34 |
+
30
|
| 35 |
+
],
|
| 36 |
+
"hcm_filter_groups": 256,
|
| 37 |
+
"hcm_filter_length": 128,
|
| 38 |
+
"hcm_layer_idxs": [
|
| 39 |
+
1,
|
| 40 |
+
5,
|
| 41 |
+
8,
|
| 42 |
+
12,
|
| 43 |
+
15,
|
| 44 |
+
19,
|
| 45 |
+
22,
|
| 46 |
+
26,
|
| 47 |
+
29
|
| 48 |
+
],
|
| 49 |
+
"hcs_filter_groups": 256,
|
| 50 |
+
"hcs_filter_length": 7,
|
| 51 |
+
"hcs_layer_idxs": [
|
| 52 |
+
0,
|
| 53 |
+
4,
|
| 54 |
+
7,
|
| 55 |
+
11,
|
| 56 |
+
14,
|
| 57 |
+
18,
|
| 58 |
+
21,
|
| 59 |
+
25,
|
| 60 |
+
28
|
| 61 |
+
],
|
| 62 |
+
"hidden_size": 4096,
|
| 63 |
+
"hyena_block_dtype": "bfloat16",
|
| 64 |
+
"hyena_filter_groups": 1,
|
| 65 |
+
"hyena_flip_x1x2": false,
|
| 66 |
+
"hyena_out_proj_bias": true,
|
| 67 |
+
"inference_mode": true,
|
| 68 |
+
"inner_mlp_size": 11008,
|
| 69 |
+
"inner_size_multiple_of": 16,
|
| 70 |
+
"interleave": true,
|
| 71 |
+
"log_intermediate_values": false,
|
| 72 |
+
"make_vocab_size_divisible_by": 8,
|
| 73 |
+
"max_batch_size": 1,
|
| 74 |
+
"max_seqlen": 8192,
|
| 75 |
+
"mha_out_proj_bias": true,
|
| 76 |
+
"mlp_activation": "gelu",
|
| 77 |
+
"mlp_dtype": "bfloat16",
|
| 78 |
+
"mlp_init_method": "torch.nn.init.zeros_",
|
| 79 |
+
"mlp_output_init_method": "torch.nn.init.zeros_",
|
| 80 |
+
"model_parallel_size": 1,
|
| 81 |
+
"model_type": "evo2",
|
| 82 |
+
"num_attention_heads": 32,
|
| 83 |
+
"num_filters": 4096,
|
| 84 |
+
"num_layers": 32,
|
| 85 |
+
"pipe_parallel_size": 1,
|
| 86 |
+
"prefill_style": "fft",
|
| 87 |
+
"print_activations": false,
|
| 88 |
+
"proj_groups": 1,
|
| 89 |
+
"qkv_proj_bias": false,
|
| 90 |
+
"rotary_emb_base": 10000,
|
| 91 |
+
"rotary_emb_scaling_factor": 1.0,
|
| 92 |
+
"short_filter_bias": false,
|
| 93 |
+
"short_filter_length": 3,
|
| 94 |
+
"smeared_gqa": false,
|
| 95 |
+
"state_size": 16,
|
| 96 |
+
"tie_embeddings": true,
|
| 97 |
+
"transformers_version": "4.57.6",
|
| 98 |
+
"use_cache": true,
|
| 99 |
+
"use_flash_attn": false,
|
| 100 |
+
"use_flash_depthwise": false,
|
| 101 |
+
"use_flash_rmsnorm": false,
|
| 102 |
+
"use_flashfft": false,
|
| 103 |
+
"use_fp8_input_projections": false,
|
| 104 |
+
"use_interpolated_rotary_pos_emb": false,
|
| 105 |
+
"use_laughing_hyena": false,
|
| 106 |
+
"vocab_size": 512,
|
| 107 |
+
"model_max_length": 8192
|
| 108 |
+
}
|
configuration_evo2.py
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Configuration for Evo2 (StripedHyena2)."""
|
| 2 |
+
|
| 3 |
+
from __future__ import annotations
|
| 4 |
+
|
| 5 |
+
import json
|
| 6 |
+
from typing import List
|
| 7 |
+
|
| 8 |
+
from transformers import PretrainedConfig
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
class Evo2Config(PretrainedConfig):
|
| 12 |
+
"""Evo2 config.
|
| 13 |
+
|
| 14 |
+
Defaults match evo2_7b_base (32-layer, 4096-hidden). Per-variant overrides
|
| 15 |
+
are written into the config.json of each repo by convert_checkpoint.py.
|
| 16 |
+
|
| 17 |
+
Block dispatch is driven by four index lists:
|
| 18 |
+
attn_layer_idxs : transformer (MHA + RoPE) blocks
|
| 19 |
+
hcl_layer_idxs : Hyena Cascade Long (IIR via log_poles + residues)
|
| 20 |
+
hcm_layer_idxs : Hyena Cascade Medium (FIR, fir_inner_filter_length=128)
|
| 21 |
+
hcs_layer_idxs : Hyena Cascade Short (FIR, fir_inner_filter_length=7)
|
| 22 |
+
Their disjoint union must equal range(num_layers).
|
| 23 |
+
"""
|
| 24 |
+
|
| 25 |
+
model_type = "evo2"
|
| 26 |
+
|
| 27 |
+
def __init__(
|
| 28 |
+
self,
|
| 29 |
+
# Architecture core
|
| 30 |
+
vocab_size: int = 512,
|
| 31 |
+
hidden_size: int = 4096,
|
| 32 |
+
num_filters: int = 4096,
|
| 33 |
+
inner_mlp_size: int = 11008,
|
| 34 |
+
num_layers: int = 32,
|
| 35 |
+
num_attention_heads: int = 32,
|
| 36 |
+
# Block dispatch
|
| 37 |
+
attn_layer_idxs: List[int] | None = None,
|
| 38 |
+
hcl_layer_idxs: List[int] | None = None,
|
| 39 |
+
hcm_layer_idxs: List[int] | None = None,
|
| 40 |
+
hcs_layer_idxs: List[int] | None = None,
|
| 41 |
+
# Filter geometry
|
| 42 |
+
hcm_filter_length: int = 128,
|
| 43 |
+
hcs_filter_length: int = 7,
|
| 44 |
+
hcl_filter_groups: int = 4096,
|
| 45 |
+
hcm_filter_groups: int = 256,
|
| 46 |
+
hcs_filter_groups: int = 256,
|
| 47 |
+
hyena_filter_groups: int = 1,
|
| 48 |
+
short_filter_length: int = 3,
|
| 49 |
+
short_filter_bias: bool = False,
|
| 50 |
+
state_size: int = 16,
|
| 51 |
+
# Channel-split conventions
|
| 52 |
+
column_split: bool = True,
|
| 53 |
+
column_split_hyena: bool = False,
|
| 54 |
+
interleave: bool = True,
|
| 55 |
+
hyena_flip_x1x2: bool = False,
|
| 56 |
+
# Norms / activations
|
| 57 |
+
eps: float = 1e-6,
|
| 58 |
+
final_norm: bool = True,
|
| 59 |
+
mlp_activation: str = "gelu",
|
| 60 |
+
evo2_style_activations: bool = True,
|
| 61 |
+
# Linear biases
|
| 62 |
+
mha_out_proj_bias: bool = True,
|
| 63 |
+
hyena_out_proj_bias: bool = True,
|
| 64 |
+
qkv_proj_bias: bool = False,
|
| 65 |
+
# MLP geometry
|
| 66 |
+
inner_size_multiple_of: int = 16,
|
| 67 |
+
make_vocab_size_divisible_by: int = 8,
|
| 68 |
+
# Embeddings
|
| 69 |
+
tie_embeddings: bool = True,
|
| 70 |
+
# Rotary / sequence
|
| 71 |
+
max_seqlen: int = 8192,
|
| 72 |
+
max_batch_size: int = 1,
|
| 73 |
+
rotary_emb_base: float = 10000.0,
|
| 74 |
+
use_interpolated_rotary_pos_emb: bool = False,
|
| 75 |
+
rotary_emb_scaling_factor: float = 1.0,
|
| 76 |
+
# Inference engine
|
| 77 |
+
prefill_style: str = "fft",
|
| 78 |
+
inference_mode: bool = True,
|
| 79 |
+
# Projection precision (TE FP8 - required for 1b / 20b / 40b)
|
| 80 |
+
use_fp8_input_projections: bool = False,
|
| 81 |
+
# Backend toggles
|
| 82 |
+
use_cache: bool = True,
|
| 83 |
+
# Vortex used this flag at runtime. Our HF port ignores it entirely
|
| 84 |
+
# (attention dispatch is driven by ``config._attn_implementation``,
|
| 85 |
+
# the standard HF mechanism). Default is False here so the config
|
| 86 |
+
# reflects what actually runs: SDPA by default unless the user passes
|
| 87 |
+
# ``attn_implementation="flash_attention_2"`` to from_pretrained.
|
| 88 |
+
use_flash_attn: bool = False,
|
| 89 |
+
use_flash_rmsnorm: bool = False,
|
| 90 |
+
use_flash_depthwise: bool = False,
|
| 91 |
+
use_flashfft: bool = False,
|
| 92 |
+
# Per-block dtypes (cast at module init)
|
| 93 |
+
attn_block_dtype: str = "bfloat16",
|
| 94 |
+
hyena_block_dtype: str = "bfloat16",
|
| 95 |
+
mlp_dtype: str = "bfloat16",
|
| 96 |
+
# Multi-tensor parallel knobs (kept for ParallelGatedMLP._compute_inner_size)
|
| 97 |
+
model_parallel_size: int = 1,
|
| 98 |
+
pipe_parallel_size: int = 1,
|
| 99 |
+
# GQA
|
| 100 |
+
proj_groups: int = 1,
|
| 101 |
+
smeared_gqa: bool = False,
|
| 102 |
+
**kwargs,
|
| 103 |
+
):
|
| 104 |
+
if attn_layer_idxs is None:
|
| 105 |
+
attn_layer_idxs = [3, 10, 17, 24, 31]
|
| 106 |
+
if hcl_layer_idxs is None:
|
| 107 |
+
hcl_layer_idxs = [2, 6, 9, 13, 16, 20, 23, 27, 30]
|
| 108 |
+
if hcm_layer_idxs is None:
|
| 109 |
+
hcm_layer_idxs = [1, 5, 8, 12, 15, 19, 22, 26, 29]
|
| 110 |
+
if hcs_layer_idxs is None:
|
| 111 |
+
hcs_layer_idxs = [0, 4, 7, 11, 14, 18, 21, 25, 28]
|
| 112 |
+
|
| 113 |
+
self.vocab_size = vocab_size
|
| 114 |
+
self.hidden_size = hidden_size
|
| 115 |
+
self.num_filters = num_filters
|
| 116 |
+
self.inner_mlp_size = inner_mlp_size
|
| 117 |
+
self.num_layers = num_layers
|
| 118 |
+
self.num_attention_heads = num_attention_heads
|
| 119 |
+
|
| 120 |
+
self.attn_layer_idxs = attn_layer_idxs
|
| 121 |
+
self.hcl_layer_idxs = hcl_layer_idxs
|
| 122 |
+
self.hcm_layer_idxs = hcm_layer_idxs
|
| 123 |
+
self.hcs_layer_idxs = hcs_layer_idxs
|
| 124 |
+
|
| 125 |
+
self.hcm_filter_length = hcm_filter_length
|
| 126 |
+
self.hcs_filter_length = hcs_filter_length
|
| 127 |
+
self.hcl_filter_groups = hcl_filter_groups
|
| 128 |
+
self.hcm_filter_groups = hcm_filter_groups
|
| 129 |
+
self.hcs_filter_groups = hcs_filter_groups
|
| 130 |
+
self.hyena_filter_groups = hyena_filter_groups
|
| 131 |
+
self.short_filter_length = short_filter_length
|
| 132 |
+
self.short_filter_bias = short_filter_bias
|
| 133 |
+
self.state_size = state_size
|
| 134 |
+
|
| 135 |
+
self.column_split = column_split
|
| 136 |
+
self.column_split_hyena = column_split_hyena
|
| 137 |
+
self.interleave = interleave
|
| 138 |
+
self.hyena_flip_x1x2 = hyena_flip_x1x2
|
| 139 |
+
|
| 140 |
+
self.eps = eps
|
| 141 |
+
self.final_norm = final_norm
|
| 142 |
+
self.mlp_activation = mlp_activation
|
| 143 |
+
self.evo2_style_activations = evo2_style_activations
|
| 144 |
+
|
| 145 |
+
self.mha_out_proj_bias = mha_out_proj_bias
|
| 146 |
+
self.hyena_out_proj_bias = hyena_out_proj_bias
|
| 147 |
+
self.qkv_proj_bias = qkv_proj_bias
|
| 148 |
+
|
| 149 |
+
self.inner_size_multiple_of = inner_size_multiple_of
|
| 150 |
+
self.make_vocab_size_divisible_by = make_vocab_size_divisible_by
|
| 151 |
+
|
| 152 |
+
self.tie_embeddings = tie_embeddings
|
| 153 |
+
|
| 154 |
+
self.max_seqlen = max_seqlen
|
| 155 |
+
self.max_batch_size = max_batch_size
|
| 156 |
+
self.rotary_emb_base = rotary_emb_base
|
| 157 |
+
self.use_interpolated_rotary_pos_emb = use_interpolated_rotary_pos_emb
|
| 158 |
+
self.rotary_emb_scaling_factor = rotary_emb_scaling_factor
|
| 159 |
+
|
| 160 |
+
self.prefill_style = prefill_style
|
| 161 |
+
self.inference_mode = inference_mode
|
| 162 |
+
|
| 163 |
+
self.use_fp8_input_projections = use_fp8_input_projections
|
| 164 |
+
|
| 165 |
+
self.use_cache = use_cache
|
| 166 |
+
self.use_flash_attn = use_flash_attn
|
| 167 |
+
self.use_flash_rmsnorm = use_flash_rmsnorm
|
| 168 |
+
self.use_flash_depthwise = use_flash_depthwise
|
| 169 |
+
self.use_flashfft = use_flashfft
|
| 170 |
+
|
| 171 |
+
self.attn_block_dtype = attn_block_dtype
|
| 172 |
+
self.hyena_block_dtype = hyena_block_dtype
|
| 173 |
+
self.mlp_dtype = mlp_dtype
|
| 174 |
+
|
| 175 |
+
self.model_parallel_size = model_parallel_size
|
| 176 |
+
self.pipe_parallel_size = pipe_parallel_size
|
| 177 |
+
|
| 178 |
+
self.proj_groups = proj_groups
|
| 179 |
+
self.smeared_gqa = smeared_gqa
|
| 180 |
+
|
| 181 |
+
super().__init__(**kwargs)
|
| 182 |
+
|
| 183 |
+
# HF generation helpers expect `num_hidden_layers`.
|
| 184 |
+
@property
|
| 185 |
+
def num_hidden_layers(self) -> int:
|
| 186 |
+
return self.num_layers
|
| 187 |
+
|
| 188 |
+
# Internal blocks were originally written against a dotdict and call
|
| 189 |
+
# `config.get(key, default)` extensively; provide a dict-like getter.
|
| 190 |
+
def get(self, key, default=None):
|
| 191 |
+
return getattr(self, key, default)
|
| 192 |
+
|
| 193 |
+
@classmethod
|
| 194 |
+
def from_original_config(cls, config_path: str, **kwargs) -> "Evo2Config":
|
| 195 |
+
with open(config_path, "r") as f:
|
| 196 |
+
config = json.load(f)
|
| 197 |
+
return cls(**config, **kwargs)
|
engine.py
ADDED
|
@@ -0,0 +1,327 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Hyena inference engine for Evo2 (StripedHyena2).
|
| 2 |
+
|
| 3 |
+
Three operator families are exercised by Evo2 blocks:
|
| 4 |
+
|
| 5 |
+
* parallel_fir(gate=False) -- outer FIR used by all hyena blocks before any
|
| 6 |
+
channel split (input projection convolution).
|
| 7 |
+
* parallel_fir(gate=True) -- inner FIR cascade used by hcm/hcs blocks
|
| 8 |
+
(x1 * v gated, then convolved by `h`,
|
| 9 |
+
then multiplied by x2 postgate).
|
| 10 |
+
* parallel_iir -- modal-form IIR (long convolution via FFT)
|
| 11 |
+
used by hcl blocks; poles + residues parameterize
|
| 12 |
+
a stable, long-range linear filter.
|
| 13 |
+
|
| 14 |
+
Sequential step paths (step_fir / step_iir) are used during generation.
|
| 15 |
+
|
| 16 |
+
Layout conventions match vortex exactly so checkpoints are bit-identical.
|
| 17 |
+
"""
|
| 18 |
+
|
| 19 |
+
from __future__ import annotations
|
| 20 |
+
|
| 21 |
+
import torch
|
| 22 |
+
import torch.nn.functional as F
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
IIR_PREFILL_MODES = ["recurrence", "modal-fft"]
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
def adjust_filter_shape_for_broadcast(u, h):
|
| 29 |
+
h = h.squeeze()
|
| 30 |
+
if len(u.shape) > len(h.shape):
|
| 31 |
+
h = h.unsqueeze(0)
|
| 32 |
+
if len(u.shape) > 3:
|
| 33 |
+
h = h.unsqueeze(1)
|
| 34 |
+
return h
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
def fftconv_func(u, k, D, dropout_mask, gelu=True, k_rev=None, bidirectional=False, **kwargs):
|
| 38 |
+
"""FFT convolution for long FIR filters (length >= 128 path)."""
|
| 39 |
+
seqlen = u.shape[-1]
|
| 40 |
+
fft_size = 2 * seqlen
|
| 41 |
+
|
| 42 |
+
k_f = torch.fft.rfft(k, n=fft_size) / fft_size
|
| 43 |
+
k_f = adjust_filter_shape_for_broadcast(u, k_f)
|
| 44 |
+
k = k.squeeze()
|
| 45 |
+
|
| 46 |
+
if bidirectional:
|
| 47 |
+
u_f = torch.fft.rfft(u.to(dtype=k.dtype), n=fft_size)
|
| 48 |
+
k, k2 = k.split(k.shape[1] // 2, dim=1)
|
| 49 |
+
k2_f = torch.fft.rfft(k2, n=fft_size) / fft_size
|
| 50 |
+
y1 = u_f * k_f
|
| 51 |
+
y2 = u_f.conj() * k2_f.conj()
|
| 52 |
+
y = torch.fft.irfft(y1 + y2, n=fft_size, norm="forward")[..., :seqlen]
|
| 53 |
+
else:
|
| 54 |
+
if k_rev is not None:
|
| 55 |
+
k_rev_f = torch.fft.rfft(k_rev, n=fft_size) / fft_size
|
| 56 |
+
k_f = k_f + k_rev_f.conj()
|
| 57 |
+
u_f = torch.fft.rfft(u.to(dtype=k.dtype), n=fft_size)
|
| 58 |
+
y = torch.fft.irfft(u_f * k_f, n=fft_size, norm="forward")[..., :seqlen]
|
| 59 |
+
|
| 60 |
+
out = y + u * D.unsqueeze(-1)
|
| 61 |
+
return out.to(dtype=u.dtype)
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
def _column_split(x, num_heads, head_size):
|
| 65 |
+
"""Compatibility helper for column_split_hyena=True (not used by Evo2)."""
|
| 66 |
+
x = x.reshape(x.shape[0], num_heads, 3 * head_size, x.shape[2])
|
| 67 |
+
x2 = x[:, :, :head_size].reshape(x.shape[0], -1, x.shape[-1])
|
| 68 |
+
x1 = x[:, :, head_size : 2 * head_size].reshape(x.shape[0], -1, x.shape[-1])
|
| 69 |
+
v = x[:, :, 2 * head_size :].reshape(x.shape[0], -1, x.shape[-1])
|
| 70 |
+
return x2, x1, v
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
class HyenaInferenceEngine:
|
| 74 |
+
def __init__(
|
| 75 |
+
self,
|
| 76 |
+
layer_idx: int | None = None,
|
| 77 |
+
iir_prefill_style: str = "modal-fft",
|
| 78 |
+
hyena_flip_x1x2: bool = False,
|
| 79 |
+
) -> None:
|
| 80 |
+
assert iir_prefill_style in IIR_PREFILL_MODES, iir_prefill_style
|
| 81 |
+
self.iir_prefill_style = iir_prefill_style
|
| 82 |
+
self.layer_idx = layer_idx
|
| 83 |
+
self.low_mem_mode = False
|
| 84 |
+
self.hyena_flip_x1x2 = hyena_flip_x1x2
|
| 85 |
+
|
| 86 |
+
# ---------------------------------------------------------------- FIR
|
| 87 |
+
def parallel_fir(
|
| 88 |
+
self,
|
| 89 |
+
fir_fn,
|
| 90 |
+
u,
|
| 91 |
+
weight,
|
| 92 |
+
bias,
|
| 93 |
+
L,
|
| 94 |
+
dims,
|
| 95 |
+
groups=None,
|
| 96 |
+
gated_bias=False,
|
| 97 |
+
column_split_hyena=False,
|
| 98 |
+
dim_last=True,
|
| 99 |
+
fir_length=3,
|
| 100 |
+
gate=False,
|
| 101 |
+
inference_params=None,
|
| 102 |
+
padding_mask=None,
|
| 103 |
+
):
|
| 104 |
+
L = u.shape[1] if dim_last else u.shape[2]
|
| 105 |
+
if gate:
|
| 106 |
+
hidden_size, num_attention_heads, hidden_size_per_attention_head, _, _ = dims
|
| 107 |
+
if column_split_hyena:
|
| 108 |
+
x2, x1, v = _column_split(u, num_attention_heads, hidden_size_per_attention_head)
|
| 109 |
+
else:
|
| 110 |
+
x2, x1, v = u.split([hidden_size, hidden_size, hidden_size], dim=1)
|
| 111 |
+
if self.hyena_flip_x1x2:
|
| 112 |
+
x1, x2 = x2, x1
|
| 113 |
+
u = x1 * v
|
| 114 |
+
|
| 115 |
+
if fir_length >= 128:
|
| 116 |
+
with torch.autocast("cuda"):
|
| 117 |
+
z = fftconv_func(
|
| 118 |
+
u.to(torch.float32),
|
| 119 |
+
weight[:, :, :L].to(torch.float32),
|
| 120 |
+
bias,
|
| 121 |
+
None,
|
| 122 |
+
gelu=False,
|
| 123 |
+
bidirectional=False,
|
| 124 |
+
groups=groups,
|
| 125 |
+
)
|
| 126 |
+
z = z.to(u.dtype)
|
| 127 |
+
else:
|
| 128 |
+
if dim_last:
|
| 129 |
+
u = u.permute(0, 2, 1) # B, D, L
|
| 130 |
+
|
| 131 |
+
z = fir_fn(
|
| 132 |
+
u.to(torch.float32),
|
| 133 |
+
weight.to(torch.float32),
|
| 134 |
+
bias=None,
|
| 135 |
+
stride=1,
|
| 136 |
+
padding=fir_length - 1,
|
| 137 |
+
groups=u.shape[1],
|
| 138 |
+
)[..., :L]
|
| 139 |
+
|
| 140 |
+
z = z.to(u.dtype)
|
| 141 |
+
|
| 142 |
+
if bias is not None:
|
| 143 |
+
if gated_bias:
|
| 144 |
+
z = z + bias[None, :, None] * u
|
| 145 |
+
else:
|
| 146 |
+
z = z + bias[None, :, None]
|
| 147 |
+
|
| 148 |
+
if isinstance(padding_mask, torch.Tensor):
|
| 149 |
+
z = z * padding_mask[:, None]
|
| 150 |
+
|
| 151 |
+
if gate:
|
| 152 |
+
z = x2 * z
|
| 153 |
+
|
| 154 |
+
if inference_params is not None:
|
| 155 |
+
fir_state = u[..., -fir_length + 1 :]
|
| 156 |
+
else:
|
| 157 |
+
fir_state = None
|
| 158 |
+
|
| 159 |
+
return z, fir_state
|
| 160 |
+
|
| 161 |
+
# ---------------------------------------------------------------- IIR
|
| 162 |
+
def parallel_iir(
|
| 163 |
+
self,
|
| 164 |
+
z_pre,
|
| 165 |
+
h,
|
| 166 |
+
D,
|
| 167 |
+
L,
|
| 168 |
+
poles,
|
| 169 |
+
residues,
|
| 170 |
+
t,
|
| 171 |
+
dims,
|
| 172 |
+
layer_idx,
|
| 173 |
+
inference_params=None,
|
| 174 |
+
prefill_style: str = "fft",
|
| 175 |
+
fftconv_fn=None,
|
| 176 |
+
padding_mask=None,
|
| 177 |
+
use_flashfft: bool = False,
|
| 178 |
+
column_split_hyena: bool = False,
|
| 179 |
+
long_fir_threshold: int | None = None,
|
| 180 |
+
):
|
| 181 |
+
fft_size = 2 * L
|
| 182 |
+
hidden_size, num_attention_heads, hidden_size_per_attention_head, _, _ = dims
|
| 183 |
+
if column_split_hyena:
|
| 184 |
+
x2, x1, v = _column_split(z_pre, num_attention_heads, hidden_size_per_attention_head)
|
| 185 |
+
else:
|
| 186 |
+
x2, x1, v = z_pre.split([hidden_size, hidden_size, hidden_size], dim=1)
|
| 187 |
+
|
| 188 |
+
if self.hyena_flip_x1x2:
|
| 189 |
+
x1, x2 = x2, x1
|
| 190 |
+
|
| 191 |
+
x1v = x1 * v
|
| 192 |
+
|
| 193 |
+
X_s = None
|
| 194 |
+
if inference_params is not None and prefill_style == "recurrence":
|
| 195 |
+
y = self.prefill_via_direct_recurrence(
|
| 196 |
+
inference_params=inference_params, x1v=x1v, L=L,
|
| 197 |
+
poles=poles, residues=residues,
|
| 198 |
+
)
|
| 199 |
+
else:
|
| 200 |
+
if use_flashfft and (L % 2) == 0:
|
| 201 |
+
y = fftconv_fn(
|
| 202 |
+
x1v.to(dtype=torch.bfloat16).contiguous(),
|
| 203 |
+
h.to(dtype=torch.float32),
|
| 204 |
+
)
|
| 205 |
+
elif long_fir_threshold is None:
|
| 206 |
+
H = torch.fft.rfft(h.to(dtype=torch.float32), n=fft_size) / fft_size
|
| 207 |
+
X_s = torch.fft.fft(x1v.to(dtype=torch.float32), n=fft_size)
|
| 208 |
+
X = X_s[..., : H.shape[-1]]
|
| 209 |
+
if len(z_pre.shape) > 3:
|
| 210 |
+
H = H.unsqueeze(1)
|
| 211 |
+
y = torch.fft.irfft(X * H, n=fft_size, norm="forward")[..., :L]
|
| 212 |
+
else:
|
| 213 |
+
assert h.shape[0] == 1, "batch size must be 1 for long_fir_threshold"
|
| 214 |
+
h = h[0][:, None]
|
| 215 |
+
h = h[..., :long_fir_threshold]
|
| 216 |
+
y = F.conv1d(
|
| 217 |
+
x1v, h.to(dtype=x1v.dtype),
|
| 218 |
+
stride=1, groups=x1v.shape[1],
|
| 219 |
+
padding=h.shape[-1] - 1,
|
| 220 |
+
)[..., :L]
|
| 221 |
+
|
| 222 |
+
y = y.to(dtype=x1v.dtype)
|
| 223 |
+
y = (y + x1v * D.unsqueeze(-1)) * x2
|
| 224 |
+
|
| 225 |
+
if inference_params is not None and prefill_style == "fft":
|
| 226 |
+
self.prefill_via_modal_fft(
|
| 227 |
+
inference_params=inference_params, x1v=x1v, X_s=X_s, L=L,
|
| 228 |
+
t=t, poles=poles, dims=dims, layer_idx=layer_idx,
|
| 229 |
+
use_flashfft=use_flashfft, fftconv_fn=fftconv_fn,
|
| 230 |
+
)
|
| 231 |
+
|
| 232 |
+
return y.permute(0, 2, 1)
|
| 233 |
+
|
| 234 |
+
# --------------------------------------------------------- step (decode)
|
| 235 |
+
def step_fir(self, u, fir_state, weight, bias=None, gated_bias=False, flip_filter=False):
|
| 236 |
+
"""Single-step FIR. fir_state holds the last (filter_len - 1) inputs."""
|
| 237 |
+
weight = weight.squeeze()
|
| 238 |
+
cache_size = fir_state.shape[-1]
|
| 239 |
+
filter_length = weight.shape[-1]
|
| 240 |
+
if flip_filter:
|
| 241 |
+
weight = weight.flip(-1)
|
| 242 |
+
weight = weight[..., -cache_size - 1 :].unsqueeze(0)
|
| 243 |
+
else:
|
| 244 |
+
weight = weight[..., : cache_size + 1].unsqueeze(0)
|
| 245 |
+
|
| 246 |
+
input_dtype = u.dtype
|
| 247 |
+
weight = weight.to(torch.float32)
|
| 248 |
+
u = u.to(torch.float32)
|
| 249 |
+
fir_state = fir_state.to(torch.float32)
|
| 250 |
+
bias = bias.to(torch.float32) if bias is not None else None
|
| 251 |
+
|
| 252 |
+
h0, h = weight[..., -1], weight[..., :-1]
|
| 253 |
+
y = h0 * u + torch.sum(fir_state * h, dim=-1)
|
| 254 |
+
|
| 255 |
+
if bias is not None:
|
| 256 |
+
if gated_bias:
|
| 257 |
+
y = y + bias * u
|
| 258 |
+
else:
|
| 259 |
+
y = y + bias
|
| 260 |
+
|
| 261 |
+
if cache_size < filter_length - 1:
|
| 262 |
+
fir_state = torch.cat([fir_state, u[..., None]], dim=-1)
|
| 263 |
+
else:
|
| 264 |
+
fir_state = torch.roll(fir_state, -1, dims=2)
|
| 265 |
+
fir_state[..., -1] = u
|
| 266 |
+
|
| 267 |
+
return y.to(input_dtype), fir_state
|
| 268 |
+
|
| 269 |
+
def step_iir(self, x2, x1, v, D, residues, poles, iir_state, iir_groups=1):
|
| 270 |
+
x1v = x1 * v
|
| 271 |
+
# `poles` arg contains log_poles (real, in modal form for evo2)
|
| 272 |
+
poles = torch.exp(poles)
|
| 273 |
+
poles = poles[..., 0][None]
|
| 274 |
+
residues = residues[None]
|
| 275 |
+
iir_state = poles * iir_state + x1v[..., None]
|
| 276 |
+
res_state = torch.sum(residues * iir_state, dim=-1)
|
| 277 |
+
|
| 278 |
+
if iir_groups > 1:
|
| 279 |
+
raise NotImplementedError
|
| 280 |
+
y = x2 * (res_state + D * x1v)
|
| 281 |
+
return y, iir_state
|
| 282 |
+
|
| 283 |
+
def prefill_via_direct_recurrence(self, inference_params, x1v, L, residues, poles, *args, **kwargs):
|
| 284 |
+
state_dim = poles.shape[1]
|
| 285 |
+
x1v_ = x1v[..., None, None]
|
| 286 |
+
x1v_ = x1v_.repeat(1, 1, 1, state_dim, 2)
|
| 287 |
+
x1v_[..., 1] = 0
|
| 288 |
+
|
| 289 |
+
state = 0 * x1v_[:, :, 0]
|
| 290 |
+
output = 0 * x1v_[:, :, :, 0, 0]
|
| 291 |
+
|
| 292 |
+
poles = poles[:, :, 0][None]
|
| 293 |
+
residues = residues[:, :, 0][None].repeat(x1v_.shape[0], 1, 1, 1)
|
| 294 |
+
|
| 295 |
+
for i in range(L):
|
| 296 |
+
state[..., 0] = poles[..., 0] * state[..., 0] - poles[..., 1] * state[..., 1] + x1v_[:, :, i, :, 0]
|
| 297 |
+
state[..., 1] = poles[..., 0] * state[..., 1] + poles[..., 1] * state[..., 0] + x1v_[:, :, i, :, 1]
|
| 298 |
+
output[:, :, i] = torch.sum(residues * state, dim=-2)[..., 0]
|
| 299 |
+
|
| 300 |
+
inference_params.state_dict[self.layer_idx] = state.to(dtype=torch.float32)
|
| 301 |
+
return output
|
| 302 |
+
|
| 303 |
+
def prefill_via_modal_fft(
|
| 304 |
+
self, inference_params, x1v, L, poles, t, dims, layer_idx,
|
| 305 |
+
X_s=None, use_flashfft=False, fftconv_fn=None,
|
| 306 |
+
state_dtype=torch.float32, *args, **kwargs,
|
| 307 |
+
):
|
| 308 |
+
"""Compute IIR state via a single FFT.
|
| 309 |
+
|
| 310 |
+
Evo2 uses *real* `log_poles` (not the complex view-as-real layout
|
| 311 |
+
that Evo1 uses), so the impulse-response IFFT is mathematically real;
|
| 312 |
+
the imaginary component is FFT round-off. We take ``.real`` explicitly
|
| 313 |
+
instead of relying on torch's lossy complex->real cast, which avoids
|
| 314 |
+
the "Casting complex values to real discards the imaginary part"
|
| 315 |
+
UserWarning at every decoded token.
|
| 316 |
+
"""
|
| 317 |
+
hidden_size, _, _, state_size, hyena_filter_groups = dims
|
| 318 |
+
|
| 319 |
+
assert X_s is not None
|
| 320 |
+
bs = x1v.shape[0]
|
| 321 |
+
fft_size = 2 * L
|
| 322 |
+
state_s = (poles.to(torch.float32) * t).exp()
|
| 323 |
+
state_S = torch.fft.fft(state_s, n=fft_size).repeat(bs, 1, 1, 1)
|
| 324 |
+
if hyena_filter_groups > 1:
|
| 325 |
+
state_S = state_S.repeat_interleave(hidden_size // hyena_filter_groups, 1)
|
| 326 |
+
state = torch.fft.ifft(X_s[..., None, :] * state_S, n=fft_size)
|
| 327 |
+
inference_params.state_dict[layer_idx] = state[..., L - 1].real.to(dtype=state_dtype)
|
generation_config.json
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"eos_token_id": 0,
|
| 3 |
+
"pad_token_id": 1,
|
| 4 |
+
"_from_model_config": true
|
| 5 |
+
}
|
hyena.py
ADDED
|
@@ -0,0 +1,517 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""StripedHyena2 block definitions for Evo2.
|
| 2 |
+
|
| 3 |
+
Block types:
|
| 4 |
+
|
| 5 |
+
* AttentionBlock -- standard pre-norm transformer block with MHA + RoPE.
|
| 6 |
+
* ParallelGatedConvBlock -- pre-norm hyena block; the inner `filter` is a
|
| 7 |
+
HyenaCascade configured per block-type idx:
|
| 8 |
+
hcl: IIR via log_poles + residues
|
| 9 |
+
hcm: FIR cascade, fir_inner_filter_length=128
|
| 10 |
+
hcs: FIR cascade, fir_inner_filter_length=7
|
| 11 |
+
|
| 12 |
+
Inside ParallelGatedConvBlock, `projections` is a TELinear (3x hidden_size
|
| 13 |
+
output) -- the FP8-capable input projection. For 7B variants without TE,
|
| 14 |
+
the pure-PyTorch fallback in layers.py is used.
|
| 15 |
+
|
| 16 |
+
The `interleave` config flag (True for all Evo2 variants) reorders the
|
| 17 |
+
channel dim after the outer FIR before the channel-split / cascade.
|
| 18 |
+
"""
|
| 19 |
+
|
| 20 |
+
from __future__ import annotations
|
| 21 |
+
|
| 22 |
+
from typing import Optional, Tuple
|
| 23 |
+
|
| 24 |
+
import torch
|
| 25 |
+
import torch.nn as nn
|
| 26 |
+
import torch.nn.functional as F
|
| 27 |
+
|
| 28 |
+
from .attention import MHA
|
| 29 |
+
from .engine import HyenaInferenceEngine
|
| 30 |
+
from .layers import ParallelGatedMLP, RMSNorm, TELinear
|
| 31 |
+
from .rotary import swap_mha_rope
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
def _interleave(z_pre: torch.Tensor) -> torch.Tensor:
|
| 35 |
+
"""Deinterleave a [x1_0,x2_0,v_0,x1_1,x2_1,v_1,...] channel layout into
|
| 36 |
+
blocks of [x1_all | x2_all | v_all]. Matches vortex.model.utils.interleave."""
|
| 37 |
+
if len(z_pre.shape) == 3: # (B, C, L) non-cached path
|
| 38 |
+
x1 = z_pre[:, 0::3, :]
|
| 39 |
+
x2 = z_pre[:, 1::3, :]
|
| 40 |
+
v = z_pre[:, 2::3, :]
|
| 41 |
+
return torch.cat([x1, x2, v], dim=1)
|
| 42 |
+
x1 = z_pre[..., 0::3]
|
| 43 |
+
x2 = z_pre[..., 1::3]
|
| 44 |
+
v = z_pre[..., 2::3]
|
| 45 |
+
return torch.cat([x1, x2, v], dim=-1)
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
def _column_split_step(z_pre, num_heads, head_size):
|
| 49 |
+
"""Per-step variant of column_split for sequential_forward (cache step)."""
|
| 50 |
+
x = z_pre.reshape(z_pre.shape[0], num_heads, 3 * head_size)
|
| 51 |
+
x2 = x[..., :head_size].reshape(z_pre.shape[0], -1)
|
| 52 |
+
x1 = x[..., head_size : 2 * head_size].reshape(z_pre.shape[0], -1)
|
| 53 |
+
v = x[..., 2 * head_size :].reshape(z_pre.shape[0], -1)
|
| 54 |
+
return x2, x1, v
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
# =============================================================================
|
| 58 |
+
# Attention block
|
| 59 |
+
# =============================================================================
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
class AttentionBlock(nn.Module):
|
| 63 |
+
def __init__(self, config, layer_idx: int) -> None:
|
| 64 |
+
super().__init__()
|
| 65 |
+
self.config = config
|
| 66 |
+
self.layer_idx = layer_idx
|
| 67 |
+
self.pre_norm = RMSNorm(config)
|
| 68 |
+
self.post_norm = RMSNorm(config)
|
| 69 |
+
self.proj_groups = config.get("proj_groups", 1)
|
| 70 |
+
dtype = self._resolve_dtype(config.get("attn_block_dtype", "bfloat16"))
|
| 71 |
+
mlp_dtype = self._resolve_dtype(config.get("mlp_dtype", "bfloat16"))
|
| 72 |
+
self.num_attention_heads = config.num_attention_heads
|
| 73 |
+
self.hidden_size = config.hidden_size
|
| 74 |
+
self.hidden_size_per_attention_head = config.hidden_size // config.num_attention_heads
|
| 75 |
+
|
| 76 |
+
attn_impl = getattr(config, "_attn_implementation", "eager")
|
| 77 |
+
|
| 78 |
+
self.inner_mha_cls = MHA(
|
| 79 |
+
embed_dim=config.hidden_size,
|
| 80 |
+
num_heads=config.num_attention_heads,
|
| 81 |
+
num_heads_kv=config.num_attention_heads // self.proj_groups,
|
| 82 |
+
rotary_emb_dim=config.hidden_size // config.num_attention_heads,
|
| 83 |
+
qkv_proj_bias=config.get("qkv_proj_bias", False),
|
| 84 |
+
rotary_emb_base=config.get("rotary_emb_base", 1000000),
|
| 85 |
+
causal=True,
|
| 86 |
+
layer_idx=layer_idx,
|
| 87 |
+
out_proj_bias=config.get("mha_out_proj_bias", True),
|
| 88 |
+
attn_implementation=attn_impl,
|
| 89 |
+
).to(dtype=dtype)
|
| 90 |
+
|
| 91 |
+
if config.get("use_interpolated_rotary_pos_emb", False):
|
| 92 |
+
swap_mha_rope(
|
| 93 |
+
mha=self.inner_mha_cls,
|
| 94 |
+
kwargs_new_rope={
|
| 95 |
+
"scaling_factor": config.get("rotary_emb_scaling_factor", 1.0)
|
| 96 |
+
},
|
| 97 |
+
)
|
| 98 |
+
|
| 99 |
+
if self.config.get("smeared_gqa", False):
|
| 100 |
+
self.inner_mha_cls.num_heads_kv = self.inner_mha_cls.num_heads
|
| 101 |
+
# Round-trip inv_freq through state_dict for safety.
|
| 102 |
+
self.inner_mha_cls.rotary_emb.register_buffer(
|
| 103 |
+
"inv_freq", self.inner_mha_cls.rotary_emb.inv_freq
|
| 104 |
+
)
|
| 105 |
+
|
| 106 |
+
self.mlp = ParallelGatedMLP(config, layer_idx).to(dtype=mlp_dtype)
|
| 107 |
+
|
| 108 |
+
@staticmethod
|
| 109 |
+
def _resolve_dtype(name) -> torch.dtype:
|
| 110 |
+
if isinstance(name, torch.dtype):
|
| 111 |
+
return name
|
| 112 |
+
mapping = {
|
| 113 |
+
"bfloat16": torch.bfloat16,
|
| 114 |
+
"float16": torch.float16,
|
| 115 |
+
"float32": torch.float32,
|
| 116 |
+
}
|
| 117 |
+
return mapping.get(name, torch.bfloat16)
|
| 118 |
+
|
| 119 |
+
def forward(
|
| 120 |
+
self,
|
| 121 |
+
u: torch.Tensor,
|
| 122 |
+
inference_params=None,
|
| 123 |
+
padding_mask: Optional[torch.Tensor] = None,
|
| 124 |
+
output_attentions: bool = False,
|
| 125 |
+
*args,
|
| 126 |
+
**kwargs,
|
| 127 |
+
) -> Tuple[torch.Tensor, Optional[torch.Tensor]]:
|
| 128 |
+
if isinstance(padding_mask, torch.Tensor):
|
| 129 |
+
# Zero attended values at pad positions (no qkv bias here).
|
| 130 |
+
u = u * padding_mask[..., None]
|
| 131 |
+
|
| 132 |
+
attn_out, attn_weights = self.inner_mha_cls(
|
| 133 |
+
self.pre_norm(u),
|
| 134 |
+
inference_params=inference_params,
|
| 135 |
+
output_attentions=output_attentions,
|
| 136 |
+
)
|
| 137 |
+
u = attn_out + u
|
| 138 |
+
|
| 139 |
+
if isinstance(padding_mask, torch.Tensor):
|
| 140 |
+
u = u * padding_mask[..., None]
|
| 141 |
+
u = self.mlp(self.post_norm(u)) + u
|
| 142 |
+
return u, attn_weights
|
| 143 |
+
|
| 144 |
+
|
| 145 |
+
# =============================================================================
|
| 146 |
+
# Hyena cascade (hcl / hcm / hcs)
|
| 147 |
+
# =============================================================================
|
| 148 |
+
|
| 149 |
+
|
| 150 |
+
class HyenaCascade(nn.Module):
|
| 151 |
+
"""The inner mixer of a hyena block.
|
| 152 |
+
|
| 153 |
+
Two execution modes selected by `fir_inner_filter_length`:
|
| 154 |
+
* None -> hcl: outer FIR -> channel split -> parallel_iir
|
| 155 |
+
(modal-form long convolution)
|
| 156 |
+
* int (e.g. 7 or 128) -> hcm/hcs: outer FIR -> interleave -> inner FIR
|
| 157 |
+
cascade via parallel_fir(gate=True)
|
| 158 |
+
"""
|
| 159 |
+
|
| 160 |
+
def __init__(
|
| 161 |
+
self,
|
| 162 |
+
config,
|
| 163 |
+
layer_idx: int,
|
| 164 |
+
hyena_filter_groups: int,
|
| 165 |
+
fir_inner_filter_length: int | None = None,
|
| 166 |
+
) -> None:
|
| 167 |
+
super().__init__()
|
| 168 |
+
self.config = config
|
| 169 |
+
self.layer_idx = layer_idx
|
| 170 |
+
self.hyena_filter_groups = hyena_filter_groups
|
| 171 |
+
|
| 172 |
+
self.use_flashfft = config.get("use_flashfft", False)
|
| 173 |
+
self.state_size = config.state_size
|
| 174 |
+
self.hidden_size = config.hidden_size
|
| 175 |
+
self.num_filters = config.num_filters
|
| 176 |
+
self.inference_mode = config.get("inference_mode", True)
|
| 177 |
+
self.column_split_hyena = config.get("column_split_hyena", False)
|
| 178 |
+
self.hyena_flip_x1x2 = config.get("hyena_flip_x1x2", False)
|
| 179 |
+
|
| 180 |
+
assert self.hidden_size % self.num_filters == 0
|
| 181 |
+
assert self.num_filters <= self.hidden_size
|
| 182 |
+
|
| 183 |
+
self.num_attention_heads = config.num_attention_heads
|
| 184 |
+
self.hidden_size_per_attention_head = (
|
| 185 |
+
self.hidden_size // self.num_attention_heads
|
| 186 |
+
)
|
| 187 |
+
|
| 188 |
+
self.fir_inner_filter_length = fir_inner_filter_length
|
| 189 |
+
self.short_filter_length = config.short_filter_length
|
| 190 |
+
self.short_filter_weight = nn.Parameter(
|
| 191 |
+
torch.randn(3 * config.hidden_size, 1, config.short_filter_length)
|
| 192 |
+
)
|
| 193 |
+
self.short_filter_bias = (
|
| 194 |
+
nn.Parameter(torch.randn(3 * config.hidden_size))
|
| 195 |
+
if config.short_filter_bias else None
|
| 196 |
+
)
|
| 197 |
+
|
| 198 |
+
self.engine = HyenaInferenceEngine(
|
| 199 |
+
layer_idx=layer_idx,
|
| 200 |
+
hyena_flip_x1x2=config.get("hyena_flip_x1x2", False),
|
| 201 |
+
)
|
| 202 |
+
self.fir_fn = F.conv1d
|
| 203 |
+
self.fir_inner_fn = F.conv1d
|
| 204 |
+
self.fftconv_fn = None
|
| 205 |
+
self.long_fir_threshold = config.get("long_fir_threshold", None)
|
| 206 |
+
if self.long_fir_threshold is not None:
|
| 207 |
+
assert not self.use_flashfft, "long_fir_threshold incompatible with flashfft"
|
| 208 |
+
|
| 209 |
+
self.num_systems = self.hyena_filter_groups
|
| 210 |
+
self.channels_per_group = self.hidden_size // self.hyena_filter_groups
|
| 211 |
+
|
| 212 |
+
if self.fir_inner_filter_length:
|
| 213 |
+
# hcm / hcs: explicit FIR filter `h` of shape (groups, 1, inner_len)
|
| 214 |
+
self.h = nn.Parameter(
|
| 215 |
+
torch.randn(self.hyena_filter_groups, 1, fir_inner_filter_length)
|
| 216 |
+
)
|
| 217 |
+
if fir_inner_filter_length >= 128:
|
| 218 |
+
self.D = nn.Parameter(torch.zeros(self.hidden_size))
|
| 219 |
+
else:
|
| 220 |
+
self.D = None
|
| 221 |
+
else:
|
| 222 |
+
# hcl: modal-form IIR, log_poles in (num_systems, state_size, 1)
|
| 223 |
+
log_poles = torch.randn(self.num_systems, self.state_size, 1, dtype=torch.float32)
|
| 224 |
+
self.log_poles = nn.Parameter(log_poles)
|
| 225 |
+
self.residues = nn.Parameter(
|
| 226 |
+
torch.randn(self.num_systems, self.state_size, dtype=torch.float32)
|
| 227 |
+
)
|
| 228 |
+
self.D = nn.Parameter(torch.zeros(self.hidden_size))
|
| 229 |
+
self.h = None
|
| 230 |
+
|
| 231 |
+
self.t = None
|
| 232 |
+
|
| 233 |
+
def forward(self, u, inference_params=None, padding_mask=None, *args, **kwargs):
|
| 234 |
+
if (
|
| 235 |
+
inference_params is not None
|
| 236 |
+
and self.layer_idx in inference_params.fir_state_dict
|
| 237 |
+
):
|
| 238 |
+
return self.sequential_forward(u, inference_params)
|
| 239 |
+
return self.parallel_forward(u, inference_params, padding_mask)
|
| 240 |
+
|
| 241 |
+
def parallel_forward(self, u, inference_params=None, padding_mask=None):
|
| 242 |
+
L = u.shape[1]
|
| 243 |
+
dims = (
|
| 244 |
+
self.hidden_size,
|
| 245 |
+
self.num_attention_heads,
|
| 246 |
+
self.hidden_size_per_attention_head,
|
| 247 |
+
self.state_size,
|
| 248 |
+
self.hyena_filter_groups,
|
| 249 |
+
)
|
| 250 |
+
z_pre, fir_state = self.engine.parallel_fir(
|
| 251 |
+
self.fir_fn, u,
|
| 252 |
+
self.short_filter_weight, self.short_filter_bias,
|
| 253 |
+
L, dims=dims, gate=False,
|
| 254 |
+
column_split_hyena=self.column_split_hyena,
|
| 255 |
+
fir_length=self.short_filter_length,
|
| 256 |
+
inference_params=inference_params,
|
| 257 |
+
padding_mask=padding_mask, dim_last=True,
|
| 258 |
+
)
|
| 259 |
+
if inference_params:
|
| 260 |
+
inference_params.fir_state_dict[self.layer_idx] = fir_state
|
| 261 |
+
|
| 262 |
+
if self.config.interleave:
|
| 263 |
+
z_pre = _interleave(z_pre)
|
| 264 |
+
|
| 265 |
+
if self.h is None:
|
| 266 |
+
# hcl path: compute IIR impulse response then convolve via FFT
|
| 267 |
+
h, _, _, _ = self.compute_filter(L, u.device)
|
| 268 |
+
else:
|
| 269 |
+
h = self.h
|
| 270 |
+
|
| 271 |
+
D = self.D
|
| 272 |
+
if self.hyena_filter_groups > 1:
|
| 273 |
+
h = h.repeat_interleave(self.hidden_size // self.hyena_filter_groups, 0)
|
| 274 |
+
|
| 275 |
+
if self.fir_inner_filter_length is not None:
|
| 276 |
+
# hcm / hcs: inner FIR cascade
|
| 277 |
+
y, fir_inner_state = self.engine.parallel_fir(
|
| 278 |
+
self.fir_inner_fn, z_pre, h, D, L,
|
| 279 |
+
dims=dims, gate=True,
|
| 280 |
+
gated_bias=self.fir_inner_filter_length >= 128,
|
| 281 |
+
dim_last=False,
|
| 282 |
+
column_split_hyena=self.column_split_hyena,
|
| 283 |
+
fir_length=self.fir_inner_filter_length,
|
| 284 |
+
inference_params=inference_params,
|
| 285 |
+
padding_mask=padding_mask,
|
| 286 |
+
groups=self.hyena_filter_groups,
|
| 287 |
+
)
|
| 288 |
+
y = y.permute(0, 2, 1)
|
| 289 |
+
if inference_params:
|
| 290 |
+
inference_params.fir_inner_state_dict[self.layer_idx] = fir_inner_state
|
| 291 |
+
else:
|
| 292 |
+
# hcl: parallel IIR via FFT
|
| 293 |
+
y = self.engine.parallel_iir(
|
| 294 |
+
z_pre, h, D, L, t=self.t,
|
| 295 |
+
poles=self.log_poles, residues=self.residues,
|
| 296 |
+
dims=dims, inference_params=inference_params,
|
| 297 |
+
layer_idx=self.layer_idx,
|
| 298 |
+
prefill_style=self.config.get("prefill_style", "fft"),
|
| 299 |
+
use_flashfft=self.use_flashfft,
|
| 300 |
+
fftconv_fn=self.fftconv_fn,
|
| 301 |
+
column_split_hyena=self.column_split_hyena,
|
| 302 |
+
long_fir_threshold=self.long_fir_threshold,
|
| 303 |
+
padding_mask=padding_mask,
|
| 304 |
+
)
|
| 305 |
+
|
| 306 |
+
return y, inference_params
|
| 307 |
+
|
| 308 |
+
def sequential_forward(self, u, inference_params):
|
| 309 |
+
if len(u.shape) > 2:
|
| 310 |
+
u = u[:, -1]
|
| 311 |
+
# Track input dtype so we can cast back at the end. step_iir produces
|
| 312 |
+
# fp32 output (log_poles / residues are fp32 for stability) which would
|
| 313 |
+
# otherwise dtype-mismatch the downstream bf16 Linear (out_filter_dense).
|
| 314 |
+
input_dtype = u.dtype
|
| 315 |
+
|
| 316 |
+
z_pre, fir_state = self.engine.step_fir(
|
| 317 |
+
u, inference_params.fir_state_dict[self.layer_idx],
|
| 318 |
+
weight=self.short_filter_weight, bias=self.short_filter_bias,
|
| 319 |
+
)
|
| 320 |
+
inference_params.fir_state_dict[self.layer_idx] = fir_state
|
| 321 |
+
|
| 322 |
+
if self.config.interleave:
|
| 323 |
+
# For a single step, dim-1 length is C and `_interleave` operates
|
| 324 |
+
# along the channel dim; reshape to (B, C, 1) so the dim==3 branch
|
| 325 |
+
# applies, then squeeze the last dim back.
|
| 326 |
+
z_pre = _interleave(z_pre.unsqueeze(-1)).squeeze(-1)
|
| 327 |
+
|
| 328 |
+
if self.column_split_hyena:
|
| 329 |
+
x2, x1, v = _column_split_step(
|
| 330 |
+
z_pre, self.num_attention_heads, self.hidden_size_per_attention_head
|
| 331 |
+
)
|
| 332 |
+
else:
|
| 333 |
+
x2, x1, v = z_pre.split([self.hidden_size, self.hidden_size, self.hidden_size], dim=1)
|
| 334 |
+
|
| 335 |
+
if self.hyena_flip_x1x2:
|
| 336 |
+
x1, x2 = x2, x1
|
| 337 |
+
|
| 338 |
+
if self.fir_inner_filter_length is not None:
|
| 339 |
+
if self.hyena_filter_groups > 1:
|
| 340 |
+
h = self.h.repeat_interleave(self.hidden_size // self.hyena_filter_groups, 0)
|
| 341 |
+
else:
|
| 342 |
+
h = self.h
|
| 343 |
+
y, fir_inner_state = self.engine.step_fir(
|
| 344 |
+
x1 * v,
|
| 345 |
+
inference_params.fir_inner_state_dict[self.layer_idx],
|
| 346 |
+
weight=h, bias=self.D,
|
| 347 |
+
flip_filter=self.fir_inner_filter_length >= 128,
|
| 348 |
+
gated_bias=self.fir_inner_filter_length >= 128,
|
| 349 |
+
)
|
| 350 |
+
y = y * x2
|
| 351 |
+
inference_params.fir_inner_state_dict[self.layer_idx] = fir_inner_state
|
| 352 |
+
else:
|
| 353 |
+
y, iir_state = self.engine.step_iir(
|
| 354 |
+
x2, x1, v, self.D,
|
| 355 |
+
self.residues, self.log_poles,
|
| 356 |
+
inference_params.state_dict[self.layer_idx],
|
| 357 |
+
iir_groups=1,
|
| 358 |
+
)
|
| 359 |
+
inference_params.state_dict[self.layer_idx] = iir_state
|
| 360 |
+
|
| 361 |
+
y = y.to(input_dtype)
|
| 362 |
+
return y[:, None], inference_params
|
| 363 |
+
|
| 364 |
+
def update_time(self, L, device):
|
| 365 |
+
if self.t is None:
|
| 366 |
+
self.t = torch.arange(L, device=device)[None, None]
|
| 367 |
+
elif self.t.shape[-1] < L:
|
| 368 |
+
self.t = torch.arange(L, device=device)[None, None]
|
| 369 |
+
else:
|
| 370 |
+
self.t = self.t[..., :L]
|
| 371 |
+
|
| 372 |
+
def compute_filter(self, L, device):
|
| 373 |
+
self.update_time(L, device)
|
| 374 |
+
filter_dtype = torch.float32
|
| 375 |
+
residues = self.residues.to(filter_dtype)
|
| 376 |
+
log_poles = self.log_poles.to(filter_dtype)
|
| 377 |
+
h = (residues[..., None] * (log_poles * self.t).exp()).sum(1)[None] # B, D, L
|
| 378 |
+
return h, filter_dtype, log_poles, residues
|
| 379 |
+
|
| 380 |
+
|
| 381 |
+
# =============================================================================
|
| 382 |
+
# Hyena block (wraps HyenaCascade with norms / projections / mlp)
|
| 383 |
+
# =============================================================================
|
| 384 |
+
|
| 385 |
+
|
| 386 |
+
class ParallelGatedConvBlock(nn.Module):
|
| 387 |
+
def __init__(
|
| 388 |
+
self,
|
| 389 |
+
config,
|
| 390 |
+
layer_idx: int,
|
| 391 |
+
hyena_filter_groups: int | None = None,
|
| 392 |
+
fir_inner_filter_length: int | None = None,
|
| 393 |
+
) -> None:
|
| 394 |
+
super().__init__()
|
| 395 |
+
self.config = config
|
| 396 |
+
self.layer_idx = layer_idx
|
| 397 |
+
self.fir_inner_filter_length = fir_inner_filter_length
|
| 398 |
+
self.hyena_filter_groups = (
|
| 399 |
+
hyena_filter_groups if hyena_filter_groups is not None else config.hidden_size
|
| 400 |
+
)
|
| 401 |
+
dtype = AttentionBlock._resolve_dtype(config.get("hyena_block_dtype", "bfloat16"))
|
| 402 |
+
mlp_dtype = AttentionBlock._resolve_dtype(config.get("mlp_dtype", "bfloat16"))
|
| 403 |
+
self.pre_norm = RMSNorm(config).to(dtype=dtype)
|
| 404 |
+
self.post_norm = RMSNorm(config).to(dtype=dtype)
|
| 405 |
+
self.filter = HyenaCascade(
|
| 406 |
+
config, layer_idx,
|
| 407 |
+
hyena_filter_groups=self.hyena_filter_groups,
|
| 408 |
+
fir_inner_filter_length=fir_inner_filter_length,
|
| 409 |
+
).to(dtype=dtype)
|
| 410 |
+
|
| 411 |
+
self.projections = TELinear(
|
| 412 |
+
config.hidden_size,
|
| 413 |
+
3 * config.hidden_size,
|
| 414 |
+
bias=config.qkv_proj_bias,
|
| 415 |
+
init_method=torch.nn.init.xavier_uniform_,
|
| 416 |
+
use_fp8=config.get("use_fp8_input_projections", False),
|
| 417 |
+
)
|
| 418 |
+
|
| 419 |
+
self.out_filter_dense = nn.Linear(
|
| 420 |
+
config.hidden_size, config.hidden_size,
|
| 421 |
+
bias=config.hyena_out_proj_bias,
|
| 422 |
+
).to(dtype)
|
| 423 |
+
self.mlp = ParallelGatedMLP(config, layer_idx).to(dtype=mlp_dtype)
|
| 424 |
+
|
| 425 |
+
def _pad_to_multiple(self, x: torch.Tensor, multiple: int = 16) -> torch.Tensor:
|
| 426 |
+
"""Right-pad along seq dim to a multiple of `multiple` when FP8 input
|
| 427 |
+
projections are enabled. TE's FP8 path requires the product of all
|
| 428 |
+
dims except the last to be divisible by 8 (we use 16 to be safe).
|
| 429 |
+
No-op when FP8 is off."""
|
| 430 |
+
if not self.config.get("use_fp8_input_projections", False):
|
| 431 |
+
return x
|
| 432 |
+
seq_len = x.size(1)
|
| 433 |
+
pad_len = (multiple - (seq_len % multiple)) % multiple
|
| 434 |
+
if pad_len == 0:
|
| 435 |
+
return x
|
| 436 |
+
return F.pad(x, (0, 0, 0, pad_len))
|
| 437 |
+
|
| 438 |
+
def _proj_norm(self, x):
|
| 439 |
+
original_seq_len = x.size(1)
|
| 440 |
+
normalized = self.pre_norm(x)
|
| 441 |
+
normalized = self._pad_to_multiple(normalized)
|
| 442 |
+
with torch.cuda.device(x.device) if x.is_cuda else _nullctx():
|
| 443 |
+
projected = self.projections(normalized)
|
| 444 |
+
if isinstance(projected, tuple):
|
| 445 |
+
projected = projected[0]
|
| 446 |
+
# Slice back to original seq length if padding was added.
|
| 447 |
+
if projected.size(1) > original_seq_len:
|
| 448 |
+
projected = projected[:, :original_seq_len, :]
|
| 449 |
+
return projected
|
| 450 |
+
|
| 451 |
+
def forward(
|
| 452 |
+
self,
|
| 453 |
+
u: torch.Tensor,
|
| 454 |
+
inference_params=None,
|
| 455 |
+
padding_mask=None,
|
| 456 |
+
output_attentions: bool = False,
|
| 457 |
+
*args,
|
| 458 |
+
**kwargs,
|
| 459 |
+
) -> Tuple[torch.Tensor, None]:
|
| 460 |
+
z = self._proj_norm(u)
|
| 461 |
+
|
| 462 |
+
if isinstance(padding_mask, torch.Tensor):
|
| 463 |
+
z = z * padding_mask[..., None]
|
| 464 |
+
|
| 465 |
+
z, inference_params = self.filter(
|
| 466 |
+
z, inference_params=inference_params, padding_mask=padding_mask,
|
| 467 |
+
)
|
| 468 |
+
z_in = self.out_filter_dense(z) + u
|
| 469 |
+
|
| 470 |
+
if isinstance(padding_mask, torch.Tensor):
|
| 471 |
+
z_in = z_in * padding_mask[..., None]
|
| 472 |
+
|
| 473 |
+
y = self.mlp(self.post_norm(z_in)) + z_in
|
| 474 |
+
# Hyena blocks have no attention matrix.
|
| 475 |
+
return y, None
|
| 476 |
+
|
| 477 |
+
|
| 478 |
+
class _nullctx:
|
| 479 |
+
def __enter__(self): return None
|
| 480 |
+
def __exit__(self, *a): return False
|
| 481 |
+
|
| 482 |
+
|
| 483 |
+
# =============================================================================
|
| 484 |
+
# Block dispatch
|
| 485 |
+
# =============================================================================
|
| 486 |
+
|
| 487 |
+
|
| 488 |
+
def get_block(config, layer_idx: int):
|
| 489 |
+
if layer_idx in config.attn_layer_idxs:
|
| 490 |
+
return AttentionBlock(config, layer_idx)
|
| 491 |
+
if layer_idx in config.hcl_layer_idxs:
|
| 492 |
+
return ParallelGatedConvBlock(
|
| 493 |
+
config, layer_idx,
|
| 494 |
+
hyena_filter_groups=config.hcl_filter_groups,
|
| 495 |
+
fir_inner_filter_length=None,
|
| 496 |
+
)
|
| 497 |
+
if layer_idx in config.hcm_layer_idxs:
|
| 498 |
+
return ParallelGatedConvBlock(
|
| 499 |
+
config, layer_idx,
|
| 500 |
+
hyena_filter_groups=config.hcm_filter_groups,
|
| 501 |
+
fir_inner_filter_length=config.hcm_filter_length,
|
| 502 |
+
)
|
| 503 |
+
if layer_idx in config.hcs_layer_idxs:
|
| 504 |
+
return ParallelGatedConvBlock(
|
| 505 |
+
config, layer_idx,
|
| 506 |
+
hyena_filter_groups=config.hcs_filter_groups,
|
| 507 |
+
fir_inner_filter_length=config.hcs_filter_length,
|
| 508 |
+
)
|
| 509 |
+
raise NotImplementedError(f"layer_idx {layer_idx} not in any block-type idxs")
|
| 510 |
+
|
| 511 |
+
|
| 512 |
+
def block_type_for_idx(config, layer_idx: int) -> str:
|
| 513 |
+
if layer_idx in config.attn_layer_idxs: return "mha"
|
| 514 |
+
if layer_idx in config.hcl_layer_idxs: return "hcl"
|
| 515 |
+
if layer_idx in config.hcm_layer_idxs: return "hcm"
|
| 516 |
+
if layer_idx in config.hcs_layer_idxs: return "hcs"
|
| 517 |
+
raise ValueError(f"block idx {layer_idx} not classified")
|
layers.py
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Basic layers for Evo2 (StripedHyena2).
|
| 2 |
+
|
| 3 |
+
* RMSNorm -- pre/post norm in each block
|
| 4 |
+
* ParallelGatedMLP -- GLU(act(l1(x)) * l2(x)) -> l3(...); evo2_style
|
| 5 |
+
activations replace `act` with Identity for layer > 0
|
| 6 |
+
* VocabParallelEmbedding -- single-process variant of vortex's
|
| 7 |
+
VocabParallelEmbedding so checkpoint keys match
|
| 8 |
+
* TELinear -- TransformerEngine FP8-capable Linear, with a
|
| 9 |
+
pure-PyTorch fallback when TE is not installed.
|
| 10 |
+
Used for the input QKV-like projections of
|
| 11 |
+
Hyena cascade blocks; required for 1B/20B/40B.
|
| 12 |
+
"""
|
| 13 |
+
|
| 14 |
+
from __future__ import annotations
|
| 15 |
+
|
| 16 |
+
from typing import Callable
|
| 17 |
+
|
| 18 |
+
import torch
|
| 19 |
+
import torch.nn as nn
|
| 20 |
+
import torch.nn.functional as F
|
| 21 |
+
from torch import Tensor
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
try:
|
| 25 |
+
from transformer_engine.pytorch import Linear as _TELinearBase
|
| 26 |
+
from transformer_engine.common.recipe import Format, DelayedScaling
|
| 27 |
+
import transformer_engine.pytorch as te
|
| 28 |
+
HAS_TE = True
|
| 29 |
+
except ImportError:
|
| 30 |
+
HAS_TE = False
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
def grab_first_if_tuple(x):
|
| 34 |
+
if x.__class__.__name__ == "tuple":
|
| 35 |
+
return x[0]
|
| 36 |
+
return x
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
class RMSNorm(nn.Module):
|
| 40 |
+
def __init__(self, config):
|
| 41 |
+
super().__init__()
|
| 42 |
+
self.eps = config.eps
|
| 43 |
+
self.hidden_size = config.hidden_size
|
| 44 |
+
self.scale = nn.Parameter(torch.ones(self.hidden_size))
|
| 45 |
+
self.register_parameter("scale", self.scale)
|
| 46 |
+
self.use_flash_rmsnorm = config.get("use_flash_rmsnorm", False)
|
| 47 |
+
if self.use_flash_rmsnorm:
|
| 48 |
+
from flash_attn.ops.rms_norm import rms_norm as rmsnorm_func
|
| 49 |
+
self.rmsnorm_func = rmsnorm_func
|
| 50 |
+
|
| 51 |
+
def forward(self, x):
|
| 52 |
+
if self.use_flash_rmsnorm:
|
| 53 |
+
return self.rmsnorm_func(x, self.scale, self.eps)
|
| 54 |
+
y = x / (x.norm(2, dim=-1, keepdim=True) * self.hidden_size ** (-1.0 / 2) + self.eps)
|
| 55 |
+
return self.scale * y
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
class ParallelGatedMLP(nn.Module):
|
| 59 |
+
"""GLU MLP. With evo2_style_activations=True, layer_idx > 0 uses Identity
|
| 60 |
+
in place of the gating activation; layer 0 keeps gelu."""
|
| 61 |
+
|
| 62 |
+
def __init__(self, config, layer_idx: int):
|
| 63 |
+
super().__init__()
|
| 64 |
+
self.layer_idx = layer_idx
|
| 65 |
+
multiple_of = config.get("inner_size_multiple_of", 64)
|
| 66 |
+
self.act_type = config.get("mlp_activation", "gelu")
|
| 67 |
+
if self.act_type == "gelu":
|
| 68 |
+
self.act = F.gelu
|
| 69 |
+
elif self.act_type == "silu":
|
| 70 |
+
self.act = F.silu
|
| 71 |
+
else:
|
| 72 |
+
raise NotImplementedError(f"Unknown mlp_activation: {self.act_type}")
|
| 73 |
+
|
| 74 |
+
if self.layer_idx > 0 and config.get("evo2_style_activations", False):
|
| 75 |
+
self.act = nn.Identity()
|
| 76 |
+
|
| 77 |
+
self.multiple_of = multiple_of * config.model_parallel_size
|
| 78 |
+
inner_size = int(2 * config.hidden_size * 4 / 3)
|
| 79 |
+
inner_size = self.multiple_of * ((inner_size + self.multiple_of - 1) // self.multiple_of)
|
| 80 |
+
if config.get("inner_mlp_size", None) is not None:
|
| 81 |
+
inner_size = config.inner_mlp_size
|
| 82 |
+
|
| 83 |
+
self.l1 = nn.Linear(config.hidden_size, inner_size, bias=False)
|
| 84 |
+
self.l2 = nn.Linear(config.hidden_size, inner_size, bias=False)
|
| 85 |
+
self.l3 = nn.Linear(inner_size, config.hidden_size, bias=False)
|
| 86 |
+
|
| 87 |
+
def forward(self, z):
|
| 88 |
+
z1, z2 = self.l1(z), self.l2(z)
|
| 89 |
+
z1, z2 = grab_first_if_tuple(z1), grab_first_if_tuple(z2)
|
| 90 |
+
y = self.l3(self.act(z1) * z2)
|
| 91 |
+
return grab_first_if_tuple(y)
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
class VocabParallelEmbedding(nn.Embedding):
|
| 95 |
+
"""Single-process variant of vortex's VocabParallelEmbedding.
|
| 96 |
+
|
| 97 |
+
Drops distributed sharding so this minimal port runs on a single device
|
| 98 |
+
(HF/accelerate handles cross-device placement via device_map="auto").
|
| 99 |
+
"""
|
| 100 |
+
|
| 101 |
+
def __init__(self, config):
|
| 102 |
+
vocab_size = config.vocab_size
|
| 103 |
+
padding_idx = config.get("padding_idx", None)
|
| 104 |
+
super().__init__(vocab_size, embedding_dim=config.hidden_size, padding_idx=padding_idx)
|
| 105 |
+
|
| 106 |
+
def embed(self, x: Tensor) -> Tensor:
|
| 107 |
+
return self.forward(x)
|
| 108 |
+
|
| 109 |
+
def unembed(self, u: Tensor) -> Tensor:
|
| 110 |
+
return u @ self.weight.T
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
if HAS_TE:
|
| 114 |
+
|
| 115 |
+
_TE_WORKSPACE_FIXUP_APPLIED = False
|
| 116 |
+
|
| 117 |
+
def fixup_te_workspace():
|
| 118 |
+
"""Patch TE's Linear module to use per-device cuBLAS workspaces.
|
| 119 |
+
|
| 120 |
+
Vortex helper, ported verbatim. Without this, TE's Linear uses a single
|
| 121 |
+
workspace tensor allocated on whatever CUDA device was current at first
|
| 122 |
+
call, then fails ("cuBLAS Error: the function failed to launch on the
|
| 123 |
+
GPU") when called from layers on other devices -- which happens with
|
| 124 |
+
device_map="auto" sharding. Idempotent; safe to call multiple times.
|
| 125 |
+
No-op when TE is not installed (the import guard above gates it).
|
| 126 |
+
"""
|
| 127 |
+
global _TE_WORKSPACE_FIXUP_APPLIED
|
| 128 |
+
if _TE_WORKSPACE_FIXUP_APPLIED:
|
| 129 |
+
return
|
| 130 |
+
from functools import lru_cache
|
| 131 |
+
|
| 132 |
+
@lru_cache
|
| 133 |
+
def te_cublas_get_workspace_per_device(device):
|
| 134 |
+
import transformer_engine.pytorch.module.base as tebase
|
| 135 |
+
with torch.cuda.device(device):
|
| 136 |
+
tebase._cublas_workspace = None # force get_workspace() to reallocate
|
| 137 |
+
return tebase.get_workspace()
|
| 138 |
+
|
| 139 |
+
def get_workspace():
|
| 140 |
+
return te_cublas_get_workspace_per_device(torch.cuda.current_device())
|
| 141 |
+
|
| 142 |
+
import transformer_engine.pytorch.module.linear as telinear
|
| 143 |
+
telinear.get_workspace = get_workspace
|
| 144 |
+
_TE_WORKSPACE_FIXUP_APPLIED = True
|
| 145 |
+
|
| 146 |
+
def set_format_recipe():
|
| 147 |
+
fp8_format = Format.HYBRID
|
| 148 |
+
fp8_recipe = DelayedScaling(fp8_format=fp8_format, amax_history_len=16, amax_compute_algo="max")
|
| 149 |
+
return fp8_format, fp8_recipe
|
| 150 |
+
|
| 151 |
+
class TELinear(_TELinearBase):
|
| 152 |
+
"""Wrapper for Transformer-Engine's Linear, matching vortex's signature.
|
| 153 |
+
|
| 154 |
+
Returns (out, None) so callers can grab_first_if_tuple, matching vortex.
|
| 155 |
+
"""
|
| 156 |
+
|
| 157 |
+
def __init__(
|
| 158 |
+
self,
|
| 159 |
+
input_size: int,
|
| 160 |
+
output_size: int,
|
| 161 |
+
init_method: Callable | None = None,
|
| 162 |
+
bias: bool = True,
|
| 163 |
+
skip_bias_add: bool = False,
|
| 164 |
+
use_fp8: bool = False,
|
| 165 |
+
**kwargs,
|
| 166 |
+
):
|
| 167 |
+
params_dtype = torch.bfloat16
|
| 168 |
+
self.te_return_bias = skip_bias_add and bias
|
| 169 |
+
self.use_fp8_input_projections = use_fp8
|
| 170 |
+
if use_fp8:
|
| 171 |
+
self.fp8_format, self.fp8_recipe = set_format_recipe()
|
| 172 |
+
|
| 173 |
+
super().__init__(
|
| 174 |
+
in_features=input_size,
|
| 175 |
+
out_features=output_size,
|
| 176 |
+
sequence_parallel=False,
|
| 177 |
+
fuse_wgrad_accumulation=False,
|
| 178 |
+
tp_group=None,
|
| 179 |
+
tp_size=1,
|
| 180 |
+
init_method=init_method,
|
| 181 |
+
params_dtype=params_dtype,
|
| 182 |
+
parallel_mode=None,
|
| 183 |
+
bias=bias,
|
| 184 |
+
return_bias=self.te_return_bias,
|
| 185 |
+
**kwargs,
|
| 186 |
+
)
|
| 187 |
+
|
| 188 |
+
def forward(self, x):
|
| 189 |
+
if self.use_fp8_input_projections:
|
| 190 |
+
with te.fp8_autocast(enabled=True, fp8_recipe=self.fp8_recipe):
|
| 191 |
+
out = super().forward(x)
|
| 192 |
+
else:
|
| 193 |
+
out = super().forward(x)
|
| 194 |
+
|
| 195 |
+
if self.te_return_bias:
|
| 196 |
+
return out
|
| 197 |
+
return out, None
|
| 198 |
+
|
| 199 |
+
else:
|
| 200 |
+
|
| 201 |
+
def fixup_te_workspace():
|
| 202 |
+
"""No-op when TransformerEngine is not installed."""
|
| 203 |
+
return
|
| 204 |
+
|
| 205 |
+
class TELinear(nn.Module):
|
| 206 |
+
"""Pure-PyTorch fallback for TELinear (no FP8). Used by 7B variants
|
| 207 |
+
when TransformerEngine isn't installed.
|
| 208 |
+
|
| 209 |
+
Parameters are registered with names that match TE's state_dict layout
|
| 210 |
+
(`weight`, `bias`), so checkpoints saved from either path are
|
| 211 |
+
cross-loadable.
|
| 212 |
+
"""
|
| 213 |
+
|
| 214 |
+
def __init__(
|
| 215 |
+
self,
|
| 216 |
+
input_size: int,
|
| 217 |
+
output_size: int,
|
| 218 |
+
init_method: Callable | None = None,
|
| 219 |
+
bias: bool = True,
|
| 220 |
+
skip_bias_add: bool = False,
|
| 221 |
+
use_fp8: bool = False,
|
| 222 |
+
**kwargs,
|
| 223 |
+
):
|
| 224 |
+
super().__init__()
|
| 225 |
+
if use_fp8:
|
| 226 |
+
raise RuntimeError(
|
| 227 |
+
"FP8 requires Transformer Engine, which is not installed. "
|
| 228 |
+
"Install it with: pip install transformer_engine>=2.3.0"
|
| 229 |
+
)
|
| 230 |
+
|
| 231 |
+
self.te_return_bias = skip_bias_add and bias
|
| 232 |
+
self.use_fp8_input_projections = False
|
| 233 |
+
self.in_features = input_size
|
| 234 |
+
self.out_features = output_size
|
| 235 |
+
self.has_bias = bias
|
| 236 |
+
|
| 237 |
+
self.weight = nn.Parameter(torch.empty(output_size, input_size, dtype=torch.bfloat16))
|
| 238 |
+
if bias:
|
| 239 |
+
self.bias = nn.Parameter(torch.zeros(output_size, dtype=torch.bfloat16))
|
| 240 |
+
else:
|
| 241 |
+
self.register_parameter("bias", None)
|
| 242 |
+
|
| 243 |
+
if init_method is not None:
|
| 244 |
+
init_method(self.weight)
|
| 245 |
+
else:
|
| 246 |
+
nn.init.xavier_uniform_(self.weight)
|
| 247 |
+
|
| 248 |
+
def forward(self, x):
|
| 249 |
+
out = F.linear(x.to(self.weight.dtype), self.weight, self.bias)
|
| 250 |
+
if self.te_return_bias:
|
| 251 |
+
return out, self.bias
|
| 252 |
+
return out, None
|
model-00001-of-00003.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:732928a54e2e83dd48d6c6fa7ec5e9b16818fd077e3b0cdeadd9f8a3032cfe62
|
| 3 |
+
size 4998468704
|
model-00002-of-00003.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:4b4f8f67c709bc5138ecf266b7432c5e003368b1b6aad26b74af779a3b04d028
|
| 3 |
+
size 4950590512
|
model-00003-of-00003.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:efb510480a47f798189d03d15fb86f2dbce53f07eb394c2dbe004a7cbcbb78fe
|
| 3 |
+
size 3015458472
|
model.safetensors.index.json
ADDED
|
@@ -0,0 +1,352 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"metadata": {
|
| 3 |
+
"total_parameters": 6481059584,
|
| 4 |
+
"total_size": 12964479104
|
| 5 |
+
},
|
| 6 |
+
"weight_map": {
|
| 7 |
+
"backbone.blocks.0.filter.h": "model-00001-of-00003.safetensors",
|
| 8 |
+
"backbone.blocks.0.filter.short_filter_weight": "model-00001-of-00003.safetensors",
|
| 9 |
+
"backbone.blocks.0.mlp.l1.weight": "model-00001-of-00003.safetensors",
|
| 10 |
+
"backbone.blocks.0.mlp.l2.weight": "model-00001-of-00003.safetensors",
|
| 11 |
+
"backbone.blocks.0.mlp.l3.weight": "model-00001-of-00003.safetensors",
|
| 12 |
+
"backbone.blocks.0.out_filter_dense.bias": "model-00001-of-00003.safetensors",
|
| 13 |
+
"backbone.blocks.0.out_filter_dense.weight": "model-00001-of-00003.safetensors",
|
| 14 |
+
"backbone.blocks.0.post_norm.scale": "model-00001-of-00003.safetensors",
|
| 15 |
+
"backbone.blocks.0.pre_norm.scale": "model-00001-of-00003.safetensors",
|
| 16 |
+
"backbone.blocks.0.projections.weight": "model-00001-of-00003.safetensors",
|
| 17 |
+
"backbone.blocks.1.filter.D": "model-00001-of-00003.safetensors",
|
| 18 |
+
"backbone.blocks.1.filter.h": "model-00001-of-00003.safetensors",
|
| 19 |
+
"backbone.blocks.1.filter.short_filter_weight": "model-00001-of-00003.safetensors",
|
| 20 |
+
"backbone.blocks.1.mlp.l1.weight": "model-00001-of-00003.safetensors",
|
| 21 |
+
"backbone.blocks.1.mlp.l2.weight": "model-00001-of-00003.safetensors",
|
| 22 |
+
"backbone.blocks.1.mlp.l3.weight": "model-00001-of-00003.safetensors",
|
| 23 |
+
"backbone.blocks.1.out_filter_dense.bias": "model-00001-of-00003.safetensors",
|
| 24 |
+
"backbone.blocks.1.out_filter_dense.weight": "model-00001-of-00003.safetensors",
|
| 25 |
+
"backbone.blocks.1.post_norm.scale": "model-00001-of-00003.safetensors",
|
| 26 |
+
"backbone.blocks.1.pre_norm.scale": "model-00001-of-00003.safetensors",
|
| 27 |
+
"backbone.blocks.1.projections.weight": "model-00001-of-00003.safetensors",
|
| 28 |
+
"backbone.blocks.10.inner_mha_cls.Wqkv.weight": "model-00001-of-00003.safetensors",
|
| 29 |
+
"backbone.blocks.10.inner_mha_cls.out_proj.bias": "model-00001-of-00003.safetensors",
|
| 30 |
+
"backbone.blocks.10.inner_mha_cls.out_proj.weight": "model-00001-of-00003.safetensors",
|
| 31 |
+
"backbone.blocks.10.inner_mha_cls.rotary_emb.inv_freq": "model-00001-of-00003.safetensors",
|
| 32 |
+
"backbone.blocks.10.mlp.l1.weight": "model-00001-of-00003.safetensors",
|
| 33 |
+
"backbone.blocks.10.mlp.l2.weight": "model-00001-of-00003.safetensors",
|
| 34 |
+
"backbone.blocks.10.mlp.l3.weight": "model-00001-of-00003.safetensors",
|
| 35 |
+
"backbone.blocks.10.post_norm.scale": "model-00001-of-00003.safetensors",
|
| 36 |
+
"backbone.blocks.10.pre_norm.scale": "model-00001-of-00003.safetensors",
|
| 37 |
+
"backbone.blocks.11.filter.h": "model-00001-of-00003.safetensors",
|
| 38 |
+
"backbone.blocks.11.filter.short_filter_weight": "model-00001-of-00003.safetensors",
|
| 39 |
+
"backbone.blocks.11.mlp.l1.weight": "model-00001-of-00003.safetensors",
|
| 40 |
+
"backbone.blocks.11.mlp.l2.weight": "model-00001-of-00003.safetensors",
|
| 41 |
+
"backbone.blocks.11.mlp.l3.weight": "model-00001-of-00003.safetensors",
|
| 42 |
+
"backbone.blocks.11.out_filter_dense.bias": "model-00001-of-00003.safetensors",
|
| 43 |
+
"backbone.blocks.11.out_filter_dense.weight": "model-00001-of-00003.safetensors",
|
| 44 |
+
"backbone.blocks.11.post_norm.scale": "model-00001-of-00003.safetensors",
|
| 45 |
+
"backbone.blocks.11.pre_norm.scale": "model-00001-of-00003.safetensors",
|
| 46 |
+
"backbone.blocks.11.projections.weight": "model-00001-of-00003.safetensors",
|
| 47 |
+
"backbone.blocks.12.filter.D": "model-00001-of-00003.safetensors",
|
| 48 |
+
"backbone.blocks.12.filter.h": "model-00001-of-00003.safetensors",
|
| 49 |
+
"backbone.blocks.12.filter.short_filter_weight": "model-00001-of-00003.safetensors",
|
| 50 |
+
"backbone.blocks.12.mlp.l1.weight": "model-00002-of-00003.safetensors",
|
| 51 |
+
"backbone.blocks.12.mlp.l2.weight": "model-00002-of-00003.safetensors",
|
| 52 |
+
"backbone.blocks.12.mlp.l3.weight": "model-00002-of-00003.safetensors",
|
| 53 |
+
"backbone.blocks.12.out_filter_dense.bias": "model-00001-of-00003.safetensors",
|
| 54 |
+
"backbone.blocks.12.out_filter_dense.weight": "model-00001-of-00003.safetensors",
|
| 55 |
+
"backbone.blocks.12.post_norm.scale": "model-00001-of-00003.safetensors",
|
| 56 |
+
"backbone.blocks.12.pre_norm.scale": "model-00001-of-00003.safetensors",
|
| 57 |
+
"backbone.blocks.12.projections.weight": "model-00001-of-00003.safetensors",
|
| 58 |
+
"backbone.blocks.13.filter.D": "model-00002-of-00003.safetensors",
|
| 59 |
+
"backbone.blocks.13.filter.log_poles": "model-00002-of-00003.safetensors",
|
| 60 |
+
"backbone.blocks.13.filter.residues": "model-00002-of-00003.safetensors",
|
| 61 |
+
"backbone.blocks.13.filter.short_filter_weight": "model-00002-of-00003.safetensors",
|
| 62 |
+
"backbone.blocks.13.mlp.l1.weight": "model-00002-of-00003.safetensors",
|
| 63 |
+
"backbone.blocks.13.mlp.l2.weight": "model-00002-of-00003.safetensors",
|
| 64 |
+
"backbone.blocks.13.mlp.l3.weight": "model-00002-of-00003.safetensors",
|
| 65 |
+
"backbone.blocks.13.out_filter_dense.bias": "model-00002-of-00003.safetensors",
|
| 66 |
+
"backbone.blocks.13.out_filter_dense.weight": "model-00002-of-00003.safetensors",
|
| 67 |
+
"backbone.blocks.13.post_norm.scale": "model-00002-of-00003.safetensors",
|
| 68 |
+
"backbone.blocks.13.pre_norm.scale": "model-00002-of-00003.safetensors",
|
| 69 |
+
"backbone.blocks.13.projections.weight": "model-00002-of-00003.safetensors",
|
| 70 |
+
"backbone.blocks.14.filter.h": "model-00002-of-00003.safetensors",
|
| 71 |
+
"backbone.blocks.14.filter.short_filter_weight": "model-00002-of-00003.safetensors",
|
| 72 |
+
"backbone.blocks.14.mlp.l1.weight": "model-00002-of-00003.safetensors",
|
| 73 |
+
"backbone.blocks.14.mlp.l2.weight": "model-00002-of-00003.safetensors",
|
| 74 |
+
"backbone.blocks.14.mlp.l3.weight": "model-00002-of-00003.safetensors",
|
| 75 |
+
"backbone.blocks.14.out_filter_dense.bias": "model-00002-of-00003.safetensors",
|
| 76 |
+
"backbone.blocks.14.out_filter_dense.weight": "model-00002-of-00003.safetensors",
|
| 77 |
+
"backbone.blocks.14.post_norm.scale": "model-00002-of-00003.safetensors",
|
| 78 |
+
"backbone.blocks.14.pre_norm.scale": "model-00002-of-00003.safetensors",
|
| 79 |
+
"backbone.blocks.14.projections.weight": "model-00002-of-00003.safetensors",
|
| 80 |
+
"backbone.blocks.15.filter.D": "model-00002-of-00003.safetensors",
|
| 81 |
+
"backbone.blocks.15.filter.h": "model-00002-of-00003.safetensors",
|
| 82 |
+
"backbone.blocks.15.filter.short_filter_weight": "model-00002-of-00003.safetensors",
|
| 83 |
+
"backbone.blocks.15.mlp.l1.weight": "model-00002-of-00003.safetensors",
|
| 84 |
+
"backbone.blocks.15.mlp.l2.weight": "model-00002-of-00003.safetensors",
|
| 85 |
+
"backbone.blocks.15.mlp.l3.weight": "model-00002-of-00003.safetensors",
|
| 86 |
+
"backbone.blocks.15.out_filter_dense.bias": "model-00002-of-00003.safetensors",
|
| 87 |
+
"backbone.blocks.15.out_filter_dense.weight": "model-00002-of-00003.safetensors",
|
| 88 |
+
"backbone.blocks.15.post_norm.scale": "model-00002-of-00003.safetensors",
|
| 89 |
+
"backbone.blocks.15.pre_norm.scale": "model-00002-of-00003.safetensors",
|
| 90 |
+
"backbone.blocks.15.projections.weight": "model-00002-of-00003.safetensors",
|
| 91 |
+
"backbone.blocks.16.filter.D": "model-00002-of-00003.safetensors",
|
| 92 |
+
"backbone.blocks.16.filter.log_poles": "model-00002-of-00003.safetensors",
|
| 93 |
+
"backbone.blocks.16.filter.residues": "model-00002-of-00003.safetensors",
|
| 94 |
+
"backbone.blocks.16.filter.short_filter_weight": "model-00002-of-00003.safetensors",
|
| 95 |
+
"backbone.blocks.16.mlp.l1.weight": "model-00002-of-00003.safetensors",
|
| 96 |
+
"backbone.blocks.16.mlp.l2.weight": "model-00002-of-00003.safetensors",
|
| 97 |
+
"backbone.blocks.16.mlp.l3.weight": "model-00002-of-00003.safetensors",
|
| 98 |
+
"backbone.blocks.16.out_filter_dense.bias": "model-00002-of-00003.safetensors",
|
| 99 |
+
"backbone.blocks.16.out_filter_dense.weight": "model-00002-of-00003.safetensors",
|
| 100 |
+
"backbone.blocks.16.post_norm.scale": "model-00002-of-00003.safetensors",
|
| 101 |
+
"backbone.blocks.16.pre_norm.scale": "model-00002-of-00003.safetensors",
|
| 102 |
+
"backbone.blocks.16.projections.weight": "model-00002-of-00003.safetensors",
|
| 103 |
+
"backbone.blocks.17.inner_mha_cls.Wqkv.weight": "model-00002-of-00003.safetensors",
|
| 104 |
+
"backbone.blocks.17.inner_mha_cls.out_proj.bias": "model-00002-of-00003.safetensors",
|
| 105 |
+
"backbone.blocks.17.inner_mha_cls.out_proj.weight": "model-00002-of-00003.safetensors",
|
| 106 |
+
"backbone.blocks.17.inner_mha_cls.rotary_emb.inv_freq": "model-00002-of-00003.safetensors",
|
| 107 |
+
"backbone.blocks.17.mlp.l1.weight": "model-00002-of-00003.safetensors",
|
| 108 |
+
"backbone.blocks.17.mlp.l2.weight": "model-00002-of-00003.safetensors",
|
| 109 |
+
"backbone.blocks.17.mlp.l3.weight": "model-00002-of-00003.safetensors",
|
| 110 |
+
"backbone.blocks.17.post_norm.scale": "model-00002-of-00003.safetensors",
|
| 111 |
+
"backbone.blocks.17.pre_norm.scale": "model-00002-of-00003.safetensors",
|
| 112 |
+
"backbone.blocks.18.filter.h": "model-00002-of-00003.safetensors",
|
| 113 |
+
"backbone.blocks.18.filter.short_filter_weight": "model-00002-of-00003.safetensors",
|
| 114 |
+
"backbone.blocks.18.mlp.l1.weight": "model-00002-of-00003.safetensors",
|
| 115 |
+
"backbone.blocks.18.mlp.l2.weight": "model-00002-of-00003.safetensors",
|
| 116 |
+
"backbone.blocks.18.mlp.l3.weight": "model-00002-of-00003.safetensors",
|
| 117 |
+
"backbone.blocks.18.out_filter_dense.bias": "model-00002-of-00003.safetensors",
|
| 118 |
+
"backbone.blocks.18.out_filter_dense.weight": "model-00002-of-00003.safetensors",
|
| 119 |
+
"backbone.blocks.18.post_norm.scale": "model-00002-of-00003.safetensors",
|
| 120 |
+
"backbone.blocks.18.pre_norm.scale": "model-00002-of-00003.safetensors",
|
| 121 |
+
"backbone.blocks.18.projections.weight": "model-00002-of-00003.safetensors",
|
| 122 |
+
"backbone.blocks.19.filter.D": "model-00002-of-00003.safetensors",
|
| 123 |
+
"backbone.blocks.19.filter.h": "model-00002-of-00003.safetensors",
|
| 124 |
+
"backbone.blocks.19.filter.short_filter_weight": "model-00002-of-00003.safetensors",
|
| 125 |
+
"backbone.blocks.19.mlp.l1.weight": "model-00002-of-00003.safetensors",
|
| 126 |
+
"backbone.blocks.19.mlp.l2.weight": "model-00002-of-00003.safetensors",
|
| 127 |
+
"backbone.blocks.19.mlp.l3.weight": "model-00002-of-00003.safetensors",
|
| 128 |
+
"backbone.blocks.19.out_filter_dense.bias": "model-00002-of-00003.safetensors",
|
| 129 |
+
"backbone.blocks.19.out_filter_dense.weight": "model-00002-of-00003.safetensors",
|
| 130 |
+
"backbone.blocks.19.post_norm.scale": "model-00002-of-00003.safetensors",
|
| 131 |
+
"backbone.blocks.19.pre_norm.scale": "model-00002-of-00003.safetensors",
|
| 132 |
+
"backbone.blocks.19.projections.weight": "model-00002-of-00003.safetensors",
|
| 133 |
+
"backbone.blocks.2.filter.D": "model-00001-of-00003.safetensors",
|
| 134 |
+
"backbone.blocks.2.filter.log_poles": "model-00001-of-00003.safetensors",
|
| 135 |
+
"backbone.blocks.2.filter.residues": "model-00001-of-00003.safetensors",
|
| 136 |
+
"backbone.blocks.2.filter.short_filter_weight": "model-00001-of-00003.safetensors",
|
| 137 |
+
"backbone.blocks.2.mlp.l1.weight": "model-00001-of-00003.safetensors",
|
| 138 |
+
"backbone.blocks.2.mlp.l2.weight": "model-00001-of-00003.safetensors",
|
| 139 |
+
"backbone.blocks.2.mlp.l3.weight": "model-00001-of-00003.safetensors",
|
| 140 |
+
"backbone.blocks.2.out_filter_dense.bias": "model-00001-of-00003.safetensors",
|
| 141 |
+
"backbone.blocks.2.out_filter_dense.weight": "model-00001-of-00003.safetensors",
|
| 142 |
+
"backbone.blocks.2.post_norm.scale": "model-00001-of-00003.safetensors",
|
| 143 |
+
"backbone.blocks.2.pre_norm.scale": "model-00001-of-00003.safetensors",
|
| 144 |
+
"backbone.blocks.2.projections.weight": "model-00001-of-00003.safetensors",
|
| 145 |
+
"backbone.blocks.20.filter.D": "model-00002-of-00003.safetensors",
|
| 146 |
+
"backbone.blocks.20.filter.log_poles": "model-00002-of-00003.safetensors",
|
| 147 |
+
"backbone.blocks.20.filter.residues": "model-00002-of-00003.safetensors",
|
| 148 |
+
"backbone.blocks.20.filter.short_filter_weight": "model-00002-of-00003.safetensors",
|
| 149 |
+
"backbone.blocks.20.mlp.l1.weight": "model-00002-of-00003.safetensors",
|
| 150 |
+
"backbone.blocks.20.mlp.l2.weight": "model-00002-of-00003.safetensors",
|
| 151 |
+
"backbone.blocks.20.mlp.l3.weight": "model-00002-of-00003.safetensors",
|
| 152 |
+
"backbone.blocks.20.out_filter_dense.bias": "model-00002-of-00003.safetensors",
|
| 153 |
+
"backbone.blocks.20.out_filter_dense.weight": "model-00002-of-00003.safetensors",
|
| 154 |
+
"backbone.blocks.20.post_norm.scale": "model-00002-of-00003.safetensors",
|
| 155 |
+
"backbone.blocks.20.pre_norm.scale": "model-00002-of-00003.safetensors",
|
| 156 |
+
"backbone.blocks.20.projections.weight": "model-00002-of-00003.safetensors",
|
| 157 |
+
"backbone.blocks.21.filter.h": "model-00002-of-00003.safetensors",
|
| 158 |
+
"backbone.blocks.21.filter.short_filter_weight": "model-00002-of-00003.safetensors",
|
| 159 |
+
"backbone.blocks.21.mlp.l1.weight": "model-00002-of-00003.safetensors",
|
| 160 |
+
"backbone.blocks.21.mlp.l2.weight": "model-00002-of-00003.safetensors",
|
| 161 |
+
"backbone.blocks.21.mlp.l3.weight": "model-00002-of-00003.safetensors",
|
| 162 |
+
"backbone.blocks.21.out_filter_dense.bias": "model-00002-of-00003.safetensors",
|
| 163 |
+
"backbone.blocks.21.out_filter_dense.weight": "model-00002-of-00003.safetensors",
|
| 164 |
+
"backbone.blocks.21.post_norm.scale": "model-00002-of-00003.safetensors",
|
| 165 |
+
"backbone.blocks.21.pre_norm.scale": "model-00002-of-00003.safetensors",
|
| 166 |
+
"backbone.blocks.21.projections.weight": "model-00002-of-00003.safetensors",
|
| 167 |
+
"backbone.blocks.22.filter.D": "model-00002-of-00003.safetensors",
|
| 168 |
+
"backbone.blocks.22.filter.h": "model-00002-of-00003.safetensors",
|
| 169 |
+
"backbone.blocks.22.filter.short_filter_weight": "model-00002-of-00003.safetensors",
|
| 170 |
+
"backbone.blocks.22.mlp.l1.weight": "model-00002-of-00003.safetensors",
|
| 171 |
+
"backbone.blocks.22.mlp.l2.weight": "model-00002-of-00003.safetensors",
|
| 172 |
+
"backbone.blocks.22.mlp.l3.weight": "model-00002-of-00003.safetensors",
|
| 173 |
+
"backbone.blocks.22.out_filter_dense.bias": "model-00002-of-00003.safetensors",
|
| 174 |
+
"backbone.blocks.22.out_filter_dense.weight": "model-00002-of-00003.safetensors",
|
| 175 |
+
"backbone.blocks.22.post_norm.scale": "model-00002-of-00003.safetensors",
|
| 176 |
+
"backbone.blocks.22.pre_norm.scale": "model-00002-of-00003.safetensors",
|
| 177 |
+
"backbone.blocks.22.projections.weight": "model-00002-of-00003.safetensors",
|
| 178 |
+
"backbone.blocks.23.filter.D": "model-00002-of-00003.safetensors",
|
| 179 |
+
"backbone.blocks.23.filter.log_poles": "model-00002-of-00003.safetensors",
|
| 180 |
+
"backbone.blocks.23.filter.residues": "model-00002-of-00003.safetensors",
|
| 181 |
+
"backbone.blocks.23.filter.short_filter_weight": "model-00002-of-00003.safetensors",
|
| 182 |
+
"backbone.blocks.23.mlp.l1.weight": "model-00002-of-00003.safetensors",
|
| 183 |
+
"backbone.blocks.23.mlp.l2.weight": "model-00002-of-00003.safetensors",
|
| 184 |
+
"backbone.blocks.23.mlp.l3.weight": "model-00002-of-00003.safetensors",
|
| 185 |
+
"backbone.blocks.23.out_filter_dense.bias": "model-00002-of-00003.safetensors",
|
| 186 |
+
"backbone.blocks.23.out_filter_dense.weight": "model-00002-of-00003.safetensors",
|
| 187 |
+
"backbone.blocks.23.post_norm.scale": "model-00002-of-00003.safetensors",
|
| 188 |
+
"backbone.blocks.23.pre_norm.scale": "model-00002-of-00003.safetensors",
|
| 189 |
+
"backbone.blocks.23.projections.weight": "model-00002-of-00003.safetensors",
|
| 190 |
+
"backbone.blocks.24.inner_mha_cls.Wqkv.weight": "model-00002-of-00003.safetensors",
|
| 191 |
+
"backbone.blocks.24.inner_mha_cls.out_proj.bias": "model-00002-of-00003.safetensors",
|
| 192 |
+
"backbone.blocks.24.inner_mha_cls.out_proj.weight": "model-00002-of-00003.safetensors",
|
| 193 |
+
"backbone.blocks.24.inner_mha_cls.rotary_emb.inv_freq": "model-00002-of-00003.safetensors",
|
| 194 |
+
"backbone.blocks.24.mlp.l1.weight": "model-00002-of-00003.safetensors",
|
| 195 |
+
"backbone.blocks.24.mlp.l2.weight": "model-00003-of-00003.safetensors",
|
| 196 |
+
"backbone.blocks.24.mlp.l3.weight": "model-00003-of-00003.safetensors",
|
| 197 |
+
"backbone.blocks.24.post_norm.scale": "model-00002-of-00003.safetensors",
|
| 198 |
+
"backbone.blocks.24.pre_norm.scale": "model-00002-of-00003.safetensors",
|
| 199 |
+
"backbone.blocks.25.filter.h": "model-00003-of-00003.safetensors",
|
| 200 |
+
"backbone.blocks.25.filter.short_filter_weight": "model-00003-of-00003.safetensors",
|
| 201 |
+
"backbone.blocks.25.mlp.l1.weight": "model-00003-of-00003.safetensors",
|
| 202 |
+
"backbone.blocks.25.mlp.l2.weight": "model-00003-of-00003.safetensors",
|
| 203 |
+
"backbone.blocks.25.mlp.l3.weight": "model-00003-of-00003.safetensors",
|
| 204 |
+
"backbone.blocks.25.out_filter_dense.bias": "model-00003-of-00003.safetensors",
|
| 205 |
+
"backbone.blocks.25.out_filter_dense.weight": "model-00003-of-00003.safetensors",
|
| 206 |
+
"backbone.blocks.25.post_norm.scale": "model-00003-of-00003.safetensors",
|
| 207 |
+
"backbone.blocks.25.pre_norm.scale": "model-00003-of-00003.safetensors",
|
| 208 |
+
"backbone.blocks.25.projections.weight": "model-00003-of-00003.safetensors",
|
| 209 |
+
"backbone.blocks.26.filter.D": "model-00003-of-00003.safetensors",
|
| 210 |
+
"backbone.blocks.26.filter.h": "model-00003-of-00003.safetensors",
|
| 211 |
+
"backbone.blocks.26.filter.short_filter_weight": "model-00003-of-00003.safetensors",
|
| 212 |
+
"backbone.blocks.26.mlp.l1.weight": "model-00003-of-00003.safetensors",
|
| 213 |
+
"backbone.blocks.26.mlp.l2.weight": "model-00003-of-00003.safetensors",
|
| 214 |
+
"backbone.blocks.26.mlp.l3.weight": "model-00003-of-00003.safetensors",
|
| 215 |
+
"backbone.blocks.26.out_filter_dense.bias": "model-00003-of-00003.safetensors",
|
| 216 |
+
"backbone.blocks.26.out_filter_dense.weight": "model-00003-of-00003.safetensors",
|
| 217 |
+
"backbone.blocks.26.post_norm.scale": "model-00003-of-00003.safetensors",
|
| 218 |
+
"backbone.blocks.26.pre_norm.scale": "model-00003-of-00003.safetensors",
|
| 219 |
+
"backbone.blocks.26.projections.weight": "model-00003-of-00003.safetensors",
|
| 220 |
+
"backbone.blocks.27.filter.D": "model-00003-of-00003.safetensors",
|
| 221 |
+
"backbone.blocks.27.filter.log_poles": "model-00003-of-00003.safetensors",
|
| 222 |
+
"backbone.blocks.27.filter.residues": "model-00003-of-00003.safetensors",
|
| 223 |
+
"backbone.blocks.27.filter.short_filter_weight": "model-00003-of-00003.safetensors",
|
| 224 |
+
"backbone.blocks.27.mlp.l1.weight": "model-00003-of-00003.safetensors",
|
| 225 |
+
"backbone.blocks.27.mlp.l2.weight": "model-00003-of-00003.safetensors",
|
| 226 |
+
"backbone.blocks.27.mlp.l3.weight": "model-00003-of-00003.safetensors",
|
| 227 |
+
"backbone.blocks.27.out_filter_dense.bias": "model-00003-of-00003.safetensors",
|
| 228 |
+
"backbone.blocks.27.out_filter_dense.weight": "model-00003-of-00003.safetensors",
|
| 229 |
+
"backbone.blocks.27.post_norm.scale": "model-00003-of-00003.safetensors",
|
| 230 |
+
"backbone.blocks.27.pre_norm.scale": "model-00003-of-00003.safetensors",
|
| 231 |
+
"backbone.blocks.27.projections.weight": "model-00003-of-00003.safetensors",
|
| 232 |
+
"backbone.blocks.28.filter.h": "model-00003-of-00003.safetensors",
|
| 233 |
+
"backbone.blocks.28.filter.short_filter_weight": "model-00003-of-00003.safetensors",
|
| 234 |
+
"backbone.blocks.28.mlp.l1.weight": "model-00003-of-00003.safetensors",
|
| 235 |
+
"backbone.blocks.28.mlp.l2.weight": "model-00003-of-00003.safetensors",
|
| 236 |
+
"backbone.blocks.28.mlp.l3.weight": "model-00003-of-00003.safetensors",
|
| 237 |
+
"backbone.blocks.28.out_filter_dense.bias": "model-00003-of-00003.safetensors",
|
| 238 |
+
"backbone.blocks.28.out_filter_dense.weight": "model-00003-of-00003.safetensors",
|
| 239 |
+
"backbone.blocks.28.post_norm.scale": "model-00003-of-00003.safetensors",
|
| 240 |
+
"backbone.blocks.28.pre_norm.scale": "model-00003-of-00003.safetensors",
|
| 241 |
+
"backbone.blocks.28.projections.weight": "model-00003-of-00003.safetensors",
|
| 242 |
+
"backbone.blocks.29.filter.D": "model-00003-of-00003.safetensors",
|
| 243 |
+
"backbone.blocks.29.filter.h": "model-00003-of-00003.safetensors",
|
| 244 |
+
"backbone.blocks.29.filter.short_filter_weight": "model-00003-of-00003.safetensors",
|
| 245 |
+
"backbone.blocks.29.mlp.l1.weight": "model-00003-of-00003.safetensors",
|
| 246 |
+
"backbone.blocks.29.mlp.l2.weight": "model-00003-of-00003.safetensors",
|
| 247 |
+
"backbone.blocks.29.mlp.l3.weight": "model-00003-of-00003.safetensors",
|
| 248 |
+
"backbone.blocks.29.out_filter_dense.bias": "model-00003-of-00003.safetensors",
|
| 249 |
+
"backbone.blocks.29.out_filter_dense.weight": "model-00003-of-00003.safetensors",
|
| 250 |
+
"backbone.blocks.29.post_norm.scale": "model-00003-of-00003.safetensors",
|
| 251 |
+
"backbone.blocks.29.pre_norm.scale": "model-00003-of-00003.safetensors",
|
| 252 |
+
"backbone.blocks.29.projections.weight": "model-00003-of-00003.safetensors",
|
| 253 |
+
"backbone.blocks.3.inner_mha_cls.Wqkv.weight": "model-00001-of-00003.safetensors",
|
| 254 |
+
"backbone.blocks.3.inner_mha_cls.out_proj.bias": "model-00001-of-00003.safetensors",
|
| 255 |
+
"backbone.blocks.3.inner_mha_cls.out_proj.weight": "model-00001-of-00003.safetensors",
|
| 256 |
+
"backbone.blocks.3.inner_mha_cls.rotary_emb.inv_freq": "model-00001-of-00003.safetensors",
|
| 257 |
+
"backbone.blocks.3.mlp.l1.weight": "model-00001-of-00003.safetensors",
|
| 258 |
+
"backbone.blocks.3.mlp.l2.weight": "model-00001-of-00003.safetensors",
|
| 259 |
+
"backbone.blocks.3.mlp.l3.weight": "model-00001-of-00003.safetensors",
|
| 260 |
+
"backbone.blocks.3.post_norm.scale": "model-00001-of-00003.safetensors",
|
| 261 |
+
"backbone.blocks.3.pre_norm.scale": "model-00001-of-00003.safetensors",
|
| 262 |
+
"backbone.blocks.30.filter.D": "model-00003-of-00003.safetensors",
|
| 263 |
+
"backbone.blocks.30.filter.log_poles": "model-00003-of-00003.safetensors",
|
| 264 |
+
"backbone.blocks.30.filter.residues": "model-00003-of-00003.safetensors",
|
| 265 |
+
"backbone.blocks.30.filter.short_filter_weight": "model-00003-of-00003.safetensors",
|
| 266 |
+
"backbone.blocks.30.mlp.l1.weight": "model-00003-of-00003.safetensors",
|
| 267 |
+
"backbone.blocks.30.mlp.l2.weight": "model-00003-of-00003.safetensors",
|
| 268 |
+
"backbone.blocks.30.mlp.l3.weight": "model-00003-of-00003.safetensors",
|
| 269 |
+
"backbone.blocks.30.out_filter_dense.bias": "model-00003-of-00003.safetensors",
|
| 270 |
+
"backbone.blocks.30.out_filter_dense.weight": "model-00003-of-00003.safetensors",
|
| 271 |
+
"backbone.blocks.30.post_norm.scale": "model-00003-of-00003.safetensors",
|
| 272 |
+
"backbone.blocks.30.pre_norm.scale": "model-00003-of-00003.safetensors",
|
| 273 |
+
"backbone.blocks.30.projections.weight": "model-00003-of-00003.safetensors",
|
| 274 |
+
"backbone.blocks.31.inner_mha_cls.Wqkv.weight": "model-00003-of-00003.safetensors",
|
| 275 |
+
"backbone.blocks.31.inner_mha_cls.out_proj.bias": "model-00003-of-00003.safetensors",
|
| 276 |
+
"backbone.blocks.31.inner_mha_cls.out_proj.weight": "model-00003-of-00003.safetensors",
|
| 277 |
+
"backbone.blocks.31.inner_mha_cls.rotary_emb.inv_freq": "model-00003-of-00003.safetensors",
|
| 278 |
+
"backbone.blocks.31.mlp.l1.weight": "model-00003-of-00003.safetensors",
|
| 279 |
+
"backbone.blocks.31.mlp.l2.weight": "model-00003-of-00003.safetensors",
|
| 280 |
+
"backbone.blocks.31.mlp.l3.weight": "model-00003-of-00003.safetensors",
|
| 281 |
+
"backbone.blocks.31.post_norm.scale": "model-00003-of-00003.safetensors",
|
| 282 |
+
"backbone.blocks.31.pre_norm.scale": "model-00003-of-00003.safetensors",
|
| 283 |
+
"backbone.blocks.4.filter.h": "model-00001-of-00003.safetensors",
|
| 284 |
+
"backbone.blocks.4.filter.short_filter_weight": "model-00001-of-00003.safetensors",
|
| 285 |
+
"backbone.blocks.4.mlp.l1.weight": "model-00001-of-00003.safetensors",
|
| 286 |
+
"backbone.blocks.4.mlp.l2.weight": "model-00001-of-00003.safetensors",
|
| 287 |
+
"backbone.blocks.4.mlp.l3.weight": "model-00001-of-00003.safetensors",
|
| 288 |
+
"backbone.blocks.4.out_filter_dense.bias": "model-00001-of-00003.safetensors",
|
| 289 |
+
"backbone.blocks.4.out_filter_dense.weight": "model-00001-of-00003.safetensors",
|
| 290 |
+
"backbone.blocks.4.post_norm.scale": "model-00001-of-00003.safetensors",
|
| 291 |
+
"backbone.blocks.4.pre_norm.scale": "model-00001-of-00003.safetensors",
|
| 292 |
+
"backbone.blocks.4.projections.weight": "model-00001-of-00003.safetensors",
|
| 293 |
+
"backbone.blocks.5.filter.D": "model-00001-of-00003.safetensors",
|
| 294 |
+
"backbone.blocks.5.filter.h": "model-00001-of-00003.safetensors",
|
| 295 |
+
"backbone.blocks.5.filter.short_filter_weight": "model-00001-of-00003.safetensors",
|
| 296 |
+
"backbone.blocks.5.mlp.l1.weight": "model-00001-of-00003.safetensors",
|
| 297 |
+
"backbone.blocks.5.mlp.l2.weight": "model-00001-of-00003.safetensors",
|
| 298 |
+
"backbone.blocks.5.mlp.l3.weight": "model-00001-of-00003.safetensors",
|
| 299 |
+
"backbone.blocks.5.out_filter_dense.bias": "model-00001-of-00003.safetensors",
|
| 300 |
+
"backbone.blocks.5.out_filter_dense.weight": "model-00001-of-00003.safetensors",
|
| 301 |
+
"backbone.blocks.5.post_norm.scale": "model-00001-of-00003.safetensors",
|
| 302 |
+
"backbone.blocks.5.pre_norm.scale": "model-00001-of-00003.safetensors",
|
| 303 |
+
"backbone.blocks.5.projections.weight": "model-00001-of-00003.safetensors",
|
| 304 |
+
"backbone.blocks.6.filter.D": "model-00001-of-00003.safetensors",
|
| 305 |
+
"backbone.blocks.6.filter.log_poles": "model-00001-of-00003.safetensors",
|
| 306 |
+
"backbone.blocks.6.filter.residues": "model-00001-of-00003.safetensors",
|
| 307 |
+
"backbone.blocks.6.filter.short_filter_weight": "model-00001-of-00003.safetensors",
|
| 308 |
+
"backbone.blocks.6.mlp.l1.weight": "model-00001-of-00003.safetensors",
|
| 309 |
+
"backbone.blocks.6.mlp.l2.weight": "model-00001-of-00003.safetensors",
|
| 310 |
+
"backbone.blocks.6.mlp.l3.weight": "model-00001-of-00003.safetensors",
|
| 311 |
+
"backbone.blocks.6.out_filter_dense.bias": "model-00001-of-00003.safetensors",
|
| 312 |
+
"backbone.blocks.6.out_filter_dense.weight": "model-00001-of-00003.safetensors",
|
| 313 |
+
"backbone.blocks.6.post_norm.scale": "model-00001-of-00003.safetensors",
|
| 314 |
+
"backbone.blocks.6.pre_norm.scale": "model-00001-of-00003.safetensors",
|
| 315 |
+
"backbone.blocks.6.projections.weight": "model-00001-of-00003.safetensors",
|
| 316 |
+
"backbone.blocks.7.filter.h": "model-00001-of-00003.safetensors",
|
| 317 |
+
"backbone.blocks.7.filter.short_filter_weight": "model-00001-of-00003.safetensors",
|
| 318 |
+
"backbone.blocks.7.mlp.l1.weight": "model-00001-of-00003.safetensors",
|
| 319 |
+
"backbone.blocks.7.mlp.l2.weight": "model-00001-of-00003.safetensors",
|
| 320 |
+
"backbone.blocks.7.mlp.l3.weight": "model-00001-of-00003.safetensors",
|
| 321 |
+
"backbone.blocks.7.out_filter_dense.bias": "model-00001-of-00003.safetensors",
|
| 322 |
+
"backbone.blocks.7.out_filter_dense.weight": "model-00001-of-00003.safetensors",
|
| 323 |
+
"backbone.blocks.7.post_norm.scale": "model-00001-of-00003.safetensors",
|
| 324 |
+
"backbone.blocks.7.pre_norm.scale": "model-00001-of-00003.safetensors",
|
| 325 |
+
"backbone.blocks.7.projections.weight": "model-00001-of-00003.safetensors",
|
| 326 |
+
"backbone.blocks.8.filter.D": "model-00001-of-00003.safetensors",
|
| 327 |
+
"backbone.blocks.8.filter.h": "model-00001-of-00003.safetensors",
|
| 328 |
+
"backbone.blocks.8.filter.short_filter_weight": "model-00001-of-00003.safetensors",
|
| 329 |
+
"backbone.blocks.8.mlp.l1.weight": "model-00001-of-00003.safetensors",
|
| 330 |
+
"backbone.blocks.8.mlp.l2.weight": "model-00001-of-00003.safetensors",
|
| 331 |
+
"backbone.blocks.8.mlp.l3.weight": "model-00001-of-00003.safetensors",
|
| 332 |
+
"backbone.blocks.8.out_filter_dense.bias": "model-00001-of-00003.safetensors",
|
| 333 |
+
"backbone.blocks.8.out_filter_dense.weight": "model-00001-of-00003.safetensors",
|
| 334 |
+
"backbone.blocks.8.post_norm.scale": "model-00001-of-00003.safetensors",
|
| 335 |
+
"backbone.blocks.8.pre_norm.scale": "model-00001-of-00003.safetensors",
|
| 336 |
+
"backbone.blocks.8.projections.weight": "model-00001-of-00003.safetensors",
|
| 337 |
+
"backbone.blocks.9.filter.D": "model-00001-of-00003.safetensors",
|
| 338 |
+
"backbone.blocks.9.filter.log_poles": "model-00001-of-00003.safetensors",
|
| 339 |
+
"backbone.blocks.9.filter.residues": "model-00001-of-00003.safetensors",
|
| 340 |
+
"backbone.blocks.9.filter.short_filter_weight": "model-00001-of-00003.safetensors",
|
| 341 |
+
"backbone.blocks.9.mlp.l1.weight": "model-00001-of-00003.safetensors",
|
| 342 |
+
"backbone.blocks.9.mlp.l2.weight": "model-00001-of-00003.safetensors",
|
| 343 |
+
"backbone.blocks.9.mlp.l3.weight": "model-00001-of-00003.safetensors",
|
| 344 |
+
"backbone.blocks.9.out_filter_dense.bias": "model-00001-of-00003.safetensors",
|
| 345 |
+
"backbone.blocks.9.out_filter_dense.weight": "model-00001-of-00003.safetensors",
|
| 346 |
+
"backbone.blocks.9.post_norm.scale": "model-00001-of-00003.safetensors",
|
| 347 |
+
"backbone.blocks.9.pre_norm.scale": "model-00001-of-00003.safetensors",
|
| 348 |
+
"backbone.blocks.9.projections.weight": "model-00001-of-00003.safetensors",
|
| 349 |
+
"backbone.embedding_layer.weight": "model-00001-of-00003.safetensors",
|
| 350 |
+
"backbone.norm.scale": "model-00003-of-00003.safetensors"
|
| 351 |
+
}
|
| 352 |
+
}
|
modeling_evo2.py
ADDED
|
@@ -0,0 +1,425 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""HuggingFace wrappers for Evo2 (StripedHyena2).
|
| 2 |
+
|
| 3 |
+
Two top-level model classes:
|
| 4 |
+
|
| 5 |
+
* Evo2Model -- bare backbone returning BaseModelOutputWithPast
|
| 6 |
+
(no LM head); the post-RMSNorm hidden state is the
|
| 7 |
+
last_hidden_state.
|
| 8 |
+
* Evo2ForCausalLM -- with the tied LM head + GenerationMixin so
|
| 9 |
+
model.generate() works out of the box.
|
| 10 |
+
|
| 11 |
+
Caching for autoregressive generation uses the custom Evo2Cache (see
|
| 12 |
+
cache.py): a dict-like container of four block-type-specific param objects
|
| 13 |
+
(mha, hcl, hcm, hcs) so all four StripedHyena2 block types can decode in
|
| 14 |
+
constant time per new token.
|
| 15 |
+
|
| 16 |
+
Per-block dtype: bfloat16 for everything except the modal-form filter
|
| 17 |
+
parameters (`log_poles`, `residues`) which must stay fp32 for stability.
|
| 18 |
+
This is enforced both at convert time (the safetensors store these as fp32)
|
| 19 |
+
and at runtime via `force_dtype()` (called from each model's __init__).
|
| 20 |
+
"""
|
| 21 |
+
|
| 22 |
+
from __future__ import annotations
|
| 23 |
+
|
| 24 |
+
from typing import Optional, Tuple, Union
|
| 25 |
+
|
| 26 |
+
import torch
|
| 27 |
+
import torch.nn as nn
|
| 28 |
+
import torch.nn.functional as F
|
| 29 |
+
from transformers import PreTrainedModel
|
| 30 |
+
from transformers.generation import GenerationMixin
|
| 31 |
+
from transformers.modeling_outputs import (
|
| 32 |
+
BaseModelOutputWithPast,
|
| 33 |
+
CausalLMOutputWithPast,
|
| 34 |
+
)
|
| 35 |
+
from transformers.utils import logging
|
| 36 |
+
|
| 37 |
+
from .cache import Evo2Cache
|
| 38 |
+
from .configuration_evo2 import Evo2Config
|
| 39 |
+
from .hyena import (
|
| 40 |
+
AttentionBlock,
|
| 41 |
+
ParallelGatedConvBlock,
|
| 42 |
+
block_type_for_idx,
|
| 43 |
+
get_block,
|
| 44 |
+
)
|
| 45 |
+
from .layers import RMSNorm, VocabParallelEmbedding
|
| 46 |
+
# Bundle the tokenizer file via trust_remote_code:
|
| 47 |
+
from .tokenization_evo2 import ByteTokenizer # noqa: F401
|
| 48 |
+
# Force HF's trust_remote_code loader to copy these transitive deps into its
|
| 49 |
+
# dynamic-module cache (it only walks top-level `from .X import Y` patterns
|
| 50 |
+
# of modeling_evo2.py, not `from . import X`, so we use the explicit form).
|
| 51 |
+
from .attention import MHA as _MHA # noqa: F401
|
| 52 |
+
from .engine import HyenaInferenceEngine as _HyenaInferenceEngine # noqa: F401
|
| 53 |
+
from .rotary import RotaryEmbedding as _RotaryEmbedding # noqa: F401
|
| 54 |
+
|
| 55 |
+
logger = logging.get_logger(__name__)
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
# =============================================================================
|
| 59 |
+
# Backbone
|
| 60 |
+
# =============================================================================
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
class StripedHyena2(nn.Module):
|
| 64 |
+
"""Pure backbone: token embedding -> N blocks -> final RMSNorm."""
|
| 65 |
+
|
| 66 |
+
def __init__(self, config: Evo2Config):
|
| 67 |
+
super().__init__()
|
| 68 |
+
# Patch TE's cuBLAS workspace handling so multi-GPU device_map="auto"
|
| 69 |
+
# works (TE otherwise allocates a single workspace on the first device
|
| 70 |
+
# it sees, then fails on layers placed on other devices). No-op when
|
| 71 |
+
# TE isn't installed.
|
| 72 |
+
from .layers import fixup_te_workspace
|
| 73 |
+
fixup_te_workspace()
|
| 74 |
+
|
| 75 |
+
self.config = config
|
| 76 |
+
self.embedding_layer = VocabParallelEmbedding(config)
|
| 77 |
+
self.norm = RMSNorm(config) if config.get("final_norm", True) else None
|
| 78 |
+
|
| 79 |
+
if config.get("use_flashfft", False):
|
| 80 |
+
import importlib
|
| 81 |
+
FlashFFTConv = importlib.import_module("flashfftconv").FlashFFTConv
|
| 82 |
+
self.flash_fft = FlashFFTConv(2 * config.max_seqlen, dtype=torch.bfloat16)
|
| 83 |
+
else:
|
| 84 |
+
self.flash_fft = None
|
| 85 |
+
|
| 86 |
+
self.blocks = nn.ModuleList(
|
| 87 |
+
get_block(config, i) for i in range(config.num_layers)
|
| 88 |
+
)
|
| 89 |
+
# Wire fftconv_fn into the hcl filters when flashfft is on.
|
| 90 |
+
if self.flash_fft is not None:
|
| 91 |
+
for block in self.blocks:
|
| 92 |
+
if isinstance(block, ParallelGatedConvBlock) and block.filter.h is None:
|
| 93 |
+
block.filter.fftconv_fn = self.flash_fft
|
| 94 |
+
|
| 95 |
+
def forward(
|
| 96 |
+
self,
|
| 97 |
+
x: torch.Tensor,
|
| 98 |
+
inference_params_dict: Optional[Evo2Cache] = None,
|
| 99 |
+
padding_mask: Optional[torch.Tensor] = None,
|
| 100 |
+
output_hidden_states: bool = False,
|
| 101 |
+
output_attentions: bool = False,
|
| 102 |
+
):
|
| 103 |
+
x = self.embedding_layer.embed(x)
|
| 104 |
+
|
| 105 |
+
all_hidden_states: list[torch.Tensor] = []
|
| 106 |
+
all_attentions: list[Optional[torch.Tensor]] = []
|
| 107 |
+
if output_hidden_states:
|
| 108 |
+
all_hidden_states.append(x)
|
| 109 |
+
|
| 110 |
+
if inference_params_dict is not None:
|
| 111 |
+
x, params_out = self._stateful_forward(
|
| 112 |
+
x, inference_params_dict,
|
| 113 |
+
all_hidden_states=all_hidden_states,
|
| 114 |
+
all_attentions=all_attentions,
|
| 115 |
+
output_hidden_states=output_hidden_states,
|
| 116 |
+
output_attentions=output_attentions,
|
| 117 |
+
)
|
| 118 |
+
else:
|
| 119 |
+
x, params_out = self._stateless_forward(
|
| 120 |
+
x, padding_mask=padding_mask,
|
| 121 |
+
all_hidden_states=all_hidden_states,
|
| 122 |
+
all_attentions=all_attentions,
|
| 123 |
+
output_hidden_states=output_hidden_states,
|
| 124 |
+
output_attentions=output_attentions,
|
| 125 |
+
)
|
| 126 |
+
|
| 127 |
+
if self.norm is not None:
|
| 128 |
+
x = self.norm(x)
|
| 129 |
+
if output_hidden_states:
|
| 130 |
+
all_hidden_states.append(x)
|
| 131 |
+
|
| 132 |
+
return x, params_out, all_hidden_states, all_attentions
|
| 133 |
+
|
| 134 |
+
def _stateful_forward(
|
| 135 |
+
self, x, cache: Evo2Cache,
|
| 136 |
+
all_hidden_states, all_attentions,
|
| 137 |
+
output_hidden_states, output_attentions,
|
| 138 |
+
):
|
| 139 |
+
for block_idx, block in enumerate(self.blocks):
|
| 140 |
+
block_name = block_type_for_idx(self.config, block_idx)
|
| 141 |
+
inference_params = cache.by_block_name(block_name)
|
| 142 |
+
x, attn = block(
|
| 143 |
+
x, inference_params=inference_params,
|
| 144 |
+
output_attentions=output_attentions,
|
| 145 |
+
)
|
| 146 |
+
if output_hidden_states:
|
| 147 |
+
all_hidden_states.append(x)
|
| 148 |
+
if output_attentions:
|
| 149 |
+
all_attentions.append(attn)
|
| 150 |
+
return x, cache
|
| 151 |
+
|
| 152 |
+
def _stateless_forward(
|
| 153 |
+
self, x, padding_mask,
|
| 154 |
+
all_hidden_states, all_attentions,
|
| 155 |
+
output_hidden_states, output_attentions,
|
| 156 |
+
):
|
| 157 |
+
if isinstance(padding_mask, torch.Tensor):
|
| 158 |
+
x = x * padding_mask[..., None]
|
| 159 |
+
for block in self.blocks:
|
| 160 |
+
x, attn = block(
|
| 161 |
+
x, inference_params=None, padding_mask=padding_mask,
|
| 162 |
+
output_attentions=output_attentions,
|
| 163 |
+
)
|
| 164 |
+
if output_hidden_states:
|
| 165 |
+
all_hidden_states.append(x)
|
| 166 |
+
if output_attentions:
|
| 167 |
+
all_attentions.append(attn)
|
| 168 |
+
return x, None
|
| 169 |
+
|
| 170 |
+
def initialize_inference_params(self, max_batch_size: int = 1) -> Evo2Cache:
|
| 171 |
+
return Evo2Cache(
|
| 172 |
+
max_seqlen=self.config.get("max_seqlen", 8192),
|
| 173 |
+
max_batch_size=max_batch_size,
|
| 174 |
+
short_filter_length=self.config.short_filter_length,
|
| 175 |
+
hcm_filter_length=self.config.hcm_filter_length,
|
| 176 |
+
hcs_filter_length=self.config.hcs_filter_length,
|
| 177 |
+
state_size=self.config.state_size,
|
| 178 |
+
)
|
| 179 |
+
|
| 180 |
+
def to_bfloat16_except_poles_residues(self):
|
| 181 |
+
"""Cast params to bf16, restore fp32 invariants:
|
| 182 |
+
|
| 183 |
+
* log_poles / residues -- bf16 collapses the modal-form IIR (the
|
| 184 |
+
poles get rounded too aggressively, the recurrence blows up).
|
| 185 |
+
Mirrors vortex's ``to_bfloat16_except_pr_lc(to_float32=True)``
|
| 186 |
+
first-pass behaviour.
|
| 187 |
+
|
| 188 |
+
* rotary_emb.inv_freq -- HF ``from_pretrained(dtype=bf16)`` casts
|
| 189 |
+
ALL buffers to bf16. ``inv_freq = 1 / base^(2i/dim)`` loses ~7
|
| 190 |
+
bits of mantissa in bf16, which shifts cos/sin tables by ~5e-2
|
| 191 |
+
per cell at position 64+, causing each attention layer to add
|
| 192 |
+
~4e-2 of noise on Q/K. We recompute inv_freq in fp32 here so
|
| 193 |
+
the cos/sin builder uses the precise stored value.
|
| 194 |
+
"""
|
| 195 |
+
for k, p in self.named_parameters():
|
| 196 |
+
if "log_poles" in k or "residues" in k:
|
| 197 |
+
p.data = p.data.to(torch.float32)
|
| 198 |
+
else:
|
| 199 |
+
p.data = p.data.to(torch.bfloat16)
|
| 200 |
+
for module in self.modules():
|
| 201 |
+
if hasattr(module, "_compute_inv_freq") and hasattr(module, "inv_freq"):
|
| 202 |
+
fresh = module._compute_inv_freq(device=module.inv_freq.device)
|
| 203 |
+
module.inv_freq.data = fresh
|
| 204 |
+
# Invalidate any cached cos/sin so the next forward rebuilds
|
| 205 |
+
# them from the precise fp32 inv_freq.
|
| 206 |
+
module._seq_len_cached = 0
|
| 207 |
+
module._cos_cached = None
|
| 208 |
+
module._sin_cached = None
|
| 209 |
+
|
| 210 |
+
|
| 211 |
+
# =============================================================================
|
| 212 |
+
# HF wrappers
|
| 213 |
+
# =============================================================================
|
| 214 |
+
|
| 215 |
+
|
| 216 |
+
class Evo2PreTrainedModel(PreTrainedModel):
|
| 217 |
+
config_class = Evo2Config
|
| 218 |
+
base_model_prefix = "backbone"
|
| 219 |
+
supports_gradient_checkpointing = False
|
| 220 |
+
_no_split_modules = ["AttentionBlock", "ParallelGatedConvBlock"]
|
| 221 |
+
_skip_keys_device_placement = "past_key_values"
|
| 222 |
+
_keys_to_ignore_on_load_missing = [r"freq", r"\.t$"]
|
| 223 |
+
_keys_to_ignore_on_load_unexpected = [r"fftconv", r"twiddle_factors", r"_extra_state$"]
|
| 224 |
+
_supports_flash_attn_2 = True
|
| 225 |
+
_supports_sdpa = True
|
| 226 |
+
# Evo2 cache is a custom Evo2Cache (not a DynamicCache); tell HF not to wrap it.
|
| 227 |
+
_supports_cache_class = False
|
| 228 |
+
# log_poles / residues parameterize a modal long-range filter; bf16 collapses
|
| 229 |
+
# them. HF will keep these in fp32 even with dtype=bf16 at load time.
|
| 230 |
+
_keep_in_fp32_modules = ["log_poles", "residues"]
|
| 231 |
+
|
| 232 |
+
@classmethod
|
| 233 |
+
def from_pretrained(cls, *args, **kwargs):
|
| 234 |
+
if "dtype" not in kwargs and "torch_dtype" not in kwargs:
|
| 235 |
+
kwargs["dtype"] = torch.bfloat16
|
| 236 |
+
return super().from_pretrained(*args, **kwargs)
|
| 237 |
+
|
| 238 |
+
|
| 239 |
+
class Evo2Model(Evo2PreTrainedModel):
|
| 240 |
+
"""Bare backbone returning BaseModelOutputWithPast."""
|
| 241 |
+
|
| 242 |
+
def __init__(self, config: Evo2Config):
|
| 243 |
+
super().__init__(config)
|
| 244 |
+
self.backbone = StripedHyena2(config)
|
| 245 |
+
self.config = config
|
| 246 |
+
self.post_init()
|
| 247 |
+
self.force_dtype()
|
| 248 |
+
|
| 249 |
+
def force_dtype(self):
|
| 250 |
+
self.backbone.to_bfloat16_except_poles_residues()
|
| 251 |
+
|
| 252 |
+
def get_input_embeddings(self):
|
| 253 |
+
return self.backbone.embedding_layer
|
| 254 |
+
|
| 255 |
+
def set_input_embeddings(self, value):
|
| 256 |
+
self.backbone.embedding_layer = value
|
| 257 |
+
|
| 258 |
+
def forward(
|
| 259 |
+
self,
|
| 260 |
+
input_ids: torch.LongTensor = None,
|
| 261 |
+
attention_mask: Optional[torch.LongTensor] = None,
|
| 262 |
+
past_key_values=None,
|
| 263 |
+
use_cache: Optional[bool] = None,
|
| 264 |
+
output_attentions: Optional[bool] = None,
|
| 265 |
+
output_hidden_states: Optional[bool] = None,
|
| 266 |
+
return_dict: Optional[bool] = None,
|
| 267 |
+
) -> Union[Tuple, BaseModelOutputWithPast]:
|
| 268 |
+
return_dict = return_dict if return_dict is not None else self.config.use_return_dict
|
| 269 |
+
output_attentions = (
|
| 270 |
+
output_attentions if output_attentions is not None else self.config.output_attentions
|
| 271 |
+
)
|
| 272 |
+
output_hidden_states = (
|
| 273 |
+
output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
|
| 274 |
+
)
|
| 275 |
+
# Default to no caching for the bare backbone: caches have large
|
| 276 |
+
# per-layer memory cost with no benefit for embedding extraction.
|
| 277 |
+
use_cache = use_cache if use_cache is not None else False
|
| 278 |
+
if use_cache and self.training:
|
| 279 |
+
use_cache = False
|
| 280 |
+
|
| 281 |
+
inputs = input_ids
|
| 282 |
+
if use_cache and past_key_values is None:
|
| 283 |
+
past_key_values = self.backbone.initialize_inference_params(
|
| 284 |
+
max_batch_size=input_ids.shape[0]
|
| 285 |
+
)
|
| 286 |
+
|
| 287 |
+
last_hidden, past_kv, hidden_states, attentions = self.backbone(
|
| 288 |
+
inputs,
|
| 289 |
+
padding_mask=attention_mask,
|
| 290 |
+
inference_params_dict=past_key_values if use_cache else None,
|
| 291 |
+
output_hidden_states=output_hidden_states,
|
| 292 |
+
output_attentions=output_attentions,
|
| 293 |
+
)
|
| 294 |
+
|
| 295 |
+
if not return_dict:
|
| 296 |
+
outputs = (last_hidden,)
|
| 297 |
+
if use_cache: outputs += (past_kv,)
|
| 298 |
+
if output_hidden_states: outputs += (tuple(hidden_states),)
|
| 299 |
+
if output_attentions: outputs += (tuple(attentions),)
|
| 300 |
+
return outputs
|
| 301 |
+
|
| 302 |
+
return BaseModelOutputWithPast(
|
| 303 |
+
last_hidden_state=last_hidden,
|
| 304 |
+
past_key_values=past_kv if use_cache else None,
|
| 305 |
+
hidden_states=tuple(hidden_states) if output_hidden_states else None,
|
| 306 |
+
attentions=tuple(attentions) if output_attentions else None,
|
| 307 |
+
)
|
| 308 |
+
|
| 309 |
+
|
| 310 |
+
class Evo2ForCausalLM(Evo2PreTrainedModel, GenerationMixin):
|
| 311 |
+
"""LM head wrapper. Tied to backbone.embedding_layer (Evo2 ties weights)."""
|
| 312 |
+
|
| 313 |
+
def __init__(self, config: Evo2Config, **kwargs):
|
| 314 |
+
super().__init__(config, **kwargs)
|
| 315 |
+
self.backbone = StripedHyena2(config)
|
| 316 |
+
self.config = config
|
| 317 |
+
|
| 318 |
+
vocab_size = config.vocab_size
|
| 319 |
+
if vocab_size % config.make_vocab_size_divisible_by != 0:
|
| 320 |
+
vocab_size += config.make_vocab_size_divisible_by - (
|
| 321 |
+
vocab_size % config.make_vocab_size_divisible_by
|
| 322 |
+
)
|
| 323 |
+
self.vocab_size = vocab_size
|
| 324 |
+
self.post_init()
|
| 325 |
+
self.force_dtype()
|
| 326 |
+
|
| 327 |
+
def force_dtype(self):
|
| 328 |
+
self.backbone.to_bfloat16_except_poles_residues()
|
| 329 |
+
|
| 330 |
+
def get_input_embeddings(self):
|
| 331 |
+
return self.backbone.embedding_layer
|
| 332 |
+
|
| 333 |
+
def set_input_embeddings(self, value):
|
| 334 |
+
self.backbone.embedding_layer = value
|
| 335 |
+
|
| 336 |
+
def get_output_embeddings(self):
|
| 337 |
+
return self.backbone.embedding_layer
|
| 338 |
+
|
| 339 |
+
def set_output_embeddings(self, value):
|
| 340 |
+
self.backbone.embedding_layer = value
|
| 341 |
+
|
| 342 |
+
def forward(
|
| 343 |
+
self,
|
| 344 |
+
input_ids: torch.LongTensor = None,
|
| 345 |
+
attention_mask: Optional[torch.LongTensor] = None,
|
| 346 |
+
labels: Optional[torch.LongTensor] = None,
|
| 347 |
+
past_key_values=None,
|
| 348 |
+
use_cache: Optional[bool] = None,
|
| 349 |
+
output_attentions: Optional[bool] = None,
|
| 350 |
+
output_hidden_states: Optional[bool] = None,
|
| 351 |
+
return_dict: Optional[bool] = None,
|
| 352 |
+
) -> Union[Tuple, CausalLMOutputWithPast]:
|
| 353 |
+
return_dict = return_dict if return_dict is not None else self.config.use_return_dict
|
| 354 |
+
output_attentions = (
|
| 355 |
+
output_attentions if output_attentions is not None else self.config.output_attentions
|
| 356 |
+
)
|
| 357 |
+
output_hidden_states = (
|
| 358 |
+
output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
|
| 359 |
+
)
|
| 360 |
+
use_cache = use_cache if use_cache is not None else self.config.use_cache
|
| 361 |
+
|
| 362 |
+
if use_cache and labels is not None:
|
| 363 |
+
logger.warning_once("use_cache=True is incompatible with loss computation; disabling.")
|
| 364 |
+
use_cache = False
|
| 365 |
+
|
| 366 |
+
inputs = input_ids
|
| 367 |
+
if use_cache:
|
| 368 |
+
if not isinstance(past_key_values, Evo2Cache):
|
| 369 |
+
past_key_values = self.backbone.initialize_inference_params(
|
| 370 |
+
max_batch_size=input_ids.shape[0]
|
| 371 |
+
)
|
| 372 |
+
else:
|
| 373 |
+
seqlen_offset = past_key_values.seqlen_offset
|
| 374 |
+
if seqlen_offset == 0:
|
| 375 |
+
past_key_values.set_offset(input_ids.shape[-1] - 1)
|
| 376 |
+
else:
|
| 377 |
+
past_key_values.advance(1)
|
| 378 |
+
inputs = input_ids[:, -1:]
|
| 379 |
+
|
| 380 |
+
last_hidden, past_kv, hidden_states, attentions = self.backbone(
|
| 381 |
+
inputs,
|
| 382 |
+
padding_mask=attention_mask,
|
| 383 |
+
inference_params_dict=past_key_values if use_cache else None,
|
| 384 |
+
output_hidden_states=output_hidden_states,
|
| 385 |
+
output_attentions=output_attentions,
|
| 386 |
+
)
|
| 387 |
+
|
| 388 |
+
logits = last_hidden @ self.backbone.embedding_layer.weight.T
|
| 389 |
+
|
| 390 |
+
loss = None
|
| 391 |
+
if labels is not None:
|
| 392 |
+
shift_logits = logits[..., :-1, :].contiguous()
|
| 393 |
+
shift_labels = labels[..., 1:].contiguous()
|
| 394 |
+
shift_logits = shift_logits.view(-1, self.config.vocab_size)
|
| 395 |
+
shift_labels = shift_labels.view(-1).to(shift_logits.device)
|
| 396 |
+
loss = F.cross_entropy(shift_logits, shift_labels)
|
| 397 |
+
|
| 398 |
+
if not return_dict:
|
| 399 |
+
outputs = (logits,)
|
| 400 |
+
if use_cache: outputs += (past_kv,)
|
| 401 |
+
if output_hidden_states: outputs += (tuple(hidden_states),)
|
| 402 |
+
if output_attentions: outputs += (tuple(attentions),)
|
| 403 |
+
if loss is not None: outputs = (loss,) + outputs
|
| 404 |
+
return outputs
|
| 405 |
+
|
| 406 |
+
return CausalLMOutputWithPast(
|
| 407 |
+
loss=loss,
|
| 408 |
+
logits=logits,
|
| 409 |
+
past_key_values=past_kv if use_cache else None,
|
| 410 |
+
hidden_states=tuple(hidden_states) if output_hidden_states else None,
|
| 411 |
+
attentions=tuple(attentions) if output_attentions else None,
|
| 412 |
+
)
|
| 413 |
+
|
| 414 |
+
@classmethod
|
| 415 |
+
def can_generate(cls) -> bool:
|
| 416 |
+
return True
|
| 417 |
+
|
| 418 |
+
def prepare_inputs_for_generation(
|
| 419 |
+
self, input_ids, attention_mask=None, past_key_values=None, **kwargs
|
| 420 |
+
):
|
| 421 |
+
return {
|
| 422 |
+
"input_ids": input_ids,
|
| 423 |
+
"attention_mask": attention_mask,
|
| 424 |
+
"past_key_values": past_key_values,
|
| 425 |
+
}
|
rotary.py
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Rotary embeddings for Evo2.
|
| 2 |
+
|
| 3 |
+
Mirrors models/evo/hf/rotary.py (same RoPE math): flash_attn fast path when
|
| 4 |
+
available, pure-PyTorch fallback otherwise. LinearlyScaledRotaryEmbedding
|
| 5 |
+
implements linear position-index interpolation (`t = t / scaling_factor`)
|
| 6 |
+
used by all the 1M / 262K context variants.
|
| 7 |
+
"""
|
| 8 |
+
|
| 9 |
+
from __future__ import annotations
|
| 10 |
+
|
| 11 |
+
import torch
|
| 12 |
+
import torch.nn as nn
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
try:
|
| 16 |
+
from flash_attn.layers.rotary import RotaryEmbedding as _FlashRotaryEmbedding
|
| 17 |
+
_HAS_FLASH_ROTARY = True
|
| 18 |
+
except ImportError:
|
| 19 |
+
_FlashRotaryEmbedding = None
|
| 20 |
+
_HAS_FLASH_ROTARY = False
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
def _rotate_half(x: torch.Tensor) -> torch.Tensor:
|
| 24 |
+
x1, x2 = x.chunk(2, dim=-1)
|
| 25 |
+
return torch.cat((-x2, x1), dim=-1)
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
def _apply_rotary(x: torch.Tensor, cos: torch.Tensor, sin: torch.Tensor) -> torch.Tensor:
|
| 29 |
+
# Compute the multiply in fp32 then cast back to x.dtype to match
|
| 30 |
+
# flash_attn's Triton kernel bit-exactly. Doing the multiply in bf16
|
| 31 |
+
# directly compounds rounding error of ~3e-2 per layer.
|
| 32 |
+
rot_dim = cos.shape[-1] * 2
|
| 33 |
+
x_rot = x[..., :rot_dim]
|
| 34 |
+
x_pass = x[..., rot_dim:]
|
| 35 |
+
orig_dtype = x.dtype
|
| 36 |
+
cos_full = torch.cat((cos, cos), dim=-1).float()
|
| 37 |
+
sin_full = torch.cat((sin, sin), dim=-1).float()
|
| 38 |
+
x_rot_f = x_rot.float()
|
| 39 |
+
rotated = (x_rot_f * cos_full) + (_rotate_half(x_rot_f) * sin_full)
|
| 40 |
+
rotated = rotated.to(orig_dtype)
|
| 41 |
+
return torch.cat((rotated, x_pass), dim=-1)
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
class _PureRotaryEmbedding(nn.Module):
|
| 45 |
+
"""Pure-PyTorch fallback RoPE. Mirrors flash_attn.layers.rotary.RotaryEmbedding's surface."""
|
| 46 |
+
|
| 47 |
+
def __init__(
|
| 48 |
+
self,
|
| 49 |
+
dim: int,
|
| 50 |
+
base: float = 10000.0,
|
| 51 |
+
interleaved: bool = False,
|
| 52 |
+
scale_base: float | None = None,
|
| 53 |
+
pos_idx_in_fp32: bool = True,
|
| 54 |
+
device=None,
|
| 55 |
+
):
|
| 56 |
+
super().__init__()
|
| 57 |
+
if interleaved:
|
| 58 |
+
raise NotImplementedError("Interleaved RoPE is not implemented.")
|
| 59 |
+
if scale_base is not None:
|
| 60 |
+
raise NotImplementedError("xPos scale_base is not implemented.")
|
| 61 |
+
self.dim = dim
|
| 62 |
+
self.base = float(base)
|
| 63 |
+
self.interleaved = interleaved
|
| 64 |
+
self.scale_base = scale_base
|
| 65 |
+
self.pos_idx_in_fp32 = pos_idx_in_fp32
|
| 66 |
+
|
| 67 |
+
inv_freq = self._compute_inv_freq(device=device)
|
| 68 |
+
self.register_buffer("inv_freq", inv_freq, persistent=False)
|
| 69 |
+
self.scale = None # xPos slot kept for swap_mha_rope compatibility
|
| 70 |
+
|
| 71 |
+
self._seq_len_cached = 0
|
| 72 |
+
self._cos_cached: torch.Tensor | None = None
|
| 73 |
+
self._sin_cached: torch.Tensor | None = None
|
| 74 |
+
|
| 75 |
+
def _compute_inv_freq(self, device=None) -> torch.Tensor:
|
| 76 |
+
return 1.0 / (
|
| 77 |
+
self.base
|
| 78 |
+
** (torch.arange(0, self.dim, 2, device=device, dtype=torch.float32) / self.dim)
|
| 79 |
+
)
|
| 80 |
+
|
| 81 |
+
def _update_cos_sin_cache(self, seqlen: int, device=None, dtype=None):
|
| 82 |
+
if (
|
| 83 |
+
seqlen > self._seq_len_cached
|
| 84 |
+
or self._cos_cached is None
|
| 85 |
+
or self._cos_cached.device != device
|
| 86 |
+
or self._cos_cached.dtype != dtype
|
| 87 |
+
or (self.training and self._cos_cached.is_inference())
|
| 88 |
+
):
|
| 89 |
+
self._seq_len_cached = seqlen
|
| 90 |
+
if self.pos_idx_in_fp32:
|
| 91 |
+
t = torch.arange(seqlen, device=device, dtype=torch.float32)
|
| 92 |
+
if self.inv_freq.dtype != torch.float32:
|
| 93 |
+
inv_freq = self._compute_inv_freq(device=device)
|
| 94 |
+
else:
|
| 95 |
+
inv_freq = self.inv_freq
|
| 96 |
+
else:
|
| 97 |
+
t = torch.arange(seqlen, device=device, dtype=self.inv_freq.dtype)
|
| 98 |
+
inv_freq = self.inv_freq
|
| 99 |
+
|
| 100 |
+
freqs = torch.outer(t, inv_freq)
|
| 101 |
+
self._cos_cached = torch.cos(freqs).to(dtype)
|
| 102 |
+
self._sin_cached = torch.sin(freqs).to(dtype)
|
| 103 |
+
|
| 104 |
+
def forward(
|
| 105 |
+
self,
|
| 106 |
+
qkv: torch.Tensor,
|
| 107 |
+
seqlen_offset: int | torch.Tensor = 0,
|
| 108 |
+
max_seqlen: int | None = None,
|
| 109 |
+
) -> torch.Tensor:
|
| 110 |
+
if isinstance(seqlen_offset, torch.Tensor):
|
| 111 |
+
seqlen_offset = int(seqlen_offset.max().item())
|
| 112 |
+
T = qkv.shape[1]
|
| 113 |
+
seqlen = max_seqlen if max_seqlen is not None else (T + seqlen_offset)
|
| 114 |
+
self._update_cos_sin_cache(seqlen, device=qkv.device, dtype=qkv.dtype)
|
| 115 |
+
|
| 116 |
+
cos = self._cos_cached[seqlen_offset : seqlen_offset + T]
|
| 117 |
+
sin = self._sin_cached[seqlen_offset : seqlen_offset + T]
|
| 118 |
+
q, k, v = qkv.unbind(dim=2)
|
| 119 |
+
cos_b = cos[None, :, None, :]
|
| 120 |
+
sin_b = sin[None, :, None, :]
|
| 121 |
+
q = _apply_rotary(q, cos_b, sin_b)
|
| 122 |
+
k = _apply_rotary(k, cos_b, sin_b)
|
| 123 |
+
return torch.stack((q, k, v), dim=2)
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
RotaryEmbedding: type = (
|
| 127 |
+
_FlashRotaryEmbedding if _HAS_FLASH_ROTARY else _PureRotaryEmbedding
|
| 128 |
+
)
|
| 129 |
+
|
| 130 |
+
|
| 131 |
+
class LinearlyScaledRotaryEmbedding(RotaryEmbedding):
|
| 132 |
+
"""RoPE with linear interpolation of position indices.
|
| 133 |
+
|
| 134 |
+
Used for evo2_7b (1M), evo2_7b_262k, evo2_20b, evo2_40b. Positions are
|
| 135 |
+
divided by ``scaling_factor`` before cos/sin tables are computed.
|
| 136 |
+
"""
|
| 137 |
+
|
| 138 |
+
def __init__(self, dim: int, scaling_factor: float = 1.0, **kwargs):
|
| 139 |
+
super().__init__(dim=dim, **kwargs)
|
| 140 |
+
self._linear_scaling_factor = float(scaling_factor)
|
| 141 |
+
|
| 142 |
+
def _update_cos_sin_cache(self, seqlen, device=None, dtype=None):
|
| 143 |
+
if (
|
| 144 |
+
seqlen <= self._seq_len_cached
|
| 145 |
+
and self._cos_cached is not None
|
| 146 |
+
and self._cos_cached.device == device
|
| 147 |
+
and self._cos_cached.dtype == dtype
|
| 148 |
+
and not (self.training and self._cos_cached.is_inference())
|
| 149 |
+
):
|
| 150 |
+
return
|
| 151 |
+
|
| 152 |
+
self._seq_len_cached = seqlen
|
| 153 |
+
if self.pos_idx_in_fp32:
|
| 154 |
+
t = torch.arange(seqlen, device=device, dtype=torch.float32)
|
| 155 |
+
t = t / self._linear_scaling_factor
|
| 156 |
+
if self.inv_freq.dtype != torch.float32:
|
| 157 |
+
inv_freq = self._compute_inv_freq(device=device) \
|
| 158 |
+
if hasattr(self, "_compute_inv_freq") \
|
| 159 |
+
else self.inv_freq.float()
|
| 160 |
+
else:
|
| 161 |
+
inv_freq = self.inv_freq
|
| 162 |
+
else:
|
| 163 |
+
t = torch.arange(seqlen, device=device, dtype=self.inv_freq.dtype)
|
| 164 |
+
t = t / self._linear_scaling_factor
|
| 165 |
+
inv_freq = self.inv_freq
|
| 166 |
+
|
| 167 |
+
freqs = torch.outer(t, inv_freq)
|
| 168 |
+
if self.scale is None:
|
| 169 |
+
self._cos_cached = torch.cos(freqs).to(dtype)
|
| 170 |
+
self._sin_cached = torch.sin(freqs).to(dtype)
|
| 171 |
+
else:
|
| 172 |
+
from einops import rearrange
|
| 173 |
+
power = (
|
| 174 |
+
torch.arange(seqlen, dtype=self.scale.dtype, device=self.scale.device)
|
| 175 |
+
- seqlen // 2
|
| 176 |
+
) / self.scale_base
|
| 177 |
+
scale = self.scale.to(device=power.device) ** rearrange(power, "s -> s 1")
|
| 178 |
+
self._cos_cached = (torch.cos(freqs) * scale).to(dtype)
|
| 179 |
+
self._sin_cached = (torch.sin(freqs) * scale).to(dtype)
|
| 180 |
+
self._cos_k_cached = (torch.cos(freqs) / scale).to(dtype)
|
| 181 |
+
self._sin_k_cached = (torch.sin(freqs) / scale).to(dtype)
|
| 182 |
+
|
| 183 |
+
|
| 184 |
+
def swap_mha_rope(mha, new_rope=LinearlyScaledRotaryEmbedding, kwargs_new_rope=None):
|
| 185 |
+
"""Replace ``mha.rotary_emb`` with a freshly-constructed scaled RoPE."""
|
| 186 |
+
weight_attr = "Wq" if getattr(mha, "cross_attn", False) else "Wqkv"
|
| 187 |
+
weight = getattr(mha, weight_attr).weight
|
| 188 |
+
dtype = weight.dtype
|
| 189 |
+
kwargs_old_rope = dict(
|
| 190 |
+
dim=mha.rotary_emb.dim,
|
| 191 |
+
base=mha.rotary_emb.base,
|
| 192 |
+
interleaved=mha.rotary_emb.interleaved,
|
| 193 |
+
scale_base=mha.rotary_emb.scale_base,
|
| 194 |
+
pos_idx_in_fp32=mha.rotary_emb.pos_idx_in_fp32,
|
| 195 |
+
device=mha.rotary_emb.inv_freq.device,
|
| 196 |
+
)
|
| 197 |
+
del mha.rotary_emb
|
| 198 |
+
kwargs_new_rope = kwargs_new_rope or {"scaling_factor": 1.0}
|
| 199 |
+
scaled = new_rope(**kwargs_new_rope, **kwargs_old_rope).to(dtype)
|
| 200 |
+
mha.rotary_emb = scaled
|
| 201 |
+
return mha
|
special_tokens_map.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{}
|
tokenization_evo2.py
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""ByteTokenizer for Evo2 (StripedHyena2).
|
| 2 |
+
|
| 3 |
+
Wraps raw UTF-8 byte values into a vocab of size 512 (only [0, 255] are real
|
| 4 |
+
bytes; the upper range pads out to match the model's vocab embedding size).
|
| 5 |
+
Mirrors vortex.model.tokenizer.CharLevelTokenizer exactly:
|
| 6 |
+
|
| 7 |
+
* eod / eos = byte 0 (chr(0))
|
| 8 |
+
* pad = byte 1 (chr(1))
|
| 9 |
+
|
| 10 |
+
No real special tokens are added at encoding time -- Evo2 is a pure byte-level
|
| 11 |
+
model and downstream pooling should treat every non-pad position as a real
|
| 12 |
+
token.
|
| 13 |
+
"""
|
| 14 |
+
|
| 15 |
+
from __future__ import annotations
|
| 16 |
+
|
| 17 |
+
from os import PathLike
|
| 18 |
+
from typing import List, Tuple
|
| 19 |
+
|
| 20 |
+
import numpy as np
|
| 21 |
+
|
| 22 |
+
from transformers.tokenization_utils import PreTrainedTokenizer
|
| 23 |
+
from transformers.tokenization_utils_base import BatchEncoding, TruncationStrategy
|
| 24 |
+
from transformers.utils.generic import PaddingStrategy
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
EMPTY: str = ""
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
class ByteTokenizer(PreTrainedTokenizer):
|
| 31 |
+
"""UTF-8 byte-level tokenizer for Evo2 (vocab_size = 512)."""
|
| 32 |
+
|
| 33 |
+
def __init__(self, byte_level: bool = True, **kwargs):
|
| 34 |
+
kwargs.setdefault("pad_token", chr(1))
|
| 35 |
+
super().__init__(byte_level=byte_level, **kwargs)
|
| 36 |
+
self.model_input_names = ["input_ids", "attention_mask"]
|
| 37 |
+
|
| 38 |
+
@property
|
| 39 |
+
def vocab_size(self) -> int:
|
| 40 |
+
return 512
|
| 41 |
+
|
| 42 |
+
@property
|
| 43 |
+
def byte_level(self) -> bool:
|
| 44 |
+
return self.init_kwargs.get("byte_level", True)
|
| 45 |
+
|
| 46 |
+
def get_vocab(self) -> dict:
|
| 47 |
+
return {chr(i): i for i in range(self.vocab_size)}
|
| 48 |
+
|
| 49 |
+
def __len__(self) -> int:
|
| 50 |
+
return self.vocab_size
|
| 51 |
+
|
| 52 |
+
def clamp(self, n: int) -> int:
|
| 53 |
+
# Matches vortex CharLevelTokenizer.clamp.
|
| 54 |
+
return max(32, min(n, self.vocab_size))
|
| 55 |
+
|
| 56 |
+
def _tokenize(self, text: str, **kwargs) -> List[str]:
|
| 57 |
+
return list(text)
|
| 58 |
+
|
| 59 |
+
def byte_tokenize(self, text: str) -> np.ndarray:
|
| 60 |
+
return np.frombuffer(text.encode("utf-8"), dtype=np.uint8)
|
| 61 |
+
|
| 62 |
+
def _convert_token_to_id(self, token: str) -> int:
|
| 63 |
+
return self.clamp(ord(token))
|
| 64 |
+
|
| 65 |
+
def _convert_id_to_token(self, index: int) -> str:
|
| 66 |
+
return chr(self.clamp(index))
|
| 67 |
+
|
| 68 |
+
def convert_tokens_to_string(self, tokens: List[str]) -> str:
|
| 69 |
+
return EMPTY.join(tokens)
|
| 70 |
+
|
| 71 |
+
def _decode(self, token_ids: List[int], **kwargs) -> str:
|
| 72 |
+
indices = np.asarray(token_ids, dtype=np.int16)
|
| 73 |
+
indices = indices.clip(min=32, max=255).astype(np.uint8)
|
| 74 |
+
return indices.tobytes().decode("utf-8", errors="replace")
|
| 75 |
+
|
| 76 |
+
def _encode_plus(self, text: str, **kwargs) -> BatchEncoding:
|
| 77 |
+
first_ids = self.byte_tokenize(text).tolist()
|
| 78 |
+
return self.prepare_for_model(
|
| 79 |
+
first_ids,
|
| 80 |
+
pair_ids=None,
|
| 81 |
+
add_special_tokens=kwargs.get("add_special_tokens", False),
|
| 82 |
+
padding=kwargs.get("padding_strategy", PaddingStrategy.DO_NOT_PAD).value,
|
| 83 |
+
truncation=kwargs.get("truncation_strategy", TruncationStrategy.DO_NOT_TRUNCATE).value,
|
| 84 |
+
max_length=kwargs.get("max_length"),
|
| 85 |
+
stride=kwargs.get("stride", 0),
|
| 86 |
+
pad_to_multiple_of=kwargs.get("pad_to_multiple_of"),
|
| 87 |
+
return_tensors=kwargs.get("return_tensors"),
|
| 88 |
+
prepend_batch_axis=True,
|
| 89 |
+
return_attention_mask=kwargs.get("return_attention_mask"),
|
| 90 |
+
return_token_type_ids=kwargs.get("return_token_type_ids"),
|
| 91 |
+
return_overflowing_tokens=kwargs.get("return_overflowing_tokens", False),
|
| 92 |
+
return_special_tokens_mask=kwargs.get("return_special_tokens_mask", False),
|
| 93 |
+
return_length=kwargs.get("return_length", False),
|
| 94 |
+
verbose=kwargs.get("verbose", True),
|
| 95 |
+
)
|
| 96 |
+
|
| 97 |
+
def _batch_encode_plus(self, batch_text_or_text_pairs, **kwargs) -> BatchEncoding:
|
| 98 |
+
input_ids = [(self.byte_tokenize(t).tolist(), None) for t in batch_text_or_text_pairs]
|
| 99 |
+
return self._batch_prepare_for_model(
|
| 100 |
+
input_ids,
|
| 101 |
+
add_special_tokens=kwargs.get("add_special_tokens", False),
|
| 102 |
+
padding_strategy=kwargs.get("padding_strategy", PaddingStrategy.DO_NOT_PAD),
|
| 103 |
+
truncation_strategy=kwargs.get("truncation_strategy", TruncationStrategy.DO_NOT_TRUNCATE),
|
| 104 |
+
max_length=kwargs.get("max_length"),
|
| 105 |
+
stride=kwargs.get("stride", 0),
|
| 106 |
+
pad_to_multiple_of=kwargs.get("pad_to_multiple_of"),
|
| 107 |
+
return_attention_mask=kwargs.get("return_attention_mask"),
|
| 108 |
+
return_token_type_ids=kwargs.get("return_token_type_ids"),
|
| 109 |
+
return_overflowing_tokens=kwargs.get("return_overflowing_tokens", False),
|
| 110 |
+
return_special_tokens_mask=kwargs.get("return_special_tokens_mask", False),
|
| 111 |
+
return_length=kwargs.get("return_length", False),
|
| 112 |
+
return_tensors=kwargs.get("return_tensors"),
|
| 113 |
+
verbose=kwargs.get("verbose", True),
|
| 114 |
+
)
|
| 115 |
+
|
| 116 |
+
def _save_pretrained(
|
| 117 |
+
self, save_directory: str | PathLike, file_names: Tuple[str], **kwargs
|
| 118 |
+
) -> Tuple[str]:
|
| 119 |
+
return file_names
|
tokenizer_config.json
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"auto_map": {
|
| 3 |
+
"AutoTokenizer": [
|
| 4 |
+
"tokenization_evo2.ByteTokenizer",
|
| 5 |
+
null
|
| 6 |
+
]
|
| 7 |
+
},
|
| 8 |
+
"tokenizer_class": "ByteTokenizer",
|
| 9 |
+
"model_max_length": 8192,
|
| 10 |
+
"pad_token": "\u0001",
|
| 11 |
+
"byte_level": true
|
| 12 |
+
}
|