Text Generation
Transformers
Safetensors
PyTorch
English
logos
causal-lm
custom-code
base-model
custom_code
Instructions to use Rorical/logos-1b-base with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use Rorical/logos-1b-base with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="Rorical/logos-1b-base", trust_remote_code=True)# Load model directly from transformers import AutoModelForCausalLM model = AutoModelForCausalLM.from_pretrained("Rorical/logos-1b-base", trust_remote_code=True, dtype="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use Rorical/logos-1b-base with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "Rorical/logos-1b-base" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "Rorical/logos-1b-base", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker
docker model run hf.co/Rorical/logos-1b-base
- SGLang
How to use Rorical/logos-1b-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 "Rorical/logos-1b-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": "Rorical/logos-1b-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 "Rorical/logos-1b-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": "Rorical/logos-1b-base", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }' - Docker Model Runner
How to use Rorical/logos-1b-base with Docker Model Runner:
docker model run hf.co/Rorical/logos-1b-base
| """Linear (Kimi Delta Attention) decoder-only transformer. | |
| Pure-PyTorch chunkwise-parallel KDA scan. | |
| """ | |
| import math | |
| from dataclasses import dataclass | |
| from typing import List, Optional, Tuple, Dict, Any | |
| import torch | |
| import torch.nn as nn | |
| import torch.nn.functional as F | |
| from einops import rearrange | |
| from .lm_loss import ( | |
| lm_cross_entropy_from_logits, | |
| token_superposition_attention_mask, | |
| token_superposition_embeddings, | |
| ) | |
| from .baseline import ( | |
| BaselineConfig, | |
| RMSNorm, | |
| SwiGLU, | |
| MoELayer, | |
| combine_lm_and_aux_loss, | |
| init_moe_router_weights, | |
| _validate_moe_config, | |
| count_parameters, | |
| model_summary, | |
| ) | |
| class _ShortConvolution(nn.Module): | |
| """Causal depthwise 1-D conv with optional cached state for O(1) decode.""" | |
| def __init__( | |
| self, | |
| hidden_size: int, | |
| kernel_size: int, | |
| activation: str = "silu", | |
| bias: bool = False, | |
| ): | |
| super().__init__() | |
| self.kernel_size = kernel_size | |
| self.conv = nn.Conv1d( | |
| hidden_size, | |
| hidden_size, | |
| kernel_size=kernel_size, | |
| groups=hidden_size, | |
| padding=kernel_size - 1, | |
| bias=bias, | |
| ) | |
| self.activation = activation | |
| def forward( | |
| self, | |
| x: torch.Tensor, | |
| cache: Optional[torch.Tensor] = None, | |
| return_cache: bool = False, | |
| ): | |
| T = x.size(1) | |
| K = self.kernel_size | |
| if cache is None: | |
| y = self.conv(x.transpose(1, 2))[..., :T].transpose(1, 2) | |
| else: | |
| x_full = torch.cat([cache, x], dim=1) | |
| y = F.conv1d( | |
| x_full.transpose(1, 2), | |
| self.conv.weight, | |
| self.conv.bias, | |
| stride=1, | |
| padding=0, | |
| groups=self.conv.groups, | |
| ).transpose(1, 2) | |
| if self.activation == "silu": | |
| y = F.silu(y) | |
| if not return_cache: | |
| return y | |
| if K <= 1: | |
| new_cache = x.new_zeros(x.size(0), 0, x.size(-1)) | |
| else: | |
| combined = torch.cat([cache, x], dim=1) if cache is not None else x | |
| if combined.size(1) >= K - 1: | |
| new_cache = combined[:, -(K - 1):].contiguous() | |
| else: | |
| pad = combined.new_zeros( | |
| combined.size(0), (K - 1) - combined.size(1), combined.size(-1) | |
| ) | |
| new_cache = torch.cat([pad, combined], dim=1) | |
| return y, new_cache | |
| class _RMSNormGatedSigmoid(nn.Module): | |
| def __init__(self, dim: int, eps: float = 1e-5): | |
| super().__init__() | |
| self.weight = nn.Parameter(torch.ones(dim)) | |
| self.eps = eps | |
| def forward(self, x: torch.Tensor, gate: torch.Tensor) -> torch.Tensor: | |
| dtype = x.dtype | |
| x_f = x.float() | |
| rms_inv = x_f.pow(2).mean(dim=-1, keepdim=True).add_(self.eps).rsqrt() | |
| y = (x_f * rms_inv).to(dtype) * self.weight | |
| return y * torch.sigmoid(gate.to(dtype)) | |
| def _kda_gate( | |
| g: torch.Tensor, | |
| A_log: torch.Tensor, | |
| dt_bias: torch.Tensor, | |
| ) -> torch.Tensor: | |
| """Log-space decay gate: ``-exp(A_log) * softplus(g + dt_bias)``.""" | |
| H, K = g.shape[-2], g.shape[-1] | |
| g = g.float() + dt_bias.float().view(H, K) | |
| dt = F.softplus(g) | |
| A = A_log.float().view(1, 1, H, 1) | |
| return -A.exp() * dt | |
| def _kda_chunk_scan( | |
| q: torch.Tensor, | |
| k: torch.Tensor, | |
| v: torch.Tensor, | |
| log_g: torch.Tensor, | |
| beta: torch.Tensor, | |
| chunk_size: int = 64, | |
| use_qk_l2norm: bool = True, | |
| initial_state: Optional[torch.Tensor] = None, | |
| output_final_state: bool = False, | |
| ): | |
| """Chunkwise-parallel KDA scan in pure PyTorch. | |
| Recurrence: ``S_i = (I - beta_i k_i k_i^T) D_i S_{i-1} + beta_i k_i v_i^T``, | |
| ``o_i = q_i @ S_i``, with ``D_i = diag(exp(log_g_i))``. Chunk-level | |
| parallelism comes from the similarity transform ``~S_i = W_i^{-1} S_i`` | |
| plus a single triangular solve per chunk. | |
| """ | |
| B, T, H, K = q.shape | |
| V = v.shape[-1] | |
| orig_dtype = v.dtype | |
| device = q.device | |
| # The body runs in fp32: per-channel decays accumulate aggressively and | |
| # CUDA's triangular_solve has no bf16/fp16 kernel. | |
| with torch.autocast(device_type=device.type, enabled=False): | |
| if use_qk_l2norm: | |
| q = F.normalize(q, dim=-1) | |
| k = F.normalize(k, dim=-1) | |
| scale = K ** -0.5 | |
| q = q.float() * scale | |
| k = k.float() | |
| v = v.float() | |
| log_g = log_g.float() | |
| beta = beta.float() | |
| pad = (chunk_size - T % chunk_size) % chunk_size | |
| if pad > 0: | |
| q = F.pad(q, (0, 0, 0, 0, 0, pad)) | |
| k = F.pad(k, (0, 0, 0, 0, 0, pad)) | |
| v = F.pad(v, (0, 0, 0, 0, 0, pad)) | |
| log_g = F.pad(log_g, (0, 0, 0, 0, 0, pad)) | |
| beta = F.pad(beta, (0, 0, 0, pad)) | |
| Nc = (T + pad) // chunk_size | |
| C = chunk_size | |
| q = rearrange(q, "b (n c) h k -> b h n c k", c=C) | |
| k = rearrange(k, "b (n c) h k -> b h n c k", c=C) | |
| v = rearrange(v, "b (n c) h v -> b h n c v", c=C) | |
| log_g = rearrange(log_g, "b (n c) h k -> b h n c k", c=C) | |
| beta = rearrange(beta, "b (n c) h -> b h n c", c=C) | |
| # Clamp the cumulative log-decay to [-15, 0]: at default A/dt_bias | |
| # ranges a 64-token cumsum can drop below -80, and exp(-cum) then | |
| # overflows fp32 and NaNs the triangular solve. | |
| cum_log_g = log_g.cumsum(dim=-2).clamp(min=-15.0) | |
| W = cum_log_g.exp() | |
| W_inv = (-cum_log_g).exp() | |
| u_mat = k * W_inv | |
| w_mat = k * W | |
| q_tilde = q * W | |
| beta_e = beta.unsqueeze(-1) | |
| beta_w = beta_e * w_mat | |
| beta_v = beta_e * v | |
| L = torch.einsum("bhnik,bhnjk->bhnij", beta_w, u_mat) | |
| upper_incl_diag = torch.triu( | |
| torch.ones(C, C, dtype=torch.bool, device=device), diagonal=0 | |
| ) | |
| L = L.masked_fill(upper_incl_diag, 0) | |
| I_plus_L = L + torch.eye(C, dtype=L.dtype, device=device) | |
| effective_v = torch.linalg.solve_triangular( | |
| I_plus_L, beta_v, upper=False, unitriangular=True | |
| ) | |
| effective_w = torch.linalg.solve_triangular( | |
| I_plus_L, beta_w, upper=False, unitriangular=True | |
| ) | |
| intra_attn = torch.einsum("bhnik,bhnjk->bhnij", q_tilde, u_mat) | |
| strict_upper = torch.triu( | |
| torch.ones(C, C, dtype=torch.bool, device=device), diagonal=1 | |
| ) | |
| intra_attn = intra_attn.masked_fill(strict_upper, 0) | |
| if initial_state is not None: | |
| S = initial_state.to(dtype=q.dtype, device=q.device) | |
| else: | |
| S = q.new_zeros(B, H, K, V) | |
| outputs: List[torch.Tensor] = [] | |
| for n in range(Nc): | |
| delta = effective_v[:, :, n] - effective_w[:, :, n] @ S | |
| o_inter = q_tilde[:, :, n] @ S | |
| o_chunk = o_inter + intra_attn[:, :, n] @ delta | |
| outputs.append(o_chunk) | |
| state_update = torch.einsum( | |
| "bhck,bhcv->bhkv", u_mat[:, :, n], delta | |
| ) | |
| S = W[:, :, n, -1].unsqueeze(-1) * (S + state_update) | |
| out = torch.stack(outputs, dim=2) | |
| out = rearrange(out, "b h n c v -> b (n c) h v") | |
| if pad > 0: | |
| out = out[:, :T] | |
| out = out.to(orig_dtype) | |
| if output_final_state: | |
| # State stays fp32 so cached decode preserves precision. | |
| return out, S | |
| return out | |
| def _kda_recurrent_step( | |
| q: torch.Tensor, | |
| k: torch.Tensor, | |
| v: torch.Tensor, | |
| log_g: torch.Tensor, | |
| beta: torch.Tensor, | |
| state: torch.Tensor, | |
| use_qk_l2norm: bool = True, | |
| ) -> Tuple[torch.Tensor, torch.Tensor]: | |
| """Single-token KDA step matching ``_kda_chunk_scan`` for ``T == 1``.""" | |
| assert q.size(1) == 1 and k.size(1) == 1 and v.size(1) == 1 | |
| orig_dtype = v.dtype | |
| K = q.size(-1) | |
| device = q.device | |
| with torch.autocast(device_type=device.type, enabled=False): | |
| if use_qk_l2norm: | |
| q = F.normalize(q, dim=-1) | |
| k = F.normalize(k, dim=-1) | |
| scale = K ** -0.5 | |
| q_t = (q[:, 0].float()) * scale | |
| k_t = k[:, 0].float() | |
| v_t = v[:, 0].float() | |
| g_t = log_g[:, 0].float() | |
| b_t = beta[:, 0].float() | |
| S = state.to(torch.float32) | |
| S = S * g_t.exp().unsqueeze(-1) | |
| kS = torch.einsum("bhk,bhkv->bhv", k_t, S) | |
| update = torch.einsum( | |
| "bhk,bhv->bhkv", (b_t.unsqueeze(-1) * k_t), (v_t - kS) | |
| ) | |
| S = S + update | |
| o = torch.einsum("bhk,bhkv->bhv", q_t, S).unsqueeze(1) | |
| return o.to(orig_dtype), S | |
| class LinearConfig(BaselineConfig): | |
| head_dim: int = 64 | |
| conv_size: int = 4 | |
| chunk_size: int = 64 | |
| A_init_range: Tuple[float, float] = (1, 16) | |
| expand: int = 2 | |
| rope_base: float = 10000.0 | |
| def __post_init__(self): | |
| if self.d_model % self.num_heads != 0: | |
| raise ValueError("d_model must be divisible by num_heads") | |
| if self.partial_rope_dim is not None: | |
| if self.partial_rope_dim % 2 != 0: | |
| raise ValueError( | |
| f"partial_rope_dim ({self.partial_rope_dim}) must be even" | |
| ) | |
| if self.head_dim < 1: | |
| raise ValueError("head_dim must be >= 1") | |
| if self.chunk_size < 1: | |
| raise ValueError("chunk_size must be >= 1") | |
| if self.conv_size < 1: | |
| raise ValueError("conv_size must be >= 1") | |
| _validate_moe_config(self) | |
| class KimiDeltaAttention(nn.Module): | |
| def __init__(self, config: LinearConfig): | |
| super().__init__() | |
| self.hidden_size = config.d_model | |
| self.num_heads = config.num_heads | |
| self.head_dim = config.head_dim | |
| self.head_k_dim = self.head_dim | |
| self.conv_size = config.conv_size | |
| self.chunk_size = config.chunk_size | |
| projection_size = self.num_heads * self.head_dim | |
| self.q_proj = nn.Linear(self.hidden_size, projection_size, bias=False) | |
| self.k_proj = nn.Linear(self.hidden_size, projection_size, bias=False) | |
| self.v_proj = nn.Linear(self.hidden_size, projection_size, bias=False) | |
| self.q_conv1d = _ShortConvolution(projection_size, self.conv_size, "silu") | |
| self.k_conv1d = _ShortConvolution(projection_size, self.conv_size, "silu") | |
| self.v_conv1d = _ShortConvolution(projection_size, self.conv_size, "silu") | |
| A = torch.empty(self.num_heads, dtype=torch.float32).uniform_( | |
| *config.A_init_range | |
| ) | |
| self.A_log = nn.Parameter(torch.log(A)) | |
| self.A_log._no_weight_decay = True | |
| self.dt_bias = nn.Parameter(torch.empty(projection_size, dtype=torch.float32)) | |
| self.dt_bias._no_weight_decay = True | |
| self.f_a_proj = nn.Linear(self.hidden_size, self.head_dim, bias=False) | |
| self.f_b_proj = nn.Linear(self.head_dim, projection_size, bias=False) | |
| self.b_proj = nn.Linear(self.hidden_size, self.num_heads, bias=False) | |
| self.g_a_proj = nn.Linear(self.hidden_size, self.head_dim, bias=False) | |
| self.g_b_proj = nn.Linear(self.head_dim, projection_size, bias=True) | |
| self.o_norm = _RMSNormGatedSigmoid(self.head_dim, eps=config.norm_eps) | |
| self.o_proj = nn.Linear(projection_size, self.hidden_size, bias=False) | |
| self._reset_parameters() | |
| def _reset_parameters(self): | |
| # Inverse-softplus init (Mamba-2 / KDA scheme). | |
| dt = torch.exp( | |
| torch.rand(self.num_heads * self.head_dim) | |
| * (math.log(0.1) - math.log(0.001)) | |
| + math.log(0.001) | |
| ) | |
| dt = torch.clamp(dt, min=1e-4) | |
| inv_dt = dt + torch.log(-torch.expm1(-dt)) | |
| with torch.no_grad(): | |
| self.dt_bias.copy_(inv_dt) | |
| def forward( | |
| self, | |
| x: torch.Tensor, | |
| attention_mask: Optional[torch.Tensor] = None, | |
| cache: Optional[Dict[str, Optional[torch.Tensor]]] = None, | |
| ) -> torch.Tensor: | |
| use_cache = cache is not None | |
| q_in = self.q_proj(x) | |
| k_in = self.k_proj(x) | |
| v_in = self.v_proj(x) | |
| if use_cache: | |
| q, cache["conv_state_q"] = self.q_conv1d( | |
| q_in, cache=cache.get("conv_state_q"), return_cache=True | |
| ) | |
| k, cache["conv_state_k"] = self.k_conv1d( | |
| k_in, cache=cache.get("conv_state_k"), return_cache=True | |
| ) | |
| v, cache["conv_state_v"] = self.v_conv1d( | |
| v_in, cache=cache.get("conv_state_v"), return_cache=True | |
| ) | |
| else: | |
| q = self.q_conv1d(q_in) | |
| k = self.k_conv1d(k_in) | |
| v = self.v_conv1d(v_in) | |
| q = rearrange(q, "... (h d) -> ... h d", d=self.head_dim) | |
| k = rearrange(k, "... (h d) -> ... h d", d=self.head_dim) | |
| v = rearrange(v, "... (h d) -> ... h d", d=self.head_dim) | |
| g_raw = self.f_b_proj(self.f_a_proj(x)) | |
| g_raw = rearrange(g_raw, "... (h d) -> ... h d", d=self.head_dim) | |
| log_g = _kda_gate(g_raw, self.A_log, self.dt_bias) | |
| beta = self.b_proj(x).float().sigmoid() | |
| # Zero q/k/v, log_g, beta at padded positions so they contribute no | |
| # content and no decay to the recurrent state. | |
| if attention_mask is not None: | |
| mask_4d = attention_mask.unsqueeze(-1).unsqueeze(-1) | |
| q = q * mask_4d.to(q.dtype) | |
| k = k * mask_4d.to(k.dtype) | |
| v = v * mask_4d.to(v.dtype) | |
| log_g = log_g * mask_4d.to(log_g.dtype) | |
| beta = beta * attention_mask.unsqueeze(-1).to(beta.dtype) | |
| if use_cache: | |
| prev_state = cache.get("recurrent_state") | |
| if prev_state is not None and x.size(1) == 1: | |
| o, new_state = _kda_recurrent_step( | |
| q, k, v, log_g, beta, prev_state, use_qk_l2norm=True | |
| ) | |
| else: | |
| o, new_state = _kda_chunk_scan( | |
| q=q, k=k, v=v, log_g=log_g, beta=beta, | |
| chunk_size=self.chunk_size, | |
| use_qk_l2norm=True, | |
| initial_state=prev_state, | |
| output_final_state=True, | |
| ) | |
| cache["recurrent_state"] = new_state | |
| else: | |
| o = _kda_chunk_scan( | |
| q=q, k=k, v=v, log_g=log_g, beta=beta, | |
| chunk_size=self.chunk_size, | |
| use_qk_l2norm=True, | |
| ) | |
| gate = self.g_b_proj(self.g_a_proj(x)) | |
| gate = rearrange(gate, "... (h d) -> ... h d", d=self.head_dim) | |
| o = self.o_norm(o, gate) | |
| o = rearrange(o, "b t h d -> b t (h d)") | |
| return self.o_proj(o) | |
| class LinearTransformerBlock(nn.Module): | |
| def __init__(self, config: LinearConfig): | |
| super().__init__() | |
| self.use_moe = config.use_moe | |
| self.kda_norm = RMSNorm(config.d_model, eps=config.norm_eps) | |
| self.kda = KimiDeltaAttention(config) | |
| self.ffn_norm = RMSNorm(config.d_model, eps=config.norm_eps) | |
| if config.use_moe: | |
| self.ffn = MoELayer(config) | |
| else: | |
| self.ffn = SwiGLU(config.d_model, config.d_ff) | |
| def forward( | |
| self, | |
| x: torch.Tensor, | |
| attention_mask: Optional[torch.Tensor] = None, | |
| is_causal: bool = True, | |
| cache: Optional[Dict[str, Optional[torch.Tensor]]] = None, | |
| ) -> Tuple[torch.Tensor, torch.Tensor, Optional[torch.Tensor]]: | |
| x = x + self.kda(self.kda_norm(x), attention_mask=attention_mask, cache=cache) | |
| if self.use_moe: | |
| ffn_out, aux_loss, topk_indices = self.ffn(self.ffn_norm(x)) | |
| x = x + ffn_out | |
| return x, aux_loss, topk_indices | |
| else: | |
| x = x + self.ffn(self.ffn_norm(x)) | |
| return x, torch.zeros((), device=x.device, dtype=x.dtype), None | |
| class LinearTransformer(nn.Module): | |
| def __init__(self, config: LinearConfig): | |
| super().__init__() | |
| self.config = config | |
| self.token_emb = nn.Embedding(config.vocab_size, config.d_model) | |
| self.layers = nn.ModuleList([ | |
| LinearTransformerBlock(config) for _ in range(config.num_layers) | |
| ]) | |
| self.final_norm = RMSNorm(config.d_model, eps=config.norm_eps) | |
| self.lm_head = nn.Linear(config.d_model, config.vocab_size, bias=False) | |
| self.lm_head.weight = self.token_emb.weight | |
| self._init_weights() | |
| def _init_weights(self): | |
| for module in self.modules(): | |
| if isinstance(module, nn.Linear): | |
| torch.nn.init.normal_(module.weight, mean=0.0, std=0.02) | |
| if module.bias is not None: | |
| torch.nn.init.zeros_(module.bias) | |
| elif isinstance(module, nn.Embedding): | |
| torch.nn.init.normal_(module.weight, mean=0.0, std=0.02) | |
| init_moe_router_weights(self, self.config.router_init_std) | |
| def forward( | |
| self, | |
| input_ids: torch.Tensor, | |
| attention_mask: Optional[torch.Tensor] = None, | |
| labels: Optional[torch.Tensor] = None, | |
| is_causal: bool = True, | |
| caches: Optional[List[Dict[str, Optional[torch.Tensor]]]] = None, | |
| token_superposition_bag_size: int = 1, | |
| ) -> Dict[str, Any]: | |
| x = token_superposition_embeddings( | |
| self.token_emb, input_ids, token_superposition_bag_size, | |
| ) | |
| attention_mask = token_superposition_attention_mask( | |
| attention_mask, token_superposition_bag_size, | |
| ) | |
| aux_loss = torch.zeros((), device=input_ids.device, dtype=x.dtype) | |
| topk_indices_list: List[Optional[torch.Tensor]] = [] | |
| for i, layer in enumerate(self.layers): | |
| layer_cache = caches[i] if caches is not None else None | |
| x, layer_aux, layer_topk = layer( | |
| x, attention_mask=attention_mask, | |
| is_causal=is_causal, cache=layer_cache, | |
| ) | |
| aux_loss = aux_loss + layer_aux | |
| topk_indices_list.append(layer_topk) | |
| x = self.final_norm(x) | |
| logits = self.lm_head(x) | |
| lm_loss: Optional[torch.Tensor] = None | |
| if labels is not None: | |
| lm_loss = lm_cross_entropy_from_logits( | |
| logits, | |
| labels, | |
| token_superposition_bag_size=token_superposition_bag_size, | |
| ignore_index=-100, | |
| ) | |
| loss = combine_lm_and_aux_loss( | |
| lm_loss, | |
| aux_loss if self.config.use_moe else None, | |
| self.training, | |
| ) | |
| return { | |
| "logits": logits, | |
| "loss": loss, | |
| "lm_loss": lm_loss, | |
| "aux_loss": aux_loss if self.config.use_moe else None, | |
| "topk_indices": topk_indices_list if self.config.use_moe else None, | |
| } | |
| def update_router_biases(self, topk_indices_list: List[Optional[torch.Tensor]]) -> None: | |
| if not self.config.use_moe: | |
| return | |
| for layer, topk_indices in zip(self.layers, topk_indices_list): | |
| if topk_indices is not None and isinstance(layer.ffn, MoELayer): | |
| layer.ffn.update_bias(topk_indices) | |
| def get_balance_stats(self) -> Dict[str, float]: | |
| if not self.config.use_moe: | |
| return {} | |
| stats = {} | |
| for idx, layer in enumerate(self.layers): | |
| if hasattr(layer.ffn, "bias"): | |
| bias = layer.ffn.bias | |
| stats[f"layer{idx}_bias_mean"] = bias.abs().mean().item() | |
| stats[f"layer{idx}_bias_max"] = bias.abs().max().item() | |
| return stats | |
| def generate( | |
| self, | |
| input_ids: torch.Tensor, | |
| max_new_tokens: int = 100, | |
| temperature: float = 1.0, | |
| top_k: Optional[int] = None, | |
| attention_mask: Optional[torch.Tensor] = None, | |
| eos_token_id: Optional[int] = None, | |
| ) -> torch.Tensor: | |
| self.train(False) | |
| caches: List[Dict[str, Optional[torch.Tensor]]] = [ | |
| { | |
| "recurrent_state": None, | |
| "conv_state_q": None, | |
| "conv_state_k": None, | |
| "conv_state_v": None, | |
| } | |
| for _ in self.layers | |
| ] | |
| def _sample(logits: torch.Tensor) -> torch.Tensor: | |
| logits = logits / temperature | |
| if top_k is not None: | |
| v, _ = torch.topk(logits, min(top_k, logits.size(-1))) | |
| logits = logits.masked_fill(logits < v[:, [-1]], float("-inf")) | |
| probs = F.softmax(logits, dim=-1) | |
| return torch.multinomial(probs, num_samples=1) | |
| outputs = self.forward(input_ids, is_causal=True, caches=caches) | |
| next_token = _sample(outputs["logits"][:, -1, :]) | |
| input_ids = torch.cat([input_ids, next_token], dim=-1) | |
| if eos_token_id is not None and (next_token == eos_token_id).all(): | |
| return input_ids | |
| for _ in range(max_new_tokens - 1): | |
| outputs = self.forward(next_token, is_causal=True, caches=caches) | |
| next_token = _sample(outputs["logits"][:, -1, :]) | |
| input_ids = torch.cat([input_ids, next_token], dim=-1) | |
| if eos_token_id is not None and (next_token == eos_token_id).all(): | |
| break | |
| return input_ids | |