Skip to content

Commit 89807be

Browse files
committed
Add DSv32
1 parent 635cad2 commit 89807be

7 files changed

Lines changed: 669 additions & 8 deletions

File tree

torchtitan/models/deepseek_v3/__init__.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ def _make_dsv3_attn_config(
157157
)
158158

159159

160-
def _build_dsv3_layers(
160+
def _build_dsv3_layers_impl(
161161
*,
162162
n_layers: int,
163163
n_dense_layers: int,
@@ -183,18 +183,17 @@ def _build_dsv3_layers(
183183
moe_comm_backend: str,
184184
non_blocking_capacity_factor: float | None,
185185
rope: RoPE.Config,
186+
attn_fn,
187+
**attn_fn_kwargs,
186188
) -> list[TransformerBlock.Config]:
187-
"""Build the list of per-layer TransformerBlock configs.
189+
"""Generic per-layer TransformerBlock config builder.
188190
189-
Layers with layer_id < n_dense_layers get a dense FeedForward and no MoE.
190-
Layers with layer_id >= n_dense_layers get a MoE and no FeedForward.
191-
192-
Router and expert inits are constructed per-layer so depth-scaled
193-
initializers are correct for each layer's position.
191+
``attn_fn(layer_id=layer_id, dim=dim, n_heads=n_heads, q_lora_rank=..., ...,
192+
rope=rope, **attn_fn_kwargs)`` produces the attention config.
194193
"""
195194
layers = []
196195
for layer_id in range(n_layers):
197-
attn_cfg = _make_dsv3_attn_config(
196+
attn_cfg = attn_fn(
198197
layer_id=layer_id,
199198
dim=dim,
200199
n_heads=n_heads,
@@ -206,6 +205,7 @@ def _build_dsv3_layers(
206205
mscale=mscale,
207206
attn_backend=attn_backend,
208207
rope=rope,
208+
**attn_fn_kwargs,
209209
)
210210

211211
if layer_id < n_dense_layers:
@@ -262,6 +262,14 @@ def _build_dsv3_layers(
262262
return layers
263263

264264

265+
def _build_dsv3_layers(**kwargs):
266+
"""V3-specific thin wrapper around ``_build_dsv3_layers_impl``."""
267+
return _build_dsv3_layers_impl(
268+
attn_fn=_make_dsv3_attn_config,
269+
**kwargs,
270+
)
271+
272+
265273
def _debugmodel(
266274
attn_backend: str,
267275
moe_comm_backend: str,
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
# Copyright (c) Meta Platforms, Inc. and affiliates.
2+
# All rights reserved.
3+
#
4+
# This source code is licensed under the BSD-style license found in the
5+
# LICENSE file in the root directory of this source tree.
6+
7+
import dataclasses
8+
from functools import partial
9+
10+
import torch.nn as nn
11+
12+
from torchtitan.components.optimizer import register_moe_load_balancing_hook
13+
from torchtitan.distributed.pipeline_parallel import pipeline_llm
14+
from torchtitan.models.common import (
15+
ComplexRoPE,
16+
CosSinRoPE,
17+
LayerNorm,
18+
Linear,
19+
RMSNorm,
20+
RoPE,
21+
)
22+
from torchtitan.protocols.model_spec import ModelSpec
23+
24+
from torchtitan.models.deepseek_v3.__init__ import (
25+
_build_dsv3_layers_impl,
26+
_EMBEDDING_INIT,
27+
_LINEAR_INIT,
28+
_NORM_INIT,
29+
_output_linear_init,
30+
_make_dsv3_attn_config,
31+
)
32+
33+
from .model import (
34+
Attention,
35+
DeepSeekV32Model,
36+
DSAFlexAttention,
37+
Indexer,
38+
)
39+
from .parallelize import parallelize_deepseekv32
40+
from .state_dict_adapter import DeepSeekV32StateDictAdapter
41+
42+
__all__ = ["parallelize_deepseekv32", "DeepSeekV32Model", "deepseekv32_configs"]
43+
44+
45+
def _make_indexer_rope_config(rope_head_dim: int, rope: RoPE.Config) -> RoPE.Config:
46+
# The reference applies rope to the indexer with interleaved=False
47+
# (rotate-half) using the SAME yarn-scaled freqs as the main MLA rope.
48+
# CosSinRoPE now shares the unified _yarn_inv_freq with ComplexRoPE, so
49+
# scaling="yarn" always produces the correct freqs (self-gated on
50+
# max_seq_len > original_seq_len).
51+
return CosSinRoPE.Config(
52+
dim=rope_head_dim, max_seq_len=rope.max_seq_len, theta=rope.theta,
53+
scaling="yarn", rope_factor=rope.rope_factor,
54+
beta_fast=rope.beta_fast, beta_slow=rope.beta_slow,
55+
original_seq_len=rope.original_seq_len,
56+
)
57+
58+
59+
def _make_dsv32_attn_config(
60+
layer_id: int, *, index_n_heads: int, index_head_dim: int, index_topk: int,
61+
**kwargs,
62+
) -> Attention.Config:
63+
"""V3 MLA + Indexer + DSAFlexAttention inner."""
64+
c = _make_dsv3_attn_config(layer_id=layer_id, **kwargs)
65+
indexer_cfg = Indexer.Config(
66+
dim=c.dim, q_lora_rank=c.q_lora_rank,
67+
index_n_heads=index_n_heads, index_head_dim=index_head_dim,
68+
rope_head_dim=c.qk_rope_head_dim, index_topk=index_topk,
69+
wq_b=Linear.Config(
70+
in_features=c.q_lora_rank,
71+
out_features=index_n_heads * index_head_dim,
72+
param_init=_LINEAR_INIT,
73+
),
74+
wk=Linear.Config(
75+
in_features=c.dim, out_features=index_head_dim,
76+
param_init=_LINEAR_INIT,
77+
),
78+
k_norm=LayerNorm.Config(normalized_shape=index_head_dim),
79+
weights_proj=Linear.Config(
80+
in_features=c.dim, out_features=index_n_heads,
81+
param_init={"weight": partial(nn.init.normal_, std=1.0)},
82+
),
83+
rope=_make_indexer_rope_config(c.qk_rope_head_dim, c.rope),
84+
)
85+
return Attention.Config(
86+
dim=c.dim, n_heads=c.n_heads,
87+
q_lora_rank=c.q_lora_rank, kv_lora_rank=c.kv_lora_rank,
88+
qk_nope_head_dim=c.qk_nope_head_dim, qk_rope_head_dim=c.qk_rope_head_dim,
89+
v_head_dim=c.v_head_dim, mscale=c.mscale,
90+
wq=c.wq, wq_a=c.wq_a, wq_b=c.wq_b, q_norm=c.q_norm,
91+
wkv_a=c.wkv_a, kv_norm=c.kv_norm, wkv_b=c.wkv_b, wo=c.wo,
92+
inner_attention=DSAFlexAttention.Config(index_topk=index_topk),
93+
rope=dataclasses.replace(c.rope),
94+
indexer=indexer_cfg,
95+
)
96+
97+
98+
def _build_dsv32_layers(**kwargs):
99+
"""V32-specific thin wrapper around ``_build_dsv3_layers_impl``."""
100+
return _build_dsv3_layers_impl(
101+
attn_fn=_make_dsv32_attn_config,
102+
**kwargs,
103+
)
104+
105+
106+
# ---------------------------------------------------------------------------
107+
# Model flavors
108+
# ---------------------------------------------------------------------------
109+
110+
def _debugmodel(
111+
attn_backend: str, moe_comm_backend: str,
112+
non_blocking_capacity_factor: float | None = None,
113+
) -> DeepSeekV32Model.Config:
114+
dim = 256
115+
layers = _build_dsv32_layers(
116+
n_layers=6, n_dense_layers=1, dim=dim, n_heads=16,
117+
q_lora_rank=64, kv_lora_rank=128, qk_nope_head_dim=32,
118+
qk_rope_head_dim=16, v_head_dim=32, mscale=0.70,
119+
dense_hidden_dim=512, moe_hidden_dim=128, num_experts=8,
120+
num_shared_experts=2, router_top_k=3, router_score_func="softmax",
121+
attn_backend=attn_backend, moe_comm_backend=moe_comm_backend,
122+
non_blocking_capacity_factor=non_blocking_capacity_factor,
123+
rope=ComplexRoPE.Config(dim=16, max_seq_len=16384, theta=10000.0,
124+
scaling="yarn", rope_factor=40.0,
125+
beta_fast=32.0, beta_slow=1.0, original_seq_len=4096),
126+
index_n_heads=4, index_head_dim=32, index_topk=16,
127+
)
128+
from torchtitan.models.common import Embedding
129+
return DeepSeekV32Model.Config(
130+
vocab_size=2048, dim=dim,
131+
tok_embeddings=Embedding.Config(num_embeddings=2048, embedding_dim=dim,
132+
param_init=_EMBEDDING_INIT),
133+
norm=RMSNorm.Config(normalized_shape=dim, param_init=_NORM_INIT),
134+
lm_head=Linear.Config(in_features=dim, out_features=2048,
135+
param_init=_output_linear_init(dim)),
136+
layers=layers,
137+
)
138+
139+
140+
deepseekv32_configs = {
141+
"debugmodel": _debugmodel,
142+
}
143+
144+
145+
def model_registry(
146+
flavor: str, attn_backend: str = "flex",
147+
moe_comm_backend: str = "standard",
148+
non_blocking_capacity_factor: float | None = None,
149+
) -> ModelSpec:
150+
config = deepseekv32_configs[flavor](
151+
attn_backend=attn_backend, moe_comm_backend=moe_comm_backend,
152+
non_blocking_capacity_factor=non_blocking_capacity_factor,
153+
)
154+
return ModelSpec(
155+
name="deepseek_v3_2", flavor=flavor, model=config,
156+
parallelize_fn=parallelize_deepseekv32, pipelining_fn=pipeline_llm,
157+
post_optimizer_build_fn=register_moe_load_balancing_hook,
158+
state_dict_adapter=DeepSeekV32StateDictAdapter,
159+
)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Copyright (c) Meta Platforms, Inc. and affiliates.
2+
# All rights reserved.
3+
#
4+
# This source code is licensed under the BSD-style license found in the
5+
# LICENSE file in the root directory of this source tree.
6+
7+
from torchtitan.config import ParallelismConfig
8+
from torchtitan.models.deepseek_v3.config_registry import deepseek_v3_debugmodel
9+
10+
from . import model_registry
11+
12+
13+
def deepseek_v3_2_debugmodel_full_dtensor():
14+
config = deepseek_v3_debugmodel()
15+
config.model_spec = model_registry("debugmodel")
16+
config.parallelism = ParallelismConfig(
17+
tensor_parallel_degree=2,
18+
spmd_backend="full_dtensor",
19+
enable_sequence_parallel=True,
20+
)
21+
return config

0 commit comments

Comments
 (0)