feat(cli): add --revision to the -m/--model resolver - #1132
Merged
Conversation
Post-merge precision fixes to comment text landed in #1129. No code changes. The hermetic 2D test's name and doc overstated what it proves. `--help` short-circuits ahead of clap's conflict validation, not only ahead of the runtime, so the test establishes that `--pp-size` and `--tp-size` are recognized long names on the `generate` subcommand, not that the combination survives validation; a future `conflicts_with` between them would not fail it. The same effect is observable elsewhere in this binary: `mlxcel list --json --verbose` exits 2 on the conflict while appending `--help` exits 0. The doc now states that limit explicitly and the test is renamed to match. The module doc also described only the parity test and now covers both. The validator comment used "repository" where this repo's own wording is "tree" (`docs/README.md`: "maintained in a separate documentation tree"; `Makefile`), which is worth matching in a comment whose job is precision about exactly that split. It also now says "per-axis operator manual pages", so it does not read as though those two pages document the 2D composition, which neither they nor `docs/distributed.md` do. `run_generate_once`, not `run_generate`, is the function that resolves `-m` ahead of the validators; `run_generate` is correct only transitively. Refs #1112
`mlxcel download` accepted `--revision` but the `-m/--model` resolver did not, so a pinned revision could be fetched and then not run by repo-id: `mlxcel run owner/name` always resolved against `main`. The resolver already threaded `revision: Option<&str>` end to end; only the two public entry points hardcoded `None`. `--revision <REV>` is now on `generate`, `run`, `serve`, `inspect` and `mlxcel-server`, with `mlxcel download`'s flag name and help wording.
The issue asked for two behaviours to be decided rather than left implicit, and both answers narrow the feature deliberately.
Store revision-awareness. `store::model_dir_under` composes `<models_root>/<owner>/<name>` with no revision component, which `store.rs` and `mlxcel rm --revision`'s own help text already record. So a revision is honoured only where it can be honoured correctly. `store::hf_cache_snapshot` is revision-aware and answers normally, and a miss fetches the requested revision. The legacy per-CWD directory and the mlxcel store carry no revision provenance, so a revision-qualified request skips them rather than accepting a hit that could be any revision. A revision-qualified miss whose store directory is already occupied is refused with the two workarounds named, because `download_repo` treats same-named non-zero files as "already present" and returns without fetching (`src/downloader/mod.rs`), so proceeding would hand back whichever revision was already on disk. That is a pre-existing hazard for `mlxcel download --revision` as well, and is worth its own issue. `locate_landed_snapshot` is split from `locate_cached_snapshot` because the post-download probe answers a different question: not "may this location answer for this revision" but "where did the bytes just fetched land", which is knowable since the store directory was verified Absent beforehand.
Revision-namespacing the store would lift all of this, but it changes an on-disk layout shared with `list`, `rm` and the `download` verb, which the issue itself says takes this out of good-first-issue territory. Left as follow-up rather than forced in here.
Local paths. `--revision` alongside an existing local path is an error. Step 1 returns such a path verbatim and has nothing to resolve a revision against, so ignoring the flag would leave a user believing they had pinned something.
The doc comment recording the gap ("The CLI subcommands do not currently expose a `--revision` flag, so they pass `None`") is replaced, and the module docs gain a Revisions section covering which locations may answer and why.
Verified: 33 `downloader::resolver` unit tests pass including 5 new ones covering the local-path refusal, the legacy and store skips, and the occupied-store refusal (which asserts nothing was fetched); 25 `cli_help_consistency` tests pass, including the cross-binary flag-surface check that both server binaries now share `--revision`; and against the built binary, `--revision` is advertised with the intended wording on `generate` and `run`, a local path plus `--revision` is refused, and an occupied store plus `--revision` is refused without a network call.
Closes #1113
`sample_generate_args` and `sample_args` build `ModelOptions` and `ServeArgs` with explicit field initializers, so adding `revision` broke the bin crate's test target with two E0063s. Both now pass `None`, which is the pre-#1113 behavior these fixtures are asserting against. Caught by `cargo clippy --lib --tests -- -D warnings`. The earlier run appeared to pass only because its output was piped through `grep | tail`, which reports the exit status of the last stage rather than cargo's. Refs #1113
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
mlxcel downloadaccepted--revisionbut the-m/--modelresolver did not, so a pinned revision could be fetched and then not run by repo-id:mlxcel run owner/namealways resolved againstmain.--revision <REV>is now ongenerate,run,serve,inspectandmlxcel-server, usingmlxcel download's flag name and help wording.The issue asked for two behaviours to be decided rather than left implicit. Both answers narrow the feature deliberately, and both are below.
Decision 1: the mlxcel store is not revision-aware, and this PR does not change that
store::model_dir_undercomposes<models_root>/<owner>/<name>with no revision component. This is not an oversight, it is already recorded in two places onmain:src/downloader/store.rssaysrevision"is only used for the HF-cache probe (the mlxcel store is not revision-namespaced)", andmlxcel rm --revisionships help text saying the same.So
--revisionis honoured only where it can be honoured correctly:store::hf_cache_snapshot(HF cache)refs/<rev>or a commit-named snapshot./models/<basename><owner>/<name>DownloadOptions.revisionThe refusal is the part worth explaining.
download_repo_blockingcheckssnapshot_complete(&local_dir, &wanted)against the requested revision's file list and, when every wanted filename is already present and non-zero, prints "all expected files already present ..., skipping" and returns without fetching. Two revisions of a repo normally share filenames, so proceeding would hand back whichever revision was already on disk while reporting success. Failing loudly is the only honest option without a layout change.This is a pre-existing hazard for
mlxcel download --revisiontoo, which has the same collision today. It is not introduced here and deserves its own issue.Revision-namespacing the store would lift every restriction above, but it changes an on-disk layout shared with
list,rmand thedownloadverb. The issue itself says that is where this stops being a good first issue, so it is left as follow-up rather than forced in.--models-diris the escape hatch for holding two revisions at once.Decision 2:
--revisionwith an existing local path is an errorStep 1 of the resolver returns an existing path verbatim and has nothing to resolve a revision against. Ignoring the flag would leave a user believing they had pinned something, so it is refused:
What changed
src/downloader/resolver.rs:resolve_model_source_with_overridetakesrevision: Option<&str>and threads it into both repo-id branches.locate_cached_snapshotgates the two non-revision-aware locations onrevision.is_none(). Newlocate_landed_snapshotis used for the post-download probes, because that asks a different question: not "may this location answer for this revision" but "where did the bytes just fetched land", which is knowable since the store directory was verifiedAbsentbeforehand. Two new errors,revision_with_local_path_errorandrevision_store_occupied_error. The doc comment recording the gap ("The CLI subcommands do not currently expose a--revisionflag, so they passNone") is replaced, and the module docs gain a Revisions section.resolve_model_source(value)keeps its one-argument shape and delegates withNone, so the public convenience entry point is not broken for external callers.src/main.rs,src/commands/run.rs,src/bin/mlx_server.rs:--revisiononModelOptions,InspectArgs,ServeArgs,RunArgsandServerArgs.src/commands/{generate,chat,serve,inspect}.rs,src/bin/mlx_server.rs: threaded through all five resolver call sites;ChatOptionscarries it so the REPL path matches.src/downloader/resolver_tests.rs: 5 new tests.src/commands/{generate,serve}_tests.rs: fixtures initialize the new field.CHANGELOG.md: entry under## [Unreleased]/### Added.Test plan
cargo test --profile test-fast --features cuda --lib downloader::resolver: 33 passed, 0 failed (5 new, covering the local-path refusal, the legacy skip, the store skip, and the occupied-store refusal, which also asserts nothing was fetched).cargo test --profile test-fast --features cuda --test cli_help_consistency: 25 passed, includingthe_two_server_binaries_accept_the_same_flag_surface, somlxcel serveandmlxcel-serverstay in sync on the new flag.cargo test --profile test-fast --features cuda --bin mlxcel serve_(13 passed) and... validate_pipeline_parallel(5 passed).cargo clippy --profile test-fast --features cuda --lib --tests -- -D warningsclean.cargo fmt --all -- --checkclean.--revisionadvertised with the intended wording ongenerateandrun; a local path plus--revisionrefused; an occupied store plus--revisionrefused with both workarounds named and no network call.Acceptance criteria
mlxcel run owner/name --revision <REV>resolves that revision (via the HF cache, or by fetching it when the store destination is free).--revisionhelp text matchesmlxcel download's wording.Follow-ups
mlxcel download --revisioncollision described above.Closes #1113