family deepseek_v32
Latent attention over only the 2048 keys a lightning indexer scores best for each query, and a mixture with a shared expert that chooses experts by sigmoid score plus a selection bias and weights them without the bias.
One block of the stack. Hover any part for its nnterp name; click to pin the card. The slider picks a block, each tick's color gives its block's shape, and the diagram redraws for the block picked.
identity layers[i].input + self_attn.attention_output + mlp.mlp_output == layer_output
⚠︎ marks a value this checkpoint has only under some load: hover it for the condition.
What print(model) shows on deepseek-ai/DeepSeek-V3.2: the native modules, standard names and every standard value with its layout.
DeepseekV32ForCausalLM(
(lm_head): Linear(in_features=7168, out_features=129280, bias=False)
(generator): Generator(
(streamer): Streamer()
)
(embed_tokens): Embedding(129280, 7168)
(layers): ModuleList(
(0-2): 3 x DeepseekV32DecoderLayer(
(self_attn): DeepseekV32Attention(
(q_a_proj): Linear(in_features=7168, out_features=1536, bias=False)
(q_a_layernorm): DeepseekV32RMSNorm((1536,), eps=1e-06)
(q_b_proj): Linear(in_features=1536, out_features=24576, bias=False)
(kv_a_proj_with_mqa): Linear(in_features=7168, out_features=576, bias=False)
(kv_a_layernorm): DeepseekV32RMSNorm((512,), eps=1e-06)
(kv_b_proj): Linear(in_features=512, out_features=32768, bias=False)
(o_proj): Linear(in_features=16384, out_features=7168, bias=False)
(indexer): DeepseekV32Indexer(
(wq_b): Linear(in_features=1536, out_features=8192, bias=False)
(wk): Linear(in_features=7168, out_features=128, bias=False)
(k_norm): LayerNorm((128,), eps=1e-06, elementwise_affine=True, bias=True)
(weights_proj): Linear(in_features=7168, out_features=64, bias=False)
)
(attention_queries) -> Queries [batch num_heads seq qk_head_dim]: The queries entering attention
(attention_keys) -> Keys [batch num_kv_heads seq qk_head_dim]: The keys entering attention
(attention_values) -> Values [batch num_kv_heads seq head_dim]: The values entering attention
(attention_scores) -> Pattern [batch num_heads query key]: The attention scores entering the softmax, masked
(attention_premix) -> HeadOutputs [batch seq num_heads head_dim]: Every head's output side by side, as the output projection takes it
(attention_output) -> Residual [batch seq hidden_size]: What the attention adds to the residual stream
(attention_probabilities) -> Pattern [batch num_heads query key]: The attention pattern the values are mixed with
(attention_head_outputs) -> HeadOutputs [batch seq num_heads head_dim]: The per-head outputs before the output projection
)
(mlp): DeepseekV32MLP(
(gate_proj): Linear(in_features=7168, out_features=18432, bias=False)
(up_proj): Linear(in_features=7168, out_features=18432, bias=False)
(down_proj): Linear(in_features=18432, out_features=7168, bias=False)
(act_fn): SiLUActivation()
(mlp_activation) -> Neurons [batch seq intermediate_size]: The activation function's output
(mlp_neurons) -> Neurons [batch seq intermediate_size]: What the down projection receives: act(gate)·up on a gated MLP, the activation itself otherwise
(mlp_output) -> Residual [batch seq hidden_size]: What the MLP adds to the residual stream
)
(input_layernorm): DeepseekV32RMSNorm((7168,), eps=1e-06)
(post_attention_layernorm): DeepseekV32RMSNorm((7168,), eps=1e-06)
(layer_input) -> Residual [batch seq hidden_size]: The residual stream entering the block
(attention_norm_output) -> Residual [batch seq hidden_size]: The normed stream entering the attention
(layer_mid) -> Residual [batch seq hidden_size]: The residual stream after the attention add
(mlp_norm_output) -> Residual [batch seq hidden_size]: The normed stream entering the MLP
(mlp_input) -> Residual [batch seq hidden_size]: What the MLP is called with
(layer_output) -> Residual [batch seq hidden_size]: The residual stream leaving the block, a tensor even when the block returns a tuple
)
(3-60): 58 x DeepseekV32DecoderLayer(
(self_attn): DeepseekV32Attention(
(q_a_proj): Linear(in_features=7168, out_features=1536, bias=False)
(q_a_layernorm): DeepseekV32RMSNorm((1536,), eps=1e-06)
(q_b_proj): Linear(in_features=1536, out_features=24576, bias=False)
(kv_a_proj_with_mqa): Linear(in_features=7168, out_features=576, bias=False)
(kv_a_layernorm): DeepseekV32RMSNorm((512,), eps=1e-06)
(kv_b_proj): Linear(in_features=512, out_features=32768, bias=False)
(o_proj): Linear(in_features=16384, out_features=7168, bias=False)
(indexer): DeepseekV32Indexer(
(wq_b): Linear(in_features=1536, out_features=8192, bias=False)
(wk): Linear(in_features=7168, out_features=128, bias=False)
(k_norm): LayerNorm((128,), eps=1e-06, elementwise_affine=True, bias=True)
(weights_proj): Linear(in_features=7168, out_features=64, bias=False)
)
(attention_queries) -> Queries [batch num_heads seq qk_head_dim]: The queries entering attention
(attention_keys) -> Keys [batch num_kv_heads seq qk_head_dim]: The keys entering attention
(attention_values) -> Values [batch num_kv_heads seq head_dim]: The values entering attention
(attention_scores) -> Pattern [batch num_heads query key]: The attention scores entering the softmax, masked
(attention_premix) -> HeadOutputs [batch seq num_heads head_dim]: Every head's output side by side, as the output projection takes it
(attention_output) -> Residual [batch seq hidden_size]: What the attention adds to the residual stream
(attention_probabilities) -> Pattern [batch num_heads query key]: The attention pattern the values are mixed with
(attention_head_outputs) -> HeadOutputs [batch seq num_heads head_dim]: The per-head outputs before the output projection
)
(mlp): DeepseekV32MoE(
(experts): DeepseekV32Experts(
(act_fn): SiLUActivation()
)
(router/gate): DeepseekV32TopkRouter()
(shared_experts): DeepseekV32MLP(
(gate_proj): Linear(in_features=7168, out_features=2048, bias=False)
(up_proj): Linear(in_features=7168, out_features=2048, bias=False)
(down_proj): Linear(in_features=2048, out_features=7168, bias=False)
(act_fn): SiLUActivation()
(mlp_activation) -> Neurons [batch seq intermediate_size]: The activation function's output
(mlp_neurons) -> Neurons [batch seq intermediate_size]: What the down projection receives: act(gate)·up on a gated MLP, the activation itself otherwise
(mlp_output) -> Residual [batch seq hidden_size]: What the MLP adds to the residual stream
)
(mlp_activation) -> Neurons [batch seq intermediate_size]: The activation function's output
(mlp_neurons) -> Neurons [batch seq intermediate_size]: What the down projection receives: act(gate)·up on a gated MLP, the activation itself otherwise
(router_logits) -> RouterLogits [batch seq num_experts]: The router's logits, one per expert, before the scoring
(expert_weights) -> ExpertWeights [batch seq top_k]: The weight each selected expert's output is scaled by
(expert_indices) -> ExpertIndices [batch seq top_k]: The expert each routing slot sends the token to
(expert_outputs) -> ExpertOutputs [batch seq top_k hidden_size]: Each routing slot's weighted expert output
(routed_output) -> Residual [batch seq hidden_size]: The routed experts' combined output
(shared_expert_output) -> Residual [batch seq hidden_size]: The shared expert's output
(mlp_output) -> Residual [batch seq hidden_size]: What the MLP adds to the residual stream
)
(input_layernorm): DeepseekV32RMSNorm((7168,), eps=1e-06)
(post_attention_layernorm): DeepseekV32RMSNorm((7168,), eps=1e-06)
(layer_input) -> Residual [batch seq hidden_size]: The residual stream entering the block
(attention_norm_output) -> Residual [batch seq hidden_size]: The normed stream entering the attention
(layer_mid) -> Residual [batch seq hidden_size]: The residual stream after the attention add
(mlp_norm_output) -> Residual [batch seq hidden_size]: The normed stream entering the MLP
(mlp_input) -> Residual [batch seq hidden_size]: What the MLP is called with
(layer_output) -> Residual [batch seq hidden_size]: The residual stream leaving the block, a tensor even when the block returns a tuple
)
)
(norm): DeepseekV32RMSNorm((7168,), eps=1e-06)
(logits) -> Logits [batch seq vocab_size]: The logits the model returns, after anything it does past lm_head (a softcap, a scale)
(token_embeddings) -> Residual [batch seq hidden_size]: The embedding module's output; layers[0].input is what enters the first block
(final_norm_output) -> Residual [batch seq hidden_size]: The residual stream after the final norm, what lm_head reads
(lm_head_output) -> Logits [batch seq vocab_size]: The head's logits before anything the model does past lm_head (a softcap, a scale)
(next_token_probs) -> NextTokenProbs [batch vocab_size]: The next-token distribution at the last position; derived, read-only
(input_ids) -> Tokens [batch seq]: The token ids the model was called with
(attention_mask) -> Tokens [batch seq]: The attention mask the model was called with; zeros are padding
(input_size): [batch, seq] of the current call; read-only
)What print(model) shows on deepseek-ai/DeepSeek-V3.2-Speciale: the native modules, standard names and every standard value with its layout.
DeepseekV32ForCausalLM(
(lm_head): Linear(in_features=7168, out_features=129280, bias=False)
(generator): Generator(
(streamer): Streamer()
)
(embed_tokens): Embedding(129280, 7168)
(layers): ModuleList(
(0-2): 3 x DeepseekV32DecoderLayer(
(self_attn): DeepseekV32Attention(
(q_a_proj): Linear(in_features=7168, out_features=1536, bias=False)
(q_a_layernorm): DeepseekV32RMSNorm((1536,), eps=1e-06)
(q_b_proj): Linear(in_features=1536, out_features=24576, bias=False)
(kv_a_proj_with_mqa): Linear(in_features=7168, out_features=576, bias=False)
(kv_a_layernorm): DeepseekV32RMSNorm((512,), eps=1e-06)
(kv_b_proj): Linear(in_features=512, out_features=32768, bias=False)
(o_proj): Linear(in_features=16384, out_features=7168, bias=False)
(indexer): DeepseekV32Indexer(
(wq_b): Linear(in_features=1536, out_features=8192, bias=False)
(wk): Linear(in_features=7168, out_features=128, bias=False)
(k_norm): LayerNorm((128,), eps=1e-06, elementwise_affine=True, bias=True)
(weights_proj): Linear(in_features=7168, out_features=64, bias=False)
)
(attention_queries) -> Queries [batch num_heads seq qk_head_dim]: The queries entering attention
(attention_keys) -> Keys [batch num_kv_heads seq qk_head_dim]: The keys entering attention
(attention_values) -> Values [batch num_kv_heads seq head_dim]: The values entering attention
(attention_scores) -> Pattern [batch num_heads query key]: The attention scores entering the softmax, masked
(attention_premix) -> HeadOutputs [batch seq num_heads head_dim]: Every head's output side by side, as the output projection takes it
(attention_output) -> Residual [batch seq hidden_size]: What the attention adds to the residual stream
(attention_probabilities) -> Pattern [batch num_heads query key]: The attention pattern the values are mixed with
(attention_head_outputs) -> HeadOutputs [batch seq num_heads head_dim]: The per-head outputs before the output projection
)
(mlp): DeepseekV32MLP(
(gate_proj): Linear(in_features=7168, out_features=18432, bias=False)
(up_proj): Linear(in_features=7168, out_features=18432, bias=False)
(down_proj): Linear(in_features=18432, out_features=7168, bias=False)
(act_fn): SiLUActivation()
(mlp_activation) -> Neurons [batch seq intermediate_size]: The activation function's output
(mlp_neurons) -> Neurons [batch seq intermediate_size]: What the down projection receives: act(gate)·up on a gated MLP, the activation itself otherwise
(mlp_output) -> Residual [batch seq hidden_size]: What the MLP adds to the residual stream
)
(input_layernorm): DeepseekV32RMSNorm((7168,), eps=1e-06)
(post_attention_layernorm): DeepseekV32RMSNorm((7168,), eps=1e-06)
(layer_input) -> Residual [batch seq hidden_size]: The residual stream entering the block
(attention_norm_output) -> Residual [batch seq hidden_size]: The normed stream entering the attention
(layer_mid) -> Residual [batch seq hidden_size]: The residual stream after the attention add
(mlp_norm_output) -> Residual [batch seq hidden_size]: The normed stream entering the MLP
(mlp_input) -> Residual [batch seq hidden_size]: What the MLP is called with
(layer_output) -> Residual [batch seq hidden_size]: The residual stream leaving the block, a tensor even when the block returns a tuple
)
(3-60): 58 x DeepseekV32DecoderLayer(
(self_attn): DeepseekV32Attention(
(q_a_proj): Linear(in_features=7168, out_features=1536, bias=False)
(q_a_layernorm): DeepseekV32RMSNorm((1536,), eps=1e-06)
(q_b_proj): Linear(in_features=1536, out_features=24576, bias=False)
(kv_a_proj_with_mqa): Linear(in_features=7168, out_features=576, bias=False)
(kv_a_layernorm): DeepseekV32RMSNorm((512,), eps=1e-06)
(kv_b_proj): Linear(in_features=512, out_features=32768, bias=False)
(o_proj): Linear(in_features=16384, out_features=7168, bias=False)
(indexer): DeepseekV32Indexer(
(wq_b): Linear(in_features=1536, out_features=8192, bias=False)
(wk): Linear(in_features=7168, out_features=128, bias=False)
(k_norm): LayerNorm((128,), eps=1e-06, elementwise_affine=True, bias=True)
(weights_proj): Linear(in_features=7168, out_features=64, bias=False)
)
(attention_queries) -> Queries [batch num_heads seq qk_head_dim]: The queries entering attention
(attention_keys) -> Keys [batch num_kv_heads seq qk_head_dim]: The keys entering attention
(attention_values) -> Values [batch num_kv_heads seq head_dim]: The values entering attention
(attention_scores) -> Pattern [batch num_heads query key]: The attention scores entering the softmax, masked
(attention_premix) -> HeadOutputs [batch seq num_heads head_dim]: Every head's output side by side, as the output projection takes it
(attention_output) -> Residual [batch seq hidden_size]: What the attention adds to the residual stream
(attention_probabilities) -> Pattern [batch num_heads query key]: The attention pattern the values are mixed with
(attention_head_outputs) -> HeadOutputs [batch seq num_heads head_dim]: The per-head outputs before the output projection
)
(mlp): DeepseekV32MoE(
(experts): DeepseekV32Experts(
(act_fn): SiLUActivation()
)
(router/gate): DeepseekV32TopkRouter()
(shared_experts): DeepseekV32MLP(
(gate_proj): Linear(in_features=7168, out_features=2048, bias=False)
(up_proj): Linear(in_features=7168, out_features=2048, bias=False)
(down_proj): Linear(in_features=2048, out_features=7168, bias=False)
(act_fn): SiLUActivation()
(mlp_activation) -> Neurons [batch seq intermediate_size]: The activation function's output
(mlp_neurons) -> Neurons [batch seq intermediate_size]: What the down projection receives: act(gate)·up on a gated MLP, the activation itself otherwise
(mlp_output) -> Residual [batch seq hidden_size]: What the MLP adds to the residual stream
)
(mlp_activation) -> Neurons [batch seq intermediate_size]: The activation function's output
(mlp_neurons) -> Neurons [batch seq intermediate_size]: What the down projection receives: act(gate)·up on a gated MLP, the activation itself otherwise
(router_logits) -> RouterLogits [batch seq num_experts]: The router's logits, one per expert, before the scoring
(expert_weights) -> ExpertWeights [batch seq top_k]: The weight each selected expert's output is scaled by
(expert_indices) -> ExpertIndices [batch seq top_k]: The expert each routing slot sends the token to
(expert_outputs) -> ExpertOutputs [batch seq top_k hidden_size]: Each routing slot's weighted expert output
(routed_output) -> Residual [batch seq hidden_size]: The routed experts' combined output
(shared_expert_output) -> Residual [batch seq hidden_size]: The shared expert's output
(mlp_output) -> Residual [batch seq hidden_size]: What the MLP adds to the residual stream
)
(input_layernorm): DeepseekV32RMSNorm((7168,), eps=1e-06)
(post_attention_layernorm): DeepseekV32RMSNorm((7168,), eps=1e-06)
(layer_input) -> Residual [batch seq hidden_size]: The residual stream entering the block
(attention_norm_output) -> Residual [batch seq hidden_size]: The normed stream entering the attention
(layer_mid) -> Residual [batch seq hidden_size]: The residual stream after the attention add
(mlp_norm_output) -> Residual [batch seq hidden_size]: The normed stream entering the MLP
(mlp_input) -> Residual [batch seq hidden_size]: What the MLP is called with
(layer_output) -> Residual [batch seq hidden_size]: The residual stream leaving the block, a tensor even when the block returns a tuple
)
)
(norm): DeepseekV32RMSNorm((7168,), eps=1e-06)
(logits) -> Logits [batch seq vocab_size]: The logits the model returns, after anything it does past lm_head (a softcap, a scale)
(token_embeddings) -> Residual [batch seq hidden_size]: The embedding module's output; layers[0].input is what enters the first block
(final_norm_output) -> Residual [batch seq hidden_size]: The residual stream after the final norm, what lm_head reads
(lm_head_output) -> Logits [batch seq vocab_size]: The head's logits before anything the model does past lm_head (a softcap, a scale)
(next_token_probs) -> NextTokenProbs [batch vocab_size]: The next-token distribution at the last position; derived, read-only
(input_ids) -> Tokens [batch seq]: The token ids the model was called with
(attention_mask) -> Tokens [batch seq]: The attention mask the model was called with; zeros are padding
(input_size): [batch, seq] of the current call; read-only
)What print(model) shows on deepseek-ai/DeepSeek-V3.2-Exp: the native modules, standard names and every standard value with its layout.
DeepseekV32ForCausalLM(
(lm_head): Linear(in_features=7168, out_features=129280, bias=False)
(generator): Generator(
(streamer): Streamer()
)
(embed_tokens): Embedding(129280, 7168)
(layers): ModuleList(
(0-2): 3 x DeepseekV32DecoderLayer(
(self_attn): DeepseekV32Attention(
(q_a_proj): Linear(in_features=7168, out_features=1536, bias=False)
(q_a_layernorm): DeepseekV32RMSNorm((1536,), eps=1e-06)
(q_b_proj): Linear(in_features=1536, out_features=24576, bias=False)
(kv_a_proj_with_mqa): Linear(in_features=7168, out_features=576, bias=False)
(kv_a_layernorm): DeepseekV32RMSNorm((512,), eps=1e-06)
(kv_b_proj): Linear(in_features=512, out_features=32768, bias=False)
(o_proj): Linear(in_features=16384, out_features=7168, bias=False)
(indexer): DeepseekV32Indexer(
(wq_b): Linear(in_features=1536, out_features=8192, bias=False)
(wk): Linear(in_features=7168, out_features=128, bias=False)
(k_norm): LayerNorm((128,), eps=1e-06, elementwise_affine=True, bias=True)
(weights_proj): Linear(in_features=7168, out_features=64, bias=False)
)
(attention_queries) -> Queries [batch num_heads seq qk_head_dim]: The queries entering attention
(attention_keys) -> Keys [batch num_kv_heads seq qk_head_dim]: The keys entering attention
(attention_values) -> Values [batch num_kv_heads seq head_dim]: The values entering attention
(attention_scores) -> Pattern [batch num_heads query key]: The attention scores entering the softmax, masked
(attention_premix) -> HeadOutputs [batch seq num_heads head_dim]: Every head's output side by side, as the output projection takes it
(attention_output) -> Residual [batch seq hidden_size]: What the attention adds to the residual stream
(attention_probabilities) -> Pattern [batch num_heads query key]: The attention pattern the values are mixed with
(attention_head_outputs) -> HeadOutputs [batch seq num_heads head_dim]: The per-head outputs before the output projection
)
(mlp): DeepseekV32MLP(
(gate_proj): Linear(in_features=7168, out_features=18432, bias=False)
(up_proj): Linear(in_features=7168, out_features=18432, bias=False)
(down_proj): Linear(in_features=18432, out_features=7168, bias=False)
(act_fn): SiLUActivation()
(mlp_activation) -> Neurons [batch seq intermediate_size]: The activation function's output
(mlp_neurons) -> Neurons [batch seq intermediate_size]: What the down projection receives: act(gate)·up on a gated MLP, the activation itself otherwise
(mlp_output) -> Residual [batch seq hidden_size]: What the MLP adds to the residual stream
)
(input_layernorm): DeepseekV32RMSNorm((7168,), eps=1e-06)
(post_attention_layernorm): DeepseekV32RMSNorm((7168,), eps=1e-06)
(layer_input) -> Residual [batch seq hidden_size]: The residual stream entering the block
(attention_norm_output) -> Residual [batch seq hidden_size]: The normed stream entering the attention
(layer_mid) -> Residual [batch seq hidden_size]: The residual stream after the attention add
(mlp_norm_output) -> Residual [batch seq hidden_size]: The normed stream entering the MLP
(mlp_input) -> Residual [batch seq hidden_size]: What the MLP is called with
(layer_output) -> Residual [batch seq hidden_size]: The residual stream leaving the block, a tensor even when the block returns a tuple
)
(3-60): 58 x DeepseekV32DecoderLayer(
(self_attn): DeepseekV32Attention(
(q_a_proj): Linear(in_features=7168, out_features=1536, bias=False)
(q_a_layernorm): DeepseekV32RMSNorm((1536,), eps=1e-06)
(q_b_proj): Linear(in_features=1536, out_features=24576, bias=False)
(kv_a_proj_with_mqa): Linear(in_features=7168, out_features=576, bias=False)
(kv_a_layernorm): DeepseekV32RMSNorm((512,), eps=1e-06)
(kv_b_proj): Linear(in_features=512, out_features=32768, bias=False)
(o_proj): Linear(in_features=16384, out_features=7168, bias=False)
(indexer): DeepseekV32Indexer(
(wq_b): Linear(in_features=1536, out_features=8192, bias=False)
(wk): Linear(in_features=7168, out_features=128, bias=False)
(k_norm): LayerNorm((128,), eps=1e-06, elementwise_affine=True, bias=True)
(weights_proj): Linear(in_features=7168, out_features=64, bias=False)
)
(attention_queries) -> Queries [batch num_heads seq qk_head_dim]: The queries entering attention
(attention_keys) -> Keys [batch num_kv_heads seq qk_head_dim]: The keys entering attention
(attention_values) -> Values [batch num_kv_heads seq head_dim]: The values entering attention
(attention_scores) -> Pattern [batch num_heads query key]: The attention scores entering the softmax, masked
(attention_premix) -> HeadOutputs [batch seq num_heads head_dim]: Every head's output side by side, as the output projection takes it
(attention_output) -> Residual [batch seq hidden_size]: What the attention adds to the residual stream
(attention_probabilities) -> Pattern [batch num_heads query key]: The attention pattern the values are mixed with
(attention_head_outputs) -> HeadOutputs [batch seq num_heads head_dim]: The per-head outputs before the output projection
)
(mlp): DeepseekV32MoE(
(experts): DeepseekV32Experts(
(act_fn): SiLUActivation()
)
(router/gate): DeepseekV32TopkRouter()
(shared_experts): DeepseekV32MLP(
(gate_proj): Linear(in_features=7168, out_features=2048, bias=False)
(up_proj): Linear(in_features=7168, out_features=2048, bias=False)
(down_proj): Linear(in_features=2048, out_features=7168, bias=False)
(act_fn): SiLUActivation()
(mlp_activation) -> Neurons [batch seq intermediate_size]: The activation function's output
(mlp_neurons) -> Neurons [batch seq intermediate_size]: What the down projection receives: act(gate)·up on a gated MLP, the activation itself otherwise
(mlp_output) -> Residual [batch seq hidden_size]: What the MLP adds to the residual stream
)
(mlp_activation) -> Neurons [batch seq intermediate_size]: The activation function's output
(mlp_neurons) -> Neurons [batch seq intermediate_size]: What the down projection receives: act(gate)·up on a gated MLP, the activation itself otherwise
(router_logits) -> RouterLogits [batch seq num_experts]: The router's logits, one per expert, before the scoring
(expert_weights) -> ExpertWeights [batch seq top_k]: The weight each selected expert's output is scaled by
(expert_indices) -> ExpertIndices [batch seq top_k]: The expert each routing slot sends the token to
(expert_outputs) -> ExpertOutputs [batch seq top_k hidden_size]: Each routing slot's weighted expert output
(routed_output) -> Residual [batch seq hidden_size]: The routed experts' combined output
(shared_expert_output) -> Residual [batch seq hidden_size]: The shared expert's output
(mlp_output) -> Residual [batch seq hidden_size]: What the MLP adds to the residual stream
)
(input_layernorm): DeepseekV32RMSNorm((7168,), eps=1e-06)
(post_attention_layernorm): DeepseekV32RMSNorm((7168,), eps=1e-06)
(layer_input) -> Residual [batch seq hidden_size]: The residual stream entering the block
(attention_norm_output) -> Residual [batch seq hidden_size]: The normed stream entering the attention
(layer_mid) -> Residual [batch seq hidden_size]: The residual stream after the attention add
(mlp_norm_output) -> Residual [batch seq hidden_size]: The normed stream entering the MLP
(mlp_input) -> Residual [batch seq hidden_size]: What the MLP is called with
(layer_output) -> Residual [batch seq hidden_size]: The residual stream leaving the block, a tensor even when the block returns a tuple
)
)
(norm): DeepseekV32RMSNorm((7168,), eps=1e-06)
(logits) -> Logits [batch seq vocab_size]: The logits the model returns, after anything it does past lm_head (a softcap, a scale)
(token_embeddings) -> Residual [batch seq hidden_size]: The embedding module's output; layers[0].input is what enters the first block
(final_norm_output) -> Residual [batch seq hidden_size]: The residual stream after the final norm, what lm_head reads
(lm_head_output) -> Logits [batch seq vocab_size]: The head's logits before anything the model does past lm_head (a softcap, a scale)
(next_token_probs) -> NextTokenProbs [batch vocab_size]: The next-token distribution at the last position; derived, read-only
(input_ids) -> Tokens [batch seq]: The token ids the model was called with
(attention_mask) -> Tokens [batch seq]: The attention mask the model was called with; zeros are padding
(input_size): [batch, seq] of the current call; read-only
)What print(model) shows on deepseek-ai/DeepSeek-V3.2-Exp-Base: the native modules, standard names and every standard value with its layout.
DeepseekV32ForCausalLM(
(lm_head): Linear(in_features=7168, out_features=129280, bias=False)
(generator): Generator(
(streamer): Streamer()
)
(embed_tokens): Embedding(129280, 7168)
(layers): ModuleList(
(0-2): 3 x DeepseekV32DecoderLayer(
(self_attn): DeepseekV32Attention(
(q_a_proj): Linear(in_features=7168, out_features=1536, bias=False)
(q_a_layernorm): DeepseekV32RMSNorm((1536,), eps=1e-06)
(q_b_proj): Linear(in_features=1536, out_features=24576, bias=False)
(kv_a_proj_with_mqa): Linear(in_features=7168, out_features=576, bias=False)
(kv_a_layernorm): DeepseekV32RMSNorm((512,), eps=1e-06)
(kv_b_proj): Linear(in_features=512, out_features=32768, bias=False)
(o_proj): Linear(in_features=16384, out_features=7168, bias=False)
(indexer): DeepseekV32Indexer(
(wq_b): Linear(in_features=1536, out_features=8192, bias=False)
(wk): Linear(in_features=7168, out_features=128, bias=False)
(k_norm): LayerNorm((128,), eps=1e-06, elementwise_affine=True, bias=True)
(weights_proj): Linear(in_features=7168, out_features=64, bias=False)
)
(attention_queries) -> Queries [batch num_heads seq qk_head_dim]: The queries entering attention
(attention_keys) -> Keys [batch num_kv_heads seq qk_head_dim]: The keys entering attention
(attention_values) -> Values [batch num_kv_heads seq head_dim]: The values entering attention
(attention_scores) -> Pattern [batch num_heads query key]: The attention scores entering the softmax, masked
(attention_premix) -> HeadOutputs [batch seq num_heads head_dim]: Every head's output side by side, as the output projection takes it
(attention_output) -> Residual [batch seq hidden_size]: What the attention adds to the residual stream
(attention_probabilities) -> Pattern [batch num_heads query key]: The attention pattern the values are mixed with
(attention_head_outputs) -> HeadOutputs [batch seq num_heads head_dim]: The per-head outputs before the output projection
)
(mlp): DeepseekV32MLP(
(gate_proj): Linear(in_features=7168, out_features=18432, bias=False)
(up_proj): Linear(in_features=7168, out_features=18432, bias=False)
(down_proj): Linear(in_features=18432, out_features=7168, bias=False)
(act_fn): SiLUActivation()
(mlp_activation) -> Neurons [batch seq intermediate_size]: The activation function's output
(mlp_neurons) -> Neurons [batch seq intermediate_size]: What the down projection receives: act(gate)·up on a gated MLP, the activation itself otherwise
(mlp_output) -> Residual [batch seq hidden_size]: What the MLP adds to the residual stream
)
(input_layernorm): DeepseekV32RMSNorm((7168,), eps=1e-06)
(post_attention_layernorm): DeepseekV32RMSNorm((7168,), eps=1e-06)
(layer_input) -> Residual [batch seq hidden_size]: The residual stream entering the block
(attention_norm_output) -> Residual [batch seq hidden_size]: The normed stream entering the attention
(layer_mid) -> Residual [batch seq hidden_size]: The residual stream after the attention add
(mlp_norm_output) -> Residual [batch seq hidden_size]: The normed stream entering the MLP
(mlp_input) -> Residual [batch seq hidden_size]: What the MLP is called with
(layer_output) -> Residual [batch seq hidden_size]: The residual stream leaving the block, a tensor even when the block returns a tuple
)
(3-60): 58 x DeepseekV32DecoderLayer(
(self_attn): DeepseekV32Attention(
(q_a_proj): Linear(in_features=7168, out_features=1536, bias=False)
(q_a_layernorm): DeepseekV32RMSNorm((1536,), eps=1e-06)
(q_b_proj): Linear(in_features=1536, out_features=24576, bias=False)
(kv_a_proj_with_mqa): Linear(in_features=7168, out_features=576, bias=False)
(kv_a_layernorm): DeepseekV32RMSNorm((512,), eps=1e-06)
(kv_b_proj): Linear(in_features=512, out_features=32768, bias=False)
(o_proj): Linear(in_features=16384, out_features=7168, bias=False)
(indexer): DeepseekV32Indexer(
(wq_b): Linear(in_features=1536, out_features=8192, bias=False)
(wk): Linear(in_features=7168, out_features=128, bias=False)
(k_norm): LayerNorm((128,), eps=1e-06, elementwise_affine=True, bias=True)
(weights_proj): Linear(in_features=7168, out_features=64, bias=False)
)
(attention_queries) -> Queries [batch num_heads seq qk_head_dim]: The queries entering attention
(attention_keys) -> Keys [batch num_kv_heads seq qk_head_dim]: The keys entering attention
(attention_values) -> Values [batch num_kv_heads seq head_dim]: The values entering attention
(attention_scores) -> Pattern [batch num_heads query key]: The attention scores entering the softmax, masked
(attention_premix) -> HeadOutputs [batch seq num_heads head_dim]: Every head's output side by side, as the output projection takes it
(attention_output) -> Residual [batch seq hidden_size]: What the attention adds to the residual stream
(attention_probabilities) -> Pattern [batch num_heads query key]: The attention pattern the values are mixed with
(attention_head_outputs) -> HeadOutputs [batch seq num_heads head_dim]: The per-head outputs before the output projection
)
(mlp): DeepseekV32MoE(
(experts): DeepseekV32Experts(
(act_fn): SiLUActivation()
)
(router/gate): DeepseekV32TopkRouter()
(shared_experts): DeepseekV32MLP(
(gate_proj): Linear(in_features=7168, out_features=2048, bias=False)
(up_proj): Linear(in_features=7168, out_features=2048, bias=False)
(down_proj): Linear(in_features=2048, out_features=7168, bias=False)
(act_fn): SiLUActivation()
(mlp_activation) -> Neurons [batch seq intermediate_size]: The activation function's output
(mlp_neurons) -> Neurons [batch seq intermediate_size]: What the down projection receives: act(gate)·up on a gated MLP, the activation itself otherwise
(mlp_output) -> Residual [batch seq hidden_size]: What the MLP adds to the residual stream
)
(mlp_activation) -> Neurons [batch seq intermediate_size]: The activation function's output
(mlp_neurons) -> Neurons [batch seq intermediate_size]: What the down projection receives: act(gate)·up on a gated MLP, the activation itself otherwise
(router_logits) -> RouterLogits [batch seq num_experts]: The router's logits, one per expert, before the scoring
(expert_weights) -> ExpertWeights [batch seq top_k]: The weight each selected expert's output is scaled by
(expert_indices) -> ExpertIndices [batch seq top_k]: The expert each routing slot sends the token to
(expert_outputs) -> ExpertOutputs [batch seq top_k hidden_size]: Each routing slot's weighted expert output
(routed_output) -> Residual [batch seq hidden_size]: The routed experts' combined output
(shared_expert_output) -> Residual [batch seq hidden_size]: The shared expert's output
(mlp_output) -> Residual [batch seq hidden_size]: What the MLP adds to the residual stream
)
(input_layernorm): DeepseekV32RMSNorm((7168,), eps=1e-06)
(post_attention_layernorm): DeepseekV32RMSNorm((7168,), eps=1e-06)
(layer_input) -> Residual [batch seq hidden_size]: The residual stream entering the block
(attention_norm_output) -> Residual [batch seq hidden_size]: The normed stream entering the attention
(layer_mid) -> Residual [batch seq hidden_size]: The residual stream after the attention add
(mlp_norm_output) -> Residual [batch seq hidden_size]: The normed stream entering the MLP
(mlp_input) -> Residual [batch seq hidden_size]: What the MLP is called with
(layer_output) -> Residual [batch seq hidden_size]: The residual stream leaving the block, a tensor even when the block returns a tuple
)
)
(norm): DeepseekV32RMSNorm((7168,), eps=1e-06)
(logits) -> Logits [batch seq vocab_size]: The logits the model returns, after anything it does past lm_head (a softcap, a scale)
(token_embeddings) -> Residual [batch seq hidden_size]: The embedding module's output; layers[0].input is what enters the first block
(final_norm_output) -> Residual [batch seq hidden_size]: The residual stream after the final norm, what lm_head reads
(lm_head_output) -> Logits [batch seq vocab_size]: The head's logits before anything the model does past lm_head (a softcap, a scale)
(next_token_probs) -> NextTokenProbs [batch vocab_size]: The next-token distribution at the last position; derived, read-only
(input_ids) -> Tokens [batch seq]: The token ids the model was called with
(attention_mask) -> Tokens [batch seq]: The attention mask the model was called with; zeros are padding
(input_size): [batch, seq] of the current call; read-only
)h = x + self_attn(input_layernorm(x)) # sparse latent attention
out = h + mlp(post_attention_layernorm(h)) # dense on blocks 0-2, a mixture after
Llama's pre-norm block and Llama's names. The block adds each sublayer's output to the stream and returns a tensor, so the identity is the plain sum on a dense block and on a mixture block:
with model.trace(prompt):
x = model.layers[1].input.save()
attn = model.layers[1].self_attn.attention_output.save()
mlp = model.layers[1].mlp.mlp_output.save()
out = model.layers[1].layer_output.save()
torch.testing.assert_close(x + attn + mlp, out)
config.mlp_layer_types says which blocks are dense: blocks 0 to 2 on every checkpoint
(first_k_dense_replace 3), a mixture on the other 58. The configs carry one
multi-token-prediction block (num_nextn_predict_layers 1), stored after the last block;
transformers does not build it, so model.layers has 61 blocks.
attention_queries and attention_keys are qk_head_dim wide (qk_nope_head_dim +
qk_rope_head_dim, 128 + 64 = 192), attention_values and attention_head_outputs head_dim
(v_head_dim, 128). transformers sets the config's head_dim to qk_rope_head_dim, the rotary
width (64); no served value is that wide. Queries go through a compressed rank (q_lora_rank
1536): q_a_proj, q_a_layernorm, then q_b_proj, with no q_proj module. Keys and values
are expanded for every head from one latent per token (kv_lora_rank 512), so attention_keys
has num_heads (128) heads. The last 64 dimensions of every head's key are one rotary key that
all heads share.
attn = model.layers[1].self_attn
with model.trace(prompt):
q = attn.attention_queries.save() # [1, 128, seq, 192]
k = attn.attention_keys.save() # [1, 128, seq, 192]
v = attn.attention_values.save() # [1, 128, seq, 128]
assert torch.equal(k[:, 0, :, -64:], k[:, 1, :, -64:]) # one rotary key
The attention rotates pair (2i, 2i + 1) of the projection into dimensions i and i + 32 of the
rotary part. The forward always does this; the config has no rope_interleave key to switch it.
attention_queries[..., -64:] and attention_keys[..., -64:] are in that rotate-half order: at
position 0, where rotary is the identity, the served rotary part is q_b_proj's even dimensions
followed by its odd ones.
with model.trace(prompt):
proj = attn.q_b_proj.output.save()
with model.trace(prompt):
q = attn.attention_queries.save()
rope = proj.view(1, -1, model.num_heads, model.qk_head_dim)[0, 0, 0, -64:]
torch.testing.assert_close(q[0, 0, 0, -64:], torch.cat([rope[0::2], rope[1::2]]))
Every checkpoint extends the context with YaRN (rope_scaling factor 40, mscale_all_dim 1.0),
and the attention multiplies the scores by qk_head_dim ** -0.5 times 1.87
(self_attn.scaling, 0.1352), not by qk_head_dim ** -0.5 (0.0722) alone; recompute
attention_scores from the queries and keys with self_attn.scaling.
A lightning indexer (self_attn.indexer: index_n_heads 64 heads of index_head_dim 128)
scores every key for every query and keeps the index_topk (2048) best. The attention sets the
other keys' mask entries to the dtype's minimum before it calls the attention function. It does
this under eager and under the default sdpa load alike, so both loads run the same sparse
computation; the interior values need attn_implementation="eager". attention_scores carry
that mask, so a dropped key reads like a future one. attention_probabilities is the dense
[batch, num_heads, query, key] pattern, exactly zero outside each query's selection.
The selection is self_attn.indexer.output, int32 key indices of shape
[batch, query, min(index_topk, seq)]; it has no standard name. The indexer ranks future keys
last but does not drop them. On a prompt of up to 2048 tokens each row therefore lists every
position, the causal mask removes the future keys, and the pattern is plain causal: row t has
t + 1 nonzero entries.
with model.trace(prompt):
sel = attn.indexer.output.save() # [1, seq, min(2048, seq)]
probs = attn.attention_probabilities.save()
rows = (probs[0, 0] != 0).sum(-1)
assert torch.equal(rows, torch.arange(1, rows.numel() + 1)) # plain causal
A written pattern is used as written, so a write can give weight to a key the indexer dropped.
The indexer runs under torch.no_grad(): no gradient reaches its projections, and the selection
does not move with a gradient-based attribution.
256 routed experts, 8 per token, and one shared expert every token runs through.
router_logits are the float32 logits before the sigmoid, and before the selection bias
(router.e_score_correction_bias). The bias is added to the sigmoids only to choose: the experts
sit in n_group 8 groups, each group scored by the sum of its two best biased scores, and a token
takes its 8 experts from its best topk_group 4 groups. expert_weights are the chosen experts'
sigmoids without the bias, renormalized to sum to one (norm_topk_prob) and multiplied by
routed_scaling_factor, so they sum to 2.5 at every token. A written router_logits moves both
the choice and the weights; a written bias moves only the choice.
moe = model.layers[3].mlp
with model.trace(prompt):
logits = moe.router_logits.save()
w = moe.expert_weights.save()
idx = moe.expert_indices.save()
routed = moe.routed_output.save()
shared = moe.shared_expert_output.save()
out = moe.mlp_output.save()
chosen = logits.sigmoid().gather(-1, idx)
scale = model.config.routed_scaling_factor
torch.testing.assert_close(w, chosen / chosen.sum(-1, keepdim=True) * scale)
torch.testing.assert_close(routed + shared, out)
The shared expert runs after the routed ones, so shared_expert_output is read after
routed_output. Ablating an expert is zeroing the weight of every slot that chose it; the other
slots keep their weights, so the token's weights then sum to less than 2.5:
with model.trace(prompt):
moe.expert_weights = moe.expert_weights.masked_fill(moe.expert_indices == 3, 0)
ablated = model.logits.save()
Blocks 0 to 2 have a dense MLP: support() reports every mixture value missing there.
DeepSeek-V3.2 (DeepseekV32ForCausalLM).
Llama's tree and Llama's block: model.{embed_tokens, layers[i].{input_layernorm, self_attn, post_attention_layernorm, mlp}, norm} and lm_head, the residual
added in the block, a bare tensor returned. Multi-head latent attention as in V3, with
DeepSeek Sparse Attention on top: each attention module carries an indexer (a
lightning indexer with its own small projections) that scores every key for every
query and keeps the index_topk best. Under eager and sdpa the selection is folded into the
attention mask (every unselected key set to the dtype's minimum) before the shared
attention_interface call, so the interior is the base's, read on the interface:
attention_scores are the scaled scores with that sparse mask added, so an
unselected key reads as the dtype's minimum, like a future one.attention_probabilities is the dense [batch, num_heads, query, key] pattern of
the sparse attention: exactly zero outside each query's selected keys, rows summing
to one over the selection. A written pattern is used as written, so a write can put
weight on keys the indexer did not select.While a prompt is no longer than index_topk (2048 on the released checkpoints) the
indexer selects every causal key and the pattern is the dense causal one. The indexer's
selection is self_attn.indexer.output, the [batch, query, min(index_topk, keys)]
int32 key indices; it has no standard name. On a prompt shorter than index_topk it
holds every key, future ones included (masked in the index scores, so ranked last), and
the causal mask removes those. The first first_k_dense_replace blocks (per
mlp_layer_types) have a dense MLP, the rest a mixture of experts. The sizes are
DeepSeek-V2's.