Instructions to use Taykhoom/Evo2-20B-1M with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use Taykhoom/Evo2-20B-1M with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="Taykhoom/Evo2-20B-1M", trust_remote_code=True)# pip install -U transformers accelerate # Load model directly from transformers import AutoModelForCausalLM model = AutoModelForCausalLM.from_pretrained("Taykhoom/Evo2-20B-1M", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use Taykhoom/Evo2-20B-1M with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "Taykhoom/Evo2-20B-1M" # 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-20B-1M", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker
docker model run hf.co/Taykhoom/Evo2-20B-1M
- SGLang
How to use Taykhoom/Evo2-20B-1M 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-20B-1M" \ --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-20B-1M", "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-20B-1M" \ --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-20B-1M", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }' - Docker Model Runner
How to use Taykhoom/Evo2-20B-1M with Docker Model Runner:
docker model run hf.co/Taykhoom/Evo2-20B-1M
Enable upstream-compatible recurrent caching with dynamic allocation
Browse files- README.md +2 -2
- cache.py +3 -0
- modeling_evo2.py +34 -8
README.md
CHANGED
|
@@ -175,7 +175,7 @@ print(tokenizer.decode(out[0]))
|
|
| 175 |
|
| 176 |
`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.
|
| 177 |
|
| 178 |
-
Generation
|
| 179 |
|
| 180 |
### Attention weights
|
| 181 |
|
|
@@ -230,7 +230,7 @@ This HuggingFace port has **not** been tested for fine-tuning - it's verified on
|
|
| 230 |
- `"eager"`: textbook einsum + softmax(QK^T) + einsum. Slowest, used internally when `output_attentions=True` so the attention matrix is materialized.
|
| 231 |
- **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)`.
|
| 232 |
- **`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.
|
| 233 |
-
- **Generation.**
|
| 234 |
- **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.
|
| 235 |
- **Dependencies.** `torch`, `transformers`, `numpy`, `safetensors`, `huggingface_hub`. `transformer-engine[pytorch]` is required for this variant's FP8 input projections. `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"`).
|
| 236 |
|
|
|
|
| 175 |
|
| 176 |
`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.
|
| 177 |
|
| 178 |
+
Generation uses recurrent MHA/Hyena state for unpadded prompts. Padded batches automatically use the exact full-recomputation path. Attention KV storage grows with the decoded sequence instead of preallocating the model's full configured context.
|
| 179 |
|
| 180 |
### Attention weights
|
| 181 |
|
|
|
|
| 230 |
- `"eager"`: textbook einsum + softmax(QK^T) + einsum. Slowest, used internally when `output_attentions=True` so the attention matrix is materialized.
|
| 231 |
- **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)`.
|
| 232 |
- **`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.
|
| 233 |
+
- **Generation cache.** Unpadded prompts use recurrent MHA KV plus HCL/HCM/HCS FIR/IIR state matching the upstream Vortex cache path. Padded batches use full recomputation. KV tensors grow geometrically with the decoded length instead of allocating `max_seqlen` up front.
|
| 234 |
- **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.
|
| 235 |
- **Dependencies.** `torch`, `transformers`, `numpy`, `safetensors`, `huggingface_hub`. `transformer-engine[pytorch]` is required for this variant's FP8 input projections. `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"`).
|
| 236 |
|
cache.py
CHANGED
|
@@ -114,6 +114,7 @@ class Evo2Cache:
|
|
| 114 |
)
|
| 115 |
self.input_ids: Optional[Tensor] = None
|
| 116 |
self.attention_mask: Optional[Tensor] = None
|
|
|
|
| 117 |
|
| 118 |
@property
|
| 119 |
def seqlen_offset(self) -> int:
|
|
@@ -147,6 +148,7 @@ class Evo2Cache:
|
|
| 147 |
self.hcs.reset()
|
| 148 |
self.input_ids = None
|
| 149 |
self.attention_mask = None
|
|
|
|
| 150 |
|
| 151 |
def prepare_inputs(
|
| 152 |
self,
|
|
@@ -154,6 +156,7 @@ class Evo2Cache:
|
|
| 154 |
attention_mask: Optional[Tensor],
|
| 155 |
) -> tuple[Tensor, Tensor, bool]:
|
| 156 |
"""Return full history and whether the caller supplied only a suffix."""
|
|
|
|
| 157 |
requested_mask = (
|
| 158 |
attention_mask.ne(0)
|
| 159 |
if attention_mask is not None
|
|
|
|
| 114 |
)
|
| 115 |
self.input_ids: Optional[Tensor] = None
|
| 116 |
self.attention_mask: Optional[Tensor] = None
|
| 117 |
+
self.mode: Optional[str] = None
|
| 118 |
|
| 119 |
@property
|
| 120 |
def seqlen_offset(self) -> int:
|
|
|
|
| 148 |
self.hcs.reset()
|
| 149 |
self.input_ids = None
|
| 150 |
self.attention_mask = None
|
| 151 |
+
self.mode = None
|
| 152 |
|
| 153 |
def prepare_inputs(
|
| 154 |
self,
|
|
|
|
| 156 |
attention_mask: Optional[Tensor],
|
| 157 |
) -> tuple[Tensor, Tensor, bool]:
|
| 158 |
"""Return full history and whether the caller supplied only a suffix."""
|
| 159 |
+
self.mode = "recompute"
|
| 160 |
requested_mask = (
|
| 161 |
attention_mask.ne(0)
|
| 162 |
if attention_mask is not None
|
modeling_evo2.py
CHANGED
|
@@ -8,9 +8,8 @@ Two top-level model classes:
|
|
| 8 |
* Evo2ForCausalLM -- with the tied LM head + GenerationMixin so
|
| 9 |
model.generate() works out of the box.
|
| 10 |
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
numerically equivalent for every released variant.
|
| 14 |
|
| 15 |
Per-block dtype: bfloat16 for everything except the modal-form filter
|
| 16 |
parameters (`log_poles`, `residues`) which must stay fp32 for stability.
|
|
@@ -136,21 +135,48 @@ class StripedHyena2(nn.Module):
|
|
| 136 |
past_key_values = self.initialize_inference_params(
|
| 137 |
max_batch_size=input_ids.shape[0],
|
| 138 |
)
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
attention_mask
|
| 142 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 143 |
|
| 144 |
last_hidden, past_kv, hidden_states, attentions = self._forward_features(
|
| 145 |
input_ids,
|
| 146 |
-
inference_params_dict=
|
|
|
|
|
|
|
|
|
|
|
|
|
| 147 |
attention_mask=attention_mask,
|
| 148 |
output_hidden_states=output_hidden_states,
|
| 149 |
output_attentions=output_attentions,
|
| 150 |
)
|
| 151 |
if use_cache:
|
| 152 |
-
past_key_values.update_history(input_ids, attention_mask)
|
| 153 |
past_kv = past_key_values
|
|
|
|
|
|
|
|
|
|
|
|
|
| 154 |
if suffix_only:
|
| 155 |
last_hidden = last_hidden[:, -requested_length:]
|
| 156 |
if output_hidden_states:
|
|
|
|
| 8 |
* Evo2ForCausalLM -- with the tied LM head + GenerationMixin so
|
| 9 |
model.generate() works out of the box.
|
| 10 |
|
| 11 |
+
Evo2Cache uses optimized recurrent MHA/Hyena state for unpadded prompts and
|
| 12 |
+
automatically uses exact full recomputation for padded batches.
|
|
|
|
| 13 |
|
| 14 |
Per-block dtype: bfloat16 for everything except the modal-form filter
|
| 15 |
parameters (`log_poles`, `residues`) which must stay fp32 for stability.
|
|
|
|
| 135 |
past_key_values = self.initialize_inference_params(
|
| 136 |
max_batch_size=input_ids.shape[0],
|
| 137 |
)
|
| 138 |
+
has_padding = (
|
| 139 |
+
attention_mask is not None
|
| 140 |
+
and not attention_mask.bool().all()
|
| 141 |
)
|
| 142 |
+
if past_key_values.mode is None:
|
| 143 |
+
past_key_values.mode = (
|
| 144 |
+
"recompute" if has_padding else "recurrent"
|
| 145 |
+
)
|
| 146 |
+
if past_key_values.mode == "recurrent" and has_padding:
|
| 147 |
+
raise ValueError(
|
| 148 |
+
"A recurrent Evo2 cache cannot switch to padded inputs. "
|
| 149 |
+
"Reset the cache and prefill the padded batch again."
|
| 150 |
+
)
|
| 151 |
+
if past_key_values.mode == "recurrent":
|
| 152 |
+
cached_length = past_key_values.get_seq_length()
|
| 153 |
+
if cached_length > 0 and input_ids.shape[1] > cached_length:
|
| 154 |
+
input_ids = input_ids[:, cached_length:]
|
| 155 |
+
if attention_mask is not None:
|
| 156 |
+
attention_mask = attention_mask[:, cached_length:]
|
| 157 |
+
else:
|
| 158 |
+
input_ids, attention_mask, suffix_only = past_key_values.prepare_inputs(
|
| 159 |
+
input_ids,
|
| 160 |
+
attention_mask,
|
| 161 |
+
)
|
| 162 |
|
| 163 |
last_hidden, past_kv, hidden_states, attentions = self._forward_features(
|
| 164 |
input_ids,
|
| 165 |
+
inference_params_dict=(
|
| 166 |
+
past_key_values
|
| 167 |
+
if use_cache and past_key_values.mode == "recurrent"
|
| 168 |
+
else None
|
| 169 |
+
),
|
| 170 |
attention_mask=attention_mask,
|
| 171 |
output_hidden_states=output_hidden_states,
|
| 172 |
output_attentions=output_attentions,
|
| 173 |
)
|
| 174 |
if use_cache:
|
|
|
|
| 175 |
past_kv = past_key_values
|
| 176 |
+
if past_key_values.mode == "recurrent":
|
| 177 |
+
past_key_values.advance(input_ids.shape[1])
|
| 178 |
+
else:
|
| 179 |
+
past_key_values.update_history(input_ids, attention_mask)
|
| 180 |
if suffix_only:
|
| 181 |
last_hidden = last_hidden[:, -requested_length:]
|
| 182 |
if output_hidden_states:
|