Text Generation
Transformers
Safetensors
domynedge
domyn
domyn-edge
long-context
agentic
fully-open
custom_code
Instructions to use domyn/Domyn-Edge-Base with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use domyn/Domyn-Edge-Base with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="domyn/Domyn-Edge-Base", trust_remote_code=True)# pip install -U transformers accelerate # Load model directly from transformers import AutoModelForCausalLM model = AutoModelForCausalLM.from_pretrained("domyn/Domyn-Edge-Base", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use domyn/Domyn-Edge-Base with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "domyn/Domyn-Edge-Base" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "domyn/Domyn-Edge-Base", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker
docker model run hf.co/domyn/Domyn-Edge-Base
- SGLang
How to use domyn/Domyn-Edge-Base 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 "domyn/Domyn-Edge-Base" \ --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": "domyn/Domyn-Edge-Base", "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 "domyn/Domyn-Edge-Base" \ --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": "domyn/Domyn-Edge-Base", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }' - Docker Model Runner
How to use domyn/Domyn-Edge-Base with Docker Model Runner:
docker model run hf.co/domyn/Domyn-Edge-Base
Download modeling_domynedge.py from domyn/Domyn-Edge-Base: direct link, hf CLI and curl.
- Browser
- Download file 23.5 kB
-
https://huggingface.co/domyn/Domyn-Edge-Base/resolve/main/modeling_domynedge.py
- Command line
-
hf download hf://domyn/Domyn-Edge-Base/modeling_domynedge.py
-
curl -L -o modeling_domynedge.py https://huggingface.co/domyn/Domyn-Edge-Base/resolve/main/modeling_domynedge.py
23.5 kB
| # SPDX-FileCopyrightText: 2026 Domyn | |
| # SPDX-License-Identifier: Apache-2.0 | |
| # | |
| # This file includes third-party code: | |
| # | |
| # - `IndexFirstAxis`, `IndexPutFirstAxis`, `unpad_input` and `pad_input` are adapted from | |
| # https://github.com/Dao-AILab/flash-attention/blob/main/flash_attn/bert_padding.py | |
| # and are distributed under the following license: | |
| # | |
| # BSD 3-Clause License | |
| # | |
| # Copyright (c) 2022, the respective contributors, as shown by the AUTHORS file. | |
| # All rights reserved. | |
| # | |
| # Redistribution and use in source and binary forms, with or without | |
| # modification, are permitted provided that the following conditions are met: | |
| # | |
| # * Redistributions of source code must retain the above copyright notice, this | |
| # list of conditions and the following disclaimer. | |
| # | |
| # * Redistributions in binary form must reproduce the above copyright notice, | |
| # this list of conditions and the following disclaimer in the documentation | |
| # and/or other materials provided with the distribution. | |
| # | |
| # * Neither the name of the copyright holder nor the names of its | |
| # contributors may be used to endorse or promote products derived from | |
| # this software without specific prior written permission. | |
| # | |
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
| # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
| # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | |
| # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
| # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
| # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
| # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
| # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| # | |
| # - `DomynEdgeRotaryEmbedding.compute_default_rope_parameters`, `rotate_half` and | |
| # `apply_rotary_pos_emb` are adapted from HuggingFace transformers | |
| # (https://github.com/huggingface/transformers/blob/main/src/transformers/models/llama/modeling_llama.py), | |
| # Copyright The HuggingFace Team, licensed under the Apache License, Version 2.0. | |
| # Modified for DomynEdge. | |
| import dataclasses | |
| import typing | |
| import einops | |
| import torch | |
| import torch.nn.attention.varlen | |
| import transformers | |
| import transformers.modeling_outputs | |
| from transformers.utils.generic import can_return_tuple, merge_with_config_defaults | |
| from transformers.utils.output_capturing import capture_outputs | |
| from .configuration_domynedge import DomynEdgeConfig | |
| class VarlenMetadataMask: | |
| cu_seq_q: torch.Tensor | |
| cu_seq_k: torch.Tensor | |
| max_q: int | |
| max_k: int | |
| class IndexFirstAxis(torch.autograd.Function): | |
| """Gather the rows of the first axis at `indices`, scattering the gradient back in backward.""" | |
| def forward(ctx, input_, indices): | |
| ctx.save_for_backward(indices) | |
| assert input_.ndim >= 2 | |
| ctx.first_axis_dim, other_shape = input_.shape[0], input_.shape[1:] | |
| second_dim = other_shape.numel() | |
| return torch.gather( | |
| einops.rearrange(input_, "b ... -> b (...)"), 0, einops.repeat(indices, "z -> z d", d=second_dim) | |
| ).reshape(-1, *other_shape) | |
| def backward(ctx, grad_output): | |
| (indices,) = ctx.saved_tensors | |
| assert grad_output.ndim >= 2 | |
| other_shape = grad_output.shape[1:] | |
| grad_output = einops.rearrange(grad_output, "b ... -> b (...)") | |
| grad_input = torch.zeros( | |
| [ctx.first_axis_dim, grad_output.shape[1]], | |
| device=grad_output.device, | |
| dtype=grad_output.dtype, | |
| ) | |
| grad_input.scatter_(0, einops.repeat(indices, "z -> z d", d=grad_output.shape[1]), grad_output) | |
| return grad_input.reshape(ctx.first_axis_dim, *other_shape), None | |
| class IndexPutFirstAxis(torch.autograd.Function): | |
| """Scatter `values` into a zero tensor at the first-axis `indices`, gathering the gradient back in backward.""" | |
| def forward(ctx, values, indices, first_axis_dim): | |
| ctx.save_for_backward(indices) | |
| assert indices.ndim == 1 | |
| assert values.ndim >= 2 | |
| output = torch.zeros(first_axis_dim, *values.shape[1:], device=values.device, dtype=values.dtype) | |
| output[indices] = values | |
| return output | |
| def backward(ctx, grad_output): | |
| (indices,) = ctx.saved_tensors | |
| grad_values = grad_output[indices] | |
| return grad_values, None, None | |
| def unpad_input( | |
| hidden_states: torch.Tensor, attention_mask: torch.Tensor | |
| ) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor, int]: | |
| """Remove the padding tokens, packing the valid tokens of all sequences along one axis. | |
| Arguments: | |
| hidden_states: (batch, seqlen, ...) | |
| attention_mask: (batch, seqlen), bool / int, 1 means valid and 0 means not valid. | |
| Return: | |
| hidden_states: (total_nnz, ...), where total_nnz = number of tokens selected in attention_mask + unused_mask. | |
| indices: (total_nnz), the indices of masked tokens from the flattened input sequence. | |
| cu_seqlens: (batch + 1), the cumulative sequence lengths, used to index into hidden_states. | |
| max_seqlen_in_batch: int | |
| """ | |
| seqlens_in_batch = attention_mask.sum(dim=-1, dtype=torch.int32) | |
| indices = torch.nonzero(attention_mask.flatten(), as_tuple=False).flatten() | |
| max_seqlen = seqlens_in_batch.max().item() | |
| cu_seqlens = torch.nn.functional.pad(torch.cumsum(seqlens_in_batch, dim=0, dtype=torch.int32), (1, 0)) | |
| return ( | |
| IndexFirstAxis.apply(einops.rearrange(hidden_states, "b s ... -> (b s) ..."), indices), | |
| indices, | |
| cu_seqlens, | |
| max_seqlen, | |
| ) | |
| def pad_input(hidden_states: torch.Tensor, indices: torch.Tensor, batch_size: int, seqlen: int) -> torch.Tensor: | |
| """Restore the padded (batch, seqlen, ...) layout from packed tokens, the inverse of `unpad_input`. | |
| Arguments: | |
| hidden_states: (total_nnz, ...), where total_nnz = number of tokens in selected in attention_mask. | |
| indices: (total_nnz), the indices that represent the non-masked tokens of the original padded input sequence. | |
| batch_size: int, batch size for the padded sequence. | |
| seqlen: int, maximum sequence length for the padded sequence. | |
| Return: | |
| hidden_states: (batch, seqlen, ...) | |
| """ | |
| output = IndexPutFirstAxis.apply(hidden_states, indices, batch_size * seqlen) | |
| return einops.rearrange(output, "(b s) ... -> b s ...", b=batch_size) | |
| class DomynEdgeFeedForward(torch.nn.Module): | |
| def __init__(self, config): | |
| super().__init__() | |
| self.config = config | |
| self.hidden_size = config.hidden_size | |
| self.intermediate_size = config.intermediate_size | |
| self.gate_proj = torch.nn.Linear(self.hidden_size, self.intermediate_size, bias=False) | |
| self.up_proj = torch.nn.Linear(self.hidden_size, self.intermediate_size, bias=False) | |
| self.down_proj = torch.nn.Linear(self.intermediate_size, self.hidden_size, bias=False) | |
| def forward(self, x): | |
| return self.down_proj(torch.nn.functional.silu(self.gate_proj(x)) * self.up_proj(x)) | |
| class DomynEdgeRotaryEmbedding(torch.nn.Module): | |
| inv_freq: torch.Tensor # fix linting for `register_buffer` | |
| def __init__(self, config: DomynEdgeConfig, device=None): | |
| super().__init__() | |
| self.max_seq_len_cached = config.max_position_embeddings | |
| self.original_max_seq_len = config.max_position_embeddings | |
| self.config = config | |
| self.rope_type = self.config.rope_parameters["rope_type"] | |
| rope_init_fn: typing.Callable = self.compute_default_rope_parameters | |
| inv_freq, self.attention_scaling = rope_init_fn(self.config, device) | |
| self.register_buffer("inv_freq", inv_freq, persistent=False) | |
| self.register_buffer("original_inv_freq", inv_freq.clone(), persistent=False) | |
| def compute_default_rope_parameters( | |
| config: DomynEdgeConfig | None = None, | |
| device: typing.Optional["torch.device"] = None, | |
| ) -> tuple["torch.Tensor", float]: | |
| """Computes the inverse frequencies according to the original RoPE implementation. | |
| Args: | |
| config ([`~transformers.PreTrainedConfig`]): | |
| The model configuration. | |
| device (`torch.device`): | |
| The device to use for initialization of the inverse frequencies. | |
| Returns: | |
| Tuple of (`torch.Tensor`, `float`), containing the inverse frequencies for the RoPE embeddings and the | |
| post-processing scaling factor applied to the computed cos/sin (unused in this type of RoPE). | |
| """ | |
| base = config.rope_parameters["rope_theta"] | |
| dim = config.rope_dim | |
| attention_factor = 1.0 # Unused in this type of RoPE | |
| # Compute the inverse frequencies | |
| inv_freq = 1.0 / ( | |
| base ** (torch.arange(0, dim, 2, dtype=torch.int64).to(device=device, dtype=torch.float) / dim) | |
| ) | |
| return inv_freq, attention_factor | |
| def forward(self, x, position_ids): | |
| inv_freq_expanded = self.inv_freq[None, :, None].float().expand(position_ids.shape[0], -1, 1).to(x.device) | |
| position_ids_expanded = position_ids[:, None, :].float() | |
| # TODO: the angles lose precision in two cases, both wrong at large positions: | |
| # - under torch.autocast(bfloat16) the matmul below runs in bf16 despite the `.float()` casts; | |
| # - after model.to(torch.bfloat16) / model.bfloat16() the `inv_freq` buffer itself is cast to bf16. | |
| # Loading with `from_pretrained(dtype=torch.bfloat16)` and no autocast is not affected. Candidate fix: | |
| # recompute `inv_freq` in fp32 here, with autocast disabled, instead of reading the buffer. | |
| freqs = (inv_freq_expanded.float() @ position_ids_expanded.float()).transpose(1, 2) | |
| emb = torch.cat((freqs, freqs), dim=-1) | |
| cos = emb.cos() * self.attention_scaling | |
| sin = emb.sin() * self.attention_scaling | |
| return cos, sin | |
| def rotate_half(x): | |
| """Rotates half the hidden dims of the input.""" | |
| x1 = x[..., : x.shape[-1] // 2] | |
| x2 = x[..., x.shape[-1] // 2 :] | |
| return torch.cat((-x2, x1), dim=-1) | |
| def apply_rotary_pos_emb(q, k, cos, sin, unsqueeze_dim=1): | |
| """Applies Rotary Position Embedding to the query and key tensors. | |
| Args: | |
| q (`torch.Tensor`): The query tensor. | |
| k (`torch.Tensor`): The key tensor. | |
| cos (`torch.Tensor`): The cosine part of the rotary embedding. | |
| sin (`torch.Tensor`): The sine part of the rotary embedding. | |
| unsqueeze_dim (`int`, *optional*, defaults to 1): | |
| The 'unsqueeze_dim' argument specifies the dimension along which to unsqueeze cos[position_ids] and | |
| sin[position_ids] so that they can be properly broadcasted to the dimensions of q and k. For example, note | |
| that cos[position_ids] and sin[position_ids] have the shape [batch_size, seq_len, head_dim]. Then, if q and | |
| k have the shape [batch_size, heads, seq_len, head_dim], then setting unsqueeze_dim=1 makes | |
| cos[position_ids] and sin[position_ids] broadcastable to the shapes of q and k. Similarly, if q and k have | |
| the shape [batch_size, seq_len, heads, head_dim], then set unsqueeze_dim=2. | |
| Returns: | |
| `tuple(torch.Tensor)` comprising of the query and key tensors rotated using the Rotary Position Embedding. | |
| """ | |
| cos = cos.unsqueeze(unsqueeze_dim) | |
| sin = sin.unsqueeze(unsqueeze_dim) | |
| qf, kf = q.float(), k.float() | |
| q_embed = (qf * cos) + (rotate_half(qf) * sin) | |
| k_embed = (kf * cos) + (rotate_half(kf) * sin) | |
| return q_embed.to(q.dtype), k_embed.to(k.dtype) | |
| class DomynEdgeAttention(torch.nn.Module): | |
| """Grouped Query Attention with support for sliding window.""" | |
| def __init__(self, config: DomynEdgeConfig, layer_idx: int): | |
| super().__init__() | |
| self.config = config | |
| self.head_dim = config.head_sizes[layer_idx] | |
| self.scaling = self.head_dim**-0.5 | |
| self.window_size = config.window_sizes[layer_idx] | |
| self.apply_rope = ( | |
| apply_rotary_pos_emb | |
| if config.position_layers[layer_idx] == "rope" | |
| else lambda q, k, cos, sin, unsqueeze_dim: (q, k) # noqa: ARG005 | |
| ) | |
| self.layer_idx = layer_idx | |
| self.enable_gqa = config.num_attention_heads > config.num_key_value_heads | |
| self.q_proj = torch.nn.Linear( | |
| config.hidden_size, config.num_attention_heads * self.head_dim, bias=config.attention_bias | |
| ) | |
| self.k_proj = torch.nn.Linear( | |
| config.hidden_size, config.num_key_value_heads * self.head_dim, bias=config.attention_bias | |
| ) | |
| self.v_proj = torch.nn.Linear( | |
| config.hidden_size, config.num_key_value_heads * self.head_dim, bias=config.attention_bias | |
| ) | |
| self.o_proj = torch.nn.Linear( | |
| config.num_attention_heads * self.head_dim, config.hidden_size, bias=config.attention_bias | |
| ) | |
| self.q_norm = torch.nn.RMSNorm(self.head_dim, eps=config.rms_norm_eps, elementwise_affine=False) | |
| self.k_norm = torch.nn.RMSNorm(self.head_dim, eps=config.rms_norm_eps, elementwise_affine=True) | |
| def forward( | |
| self, | |
| hidden_states: torch.Tensor, | |
| position_embeddings: tuple[torch.Tensor, torch.Tensor], | |
| attention_mask: torch.Tensor, | |
| past_key_values: transformers.Cache | None = None, | |
| **_kwargs, | |
| ) -> tuple[torch.Tensor, torch.Tensor | None]: | |
| batch_size, sequence_length, _ = hidden_states.shape | |
| q = self.q_norm( | |
| self.q_proj(hidden_states).view(batch_size, sequence_length, self.config.num_attention_heads, self.head_dim) | |
| ) | |
| k = self.k_norm( | |
| self.k_proj(hidden_states).view(batch_size, sequence_length, self.config.num_key_value_heads, self.head_dim) | |
| ) | |
| v = self.v_proj(hidden_states).view(batch_size, sequence_length, self.config.num_key_value_heads, self.head_dim) | |
| cos, sin = position_embeddings | |
| q, k = self.apply_rope(q, k, cos, sin, unsqueeze_dim=2) | |
| if past_key_values is not None: | |
| k, v = k.transpose(1, 2), v.transpose(1, 2) | |
| k, v = past_key_values.update(k, v, self.layer_idx) | |
| k, v = k.transpose(1, 2), v.transpose(1, 2) | |
| if q.size(1) > 1: | |
| q, q_indices, q_cu_seqlen, q_maxseq = unpad_input(q, attention_mask[:, -sequence_length:]) | |
| else: | |
| q_maxseq = 1 | |
| q_cu_seqlen = torch.arange(batch_size + 1, dtype=torch.int32, device=q.device) | |
| q_indices = q_cu_seqlen[:-1] | |
| q = q.squeeze(1) | |
| k, _, k_cu_seqlen, k_maxseq = unpad_input(k, attention_mask) | |
| v, *_ = unpad_input(v, attention_mask) | |
| attn_output = torch.nn.attention.varlen.varlen_attn( | |
| q if q.dtype in [torch.float16, torch.bfloat16] else q.to(torch.bfloat16), | |
| k if k.dtype in [torch.float16, torch.bfloat16] else k.to(torch.bfloat16), | |
| v if v.dtype in [torch.float16, torch.bfloat16] else v.to(torch.bfloat16), | |
| cu_seq_q=q_cu_seqlen, | |
| cu_seq_k=k_cu_seqlen, | |
| max_q=q_maxseq, | |
| max_k=k_maxseq, | |
| scale=self.scaling, | |
| window_size=self.window_size, | |
| enable_gqa=self.enable_gqa, | |
| ).to(q.dtype) | |
| attn_output = pad_input(attn_output, q_indices, batch_size, sequence_length) | |
| attn_output = attn_output.view(batch_size, sequence_length, self.config.num_attention_heads * self.head_dim) | |
| return self.o_proj(attn_output) | |
| class DomynEdgeDecoderLayer(torch.nn.Module): | |
| def __init__(self, config: DomynEdgeConfig, layer_idx: int): | |
| super().__init__() | |
| self.config = config | |
| self.attention = DomynEdgeAttention(config=config, layer_idx=layer_idx) | |
| self.feedforward = DomynEdgeFeedForward(config) | |
| self.pre_attention_norm = torch.nn.RMSNorm(config.hidden_size, eps=config.rms_norm_eps) | |
| self.pre_feedforward_norm = torch.nn.RMSNorm(config.hidden_size, eps=config.rms_norm_eps) | |
| self.post_attention_norm = torch.nn.RMSNorm(config.hidden_size, eps=config.rms_norm_eps) | |
| self.post_feedforward_norm = torch.nn.RMSNorm(config.hidden_size, eps=config.rms_norm_eps) | |
| def forward( | |
| self, | |
| hidden_states: torch.Tensor, | |
| attention_mask: torch.Tensor | None = None, | |
| past_key_values: transformers.Cache | None = None, | |
| position_embeddings: tuple[torch.Tensor, torch.Tensor] | None = None, | |
| **kwargs, | |
| ) -> torch.Tensor: | |
| # Self Attention | |
| hidden_states = hidden_states + self.post_attention_norm( | |
| self.attention( | |
| hidden_states=self.pre_attention_norm(hidden_states), | |
| attention_mask=attention_mask, | |
| past_key_values=past_key_values, | |
| position_embeddings=position_embeddings, | |
| **kwargs, | |
| ) | |
| ) | |
| ## Fully Connected | |
| return hidden_states + self.post_feedforward_norm(self.feedforward(self.pre_feedforward_norm(hidden_states))) | |
| class DomynEdgePreTrainedModel(transformers.PreTrainedModel): | |
| """Base class wiring DomynEdge into the HuggingFace `PreTrainedModel` machinery.""" | |
| config: DomynEdgeConfig | |
| base_model_prefix = "model" | |
| supports_gradient_checkpointing = False | |
| _supports_flash_attn = True | |
| _supports_sdpa = False | |
| _supports_flex_attn = False | |
| _can_compile_fullgraph = True | |
| _supports_attention_backend = False | |
| _can_record_outputs = { | |
| "hidden_states": DomynEdgeDecoderLayer, | |
| } | |
| class DomynEdgeModel(DomynEdgePreTrainedModel): | |
| """DomynEdge decoder stack without the language modeling head.""" | |
| def __init__(self, config: DomynEdgeConfig): | |
| """Build the embeddings, decoder layers, final norm and rotary embedding from `config`.""" | |
| super().__init__(config) | |
| self.padding_idx = config.pad_token_id | |
| self.vocab_size = config.vocab_size | |
| self.embed_tokens = torch.nn.Embedding(config.vocab_size, config.hidden_size, self.padding_idx) | |
| self.layers = torch.nn.ModuleList( | |
| [DomynEdgeDecoderLayer(config, layer_idx) for layer_idx in range(config.num_hidden_layers)] | |
| ) | |
| self.norm = torch.nn.RMSNorm(config.hidden_size, eps=config.rms_norm_eps) | |
| self.rotary_emb = DomynEdgeRotaryEmbedding(config=config) | |
| # Initialize weights and apply final processing | |
| self.post_init() | |
| def forward( | |
| self, | |
| input_ids: torch.LongTensor | None = None, | |
| attention_mask: torch.Tensor | None = None, | |
| past_key_values: transformers.Cache | None = None, | |
| inputs_embeds: torch.FloatTensor | None = None, | |
| position_ids: torch.LongTensor | None = None, | |
| use_cache: bool | None = None, | |
| **kwargs, | |
| ) -> transformers.modeling_outputs.BaseModelOutputWithPast: | |
| """Run the decoder stack and return the final hidden states (and the cache when `use_cache` is set).""" | |
| if input_ids is not None and inputs_embeds is not None: | |
| msg = "You must specify exactly one of input_ids or inputs_embeds" | |
| raise ValueError(msg) | |
| if inputs_embeds is None: | |
| inputs_embeds = self.embed_tokens(input_ids) | |
| if use_cache and past_key_values is None: | |
| past_key_values = transformers.DynamicCache(config=self.config) | |
| past_seen_tokens = past_key_values.get_seq_length() if past_key_values is not None else 0 | |
| if position_ids is None: | |
| position_ids = torch.arange(inputs_embeds.shape[1], device=inputs_embeds.device) + past_seen_tokens | |
| position_ids = position_ids.unsqueeze(0) | |
| hidden_states = inputs_embeds | |
| position_embeddings = self.rotary_emb(hidden_states, position_ids) | |
| if attention_mask is None: | |
| attention_mask = torch.ones( | |
| (hidden_states.shape[0], past_seen_tokens + hidden_states.shape[1]), | |
| device=hidden_states.device, | |
| dtype=torch.bool, | |
| ) | |
| for decoder_layer in self.layers: | |
| hidden_states = decoder_layer( | |
| hidden_states, | |
| attention_mask=attention_mask, | |
| position_embeddings=position_embeddings, | |
| past_key_values=past_key_values, | |
| **kwargs, | |
| ) | |
| hidden_states = self.norm(hidden_states) | |
| return transformers.modeling_outputs.BaseModelOutputWithPast( | |
| last_hidden_state=hidden_states, | |
| past_key_values=past_key_values if use_cache else None, | |
| ) | |
| class DomynEdgeForCausalLM(DomynEdgePreTrainedModel, transformers.GenerationMixin): | |
| """DomynEdge model with a language modeling head tied to the input embeddings.""" | |
| _tied_weights_keys = {"lm_head.weight": "model.embed_tokens.weight"} | |
| def __init__(self, config): | |
| """Build the decoder stack and the language modeling head from `config`.""" | |
| super().__init__(config) | |
| self.model = DomynEdgeModel(config) | |
| self.vocab_size = config.vocab_size | |
| self.lm_head = torch.nn.Linear(config.hidden_size, config.vocab_size, bias=False) | |
| # Initialize weights and apply final processing | |
| self.post_init() | |
| def forward( | |
| self, | |
| input_ids: torch.LongTensor | None = None, | |
| attention_mask: torch.Tensor | None = None, | |
| position_ids: torch.LongTensor | None = None, | |
| past_key_values: transformers.Cache | None = None, | |
| inputs_embeds: torch.FloatTensor | None = None, | |
| labels: torch.LongTensor | None = None, | |
| use_cache: bool | None = None, | |
| logits_to_keep: int | torch.Tensor = 0, | |
| **kwargs, | |
| ) -> transformers.modeling_outputs.CausalLMOutputWithPast: | |
| """Compute logits for the last `logits_to_keep` positions, plus the loss when `labels` are given.""" | |
| outputs = self.model( | |
| input_ids=input_ids, | |
| attention_mask=attention_mask, | |
| position_ids=position_ids, | |
| past_key_values=past_key_values, | |
| inputs_embeds=inputs_embeds, | |
| use_cache=use_cache, | |
| **kwargs, | |
| ) | |
| hidden_states = outputs.last_hidden_state | |
| # Only compute necessary logits, and do not upcast them to float if we are not computing the loss | |
| slice_indices = slice(-logits_to_keep, None) if isinstance(logits_to_keep, int) else logits_to_keep | |
| logits = self.lm_head(hidden_states[:, slice_indices, :]) | |
| loss = ( | |
| self.loss_function(logits=logits, labels=labels, vocab_size=self.config.vocab_size, **kwargs) | |
| if labels is not None | |
| else None | |
| ) | |
| return transformers.modeling_outputs.CausalLMOutputWithPast( | |
| loss=loss, | |
| logits=logits, | |
| past_key_values=outputs.past_key_values, | |
| hidden_states=outputs.hidden_states, | |
| attentions=outputs.attentions, | |
| ) | |
| __all__ = [ | |
| "DomynEdgeForCausalLM", | |
| "DomynEdgeModel", | |
| "DomynEdgePreTrainedModel", | |
| ] | |