Text Generation
MLX
Safetensors
laguna
oq
quantized
Mixture of Experts
conversational
custom_code
5-bit
Instructions to use mlx-community/Laguna-S-2.1-oQ5e with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- MLX
How to use mlx-community/Laguna-S-2.1-oQ5e with MLX:
# Make sure mlx-lm is installed # pip install --upgrade mlx-lm # Generate text with mlx-lm from mlx_lm import load, generate model, tokenizer = load("mlx-community/Laguna-S-2.1-oQ5e") prompt = "Write a story about Einstein" messages = [{"role": "user", "content": prompt}] prompt = tokenizer.apply_chat_template( messages, add_generation_prompt=True ) text = generate(model, tokenizer, prompt=prompt, verbose=True) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- LM Studio
- Pi
How to use mlx-community/Laguna-S-2.1-oQ5e with Pi:
Start the MLX server
# Install MLX LM: uv tool install mlx-lm # Start a local OpenAI-compatible server: mlx_lm.server --model "mlx-community/Laguna-S-2.1-oQ5e"
Configure the model in Pi
# Install Pi: npm install -g @mariozechner/pi-coding-agent # Add to ~/.pi/agent/models.json: { "providers": { "mlx-lm": { "baseUrl": "http://localhost:8080/v1", "api": "openai-completions", "apiKey": "none", "models": [ { "id": "mlx-community/Laguna-S-2.1-oQ5e" } ] } } }Run Pi
# Start Pi in your project directory: pi
- Hermes Agent new
How to use mlx-community/Laguna-S-2.1-oQ5e with Hermes Agent:
Start the MLX server
# Install MLX LM: uv tool install mlx-lm # Start a local OpenAI-compatible server: mlx_lm.server --model "mlx-community/Laguna-S-2.1-oQ5e"
Configure Hermes
# Install Hermes: curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash hermes setup # Point Hermes at the local server: hermes config set model.provider custom hermes config set model.base_url http://127.0.0.1:8080/v1 hermes config set model.default mlx-community/Laguna-S-2.1-oQ5e
Run Hermes
hermes
- OpenClaw new
How to use mlx-community/Laguna-S-2.1-oQ5e with OpenClaw:
Start the MLX server
# Install MLX LM: uv tool install mlx-lm # Start a local OpenAI-compatible server: mlx_lm.server --model "mlx-community/Laguna-S-2.1-oQ5e"
Configure OpenClaw
# Install OpenClaw: npm install -g openclaw@latest # Register the local server and set it as the default model: openclaw onboard --non-interactive --mode local \ --auth-choice custom-api-key \ --custom-base-url http://127.0.0.1:8080/v1 \ --custom-model-id "mlx-community/Laguna-S-2.1-oQ5e" \ --custom-provider-id mlx-lm \ --custom-compatibility openai \ --custom-text-input \ --accept-risk \ --skip-health
Run OpenClaw
openclaw agent --local --agent main --message "Hello from Hugging Face"
- MLX LM
How to use mlx-community/Laguna-S-2.1-oQ5e with MLX LM:
Generate or start a chat session
# Install MLX LM uv tool install mlx-lm # Interactive chat REPL mlx_lm.chat --model "mlx-community/Laguna-S-2.1-oQ5e"
Run an OpenAI-compatible server
# Install MLX LM uv tool install mlx-lm # Start the server mlx_lm.server --model "mlx-community/Laguna-S-2.1-oQ5e" # Calling the OpenAI-compatible server with curl curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "mlx-community/Laguna-S-2.1-oQ5e", "messages": [ {"role": "user", "content": "Hello"} ] }'
File size: 13,142 Bytes
2f389f3 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 | # ruff: noqa
# Copyright 2025 Poolside and the HuggingFace Inc. team. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from transformers.configuration_utils import PreTrainedConfig
from transformers.modeling_rope_utils import RopeParameters
from transformers.utils.import_utils import is_causal_conv1d_available, is_flash_linear_attention_available
class LagunaConfig(PreTrainedConfig):
r"""
Configuration class for Laguna model.
Laguna is Poolside's MoE architecture with:
- Attention output gating (softplus gate)
- Sigmoid routing instead of softmax
- No QKV bias
- Explicit head_dim parameter
Args:
head_dim (`int`, *optional*, defaults to 128):
Dimension of attention heads. Laguna uses explicit head_dim rather than
computing it from hidden_size // num_attention_heads.
qkv_bias (`bool`, *optional*, defaults to `False`):
Whether to add bias to QKV projections. Laguna uses no QKV bias.
attention_bias (`bool`, *optional*, defaults to `False`):
Whether to add bias to attention output projection. Laguna uses no attention bias.
gating (`bool` or `str`, *optional*, defaults to `True`):
Attention output gating mode. When ``True`` or ``"per-element"`` a g_proj
linear layer with output size ``num_attention_heads * head_dim`` is added
and ``attn_output = attn_output * softplus(g_proj(x))``. When ``"per-head"``
g_proj has output size ``num_attention_heads`` and the gate broadcasts across
``head_dim``. When ``False`` no gating is applied.
partial_rotary_factor (`float`, *optional*):
Fraction of head_dim to apply rotary embeddings to. When set, this value is
injected into ``rope_parameters`` (and ``swa_rope_parameters``) if not already
specified there. When ``None`` the default behaviour of the rope implementation
is used (typically full rotary).
num_attention_heads_per_layer (`list[int]`, *optional*):
Optional per-layer override for ``num_attention_heads``. When provided the list
length must equal ``num_hidden_layers`` and each entry is the head count used by
that layer. When ``None`` every layer uses ``num_attention_heads``.
vocab_size (`int`, *optional*, defaults to 100352):
Vocabulary size of the Laguna model.
hidden_size (`int`, *optional*, defaults to 2048):
Dimension of the hidden representations.
intermediate_size (`int`, *optional*, defaults to 8192):
Dimension of the MLP representations for dense layers.
num_hidden_layers (`int`, *optional*, defaults to 48):
Number of hidden layers in the Transformer.
num_attention_heads (`int`, *optional*, defaults to 32):
Number of attention heads.
num_key_value_heads (`int`, *optional*, defaults to 8):
Number of key-value heads for GQA.
max_position_embeddings (`int`, *optional*, defaults to 4096):
Maximum sequence length.
rms_norm_eps (`float`, *optional*, defaults to 1e-6):
Epsilon for RMSNorm layers.
sliding_window (`int`, *optional*):
Sliding window attention size. Used by layers whose type in ``layer_types``
is ``"sliding_attention"``. When ``None``, all layers use full attention.
layer_types (`list[str]`, *optional*):
Per-layer attention type. Each element should be ``"sliding_attention"`` or
``"full_attention"``. Length must equal ``num_hidden_layers``. When ``None``,
all layers default to global attention.
swa_attention_sink_enabled (`bool`, *optional*, defaults to `False`):
Whether to enable learnable attention sinks on sliding-window attention layers.
When enabled, a per-head bias parameter is added that allows the model to attend
to position 0 even when it falls outside the sliding window.
swa_rope_parameters (`RopeParameters`, *optional*):
Separate RoPE configuration for sliding-window attention layers. When ``None``,
SWA layers use the same RoPE as global attention layers.
num_experts (`int`, *optional*, defaults to 256):
Number of routed experts.
num_experts_per_tok (`int`, *optional*, defaults to 16):
Number of experts selected per token (top-k).
moe_intermediate_size (`int`, *optional*, defaults to 1024):
Intermediate size of routed experts.
shared_expert_intermediate_size (`int`, *optional*, defaults to 1024):
Intermediate size of the shared expert.
norm_topk_prob (`bool`, *optional*, defaults to `True`):
Whether to normalize top-k routing probabilities.
decoder_sparse_step (`int`, *optional*, defaults to 1):
Frequency of MoE layers (1 = every layer is MoE after mlp_only_layers).
mlp_only_layers (`list[int]`, *optional*, defaults to `[0]`):
Layer indices that use dense MLP instead of MoE.
router_aux_loss_coef (`float`, *optional*, defaults to 0.001):
Auxiliary loss coefficient for load balancing.
moe_routed_scaling_factor (`float`, *optional*, defaults to 1.0):
Scalar multiplier applied to the routed-expert output before combining with the
shared-expert output.
moe_apply_router_weight_on_input (`bool`, *optional*, defaults to `False`):
When ``True`` the top-k routing weights are multiplied into each expert's input
rather than its output. Matches the numerical form used by the trained checkpoint.
moe_router_logit_softcapping (`float`, *optional*, defaults to 0.0):
Optional soft-capping value ``c`` applied to router logits as
``x = tanh(x / c) * c`` before sigmoid + top-k. Disabled when ``0``.
rope_parameters (`RopeParameters`, *optional*):
RoPE configuration. Defaults to rope_theta=500000.0.
"""
model_type = "laguna"
keys_to_ignore_at_inference = ["past_key_values"]
# PreTrainedConfig in transformers v5 no longer auto-declares these; subclasses
# opt in by providing class-level annotations with defaults.
pad_token_id: int | None = None
bos_token_id: int | None = None
eos_token_id: int | list[int] | None = None
base_model_tp_plan = {
"layers.*.self_attn.q_proj": "colwise",
"layers.*.self_attn.k_proj": "colwise",
"layers.*.self_attn.v_proj": "colwise",
"layers.*.self_attn.g_proj": "colwise", # Laguna-specific gating projection
"layers.*.self_attn.o_proj": "rowwise",
"layers.*.mlp.gate_proj": "colwise",
"layers.*.mlp.up_proj": "colwise",
"layers.*.mlp.down_proj": "rowwise",
}
base_model_pp_plan = {
"embed_tokens": (["input_ids"], ["inputs_embeds"]),
"layers": (["hidden_states", "attention_mask"], ["hidden_states"]),
"norm": (["hidden_states"], ["hidden_states"]),
}
def __init__(
self,
vocab_size: int = 100352,
hidden_size: int = 2048,
intermediate_size: int = 8192,
num_hidden_layers: int = 48,
num_attention_heads: int = 32,
num_key_value_heads: int = 8,
head_dim: int = 128,
qkv_bias: bool = False,
attention_bias: bool = False,
gating: bool | str = True,
hidden_act: str = "silu",
max_position_embeddings: int = 4096,
initializer_range: float = 0.02,
rms_norm_eps: float = 1e-6,
use_cache: bool = True,
tie_word_embeddings: bool = False,
rope_parameters: RopeParameters | dict[str, RopeParameters] | None = None,
partial_rotary_factor: float | None = None,
attention_dropout: float = 0.0,
sliding_window: int | None = None,
layer_types: list[str] | None = None,
num_attention_heads_per_layer: list[int] | None = None,
swa_attention_sink_enabled: bool = False,
swa_rope_parameters: RopeParameters | None = None,
num_experts: int = 256,
num_experts_per_tok: int = 16,
moe_intermediate_size: int = 1024,
shared_expert_intermediate_size: int = 1024,
norm_topk_prob: bool = True,
decoder_sparse_step: int = 1,
mlp_only_layers: list[int] | None = None,
router_aux_loss_coef: float = 0.001,
moe_routed_scaling_factor: float = 1.0,
moe_apply_router_weight_on_input: bool = False,
moe_router_logit_softcapping: float = 0.0,
output_router_logits: bool = False,
**kwargs,
):
# Default mlp_only_layers: first layer is dense (moe_first_k_dense_replace=1)
if mlp_only_layers is None:
mlp_only_layers = [0]
# Default layer_types: all layers use full attention (Laguna-M). Laguna-XS
# ships an explicit list with a mix of "full_attention" and "sliding_attention".
# Downstream mask builders (``create_masks_for_generate``) iterate
# ``layer_types``, so it must be a list — not left as ``None``.
if layer_types is None:
layer_types = ["full_attention"] * num_hidden_layers
# Default rope_parameters with Laguna's theta
if rope_parameters is None:
rope_parameters = {"rope_type": "default", "rope_theta": 500000.0}
# config.json stores SWA rope nested in rope_parameters["sliding_attention"]
# and carries no top-level swa_rope_parameters. Derive it here, else the
# sliding-window layers silently reuse the full-attention rope.
if swa_rope_parameters is None and isinstance(rope_parameters, dict):
swa_rope_parameters = rope_parameters.get("sliding_attention")
# If ``partial_rotary_factor`` is set at the top level, inject it into any
# rope dict that does not already carry one so the rotary embedding picks
# it up consistently for both full-attention and SWA layers.
if partial_rotary_factor is not None:
if isinstance(rope_parameters, dict) and "partial_rotary_factor" not in rope_parameters:
rope_parameters = {**rope_parameters, "partial_rotary_factor": partial_rotary_factor}
if isinstance(swa_rope_parameters, dict) and "partial_rotary_factor" not in swa_rope_parameters:
swa_rope_parameters = {
**swa_rope_parameters,
"partial_rotary_factor": partial_rotary_factor,
}
self.vocab_size = vocab_size
self.hidden_size = hidden_size
self.intermediate_size = intermediate_size
self.num_hidden_layers = num_hidden_layers
self.num_attention_heads = num_attention_heads
self.num_key_value_heads = num_key_value_heads
self.head_dim = head_dim
self.qkv_bias = qkv_bias
self.attention_bias = attention_bias
self.gating = gating
self.hidden_act = hidden_act
self.max_position_embeddings = max_position_embeddings
self.initializer_range = initializer_range
self.rms_norm_eps = rms_norm_eps
self.use_cache = use_cache
self.rope_parameters = rope_parameters
self.partial_rotary_factor = partial_rotary_factor
self.attention_dropout = attention_dropout
# Sliding window attention arguments
self.sliding_window = sliding_window
self.layer_types = layer_types
self.num_attention_heads_per_layer = num_attention_heads_per_layer
self.swa_attention_sink_enabled = swa_attention_sink_enabled
self.swa_rope_parameters = swa_rope_parameters
# MoE arguments
self.num_experts = num_experts
self.num_experts_per_tok = num_experts_per_tok
self.moe_intermediate_size = moe_intermediate_size
self.shared_expert_intermediate_size = shared_expert_intermediate_size
self.norm_topk_prob = norm_topk_prob
self.decoder_sparse_step = decoder_sparse_step
self.mlp_only_layers = mlp_only_layers
self.router_aux_loss_coef = router_aux_loss_coef
self.moe_routed_scaling_factor = moe_routed_scaling_factor
self.moe_apply_router_weight_on_input = moe_apply_router_weight_on_input
self.moe_router_logit_softcapping = moe_router_logit_softcapping
self.output_router_logits = output_router_logits
super().__init__(tie_word_embeddings=tie_word_embeddings, **kwargs)
__all__ = ["LagunaConfig"]
|