Skip to content

Commit ed08a80

Browse files
committed
Add pure-nnx configuration to standalone checkpoint conversion scripts
1 parent 0faa9be commit ed08a80

2 files changed

Lines changed: 45 additions & 20 deletions

File tree

src/maxtext/checkpoint_conversion/standalone_scripts/convert_gpt_oss_ckpt.py

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353

5454

5555
def _convert_huggingface_to_jax_weights(
56-
base_model_path: str, model_size: str, model_params: dict, mem_info: psutil.Process
56+
base_model_path: str, model_size: str, model_params: dict, mem_info: psutil.Process, pure_nnx: bool = True
5757
):
5858
"""Convert a Huggingface Checkpoint to a dictionary of Numpy arrays representing the weights.
5959
@@ -62,6 +62,7 @@ def _convert_huggingface_to_jax_weights(
6262
model_size (str): Size of the base model.
6363
model_params (dict): Dictionary containing model parameters.
6464
mem_info (psutil.Process): Process object to track memory usage.
65+
pure_nnx (bool): Whether to format weights for pure NNX.
6566
6667
Returns:
6768
jax_weights (dict): Dictionary containing the converted weights.
@@ -96,12 +97,14 @@ def _convert_huggingface_to_jax_weights(
9697
"decoder": {
9798
"decoder_norm": {"scale": None},
9899
"logits_dense": {"kernel": None},
99-
"layers": {},
100100
},
101101
}
102+
if pure_nnx:
103+
jax_weights["decoder"]["layers"] = {}
104+
102105
# block 0, 1
103106
for block_idx in range(layer_cycle_interval):
104-
jax_weights["decoder"]["layers"][f"layers_{block_idx}"] = {
107+
layer_dict = {
105108
"pre_self_attention_layer_norm": {"scale": None},
106109
"post_self_attention_layer_norm": {"scale": None},
107110
"GptOssAttention": {
@@ -121,6 +124,13 @@ def _convert_huggingface_to_jax_weights(
121124
"wo_bias": None,
122125
},
123126
}
127+
if pure_nnx:
128+
jax_weights["decoder"]["layers"][block_idx] = layer_dict
129+
else:
130+
jax_weights["decoder"][f"layers_{block_idx}"] = layer_dict
131+
132+
def get_layer(b_idx):
133+
return jax_weights["decoder"]["layers"][b_idx] if pure_nnx else jax_weights["decoder"][f"layers_{b_idx}"]
124134

125135
# decoder norm scale ###########################################
126136
max_logging.log("Processing decoder norm scale")
@@ -147,7 +157,7 @@ def _convert_huggingface_to_jax_weights(
147157
for layer_idx in MemoryMonitorTqdm(range(base_num_decoder_layers), desc="layers", leave=True):
148158
block_layer_idx, block_idx = divmod(layer_idx, layer_cycle_interval)
149159
stack_shape = (base_num_decoder_layers // layer_cycle_interval,)
150-
self_attention = jax_weights["decoder"]["layers"][f"layers_{block_idx}"]["GptOssAttention"]
160+
self_attention = get_layer(block_idx)["GptOssAttention"]
151161

152162
wq = _pt_to_np(chkpt_vars[f"layers.{layer_idx}.attention.wq.weight"], cast_dtype=CAST_DTYPE)
153163
wk = _pt_to_np(chkpt_vars[f"layers.{layer_idx}.attention.wk.weight"], cast_dtype=CAST_DTYPE)
@@ -200,7 +210,7 @@ def _convert_huggingface_to_jax_weights(
200210
self_attention["sinks"][block_layer_idx, ...] = sinks
201211

202212
for block_idx in range(layer_cycle_interval):
203-
self_attention = jax_weights["decoder"]["layers"][f"layers_{block_idx}"]["GptOssAttention"]
213+
self_attention = get_layer(block_idx)["GptOssAttention"]
204214
self_attention["query"]["kernel"] = self_attention["query"]["kernel"].transpose(1, 0, 2, 3)
205215
self_attention["key"]["kernel"] = self_attention["key"]["kernel"].transpose(1, 0, 2, 3)
206216
self_attention["value"]["kernel"] = self_attention["value"]["kernel"].transpose(1, 0, 2, 3)
@@ -218,7 +228,7 @@ def _convert_huggingface_to_jax_weights(
218228
for layer_idx in MemoryMonitorTqdm(range(base_num_decoder_layers), desc="layers", leave=True):
219229
block_layer_idx, block_idx = divmod(layer_idx, layer_cycle_interval)
220230
stack_shape = (base_num_decoder_layers // layer_cycle_interval,)
221-
layer_weight = jax_weights["decoder"]["layers"][f"layers_{block_idx}"]
231+
layer_weight = get_layer(block_idx)
222232

223233
pre_self_attention_layernorm = _pt_to_np(
224234
chkpt_vars[f"layers.{layer_idx}.attention_norm.weight"], cast_dtype=CAST_DTYPE
@@ -237,7 +247,7 @@ def _convert_huggingface_to_jax_weights(
237247
layer_weight["post_self_attention_layer_norm"]["scale"][block_layer_idx, ...] = post_self_attention_layernorm # pylint: disable=E1137
238248

239249
for block_idx in range(layer_cycle_interval):
240-
layer_weight = jax_weights["decoder"]["layers"][f"layers_{block_idx}"]
250+
layer_weight = get_layer(block_idx)
241251
layer_weight["pre_self_attention_layer_norm"]["scale"] = layer_weight["pre_self_attention_layer_norm"][
242252
"scale"
243253
].transpose(1, 0)
@@ -253,7 +263,7 @@ def _convert_huggingface_to_jax_weights(
253263
for layer_idx in MemoryMonitorTqdm(range(base_num_decoder_layers), desc="layers", leave=True):
254264
block_layer_idx, block_idx = divmod(layer_idx, layer_cycle_interval)
255265
stack_shape = (base_num_decoder_layers // layer_cycle_interval,)
256-
mlp_weight = jax_weights["decoder"]["layers"][f"layers_{block_idx}"]["GptOssMlp"]
266+
mlp_weight = get_layer(block_idx)["GptOssMlp"]
257267

258268
gate = _pt_to_np(chkpt_vars[f"layers.{layer_idx}.feed_forward.gate.weight"], cast_dtype=CAST_DTYPE)
259269
gate_bias = _pt_to_np(chkpt_vars[f"layers.{layer_idx}.feed_forward.gate.bias"], cast_dtype=CAST_DTYPE)
@@ -296,7 +306,7 @@ def _convert_huggingface_to_jax_weights(
296306
gc.collect()
297307

298308
for block_idx in range(layer_cycle_interval):
299-
mlp_weight = jax_weights["decoder"]["layers"][f"layers_{block_idx}"]["GptOssMlp"]
309+
mlp_weight = get_layer(block_idx)["GptOssMlp"]
300310
mlp_weight["gate"]["kernel"] = mlp_weight["gate"]["kernel"].transpose(1, 0, 2)
301311
mlp_weight["wi_0"] = mlp_weight["wi_0"].transpose(1, 0, 2, 3)
302312
mlp_weight["wi_1"] = mlp_weight["wi_1"].transpose(1, 0, 2, 3)
@@ -312,20 +322,21 @@ def _convert_huggingface_to_jax_weights(
312322
return jax_weights
313323

314324

315-
def convert_to_jax_weights(base_model_path: str, model_size: str):
325+
def convert_to_jax_weights(base_model_path: str, model_size: str, pure_nnx: bool = True):
316326
"""
317327
Function to convert the checkpoint at base_model_path into Orbax checkpoint
318328
for MaxText and output jax_weights ready for MaxText
319329
320330
Args:
321331
base_model_path: checkpoint path
322332
model_size: gpt-oss-20b, gpt-oss-120b
333+
pure_nnx: whether to format weights for pure NNX
323334
"""
324335
model_params = MODEL_PARAMS_DICT[model_size]
325336
mem_info = psutil.Process()
326337
logging.debug("Memory usage: %f GB", mem_info.memory_info().rss / (1024**3))
327338
max_logging.log(f"Loading the base model from {base_model_path}")
328-
return _convert_huggingface_to_jax_weights(base_model_path, model_size, model_params, mem_info)
339+
return _convert_huggingface_to_jax_weights(base_model_path, model_size, model_params, mem_info, pure_nnx)
329340

330341

331342
if __name__ == "__main__":
@@ -336,6 +347,7 @@ def convert_to_jax_weights(base_model_path: str, model_size: str):
336347
parser.add_argument("--simulated-cpu-devices-count", type=int, required=False, default=16)
337348
parser.add_argument("--use-ocdbt", type=str2bool, required=False, default=True)
338349
parser.add_argument("--use-zarr3", type=str2bool, required=False, default=True)
350+
parser.add_argument("--pure-nnx", type=str2bool, required=False, default=False)
339351
args = parser.parse_args()
340352

341353
overall_start = time.time()
@@ -348,7 +360,7 @@ def convert_to_jax_weights(base_model_path: str, model_size: str):
348360

349361
# transform
350362
start = time.time()
351-
weights = convert_to_jax_weights(args.base_model_path, args.model_size)
363+
weights = convert_to_jax_weights(args.base_model_path, args.model_size, args.pure_nnx)
352364
max_logging.log(f"Elapse for transform: {(time.time() - start) / 60:.2f} min")
353365

354366
# save

src/maxtext/checkpoint_conversion/standalone_scripts/convert_gpt_oss_unscanned_ckpt.py

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ def _hf_to_maxtext_mapping(layer_idx: int = -1) -> dict:
120120

121121

122122
def _convert_huggingface_to_jax_weights(
123-
base_model_path: str, model_size: str, model_params: dict, mem_info: psutil.Process
123+
base_model_path: str, model_size: str, model_params: dict, mem_info: psutil.Process, pure_nnx: bool = True
124124
):
125125
"""Convert a Huggingface Checkpoint to a dictionary of Numpy arrays representing the weights.
126126
@@ -129,6 +129,7 @@ def _convert_huggingface_to_jax_weights(
129129
model_size (str): Size of the base model.
130130
model_params (dict): Dictionary containing model parameters.
131131
mem_info (psutil.Process): Process object to track memory usage.
132+
pure_nnx (bool): Whether to format weights for pure NNX.
132133
133134
Returns:
134135
jax_weights (dict): Dictionary containing the converted weights.
@@ -164,8 +165,11 @@ def _convert_huggingface_to_jax_weights(
164165
"logits_dense": {"kernel": None},
165166
},
166167
}
168+
if pure_nnx:
169+
jax_weights["decoder"]["layers"] = {}
170+
167171
for layer_idx in range(base_num_decoder_layers):
168-
jax_weights["decoder"][f"layers_{layer_idx}"] = {
172+
layer_dict = {
169173
"pre_self_attention_layer_norm": {"scale": None},
170174
"post_self_attention_layer_norm": {"scale": None},
171175
"GptOssAttention": {
@@ -185,6 +189,13 @@ def _convert_huggingface_to_jax_weights(
185189
"wo_bias": None,
186190
},
187191
}
192+
if pure_nnx:
193+
jax_weights["decoder"]["layers"][layer_idx] = layer_dict
194+
else:
195+
jax_weights["decoder"][f"layers_{layer_idx}"] = layer_dict
196+
197+
def get_layer(l_idx):
198+
return jax_weights["decoder"]["layers"][l_idx] if pure_nnx else jax_weights["decoder"][f"layers_{l_idx}"]
188199

189200
# decoder norm scale ###########################################
190201
max_logging.log("Processing decoder norm scale")
@@ -209,7 +220,7 @@ def _convert_huggingface_to_jax_weights(
209220
# self attention ###############################################
210221
max_logging.log("Processing self attention")
211222
for layer_idx in tqdm(range(base_num_decoder_layers), desc="layers", leave=False):
212-
self_attention = jax_weights["decoder"][f"layers_{layer_idx}"]["GptOssAttention"]
223+
self_attention = get_layer(layer_idx)["GptOssAttention"]
213224

214225
wq = _pt_to_np(chkpt_vars[f"layers.{layer_idx}.attention.wq.weight"], cast_dtype=CAST_DTYPE)
215226
wk = _pt_to_np(chkpt_vars[f"layers.{layer_idx}.attention.wk.weight"], cast_dtype=CAST_DTYPE)
@@ -247,7 +258,7 @@ def _convert_huggingface_to_jax_weights(
247258
# layer weight pre and post self attention norm ################
248259
max_logging.log("Processing pre and post self attention norms")
249260
for layer_idx in tqdm(range(base_num_decoder_layers), desc="layers", leave=False):
250-
layer_weight = jax_weights["decoder"][f"layers_{layer_idx}"]
261+
layer_weight = get_layer(layer_idx)
251262
pre_self_attention_layernorm = _pt_to_np(
252263
chkpt_vars[f"layers.{layer_idx}.attention_norm.weight"], cast_dtype=CAST_DTYPE
253264
)
@@ -262,7 +273,7 @@ def _convert_huggingface_to_jax_weights(
262273
max_logging.log("Processing layer weights")
263274

264275
for layer_idx in tqdm(range(base_num_decoder_layers), desc="layers", leave=False):
265-
mlp_weight = jax_weights["decoder"][f"layers_{layer_idx}"]["GptOssMlp"]
276+
mlp_weight = get_layer(layer_idx)["GptOssMlp"]
266277

267278
gate = _pt_to_np(chkpt_vars[f"layers.{layer_idx}.feed_forward.gate.weight"], cast_dtype=CAST_DTYPE)
268279
gate_bias = _pt_to_np(chkpt_vars[f"layers.{layer_idx}.feed_forward.gate.bias"], cast_dtype=CAST_DTYPE)
@@ -299,20 +310,21 @@ def _convert_huggingface_to_jax_weights(
299310
return jax_weights
300311

301312

302-
def convert_to_jax_weights(base_model_path: str, model_size: str):
313+
def convert_to_jax_weights(base_model_path: str, model_size: str, pure_nnx: bool = True):
303314
"""
304315
Function to convert the checkpoint at base_model_path into Orbax checkpoint
305316
for MaxText and output jax_weights ready for MaxText
306317
307318
Args:
308319
base_model_path: checkpoint path
309320
model_size: gpt-oss-20b, gpt-oss-120b
321+
pure_nnx: whether to format weights for pure NNX
310322
"""
311323
model_params = MODEL_PARAMS_DICT[model_size]
312324
mem_info = psutil.Process()
313325
logging.debug("Memory usage: %f GB", mem_info.memory_info().rss / (1024**3))
314326
max_logging.log(f"Loading the base model from {base_model_path}")
315-
return _convert_huggingface_to_jax_weights(base_model_path, model_size, model_params, mem_info)
327+
return _convert_huggingface_to_jax_weights(base_model_path, model_size, model_params, mem_info, pure_nnx)
316328

317329

318330
if __name__ == "__main__":
@@ -323,6 +335,7 @@ def convert_to_jax_weights(base_model_path: str, model_size: str):
323335
parser.add_argument("--simulated-cpu-devices-count", type=int, required=False, default=16)
324336
parser.add_argument("--use-ocdbt", type=str2bool, required=False, default=True)
325337
parser.add_argument("--use-zarr3", type=str2bool, required=False, default=True)
338+
parser.add_argument("--pure-nnx", type=str2bool, required=False, default=False)
326339
args = parser.parse_args()
327340

328341
if args.model_size not in MODEL_PARAMS_DICT:
@@ -333,7 +346,7 @@ def convert_to_jax_weights(base_model_path: str, model_size: str):
333346

334347
save_weights_to_checkpoint(
335348
args.maxtext_model_path,
336-
convert_to_jax_weights(args.base_model_path, args.model_size),
349+
convert_to_jax_weights(args.base_model_path, args.model_size, args.pure_nnx),
337350
args.simulated_cpu_devices_count,
338351
args.use_ocdbt,
339352
args.use_zarr3,

0 commit comments

Comments
 (0)