Skip to content

Commit bc9d5aa

Browse files
committed
feat(scan_layers): dynamically set scan_layers from checkpoint metadata
1 parent fd0df72 commit bc9d5aa

16 files changed

Lines changed: 179 additions & 36 deletions

File tree

docs/guides/checkpointing_solutions/convert_checkpoint.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ You can find your converted checkpoint files under `${BASE_OUTPUT_DIRECTORY}/0/i
7878
### Key Parameters
7979

8080
- `model_name`: The specific model identifier. It must match a supported entry in the MaxText [globals.py](https://github.com/AI-Hypercomputer/maxtext/blob/16b684840db9b96b19e24e84ac49f06af7204ae3/src/maxtext/utils/globals.py#L46C1-L46C7).
81-
- `scan_layers`: Controls whether the output uses a scanned (`scan_layers=true`) or unscanned (`scan_layers=false`) checkpoint format. Refer [to the Checkpoints guide](checkpoints) for more information. **IMPORTANT:** This setting *must* match the `scan_layers` value used during model training or loading. A mismatch will cause PyTree loading errors (though MaxText will intercept these and raise a descriptive `ValueError` explaining the mismatch).
81+
- `scan_layers`: Controls whether the output uses a scanned (`scan_layers=true`) or unscanned (`scan_layers=false`) checkpoint format. Refer [to the Checkpoints guide](checkpoints) for more information. **Note:** When resuming or loading a checkpoint in MaxText, this setting will automatically be loaded from the checkpoint metadata, meaning you do not have to manually specify it during model execution. If you do explicitly specify a value for `scan_layers`, it must match the checkpoint's saved configuration, or a `ValueError` mismatch error will be raised.
8282
- `use_multimodal`: Indicates if multimodality is used, important for Gemma3.
8383
- `base_output_directory`: The path where the converted Orbax checkpoint will be stored; it can be Google Cloud Storage (GCS) or local.
8484
- `hardware=cpu`: The conversion script runs on a CPU machine.
@@ -298,9 +298,9 @@ Here is an example [PR to add support for gemma3 multi-modal model](https://gith
298298

299299
- **Error:** `Type ShapeDtypeStruct is not a valid JAX type` or generic **PyTree structure/shape mismatches** (e.g., Orbax reporting `"X/Y paths matched"`, such as `143/145 paths`).
300300

301-
- **Cause: Configuration mismatch** (e.g., `scan_layers`) between the checkpoint conversion script (e.g., `to_maxtext.py` or `to_huggingface.py`) and the trainer/inference runner (e.g., `train.py`).
301+
- **Cause: Configuration mismatch** (e.g., `scan_layers`) between the checkpoint conversion script (e.g., `to_maxtext.py` or `to_huggingface.py`) and the trainer/inference runner (e.g., `train.py`). (Note: Since MaxText automatically loads `scan_layers` from the checkpoint's saved metadata, you should only encounter this error if you explicitly set a mismatching value on the command line, which raises a `ValueError` mismatch error).
302302

303-
- **Solution:** Ensure the `scan_layers` flag is set to the exact same value (`True` or `False`) in both the conversion command and your training/execution command.
303+
- **Solution:** Omit the `scan_layers` parameter from your training or execution command to allow MaxText to automatically resolve it from the checkpoint metadata, or ensure any explicitly specified `scan_layers` parameter matches the format of the loaded checkpoint.
304304

305305
- **Error:** The converted checkpoint loads without errors but produces nonsensical output.
306306

docs/reference/core_concepts/checkpoints.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ In MaxText, the **`scan_layers`** configuration parameter is used to control thi
7474
- `scan_layers=false` tells MaxText to keep layer parameters unstacked (often required for inference and certain model architectures).
7575

7676
> [!IMPORTANT]
77-
> **PyTree Structure Compatibility:** Because JAX expects the loaded PyTree structure to exactly match the model's instantiated structure, the value of the `scan_layers` flag during execution (training, SFT, RL, DPO, or decoding) **must** match the format of the checkpoint being loaded. A mismatch will cause PyTree loading or shape/path mismatch errors (which MaxText will intercept to raise a descriptive `ValueError` pointing to the scan_layers setting).
77+
> **Automatic scan_layers Resolution:** MaxText automatically loads `scan_layers` from the checkpoint's saved metadata when resuming (via `load_parameters_path`) if you do not explicitly specify `scan_layers` on the command-line. If you explicitly specify a value for `scan_layers` that conflicts with the checkpoint format, MaxText will raise a descriptive `ValueError` mismatch error to prevent JAX PyTree structure or shape mismatch errors during loading.
7878
7979
### Takeaways
8080

docs/run_maxtext/run_maxtext_localhost.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ python3 -m maxtext.inference.decode \
7070
**Note:** Because the model hasn't been properly trained, the output text will be random. To generate meaningful output, you need to load a trained checkpoint using the `load_parameters_path` argument. For instructions on how to convert pre-trained Hugging Face model checkpoints (like Llama or Gemma) to MaxText's Orbax format, please refer to the [Checkpoint Conversion Guide](../guides/checkpointing_solutions/convert_checkpoint.md).
7171

7272
> [!NOTE]
73-
> **Checkpoints & `scan_layers` compatibility:** When loading an external or converted checkpoint via `load_parameters_path`, the `scan_layers` setting in your command **must** match the setting used to save the checkpoint. If the checkpoint was saved/converted with `scan_layers=False` (common for Hugging Face conversions and inference runs), you must specify `scan_layers=False` in your command. Otherwise, JAX/Orbax will raise PyTree structure mismatch errors.
73+
> **Checkpoints & `scan_layers` Auto-Resolution:** When resuming or loading an external or converted checkpoint via `load_parameters_path`, MaxText automatically loads `scan_layers` with the checkpoint's saved format (stacked vs unstacked). You do not need to explicitly specify `scan_layers` on your command line when resuming. If you do explicitly specify a `scan_layers` value, it must match the checkpoint's saved configuration, or a `ValueError` mismatch error will be raised.
7474
7575
### Running models using provided configs
7676

docs/tutorials/posttraining/dpo.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,11 @@ export MAXTEXT_CKPT_PATH=<CKPT_PATH> # e.g., gs://my-bucket/my-model-checkpoint/
104104
```
105105

