Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
bcf0dfc
feat(kimi_k3): Step 1 - Add Kimi K3 decoder block type, configs, and …
jfacevedo-google Aug 21, 2026
9a4d02f
feat(kimi_k3): Step 2 - Add SituAndMul activation function and unit t…
jfacevedo-google Aug 21, 2026
232f28c
feat(kimi_k3): Step 3 - Add Kimi Decoupled Attention (KDA) layer and …
jfacevedo-google Aug 21, 2026
a26b104
feat(kimi_k3): Step 4 - Add mla_use_output_gate to MLA layer and unit…
jfacevedo-google Aug 21, 2026
769a4af
feat(kimi_k3): Step 5 - Add 896-expert MoE & Latent MoE support and u…
jfacevedo-google Aug 21, 2026
79db3d2
feat(kimi_k3): Step 6 - Assemble KimiLinearModel backbone and add end…
jfacevedo-google Aug 21, 2026
bf801f4
feat(kimi_k3): Add routed_bias: true for noaux_tc quantile balancing …
jfacevedo-google Aug 21, 2026
7cb4f8a
feat(kimi_k3): Add HuggingFace weight conversion, MXFP4 dequantizatio…
jfacevedo-google Aug 21, 2026
55fc3ff
test(kimi_k3): Add 2-layer logit parity test with Orbax restore and f…
jfacevedo-google Aug 21, 2026
b109254
test(kimi_k3): Wire multi-process runner into KimiK3LogitParityTest f…
jfacevedo-google Aug 22, 2026
2b10f89
fix(kimi_k3): Fix KimiDecoderLayer deterministic evaluation & add rig…
jfacevedo-google Aug 22, 2026
25f141a
fix(kimi_k3): Address PR 4967 reviews - add ShortConv1D autoregressiv…
jfacevedo-google Aug 22, 2026
c5aa91d
fix(conversion): Safely resolve model_name from config in to_maxtext …
jfacevedo-google Aug 24, 2026
ce4ee5d
fix(conversion): Add import logging in to_maxtext and map KDA vs MLA …
jfacevedo-google Aug 24, 2026
25e4dca
fix(conversion): Add o_norm-scale to KDA param mapping
jfacevedo-google Aug 24, 2026
1a26699
fix(conversion): Use max_logging.log for index fallback warning
jfacevedo-google Aug 24, 2026
00100c7
test(kimi_k3): Fix layer indexing assertion in kimi_k3_hf_loading_test
jfacevedo-google Aug 24, 2026
efdb877
fix(conversion): Convert output_directory to absolute path for Orbax …
jfacevedo-google Aug 24, 2026
e858978
perf(test): Use jax.eval_shape to eliminate memory allocation and ena…
jfacevedo-google Aug 24, 2026
d433ac1
test(kimi_k3): Update kimi_k3_hf_loading_test with StandardRestore an…
jfacevedo-google Aug 24, 2026
e4b1133
test(kimi_k3): Mark KimiK3HFLoadingTest with pytest.mark.tpu_only to …
jfacevedo-google Aug 24, 2026
8b89d5b
fix(test): Use pure Linen model and get_abstract_param to completely …
jfacevedo-google Aug 24, 2026
a629e96
test(kimi_k3): Use 100% pure Flax NNX with nnx.eval_shape, nnx.split,…
jfacevedo-google Aug 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 34 additions & 8 deletions src/maxtext/checkpoint_conversion/to_maxtext.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,12 @@
import argparse
from functools import partial
import json
import logging
import os
import sys
import threading
import time

