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
Download modeling_evo2.py from Taykhoom/Evo2-20B-1M: direct link, hf CLI and curl.
- Browser
- Download file 21.6 kB
-
https://huggingface.co/Taykhoom/Evo2-20B-1M/resolve/main/modeling_evo2.py
- Command line
-
hf download hf://Taykhoom/Evo2-20B-1M/modeling_evo2.py
-
curl -L -o modeling_evo2.py https://huggingface.co/Taykhoom/Evo2-20B-1M/resolve/main/modeling_evo2.py
21.6 kB
| """HuggingFace wrappers for Evo2 (StripedHyena2). | |
| Two top-level model classes: | |
| * Evo2Model -- bare backbone returning BaseModelOutputWithPast | |
| (no LM head); the post-RMSNorm hidden state is the | |
| last_hidden_state. | |
| * Evo2ForCausalLM -- with the tied LM head + GenerationMixin so | |
| model.generate() works out of the box. | |
| Evo2Cache uses optimized recurrent MHA/Hyena state for unpadded prompts and | |
| automatically uses exact full recomputation for padded batches. | |
| Per-block dtype: bfloat16 for everything except the modal-form filter | |
| parameters (`log_poles`, `residues`) which must stay fp32 for stability. | |
| This is enforced both at convert time (the safetensors store these as fp32) | |
| and automatically after checkpoint loading. | |
| """ | |
| from __future__ import annotations | |
| from typing import Optional, Tuple, Union | |
| import torch | |
| import torch.nn as nn | |
| import torch.nn.functional as F | |
| from transformers import PreTrainedModel | |
| from transformers.generation import GenerationMixin | |
| from transformers.modeling_outputs import ( | |
| BaseModelOutputWithPast, | |
| CausalLMOutputWithPast, | |
| ) | |
| from transformers.utils import logging | |
| from .cache import Evo2Cache | |
| from .configuration_evo2 import Evo2Config | |
| from .hyena import ( | |
| AttentionBlock, | |
| ParallelGatedConvBlock, | |
| block_type_for_idx, | |
| get_block, | |
| ) | |
| from .layers import RMSNorm, VocabParallelEmbedding | |
| # Bundle the tokenizer file via trust_remote_code: | |
| from .tokenization_evo2 import ByteTokenizer # noqa: F401 | |
| # Force HF's trust_remote_code loader to copy these transitive deps into its | |
| # dynamic-module cache (it only walks top-level `from .X import Y` patterns | |
| # of modeling_evo2.py, not `from . import X`, so we use the explicit form). | |
| from .attention import MHA as _MHA # noqa: F401 | |
| from .engine import HyenaInferenceEngine as _HyenaInferenceEngine # noqa: F401 | |
| from .rotary import ( # noqa: F401 | |
| RotaryEmbedding as _RotaryEmbedding, | |
| restore_rotary_inv_freq, | |
| ) | |
| try: # optional; needs triton | |
| from .kernels import hcs_conv as _hcs_conv # noqa: F401 | |
| except ImportError: | |
| pass | |
| logger = logging.get_logger(__name__) | |
| # ============================================================================= | |
| # Backbone | |
| # ============================================================================= | |
| class StripedHyena2(nn.Module): | |
| """Pure backbone: token embedding -> N blocks -> final RMSNorm.""" | |
| def __init__(self, config: Evo2Config): | |
| super().__init__() | |
| # Patch TE's cuBLAS workspace handling so multi-GPU device_map="auto" | |
| # works (TE otherwise allocates a single workspace on the first device | |
| # it sees, then fails on layers placed on other devices). No-op when | |
| # TE isn't installed. | |
| from .layers import fixup_te_workspace | |
| fixup_te_workspace() | |
| self.config = config | |
| kernels = ("use_hcs_kernel", "use_hcm_kernel", "use_hcl_kernel") | |
| if config.hidden_size == 1920 and any(config.get(k, False) for k in kernels): | |
| # Same caveat as vortex: the kernels regress generation quality on the 1B. | |
| logger.warning("use_hc*_kernel regresses generation quality on Evo 2 1B; disable it if that matters.") | |
| self.embedding_layer = VocabParallelEmbedding(config) | |
| self.norm = RMSNorm(config) if config.get("final_norm", True) else None | |
| if config.get("use_flashfft", False): | |
| import importlib | |
| FlashFFTConv = importlib.import_module("flashfftconv").FlashFFTConv | |
| self.flash_fft = FlashFFTConv(2 * config.max_seqlen, dtype=torch.bfloat16) | |
| else: | |
| self.flash_fft = None | |
| self.blocks = nn.ModuleList( | |
| get_block(config, i) for i in range(config.num_layers) | |
| ) | |
| # Wire fftconv_fn into the hcl filters when flashfft is on. | |
| if self.flash_fft is not None: | |
| for block in self.blocks: | |
| if isinstance(block, ParallelGatedConvBlock) and block.filter.h is None: | |
| block.filter.fftconv_fn = self.flash_fft | |
| def forward( | |
| self, | |
| input_ids: torch.LongTensor = None, | |
| attention_mask: Optional[torch.LongTensor] = None, | |
| past_key_values: Optional[Evo2Cache] = None, | |
| use_cache: Optional[bool] = None, | |
| output_attentions: Optional[bool] = None, | |
| output_hidden_states: Optional[bool] = None, | |
| return_dict: Optional[bool] = None, | |
| ) -> Union[Tuple, BaseModelOutputWithPast]: | |
| """Run the backbone using the standard HuggingFace base-model API.""" | |
| if input_ids is None: | |
| raise ValueError("input_ids must be provided.") | |
| return_dict = ( | |
| return_dict if return_dict is not None else self.config.use_return_dict | |
| ) | |
| output_attentions = ( | |
| output_attentions | |
| if output_attentions is not None | |
| else self.config.output_attentions | |
| ) | |
| output_hidden_states = ( | |
| output_hidden_states | |
| if output_hidden_states is not None | |
| else self.config.output_hidden_states | |
| ) | |
| # The bare backbone defaults to no cache because embedding extraction | |
| # does not benefit from autoregressive state. | |
| use_cache = use_cache if use_cache is not None else False | |
| if use_cache and self.training: | |
| use_cache = False | |
| if attention_mask is not None: | |
| attention_mask = attention_mask.ne(0) | |
| suffix_only = False | |
| requested_length = input_ids.shape[1] | |
| if use_cache: | |
| if not isinstance(past_key_values, Evo2Cache): | |
| past_key_values = self.initialize_inference_params( | |
| max_batch_size=input_ids.shape[0], | |
| ) | |
| has_padding = ( | |
| attention_mask is not None | |
| and not attention_mask.bool().all() | |
| ) | |
| if past_key_values.mode is None: | |
| past_key_values.mode = ( | |
| "recompute" if has_padding else "recurrent" | |
| ) | |
| if past_key_values.mode == "recurrent" and has_padding: | |
| raise ValueError( | |
| "A recurrent Evo2 cache cannot switch to padded inputs. " | |
| "Reset the cache and prefill the padded batch again." | |
| ) | |
| if past_key_values.mode == "recurrent": | |
| cached_length = past_key_values.get_seq_length() | |
| if cached_length > 0 and input_ids.shape[1] > cached_length: | |
| input_ids = input_ids[:, cached_length:] | |
| if attention_mask is not None: | |
| attention_mask = attention_mask[:, cached_length:] | |
| else: | |
| input_ids, attention_mask, suffix_only = past_key_values.prepare_inputs( | |
| input_ids, | |
| attention_mask, | |
| ) | |
| last_hidden, past_kv, hidden_states, attentions = self._forward_features( | |
| input_ids, | |
| inference_params_dict=( | |
| past_key_values | |
| if use_cache and past_key_values.mode == "recurrent" | |
| else None | |
| ), | |
| attention_mask=attention_mask, | |
| output_hidden_states=output_hidden_states, | |
| output_attentions=output_attentions, | |
| ) | |
| if use_cache: | |
| past_kv = past_key_values | |
| if past_key_values.mode == "recurrent": | |
| past_key_values.advance(input_ids.shape[1]) | |
| else: | |
| past_key_values.update_history(input_ids, attention_mask) | |
| if suffix_only: | |
| last_hidden = last_hidden[:, -requested_length:] | |
| if output_hidden_states: | |
| hidden_states = [ | |
| state[:, -requested_length:] | |
| for state in hidden_states | |
| ] | |
| if output_attentions: | |
| attentions = [ | |
| ( | |
| attention[..., -requested_length:, :] | |
| if attention is not None | |
| else None | |
| ) | |
| for attention in attentions | |
| ] | |
| if not return_dict: | |
| outputs = (last_hidden,) | |
| if use_cache: | |
| outputs += (past_kv,) | |
| if output_hidden_states: | |
| outputs += (tuple(hidden_states),) | |
| if output_attentions: | |
| outputs += (tuple(attentions),) | |
| return outputs | |
| return BaseModelOutputWithPast( | |
| last_hidden_state=last_hidden, | |
| past_key_values=past_kv if use_cache else None, | |
| hidden_states=tuple(hidden_states) if output_hidden_states else None, | |
| attentions=tuple(attentions) if output_attentions else None, | |
| ) | |
| def _forward_features( | |
| self, | |
| input_ids: torch.LongTensor, | |
| inference_params_dict: Optional[Evo2Cache] = None, | |
| attention_mask: Optional[torch.Tensor] = None, | |
| output_hidden_states: bool = False, | |
| output_attentions: bool = False, | |
| ): | |
| x = self.embedding_layer.embed(input_ids) | |
| all_hidden_states: list[torch.Tensor] = [] | |
| all_attentions: list[Optional[torch.Tensor]] = [] | |
| if output_hidden_states: | |
| all_hidden_states.append(x) | |
| if inference_params_dict is not None: | |
| x, params_out = self._stateful_forward( | |
| x, inference_params_dict, | |
| all_hidden_states=all_hidden_states, | |
| all_attentions=all_attentions, | |
| output_hidden_states=output_hidden_states, | |
| output_attentions=output_attentions, | |
| ) | |
| else: | |
| x, params_out = self._stateless_forward( | |
| x, padding_mask=attention_mask, | |
| all_hidden_states=all_hidden_states, | |
| all_attentions=all_attentions, | |
| output_hidden_states=output_hidden_states, | |
| output_attentions=output_attentions, | |
| ) | |
| if self.norm is not None: | |
| x = self.norm(x) | |
| if output_hidden_states: | |
| all_hidden_states.append(x) | |
| return x, params_out, all_hidden_states, all_attentions | |
| def get_input_embeddings(self): | |
| return self.embedding_layer | |
| def set_input_embeddings(self, value): | |
| self.embedding_layer = value | |
| def _stateful_forward( | |
| self, x, cache: Evo2Cache, | |
| all_hidden_states, all_attentions, | |
| output_hidden_states, output_attentions, | |
| ): | |
| for block_idx, block in enumerate(self.blocks): | |
| block_name = block_type_for_idx(self.config, block_idx) | |
| inference_params = cache.by_block_name(block_name) | |
| x, attn = block( | |
| x, inference_params=inference_params, | |
| output_attentions=output_attentions, | |
| ) | |
| if output_hidden_states: | |
| all_hidden_states.append(x) | |
| if output_attentions: | |
| all_attentions.append(attn) | |
| return x, cache | |
| def _stateless_forward( | |
| self, x, padding_mask, | |
| all_hidden_states, all_attentions, | |
| output_hidden_states, output_attentions, | |
| ): | |
| if isinstance(padding_mask, torch.Tensor): | |
| x = x * padding_mask[..., None] | |
| for block in self.blocks: | |
| x, attn = block( | |
| x, inference_params=None, padding_mask=padding_mask, | |
| output_attentions=output_attentions, | |
| ) | |
| if output_hidden_states: | |
| all_hidden_states.append(x) | |
| if output_attentions: | |
| all_attentions.append(attn) | |
| return x, None | |
| def initialize_inference_params(self, max_batch_size: int = 1) -> Evo2Cache: | |
| return Evo2Cache( | |
| max_seqlen=self.config.get("max_seqlen", 8192), | |
| max_batch_size=max_batch_size, | |
| short_filter_length=self.config.short_filter_length, | |
| hcm_filter_length=self.config.hcm_filter_length, | |
| hcs_filter_length=self.config.hcs_filter_length, | |
| state_size=self.config.state_size, | |
| ) | |
| def to_dtype_except_poles_residues(self, dtype): | |
| """Cast params to bf16, restore fp32 invariants: | |
| * log_poles / residues -- bf16 collapses the modal-form IIR (the | |
| poles get rounded too aggressively, the recurrence blows up). | |
| Mirrors vortex's ``to_bfloat16_except_pr_lc(to_float32=True)`` | |
| first-pass behaviour. | |
| * rotary_emb.inv_freq -- HF ``from_pretrained(dtype=bf16)`` casts | |
| ALL buffers to bf16. ``inv_freq = 1 / base^(2i/dim)`` loses ~7 | |
| bits of mantissa in bf16, which shifts cos/sin tables by ~5e-2 | |
| per cell at position 64+, causing each attention layer to add | |
| ~4e-2 of noise on Q/K. We rebuild inv_freq here as vortex | |
| runs it: the checkpoint's bf16 values held in fp32. | |
| """ | |
| for k, p in self.named_parameters(): | |
| if "log_poles" not in k and "residues" not in k: | |
| p.data = p.data.to(dtype) | |
| self.restore_precision_invariants() | |
| def to_bfloat16_except_poles_residues(self): | |
| self.to_dtype_except_poles_residues(torch.bfloat16) | |
| def restore_precision_invariants(self): | |
| """Restore exact RoPE frequencies and fp32 modal-filter parameters.""" | |
| for k, p in self.named_parameters(): | |
| if ( | |
| ("log_poles" in k or "residues" in k) | |
| and p.dtype != torch.float32 | |
| ): | |
| p.data = p.data.to(torch.float32) | |
| for module in self.modules(): | |
| if hasattr(module, "inv_freq"): | |
| restore_rotary_inv_freq(module) | |
| def _apply(self, fn, recurse=True): | |
| result = super()._apply(fn, recurse=recurse) | |
| self.restore_precision_invariants() | |
| return result | |
| # ============================================================================= | |
| # HF wrappers | |
| # ============================================================================= | |
| class Evo2PreTrainedModel(PreTrainedModel): | |
| config_class = Evo2Config | |
| base_model_prefix = "backbone" | |
| supports_gradient_checkpointing = False | |
| _no_split_modules = ["AttentionBlock", "ParallelGatedConvBlock"] | |
| _skip_keys_device_placement = "past_key_values" | |
| _keys_to_ignore_on_load_missing = [r"freq", r"\.t$", r"_extra_state"] | |
| _keys_to_ignore_on_load_unexpected = [ | |
| r"fftconv", | |
| r"twiddle_factors", | |
| r"_extra_state$", | |
| r"\.filter\.t$", | |
| r"rotary_emb\.inv_freq", | |
| ] | |
| _supports_flash_attn_2 = True | |
| _supports_sdpa = True | |
| # Evo2 cache is a custom Evo2Cache (not a DynamicCache); tell HF not to wrap it. | |
| _supports_cache_class = False | |
| # log_poles / residues parameterize a modal long-range filter; bf16 collapses | |
| # them. HF will keep these in fp32 even with dtype=bf16 at load time. | |
| _keep_in_fp32_modules = ["log_poles", "residues"] | |
| def from_pretrained(cls, *args, **kwargs): | |
| requested_dtype = kwargs.get("dtype", kwargs.get("torch_dtype")) | |
| if requested_dtype == torch.float16: | |
| raise ValueError( | |
| "Evo2 does not support float16 inference because its modal " | |
| "filters are numerically unstable in FP16. Use bfloat16 " | |
| "(recommended) or float32." | |
| ) | |
| if "dtype" not in kwargs and "torch_dtype" not in kwargs: | |
| kwargs["dtype"] = torch.bfloat16 | |
| requested_dtype = torch.bfloat16 | |
| loaded = super().from_pretrained(*args, **kwargs) | |
| model = loaded[0] if isinstance(loaded, tuple) else loaded | |
| if isinstance(requested_dtype, torch.dtype): | |
| model.backbone.to_dtype_except_poles_residues(requested_dtype) | |
| else: | |
| model.backbone.restore_precision_invariants() | |
| return loaded | |
| class Evo2Model(Evo2PreTrainedModel): | |
| """Bare backbone returning BaseModelOutputWithPast.""" | |
| def __init__(self, config: Evo2Config): | |
| super().__init__(config) | |
| self.backbone = StripedHyena2(config) | |
| self.config = config | |
| self.post_init() | |
| self.force_dtype() | |
| def force_dtype(self): | |
| self.backbone.to_bfloat16_except_poles_residues() | |
| def get_input_embeddings(self): | |
| return self.backbone.embedding_layer | |
| def set_input_embeddings(self, value): | |
| self.backbone.embedding_layer = value | |
| def forward( | |
| self, | |
| input_ids: torch.LongTensor = None, | |
| attention_mask: Optional[torch.LongTensor] = None, | |
| past_key_values=None, | |
| use_cache: Optional[bool] = None, | |
| output_attentions: Optional[bool] = None, | |
| output_hidden_states: Optional[bool] = None, | |
| return_dict: Optional[bool] = None, | |
| ) -> Union[Tuple, BaseModelOutputWithPast]: | |
| return self.backbone( | |
| input_ids=input_ids, | |
| attention_mask=attention_mask, | |
| past_key_values=past_key_values, | |
| use_cache=use_cache, | |
| output_attentions=output_attentions, | |
| output_hidden_states=output_hidden_states, | |
| return_dict=return_dict, | |
| ) | |
| class Evo2ForCausalLM(Evo2PreTrainedModel, GenerationMixin): | |
| """LM head wrapper. Tied to backbone.embedding_layer (Evo2 ties weights).""" | |
| def __init__(self, config: Evo2Config, **kwargs): | |
| super().__init__(config, **kwargs) | |
| self.backbone = StripedHyena2(config) | |
| self.config = config | |
| vocab_size = config.vocab_size | |
| if vocab_size % config.make_vocab_size_divisible_by != 0: | |
| vocab_size += config.make_vocab_size_divisible_by - ( | |
| vocab_size % config.make_vocab_size_divisible_by | |
| ) | |
| self.vocab_size = vocab_size | |
| self.post_init() | |
| self.force_dtype() | |
| def force_dtype(self): | |
| self.backbone.to_bfloat16_except_poles_residues() | |
| def get_input_embeddings(self): | |
| return self.backbone.embedding_layer | |
| def set_input_embeddings(self, value): | |
| self.backbone.embedding_layer = value | |
| def get_output_embeddings(self): | |
| return self.backbone.embedding_layer | |
| def set_output_embeddings(self, value): | |
| self.backbone.embedding_layer = value | |
| def forward( | |
| self, | |
| input_ids: torch.LongTensor = None, | |
| attention_mask: Optional[torch.LongTensor] = None, | |
| labels: Optional[torch.LongTensor] = None, | |
| past_key_values=None, | |
| use_cache: Optional[bool] = None, | |
| output_attentions: Optional[bool] = None, | |
| output_hidden_states: Optional[bool] = None, | |
| return_dict: Optional[bool] = None, | |
| ) -> Union[Tuple, CausalLMOutputWithPast]: | |
| return_dict = return_dict if return_dict is not None else self.config.use_return_dict | |
| output_attentions = ( | |
| output_attentions if output_attentions is not None else self.config.output_attentions | |
| ) | |
| output_hidden_states = ( | |
| output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states | |
| ) | |
| use_cache = use_cache if use_cache is not None else self.config.use_cache | |
| if use_cache and labels is not None: | |
| logger.warning_once("use_cache=True is incompatible with loss computation; disabling.") | |
| use_cache = False | |
| inputs = input_ids | |
| backbone_outputs = self.backbone( | |
| input_ids=inputs, | |
| attention_mask=attention_mask, | |
| past_key_values=past_key_values, | |
| use_cache=use_cache, | |
| output_hidden_states=output_hidden_states, | |
| output_attentions=output_attentions, | |
| return_dict=True, | |
| ) | |
| last_hidden = backbone_outputs.last_hidden_state | |
| past_kv = backbone_outputs.past_key_values | |
| hidden_states = backbone_outputs.hidden_states | |
| attentions = backbone_outputs.attentions | |
| logits = last_hidden @ self.backbone.embedding_layer.weight.T | |
| loss = None | |
| if labels is not None: | |
| shift_logits = logits[..., :-1, :].contiguous() | |
| shift_labels = labels[..., 1:].contiguous() | |
| shift_logits = shift_logits.view(-1, self.config.vocab_size) | |
| shift_labels = shift_labels.view(-1).to(shift_logits.device) | |
| loss = F.cross_entropy(shift_logits, shift_labels) | |
| if not return_dict: | |
| outputs = (logits,) | |
| if use_cache: outputs += (past_kv,) | |
| if output_hidden_states: outputs += (hidden_states,) | |
| if output_attentions: outputs += (attentions,) | |
| if loss is not None: outputs = (loss,) + outputs | |
| return outputs | |
| return CausalLMOutputWithPast( | |
| loss=loss, | |
| logits=logits, | |
| past_key_values=past_kv if use_cache else None, | |
| hidden_states=hidden_states, | |
| attentions=attentions, | |
| ) | |
| def can_generate(cls) -> bool: | |
| return True | |
| def prepare_inputs_for_generation( | |
| self, input_ids, attention_mask=None, past_key_values=None, **kwargs | |
| ): | |
| return { | |
| "input_ids": input_ids, | |
| "attention_mask": attention_mask, | |
| "past_key_values": past_key_values, | |
| "use_cache": kwargs.get("use_cache", self.config.use_cache), | |
| } | |