Model techniques map
ModelsStep-3.7-Flash

StepFun · released 2026-05-29

Step-3.7-Flash

What Step-3.7-Flash’s own documents say it is built from — every method with the sentence that describes it.

Curator’s note196B language backbone / ~11B active + 1.88B vision encoder, 256K context, selectable reasoning levels. No arXiv paper found; the static.stepfun.com blog page is the primary technical document.

Against the consensus recipe

Its documents state 6 of the 15 methods the field agrees on.

The recipe from the overview: the methods the most labs adopt, per stage. A missing one is something the documents do not say, not something the model lacks.

  1. Data curation

  2. Training objective

  3. Model architecture

  4. Optimization

  5. Post-training

  6. Inference & serving

Checked in its code

Its code shows 11 of the 19 architecture features checked — 9 of them are not stated in its documents.

Documents say what a lab chose to describe; the modeling code says what the checkpoint runs. Each feature below was put to a code verifier, and only the config values and source lines it cited that were found in the files are shown, linked to the line.

Read from Hugging Face Transformers (modeling_step3p7.py, configuration_step3p7.py) and config.json at revision 5f6244077a, by anthropic/claude-sonnet-5 on 2026-09-25.

FeatureCodeIts documentsEvidence
Grouped-query attention code only in its codenot stated

