|
45 | 45 | # Placeholder: internal |
46 | 46 |
|
47 | 47 | # pylint: disable=too-many-positional-arguments |
48 | | -from maxtext.layers.multi_token_prediction import calculate_mtp_acceptance_rate, calculate_mtp_loss |
| 48 | +from maxtext.layers.multi_token_prediction import calculate_mtp_acceptance_rate, calculate_mtp_loss, mtp_acceptance, mtp_losses |
49 | 49 | from maxtext.common import checkpointing, profiler |
50 | 50 | from maxtext.common.goodput import ( |
51 | 51 | GoodputEvent, |
@@ -197,6 +197,16 @@ def loss_fn(model, config, data, dropout_rng, params, sparsity_state=None, is_tr |
197 | 197 | intermediates = nnx.pop(model, nnx.Intermediate) |
198 | 198 | intermediate_outputs = intermediates.to_pure_dict() |
199 | 199 |
|
| 200 | + # MTP sows mtp_losses/mtp_acceptance as custom Variable subclasses, not |
| 201 | + # Intermediate, so the nnx.pop above misses them. Pop them here under their |
| 202 | + # collection names so calculate_mtp_loss / calculate_mtp_acceptance_rate |
| 203 | + # find them. Otherwise the MTP loss is silently zeroed. They are also |
| 204 | + # excluded from the returned state below so they don't leak into |
| 205 | + # out_shardings. |
| 206 | + if config.mtp_num_layers > 0: |
| 207 | + intermediate_outputs["mtp_losses"] = nnx.pop(model, mtp_losses).to_pure_dict() |
| 208 | + intermediate_outputs["mtp_acceptance"] = nnx.pop(model, mtp_acceptance).to_pure_dict() |
| 209 | + |
200 | 210 | if config.num_vocab_tiling > 1: |
201 | 211 | hidden_state_key = ("decoder", "hidden_states") |
202 | 212 | hidden_states = maxtext_utils.get_nested_value(intermediate_outputs, hidden_state_key)[0] |
@@ -532,9 +542,10 @@ def move(path, value): |
532 | 542 |
|
533 | 543 | if isinstance(model, nn.Module): |
534 | 544 | return new_state, metrics |
535 | | - # Drop Intermediates (e.g. sowed max_logits for QK-Clip) before returning; |
536 | | - # they're absent from state_mesh_shardings and would cause a leaf-count mismatch. |
537 | | - return nnx.state(new_state, nnx.Not(nnx.Intermediate)), metrics |
| 545 | + # Drop Intermediates (e.g. sowed max_logits for QK-Clip) and the MTP sown |
| 546 | + # vars (mtp_losses/mtp_acceptance) before returning. They're absent from |
| 547 | + # state_mesh_shardings and would cause a leaf-count / structure mismatch. |
| 548 | + return nnx.state(new_state, nnx.Not(nnx.Any(nnx.Intermediate, mtp_losses, mtp_acceptance))), metrics |
538 | 549 |
|
539 | 550 |
|
540 | 551 | def eval_step(model, config, state, data, dropout_rng=None): |
|
0 commit comments