from typing import Any, Callable, List, Sequence
import absl
import ml_dtypes
Expand Down Expand Up @@ -474,10 +476,23 @@ def _get_hf_loading_function(hf_source_keys_or_key, tensor_getter, hook_fn, mt_t
if not isinstance(hf_source_keys_or_key, list):
# Case 1: Single hf key (str)
def _loader(getter, key, shape, hook):
if key is None:
return np.zeros(shape, dtype=np.float32)
if isinstance(key, (list, tuple)):
tensors = tuple(getter(k) for k in key)
return apply_hook_fns(tensors, shape, hook)
return apply_hook_fns(getter(key), shape, hook)
try:
tensor = getter(key)
except ValueError as e:
if "not found in HF checkpoint index" in str(e):
max_logging.log(f"Warning: Key {key} not found in HF checkpoint index; falling back to zeros with shape {shape}.")
return np.zeros(shape, dtype=np.float32)
raise e
Comment on lines +486 to +490

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Silently returning zeros when a key is not found in the HF checkpoint index can mask parameter mapping typos or missing weights, leading to silent model corruption. It is highly recommended to log a warning when this fallback occurs.

Suggested change
except ValueError as e:
if "not found in HF checkpoint index" in str(e):
return np.zeros(shape, dtype=np.float32)
raise e
except ValueError as e:
if "not found in HF checkpoint index" in str(e):
max_logging.log(f"Warning: key {key} not found in HF checkpoint index. Initializing with zeros.")
return np.zeros(shape, dtype=np.float32)
raise e



return apply_hook_fns(tensor, shape, hook)



load_fn = partial(
_loader,
Expand Down Expand Up @@ -727,7 +742,7 @@ def convert_lora_to_maxtext_adapter(
max_logging.log("Warning: You want an Instruct version, so we are using the base model architecture instead.")
model_key = model_key.replace("-Instruct", "")
hf_config_obj = HF_MODEL_CONFIGS[model_key]
hf_config_dict = hf_config_obj.to_dict()
hf_config_dict = hf_config_obj.to_dict() if hasattr(hf_config_obj, "to_dict") else hf_config_obj
param_map_mt_to_hf = PARAM_MAPPING[model_key](hf_config_dict, config, config.scan_layers)

mt_adapter_tree = {}
Expand Down Expand Up @@ -868,6 +883,7 @@ def main(
) -> None:
overall_start = time.time()
# Check if the user is using an Instruct version. If so, use the base model architecture
model_name_original = None
for i, arg in enumerate(args):
if arg.startswith("model_name="):
model_name_arg = args[i].split("=")[1]
Expand All @@ -878,23 +894,29 @@ def main(
args[i] = f"model_name={model_name_arg}"
break

# Initialize maxtext config
config = pyconfig.initialize(args)
max_utils.print_system_information()

if model_name_original is None:
model_name_original = config.model_name

# check the supported model ids
if model_name_original not in HF_IDS:
raise ValueError(
f"Unsupported model name: {model_name_original}.\
Supported models are: {list(HF_IDS.keys())}"
f"Unsupported model name: {model_name_original}."
f" Supported models are: {list(HF_IDS.keys())}"
)

model_id = hf_model_path or HF_IDS[model_name_original]

# Initialize maxtext config
config = pyconfig.initialize(args)
max_utils.print_system_information()

if not config.base_output_directory:
output_directory = f"tmp/{config.run_name}"
else:
output_directory = config.base_output_directory
output_directory = os.path.abspath(output_directory)


hf_token = config.hf_access_token

Expand Down Expand Up @@ -1009,16 +1031,20 @@ def _eager_getter(key):
model_key = config.model_name
# load config
hf_config_obj = HF_MODEL_CONFIGS[model_key]
hf_config_dict = hf_config_obj.to_dict()
hf_config_dict = hf_config_obj.to_dict() if hasattr(hf_config_obj, "to_dict") else hf_config_obj
# example of param mapping (gemma2, maxtext:huggingface):
# "params-decoder-layers_{maxtext_layer_idx}-pre_self_attention_norm_global-scale":
# f"model.layers.{global_layer_idx}.input_layernorm.weight",
param_map_mt_to_hf = PARAM_MAPPING[model_key](hf_config_dict, config, config.scan_layers)
# Example of Hook FN mapping, to perform reshape:
# f"params-decoder-layers_{maxtext_layer_idx}-self_attention_global-key-kernel": reshape_kernel,
hook_fn_map_mt = HOOK_FNS[model_key](hf_config_dict, config, config.scan_layers, saving_to_hf=False)
for h in hook_fn_map_mt.values():
if hasattr(h, "set_getter"):
h.set_getter(tensor_getter)
max_logging.log("Parameter mappings and hooks obtained.")


maxtext_abstract_dict, abstract_params_treedef = get_maxtext_model_info(config)

# Weight transformation
Expand Down
23 changes: 23 additions & 0 deletions src/maxtext/checkpoint_conversion/utils/hf_model_configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -1936,4 +1936,27 @@ def __init__(self, **kwargs):
"olmo3-7b": olmo3_7b_config,
"olmo3-7b-pt": olmo3_7b_config,
"olmo3-32b": olmo3_32b_config,
"kimi-k3": {
"model_type": "kimi_k3",
"architectures": ["KimiK3ForConditionalGeneration"],
"text_config": {
"hidden_size": 7168,
"num_hidden_layers": 93,
"num_attention_heads": 64,
"num_key_value_heads": 64,
"vocab_size": 163840,
"n_routed_experts": 896,
"num_experts_per_tok": 16,
"n_shared_experts": 2,
},
"hidden_size": 7168,
"num_hidden_layers": 93,
"num_attention_heads": 64,
"num_key_value_heads": 64,
"vocab_size": 163840,
"n_routed_experts": 896,
"num_experts_per_tok": 16,
"n_shared_experts": 2,
},
}

Loading
Loading