Text attention uses 64 query heads with 8 shared KV heads (num_key_value_groups = num_heads // num_key_value_heads) and repeat_kv expands the KV heads per group.

text_config.num_attention_heads = 64text_config.num_attention_groups = 8
self.num_key_value_groups = self.num_heads // config.num_key_value_heads
modeling_step3p7.py · L688
    hidden_states = hidden_states[:, :, None, :, :].expand(batch, num_key_value_heads, n_rep, slen, head_dim)
    return hidden_states.reshape(batch, num_key_value_heads * n_rep, slen, head_dim)
modeling_step3p7.py · L134–135
Multi-head latent attention not in its codenot stated

The attention module uses standard separate q/k/v projections sized by head_dim with no low-rank latent KV projection or lora rank config keys.

Sliding-window attention code only in its codenot stated

layer_types marks most layers as sliding_attention with sliding_window=512, and Step3p7Attention sets self.sliding_window from config.sliding_window when the layer is local.

text_config.sliding_window = 512text_config.layer_types = ["full_attention", "sliding_attention", "sliding_attention", "sliding_attenti…
self.is_local_attention = config.layer_types[layer_idx] == "sliding_attention"
        self.sliding_window = config.sliding_window if self.is_local_attention else None
modeling_step3p7.py · L703–704
Interleaved sliding-window and global attention code only in its codenot stated

layer_types interleaves one full_attention layer every four layers with three sliding_attention layers, and the model builds separate causal masks per type dispatched by layer index.

text_config.layer_types = ["full_attention", "sliding_attention", "sliding_attention", "sliding_attenti…
causal_mask_mapping = {
                "full_attention": create_causal_mask(**mask_kwargs),
                "sliding_attention": create_sliding_window_causal_mask(**sliding_mask_kwargs),
            }
modeling_step3p7.py · L898–901
Indexer-selected sparse attention (DeepSeek Sparse Attention) code unclearnot stated

The config carries legacy sparse-index fields (index_n_heads, index_head_dim, etc.) mapped from sparse_attention_config, and the config code references a 'minimax_m3_sparse' layer type and Lightning Indexer, but no indexer module implementation is present in the given files and this config's layer_types contains no such entries.

if self.layer_types is None and "sparse_attention_freq" in sparse_cfg:
            self.layer_types = [
                "minimax_m3_sparse" if f else "full_attention" for f in sparse_cfg["sparse_attention_freq"]
            ]
configuration_step3p7.py · L280–283
Linear-attention or state-space layers alongside full attention not in its codenot stated

layer_types only contains full_attention and sliding_attention values for softmax attention layers; there is no linear-attention or state-space layer type or module in the modeling file.

text_config.layer_types = ["full_attention", "sliding_attention", "sliding_attention", "sliding_attenti…
Gated DeltaNet layers not in its codenot stated

No gated delta-rule recurrent module exists in the given code; layer_types only distinguishes full and sliding softmax attention.

Mamba-2 layers not in its codenot stated

No Mamba-2/SSD state-space block implementation exists in the given files; only Step3p7Attention (softmax) and MLP/MoE blocks are defined.

Learnable attention sink not in its codenot stated

The config declares sink: false and no per-head sink logit parameter or addition to the softmax denominator appears in the attention code.

text_config.sink = false
Gated attention output code only in its codenot stated

Step3p7Attention computes a gate projection (g_proj) and multiplies the attention output by its sigmoid before the output projection.

attn_output = attn_output * gate_states.unsqueeze(-1).sigmoid()
modeling_step3p7.py · L751
self.gate_per_head = config.gating is True or config.gating == "per-head"
        g_proj_dim = self.num_heads if self.gate_per_head else self.num_heads * self.head_dim
        self.g_proj = nn.Linear(config.hidden_size, g_proj_dim, bias=False)
modeling_step3p7.py · L708–710
QK normalization code only in its codenot stated

Step3p7Attention applies RMSNorm (q_norm/k_norm) per head to queries and keys before RoPE and the attention dot product.

query_states = self.q_norm(self.q_proj(hidden_states).view(hidden_shape)).transpose(1, 2)
        key_states = self.k_norm(self.k_proj(hidden_states).view(hidden_shape)).transpose(1, 2)
modeling_step3p7.py · L723–724
Partial RoPE code only in its codenot stated

partial_rotary_factors is 0.5 for full_attention layers, and compute_default_rope_parameters scales the rotary dim by partial_rotary_factor, applying rotation to only part of the head.

text_config.partial_rotary_factors = [0.5, 1.0, 1.0, 1.0, 0.5, 1.0, 1.0, 1.0, 0.5, 1.0, 1.0, 1.0, 0.5, 1.0, 1.0, 1…
partial_rotary_factor = config.rope_parameters[layer_type].get("partial_rotary_factor", 1.0)
        head_dim = getattr(config, "head_dim", None) or config.hidden_size // config.num_attention_heads
        dim = int(head_dim * partial_rotary_factor)
modeling_step3p7.py · L478–480
YaRN RoPE scaling not in its codenot stated

rope_scaling is present but its rope_type is 'llama3', not YaRN, so no YaRN-specific scaling code path is triggered for this config.

text_config.rope_scaling = {"rope_type": "llama3", "factor": 2.0, "original_max_position_embeddings": 13…
Layers without positional encoding (NoPE) not in its codenot stated

Every layer_type (full_attention and sliding_attention) has a rope_parameters entry built and applied via Step3p7RotaryEmbedding; there is no layer type that skips RoPE entirely.

text_config.layer_types = ["full_attention", "sliding_attention", "sliding_attention", "sliding_attenti…
for layer_type in set(self.config.layer_types):
            position_embeddings[layer_type] = self.rotary_emb(hidden_states, position_ids, layer_type)
modeling_step3p7.py · L906–907
Mixture of experts in its code core

Step3p7SparseMoeBlock routes tokens via Step3p7TopKRouter's top-k selection over 288 routed experts with 8 selected per token.

text_config.moe_num_experts = 288text_config.moe_top_k = 8
_, top_k_index = torch.topk(scores_for_choice, self.top_k, dim=-1, sorted=False)
modeling_step3p7.py · L606
Shared expert code only in its codenot stated

Each MoE block includes a Step3p7MLP shared expert with nonzero share_expert_dim (1280) added unconditionally to the routed output.

text_config.share_expert_dim = 1280
self.shared_experts = Step3p7MLP(config, layer_idx, is_shared_expert=True)
modeling_step3p7.py · L620
hidden_states = hidden_states + shared_output
modeling_step3p7.py · L632
Auxiliary-loss-free load balancing (selection bias) code only in its codenot stated

The router adds a learned e_score_correction_bias to routing scores only for the top-k selection (not for the weighting), matching DeepSeek-V3-style bias-based balancing, enabled via use_moe_router_bias.

text_config.use_moe_router_bias = true
scores_for_choice = routing_weights + self.e_score_correction_bias
        _, top_k_index = torch.topk(scores_for_choice, self.top_k, dim=-1, sorted=False)
        top_k_weights = routing_weights.gather(1, top_k_index)
modeling_step3p7.py · L605–607
Multi-token prediction layers in its code optional

num_nextn_predict_layers=3 declares three trailing MTP layers, and the text model filters their weight keys as unexpected on plain load, confirming they are declared/skipped per config.

text_config.num_nextn_predict_layers = 3
if config.num_nextn_predict_layers:
            # Checkpoints append `num_nextn_predict_layers` MTP layers; ignore them as unexpected keys
            # on regular load. Matches loosely on `layers.<N>.` (not anchored to this model's module
modeling_step3p7.py · L843–845
SwiGLU feed-forward code only in its codenot stated

Step3p7MLP and Step3p7Experts compute silu(gate_proj(x)) * up_proj(x) style gating, and hidden_act is normalized to 'silu' in the config post_init.

gate = self.act_fn(self.gate_proj(x)).clamp(max=self.limit)
        up = self.up_proj(x).clamp(min=-self.limit, max=self.limit)
        return self.down_proj(gate * up)
modeling_step3p7.py · L547–549

model architecture 7

token mixer 1

softmax attention 1

channel mixer 1

mixture of experts 1

prediction head 1

multimodal architecture 3

context capacity 1

optimization 4

training precision 2

BF16 used
NVFP4 optional

training parallelism 2

inference & serving 25

decoding strategy 3

reasoning control 2

inference quantization 11

inference scheduling 1

inference kernel 2

agentic scaffolding 6

software implementation 3

inference engine 1

kernel & quantization library 2

unfiled 3

Sources

The curated document list for this model. "not fetched" means the URL is recorded but its text was not read in the current run.