106106
> [!IMPORTANT]
107-
> **Matching the `scan_layers` Parameter:**
108-
> The `scan_layers` setting during your fine-tuning run **must match** the setting used when creating the checkpoint at `MAXTEXT_CKPT_PATH`.
107+
> **Automatic `scan_layers` Resolution:**
108+
> MaxText automatically loads `scan_layers` from the checkpoint's saved metadata when resuming (via `load_parameters_path`) if you do not explicitly specify it on the command-line.
109109
>
110-
> - If the checkpoint was converted or saved with `scan_layers=False` (which is common for Hugging Face conversions and inference-ready models), you **must also provide `scan_layers=False` in the MaxText command.**
111-
> - If `scan_layers` does not match, MaxText will raise a `ValueError`.
110+
> - You do not need to manually supply `scan_layers=False` (or `scan_layers=True`) when loading checkpoints; MaxText will configure this automatically.
111+
> - If you do explicitly provide a `scan_layers` argument, it must match the checkpoint's saved setting or a `ValueError` mismatch error will be raised.
112112
> See the [Checkpoints concept guide](../../reference/core_concepts/checkpoints.md) for more details.
113113
114114
## Running DPO Training

docs/tutorials/posttraining/multimodal.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,11 @@ export MAXTEXT_CKPT_PATH=<CKPT_PATH> # e.g., gs://my-bucket/my-model-checkpoint/
101101
```
102102

103103
> [!IMPORTANT]
104-
> **Matching the `scan_layers` Parameter:**
105-
> The `scan_layers` setting during your fine-tuning run **must match** the setting used when creating the checkpoint at `MAXTEXT_CKPT_PATH`.
104+
> **Automatic `scan_layers` Resolution:**
105+
> MaxText automatically loads `scan_layers` from the checkpoint's saved metadata when resuming (via `load_parameters_path`) if you do not explicitly specify it on the command-line.
106106
>
107-
> - If the checkpoint was converted or saved with `scan_layers=False` (which is common for Hugging Face conversions and inference-ready models), you **must also provide `scan_layers=False` in the MaxText command.**
107+
> - You do not need to manually supply `scan_layers=False` (or `scan_layers=True`) when loading checkpoints; MaxText will configure this automatically.
108+
> - If you do explicitly provide a `scan_layers` argument, it must match the checkpoint's saved setting or a `ValueError` mismatch error will be raised.
108109
109110
## Multimodal Decode
110111

docs/tutorials/posttraining/rl_on_multi_host.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,11 +149,11 @@ export MAXTEXT_CKPT_PATH=<CKPT_PATH> # e.g., gs://my-bucket/my-model-checkpoint/
149149
```
150150

151151
> [!IMPORTANT]
152-
> **Matching the `scan_layers` Parameter:**
153-
> The `scan_layers` setting during your RL training run **must match** the setting used when creating the checkpoint at `MAXTEXT_CKPT_PATH`.
152+
> **Automatic `scan_layers` Resolution:**
153+
> MaxText automatically loads `scan_layers` from the checkpoint's saved metadata when resuming (via `load_parameters_path`) if you do not explicitly specify it on the command-line.
154154
>
155-
> - If the checkpoint was converted or saved with `scan_layers=False` (which is common for Hugging Face conversions and inference-ready models), you **must also provide `scan_layers=False` in the MaxText command.**
156-
> - If `scan_layers` does not match, MaxText will raise a `ValueError`.
155+
> - You do not need to manually supply `scan_layers=False` (or `scan_layers=True`) when loading checkpoints; MaxText will configure this automatically.
156+
> - If you do explicitly provide a `scan_layers` argument, it must match the checkpoint's saved setting or a `ValueError` mismatch error will be raised.
157157
> See the [Checkpoints concept guide](../../reference/core_concepts/checkpoints.md) for more details.
158158
159159
## Submit your RL workload via Pathways

