fix(inference): sam2_video is a point-prompt model, and an unknown type refuses - #458
Merged
Conversation
…pe refuses The adapter is chosen from the `model_type` the model's own config declares. `SEGMENTER_FAMILIES` held only `sam2`, and the published SAM 2 checkpoints — including `facebook/sam2-hiera-base-plus`, the id the connection form suggests — declare `sam2_video`. That fell through to the detector adapter, which refused a click by saying the model "answers text prompts": a confident sentence about some other model. Both spellings of the architecture are now named, and the fallback is gone. Resolution is by membership of two disjoint sets, and a `model_type` in neither — including the empty string an unreadable config yields — is refused with what was declared and what this build supports. A guess is invisible until the wrong adapter reports the loss in its own vocabulary. The detector set is `grounding-dino` and `mm-grounding-dino` rather than every zero-shot detector `transformers` registers: the adapter post-processes with a signature only that family takes. Closes #456
This was referenced Aug 9, 2026
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.
A local connection for
facebook/sam2-hiera-base-plus@main— the model id theconnection form pre-fills — refused point suggestions with a sentence about text
prompts. The adapter is chosen from the
model_typethe model's own config declares,and
SEGMENTER_FAMILIESheld onlysam2while the published SAM 2 checkpoints declaresam2_video. So the commonest point-prompt model in the product resolved to thedetector, and the detector refused the click in its own vocabulary.
Today's behaviour, verbatim
Against the real workspace connection, at
8084e4a, weights already in the cache:Nothing about that sentence is true of that model.
The fix
sam2_videois named besidesam2. Not a door held open for 0.2.0, which is whatthe old comment called it — it is what the checkpoints ship today, and
transformersloads one into the image model deliberately, saying so as it does:
So no adapter changed.
LocalSamProvider'sSam2Modelwas already the right class.The fallback is gone. Resolution is now membership of two disjoint sets, and a
model_typein neither is refused with what the config declared and what this buildsupports:
The empty string an unreadable config yields reaches the same refusal by the same route,
with a different opening — "does not say what model type it is" — and a second remedy,
because damaged files are the usual cause and
download_weightsis what fixes them.family_ofitself is unchanged: reading the config and deciding what to do about it stayseparate jobs.
Two judgment calls inside the scope, both narrower than the obvious reading
The SAM 2 set is whole models only. The locked
transformersregisters fourmodel_types matching SAM 2:sam2,sam2_video,sam2_vision_modelandsam2_hiera_det_model. The last two are the encoder halves a full config nests, notcheckpoints anything can prompt — a connection naming one has no mask decoder to run.
The task said to enumerate what exists and cover them; covering those two would have been
the guess this PR removes, so they fall to the refusal instead.
The detector set is two names, not five.
transformers_providerpost-processes withpost_process_grounded_object_detection(outputs, input_ids, threshold=…, text_threshold=…).Measured against the locked
transformers, only the grounding-dino family takes thatsignature:
For the last three,
input_idswould land inthresholdandtext_thresholdis not aparameter at all. They were reachable through the old fallback and would have failed
inside a post-processor; naming them here would have claimed a support that does not
exist. This is the task's "other reachable fall-through paths … refuse, never guess"
clause, applied.
Verification
Red before green. Both failing tests existed before the fix. With the new constants
in place and the mapping still
frozenset({"sam2"}):Mutation verification. Committed first, each mutation's anchor asserted present
exactly once before and its replacement asserted in the file after, each reverted to
byte-identical committed text:
frozenset({"sam2", "sam2_video"})→frozenset({"sam2"})test_the_video_variant_of_the_architecture_resolves_to_the_point_prompt_adapterraise InferenceConnectionNotRunnable(_no_adapter_for(…))→ the oldreturn LocalTransformersProvider(…)test_an_unknown_model_type_is_refused_rather_than_handed_to_a_familyEnd to end on this machine, same connection, same asset, weights already in the
workspace cache — no download:
An empty label is correct and deliberate: pointing says where, not what (D3/D4 on #424).
Two environment notes, so the run above is reproducible rather than magic. This host's
~/.localcarries a scikit-learn whose scipy is missing, which makestransformersfail to import
GenerationMixin; and the extra does not carrytorchvision— see below.Both were worked around outside the repository, on
PYTHONPATH, and nothing in thisdiff depends on either.
Gate
Staged (~10-minute harness ceiling), pytest split by the directories
ls tests/reportedat run time —
tests/fixturesandtests/scriptsare both new to this list since thelast staged run, and
tests/scriptsis node rather than pytest.pytest tests/architecture tests/cli tests/examples tests/fixtures tests/formats tests/inference tests/jobs tests/mcp tests/packaging tests/test_versioning.pypytest tests/kernelpytest tests/serverruff check .ruff format --check .mypy src/visionset(150 files)lint-imports(4 kept, 0 broken)check.sh frontendcheck.sh generatedcheck.sh browser(233 passed, no flakes; cycle 1 passed)Frontend totals: annotator 904 passed (34 files), ui-core 806 passed (45 files). No
frontend or wire surface is touched by the diff;
openapi.jsonand the generated clientare unchanged.
Found, not fixed
The
local-inferenceextra does not declaretorchvision, so SAM 2 cannot be loadedfrom a clean install — #457. With the resolver fixed and the extra exactly as declared,
the same call reaches:
This PR is still the right fix and is a prerequisite: it turns a false sentence about the
user's model into an honest one from
transformersabout a missing library. But thesuggested default model cannot run until #457 lands, and #457 is a
pyproject.tomlandlockfile change, outside this task's stated scope.
pyproject.toml's comment on the extra is false at HEAD — it says "uv.lockdoes notcarry extras", and the lock carries
provides-extras = ["local-inference"]with all fourpackages pinned. Carried over from #455's own "found, not fixed"; still nobody's diff.
Out of scope, and untouched
The suggest route, the editor, and the D1 default model id — the id is correct and the
resolver was wrong. No adapter changed. No new dependency.
Closes #456