feat: download only config-selected models in setup#26
Merged
Conversation
Previously, setup always downloaded all non-optional models (scrfd_2.5g + w600k_r50) regardless of the active config, then additionally fetched any optional models the config referenced. This meant switching to high-accuracy models (det_10g + glintr100) still triggered a download of the unused default models. The filter now selects exactly the two models named in recognition.detector_model and recognition.embedder_model. On a fresh install the defaults resolve to the standard models, so behavior is unchanged for first-run users. Re-running setup after changing the config to a different model pair downloads the new models only. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates facelock setup to download (and verify/skip) only the face recognition models explicitly selected in the user’s config, instead of always downloading the default non-optional models as well.
Changes:
- Restrict model selection in both interactive and non-interactive setup flows to
recognition.detector_modelandrecognition.embedder_model. - Add
#[allow(dead_code)]toModelEntry::optionalsince it’s still deserialized and used by tests but no longer referenced in non-test code.
Comments suppressed due to low confidence (1)
crates/facelock-cli/src/commands/setup.rs:1020
- Same issue as the wizard: when either configured model filename is not found in the bundled manifest, this filter can produce
needed.len() == 0and non-interactive setup will continue to completion (writing the setup marker) without ensuring the configured models exist and are valid. Consider resolving each configured model individually (manifest entry -> download/verify; non-manifest -> verify file exists inmodel_dirand validate against the configured *_sha256, otherwise fail with an actionable error).
// 3. Check and download only the models actually selected in the config.
// Non-optional (default) models that aren't referenced by the config are
// skipped — if the user chose different models there is no reason to fetch
// the defaults as well. On a first run the config defaults resolve to the
// standard models (scrfd_2.5g + w600k_r50) so those are still downloaded.
let configured_detector = &config.recognition.detector_model;
let configured_embedder = &config.recognition.embedder_model;
let needed: Vec<&ModelEntry> = manifest
.models
.iter()
.filter(|m| m.filename == *configured_detector || m.filename == *configured_embedder)
.collect();
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+509
to
516
| // Only download the models actually selected in the config. | ||
| // Non-optional (default) models that aren't selected are skipped — the user | ||
| // chose different models, so there is no point fetching the defaults too. | ||
| let needed: Vec<&ModelEntry> = manifest | ||
| .models | ||
| .iter() | ||
| .filter(|m| { | ||
| !m.optional || m.filename == *configured_detector || m.filename == *configured_embedder | ||
| }) | ||
| .filter(|m| m.filename == *configured_detector || m.filename == *configured_embedder) | ||
| .collect(); |
Comment on lines
1013
to
1020
| let configured_detector = &config.recognition.detector_model; | ||
| let configured_embedder = &config.recognition.embedder_model; | ||
|
|
||
| let needed: Vec<&ModelEntry> = manifest | ||
| .models | ||
| .iter() | ||
| .filter(|m| { | ||
| !m.optional || m.filename == *configured_detector || m.filename == *configured_embedder | ||
| }) | ||
| .filter(|m| m.filename == *configured_detector || m.filename == *configured_embedder) | ||
| .collect(); |
tyvsmith
added a commit
that referenced
this pull request
May 17, 2026
Refresh CHANGELOG to capture work merged since the initial draft: - Signed APT repository publishing with main/legacy channels (#21) - E2E package install validation for .deb and .rpm (#23) - Streaming model download progress (#24) - Config-selected model downloads in setup (#26) - Security hardening: SHA256-verified models, persistent rate limiting, D-Bus method-level authorization, hardened PAM env (#16) - Runtime-selectable GPU execution provider (no compile-time flags) Also fix pkg-validate.sh removal tests to only run when the package is actually managed by dpkg/rpm — previously failed in test-deb / test-rpm where files are copied into the container directly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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
facelock setupalways downloaded all non-optional models (scrfd_2.5g + w600k_r50) plus any optional models the config referenced, even when the user had configured a completely different model pairwizard_model_downloadandrun_non_interactiveto select exactly the models named inrecognition.detector_modelandrecognition.embedder_model#[allow(dead_code)]toModelEntry::optionalwhich is still deserialized from the manifest TOML and used in testsRe-opens #25 (auto-closed when its stacked base branch was deleted on #24 merge). Rebased onto current
main.Test plan
cargo build --workspacepassescargo clippy --workspace -- -D warningspasses with zero warnings/errorscargo test --workspacepasses (all 274 tests pass)det_10g.onnx+glintr100.onnxin config, runfacelock setup --non-interactive, confirm only those two models are downloaded