docs/tutorials/posttraining/sft.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,11 @@ export MAXTEXT_CKPT_PATH=<CKPT_PATH> # e.g., gs://my-bucket/my-model-checkpoint/
8989
```
9090

9191
> [!IMPORTANT]
92-
> **Matching the `scan_layers` Parameter:**
93-
> The `scan_layers` setting during your fine-tuning run **must match** the setting used when creating the checkpoint at `MAXTEXT_CKPT_PATH`.
92+
> **Automatic `scan_layers` Resolution:**
93+
> MaxText automatically loads `scan_layers` from the checkpoint's saved metadata when resuming (via `load_parameters_path`) if you do not explicitly specify it on the command-line.
9494
>
95-
> - If the checkpoint was converted or saved with `scan_layers=False` (which is common for Hugging Face conversions and inference-ready models), you **must also provide `scan_layers=False` in the MaxText command.**
96-
> - If `scan_layers` does not match, MaxText will raise a `ValueError`.
95+
> - You do not need to manually supply `scan_layers=False` (or `scan_layers=True`) when loading checkpoints; MaxText will configure this automatically.
96+
> - If you do explicitly provide a `scan_layers` argument, it must match the checkpoint's saved setting or a `ValueError` mismatch error will be raised.
9797
> See the [Checkpoints concept guide](../../reference/core_concepts/checkpoints.md) for more details.
9898
9999
## Run SFT on Hugging Face Dataset

docs/tutorials/posttraining/sft_on_multi_host.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,11 @@ export MAXTEXT_CKPT_PATH=<CKPT_PATH> # gs://my-bucket/my-checkpoint-directory/0/
140140
```
141141

142142
> [!IMPORTANT]
143-
> **Matching the `scan_layers` Parameter:**
144-
> The `scan_layers` setting during your fine-tuning run **must match** the setting used when creating the checkpoint at `MAXTEXT_CKPT_PATH`.
143+
> **Automatic `scan_layers` Resolution:**
144+
> MaxText automatically loads `scan_layers` from the checkpoint's saved metadata when resuming (via `load_parameters_path`) if you do not explicitly specify it on the command-line.
145145
>
146-
> - If the checkpoint was converted or saved with `scan_layers=False` (which is common for Hugging Face conversions and inference-ready models), you **must also provide `scan_layers=False` in the MaxText command.**
147-
> - If `scan_layers` does not match, MaxText will raise a `ValueError`.
146+
> - You do not need to manually supply `scan_layers=False` (or `scan_layers=True`) when loading checkpoints; MaxText will configure this automatically.
147+
> - If you do explicitly provide a `scan_layers` argument, it must match the checkpoint's saved setting or a `ValueError` mismatch error will be raised.
148148
> See the [Checkpoints concept guide](../../reference/core_concepts/checkpoints.md) for more details.
149149
150150
## Submit workload on GKE cluster

src/maxtext/checkpoint_conversion/to_huggingface.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@
9898
from maxtext.utils import max_utils
9999
from maxtext.utils.globals import HF_IDS
100100
from maxtext.utils.lora_utils import sync_lora_metadata
101+
from maxtext.utils.model_creation_utils import verify_and_sync_scan_layers
101102

102103

103104
flags.DEFINE_bool(
@@ -443,6 +444,14 @@ def main(argv: Sequence[str]) -> None:
443444
assert (
444445
config.load_full_state_path == ""
445446
), "This script expects parameters, not a full state. Use generate_param_only_checkpoint first if needed."
447+
448+
if not config.load_parameters_path and config.lora.lora_restore_path:
449+
# Standalone LoRA conversion uses lora_restore_path for metadata
450+
temp_config = config.model_copy(update={"load_parameters_path": config.lora.lora_restore_path})
451+
temp_config = verify_and_sync_scan_layers(temp_config)
452+
config = config.model_copy(update={"scan_layers": temp_config.scan_layers})
453+
else:
454+
config = verify_and_sync_scan_layers(config)
446455
max_utils.print_system_information()
447456
overall_start = time.time()
448457

src/maxtext/checkpoint_conversion/to_maxtext.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,6 +1070,7 @@ def _eager_getter(key):
10701070
simulated_cpu_devices_count,
10711071
config.checkpoint_storage_use_ocdbt,
10721072
config.checkpoint_storage_use_zarr3,
1073+
config=config,
10731074
)
10741075

10751076
print_ram_usage("Program Ends")

0 commit comments

Comments
 (0)