Repository navigation
Conversation
Change map
|
There was a problem hiding this comment.
🧹 Nitpick comments: 1
packages/kumo-engine/test/test_holdout_df.py: 1
112-125: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winCover explanation processing with
refit_trainval.The production path runs
best_trainer.explain(...)before_published_holdout(...). The matrix does not combineexplain=Truewithrefit_trainval=True, so a regression in mode restoration or holdout selection for this path can pass. Add both reachablerefit_trainvalexplanation cases at this matrix site.Suggested fix
@pytest.mark.parametrize('refit_trainval,refit_full,explain,model', [ (False, False, False, 'fit'), (True, True, False, 'refit_trainval'), + (True, False, True, 'refit_trainval'), + (True, True, True, 'refit_trainval'), (False, True, True, 'fit'), ])
ℹ️ Review info
⚙️ Run configuration
- Configuration used: Repository: NVIDIA/kumo-engine/.coderabbit.yaml
- Review profile: QUIET
- Plan: Enterprise
- Run ID:
b9ce2f06-0cec-4ff9-9845-51a2fb62bc8d
📒 Files selected for processing: 1
packages/kumo-engine/kumo/engine/trainer/trainer.py
Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 5 remain after this review.
0c37212 to
5cebd6f
Compare
5cebd6f to
39f2531
Compare
5cebd6f to
2108fae
Compare
2108fae to
c36dfd8
Compare
ce86b46 to
893be81
Compare
893be81 to
f8c6502
Compare
fit() read test_df.parquet from best_trainer.log_dir, which is whichever refit stage ran last, not necessarily the model the bundle publishes. With refit_full the published model has seen the test split, so its holdout is meaningless. Read the holdout from the published model's log dir (Trainer.published_fit_mode, also used to pick the prediction model) and return none for refit_full. get_log_dir takes an optional fit_mode override. Verified: test_holdout_df (fit / refit_trainval with explain / refit_full), test_training_explanations, test_semantic_carry_forward: 35 passed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
test_artifacts.py's fake trainer borrows Trainer methods; select_fit_mode now calls published_fit_mode, so the fake needs it too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
f8c6502 to
86fa3c6
Compare
Victsm
left a comment
There was a problem hiding this comment.
Re-reviewed 86fa3c6. The bot’s requested train/validation-refit + explanations regression is now covered. Holdout selection uses the same published-model priority as prediction, without changing the trainer’s active mode; a full-data refit correctly reports no holdout. No remaining correctness blocker found.
The extra full-refit + explanations matrix case suggested by the bot remains optional coverage; it does not block this change.
GitHub merge gates remain separate: the PR change-table validation is red, and the config/connector test failure is from two missing BigQuery permission-test identities.
Local validation of the exact Python head: all 11 holdout tests passed, including real fit/refit and explanation runs, alongside 36 passing semantic-carry-forward/explanation tests. Used an isolated compatible DiskGraph binary; initial native-version/PATH setup failures are retained in the local logs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The refit_full case now also explains, as in the upper PRs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Series: kumo-engine MLOps series: every snapshot, training table, model and prediction run carries a self-contained _provenance.json;
with kumo.mlops(...)stores each artifact under one artifact root, tracks fits and prediction runs in MLflow or Snowflake and registers models; volumes and stages can hold files; prediction runs are monitored for drift and realized performance.Stack: #53 → #112 → #50 → #60 → #64; #114 on #112; #115 on #64
Merge order: one linear stack; merge bottom to top (#53 first); #114 sits on #112 and merges any time after it; #115 sits on #64 and merges after it
Summary
This PR makes
TrainingResult.holdout_paththe holdout of the model that was published, orNonewhen that model has no holdout. The answer no longer depends on whether explanations are on.The holdout is the test-split predictions
fit()writes totest_df.parquet.holdout_pathpoints at that file andholdout_df()reads it. Teams use it to check the calibration and score distribution of the model they are about to ship.One fit can train up to three models from the best trial, and the bundle ships the one trained on the most data:
fitrefit_trainval(training_job.refit_trainval)refit_full(training_job.refit_full)Usage
With
refit_fullon,holdout_pathisNone,holdout_df()raisesFileNotFoundError, and the log says:The published model is refit on the full data, including the test split, so it has no holdout predictions.Production questions answered
refit_fullmodel? It trained on the test split; the log says so.How it works
fit()asks kumo-core which fit mode the bundle publishes (Trainer.published_fit_mode():refit_full, elserefit_trainval, elsefit) and readstest_df.parquetonly from that model's run directory. Forrefit_fullit returnsNone. Prediction and the holdout lookup share this one definition of the published model.Run directory of a CPU fit on a small synthetic graph (
users,items,orders) with both refits on; the best trial isversion_1:Which file
holdout_pathreturns, before and after:version_N/version_N/version_N_refit_trainval/version_N_refit_trainval/NoneNoneversion_N/(not the shipped model)NoneNoneNoneversion_N_refit_trainval/(not the shipped model)NoneBefore, the lookup followed whichever fit mode the trainer object was last left in, and
explain()changed that mode as a side effect. kumo-core gainsTrainer.published_fit_mode()and an optionalfit_modeargument onTrainer.get_log_dir, so the lookup reads another mode's directory without changing the trainer or creating empty directories.Back-compat
Only the choice of file changes. No fields, checks or errors are added, and the run directory layout is unchanged.
refit_trainvalonlyholdout_pathas before, explanations on or off.refit_full, explanations offNone, as before.refit_full, explanations onNone. It used to return an earlier model's holdout without saying so.None, as before.Trainer.load()None, as before.Testing
test_holdout_df.py: real CPU fits with no refit (file underversion_N/),refit_trainvalwith explanations on (underversion_N_refit_trainval/), and both refits (None); the holdout is never inside the bundle.test_training_explanations.py,test_semantic_carry_forward.py: fake trainers answerpublished_fit_mode()andget_log_dir(fit_mode=).test_artifacts.py, training and checkpoint suites pass with the newget_log_dirargument.Out of scope
refit_fullmodel. Thefitandrefit_trainvaltest predictions stay in the run directory shown above; they are not returned as the shipped model's.Change map: see the
kumo-pr-change-mapcomment.🤖 Generated with Claude Code