fix(external-llm): match Ollama models carrying the default :latest tag - #2512
Open
Hoang130203 wants to merge 1 commit into
Open
fix(external-llm): match Ollama models carrying the default :latest tag#2512Hoang130203 wants to merge 1 commit into
Hoang130203 wants to merge 1 commit into
Conversation
The external-model reuse path normalises both sides of a comparison and
then requires an exact string match. Normalisation translated `:` to `-`
only after stripping quantization suffixes, so anything Ollama put in the
tag position survived into the name.
Ollama's default tag is `latest`. `ollama pull qwen3-30b-a3b` is listed by
/api/tags as `qwen3-30b-a3b:latest`, which normalised to
`qwen3-30b-a3b-latest` and matched the tier target `qwen3-30b-a3b` at
nothing:
qwen3-30b-a3b:latest -> qwen3-30b-a3b-latest NO MATCH
gemma-4-e4b-it:latest -> gemma-4-e4b-it-latest NO MATCH
qwen3.5-2b:q8_0 -> qwen3.5-2b-q8-0 NO MATCH
That is the commonest case there is: the user already has exactly the
model ODS wants, pulled by bare name. Reuse declined it and the installer
downloaded a duplicate multi-GB GGUF — the opposite of what the feature
exists to do. A user who happened to pull with an explicit size tag
(qwen3.5:9b) matched fine, which is why this survived.
Do tag handling before the quantization strip: drop a trailing `:latest`,
then translate the colon so a quantization arriving as a tag is
recognisable to the existing pattern. Size tags still survive as part of
the identity (qwen3.5:9b -> qwen3.5-9b), and `latest` is only ever
stripped as a tag, never from inside a name.
Extends tests/test-external-services.sh with 12 assertions: every tag
shape, the tier-target-to-Ollama-listing matches, and negative cases so a
different size or a different model carrying :latest still does not match.
Hoang130203
force-pushed
the
fix/external-llm-ollama-latest-tag
branch
from
August 7, 2026 04:22
0b8ca68 to
db96d5a
Compare
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
external_llm_model_matches()normalises both sides and requires an exactmatch. The normaliser translated
:to-after stripping quantizationsuffixes, so whatever Ollama put in the tag position survived into the name.
Ollama's default tag is
latest—ollama pull qwen3-30b-a3bis reported by/api/tagsasqwen3-30b-a3b:latest. Againstorigin/main:So the commonest case there is — the user already has exactly the model the
tier map wants, pulled by bare name — was declined, and the installer
downloaded a duplicate multi-GB GGUF instead of reusing it. That is the
opposite of what
feat(installer): reuse validated external model servicesexists to do.
The last line is why this survived: a user who happened to pull with an
explicit size tag (
qwen3.5:9b) matched fine, and that is the case theexisting test covers.
Fix
Do tag handling before the quantization strip:
Two properties I was careful to keep:
qwen3.5:9b→qwen3.5-9b,llama3.2:3b→llama3.2-3b.latestis only ever a tag. Anchored to:latest$, so a model namedmy-latest-modelis untouched.After:
Test
Extends
tests/test-external-services.shwith 12 assertions: every tag shape,the tier-target-against-Ollama-listing matches, and negative cases so a
different size or a different model carrying
:lateststill does not match.AI Assistance
AI assisted with the sed ordering and wording this description. I found the bug
by running the shipped normaliser against the model ids Ollama actually reports
for the models this repo's tier map selects, and checked the false-positive
cases before pushing.
Release Lane
release/2.6.xmainStable hotfix reason:
Changed Surface
(One sed pipeline in
installers/lib/external-services.sh, plus assertions inits existing test.)
Risk And Validation
git diff --checkrelease/2.6.xCommands/results:
Caveat on those 5 remaining failures — they are not mine. Unmodified
origin/mainreports17 passed, 5 failedon my host; with this PR it is29 passed, 5 failed. The same five fail either way. They are the phase-06and URL-validation cases that shell out to
python3, which on my Windows devbox resolves to the Microsoft Store alias and refuses to run (the same issue
#2368 addresses for two other scripts). CI has a real
python3. My change adds12 passing assertions and introduces no new failures.
Operational Change Check
external_llm_normalize_model_nameruns during install when ODS probes anexisting Ollama or LM Studio for a model it can reuse. The change makes the
matcher accept ids it previously rejected; it does not make it accept
different models — the negative assertions above pin that. The visible effect
is that an install which previously downloaded a duplicate GGUF now reuses the
local copy, which is the documented intent of the feature.
Notes For Reviewers
Why
:latestgets its own rule rather than falling out of the colontranslation. Dropping it entirely is right —
latestcarries no identity —but only in the tag position. Translating first and then trying to strip a
trailing
-latestwould also eat the tail of a model legitimately named...-latest, so the rule is anchored to:latest$before the colon is gone.The
my-latest-modelassertion pins that.Tags I deliberately did not touch. Ollama also uses tags like
:instruct,:textand:fp16.fp16is already in the quant pattern andnow reachable through the tag position too.
instructstays part of the name(
qwen3.5:9b-instruct-q4_K_M→qwen3.5-9b-instruct), which is correct —instruct and base are different models. If your tier targets ever name an
instruct variant, that will match; if they name the base, it will not, which is
the behaviour you want.