#863 made size the discriminator when the *installed tag* carried one, so
qwen3:8b no longer marks a whole family installed. The mirror case is still
open: when the *catalog name* has no size, the candidate is family-level and
matches any tag in that family.
deepseek-ai/DeepSeek-R1 maps to the bare tag `deepseek-r1`, which is also the
family prefix of the Qwen distill. An install of deepseek-r1:14b therefore
marks the 684.5B original installed, a 397 GB model reported as present on a
24 GB card.
Family matching is still needed (phi-4 -> phi4:14b), so the fix keeps it and
adds a size check: reject when the catalog parameter count and the tag size
differ by more than 2x. The threshold is deliberately loose because tags
round, and an unknown size on either side keeps the previous permissive
behaviour rather than dropping a real install.
Uses a new known_params_b() that returns None when the size is unrecorded,
since params_b() falls back to 7.0 and a guessed size must never be grounds
for rejecting a match.
* bench(nvidia-gb10): add 1786611367-03c54b31-1.json
* bench(nvidia-gb10): add 1786611367-06d57be3-2.json
* fix(nvidia-gb10): restore .gguf extension on Step-3.7-Flash
The sharded quant lives in a subfolder whose key carries no extension, so
the model tag could not normalize to its catalog identifier and the
measurement would have been dropped during lookup.
best_quant_for_runtime_budget returned None for vLLM because a
pre-quantized model cannot be re-quantized, but callers read None as
"does not fit". Every AWQ/GPTQ/AutoRound model on a GPU therefore fell
into the failure branch and picked up an "Insufficient VRAM and system
RAM" note, while the same branch returned memory figures that scored
the model Perfect.
The vLLM branch now reports the model's own fixed footprint when it fits
the budget and still returns None when it does not. Fixed in the
function rather than the call site, since the same ambiguity is
reachable from the CPU path.
On a 24 GB card this drops contradictory notes from 319 to 0 across the
catalog. Seven models change fit level, all vLLM, all Too Tight to
Marginal.
`strip_gguf_quant_suffix` enumerated published quant variants one by one,
so anything outside that list never reduced to the catalog id and the file
read as neither installed nor served. The gaps were whole publishers:
bartowski `_L` files (`-q3_k_l`, `-q4_k_l`, `-q5_k_l`) and Unsloth Dynamic
`_XL`/`IQ4_NL` files.
Match on the quant family stem instead — `-qN_k` for K-quants, `-iqN_` for
I-quants — so `_S`/`_M`/`_L`/`_XL` and `_NL`/`_XS`/`_XXS` all reduce the
same way and the next published variant needs no code change. `-q6_k` and
`-q2_k` already worked this way; the other families now follow.
Three entries in the NVIDIA GB10 community submission (#872) were being
silently dropped during lookup on this bug:
Step-3.7-Flash-UD-IQ4_NL.gguf 21.41 tok/s
Qwen-AgentWorld-35B-A3B-UD-Q4_K_XL.gguf 64.17 tok/s
LFM2.5-8B-A1B-UD-Q4_K_XL.gguf 151.04 tok/s
The same function backs local install detection, so users with an Unsloth
UD-XL or bartowski _L GGUF on disk were shown the model as not installed.
Semver-compatible bumps now collapse into a single weekly PR per
ecosystem (cargo, github-actions) instead of one PR per dependency.
Major bumps are deliberately left ungrouped so they still arrive as
individual PRs and get individual review.
Existing cooldown settings are unchanged, so grouping composes with the
current 'let releases settle' policy.
Pin all four official Qwen3.8 repos in the curated catalog:
Qwen/Qwen3.8-27B 27.78B dense, 64 layers (16 full / 48 linear)
Qwen/Qwen3.8-27B-FP8 same weights, FP8 checkpoint
Qwen/Qwen3.8-2.4T-A95B 2.446T total / 95B active, 512 experts (10 active),
92 layers (23 full / 69 linear)
Qwen/Qwen3.8-2.4T-A95B-FP8 same, FP8 checkpoint
The automated weekly refresh in #892 picked up three of these via trending
discovery, but none were in TARGET_MODELS, so they could drop out of any
later scrape; the non-FP8 2.4T-A95B was missing entirely. Catalog entries
were merged in surgically (four entries) rather than by a full re-scrape so
this diff stays reviewable alongside #892.
infer_attention_layout_from_name now matches qwen3.8- and handles the new
-a95b 92-layer shape, and OLLAMA_MAPPINGS gains qwen3.8-27b -> qwen3.8:27b
(Ollama publishes only the 27B; the 2.4T has no library entry).
Also fixes a generation-scoring bug this surfaced. parse_generation
consulted the architecture string before the model name, but Qwen3.6 and
Qwen3.8 both ship as model_type "qwen3_5" -- so every Qwen3.6 model in the
catalog scored as generation 3.5, and the name-based 3.6 branch added in
5397a8a was dead code for anything with an architecture set. The existing
test passed None for architecture, so it never caught this.
qwen_minor_generation_from_name is now consulted first inside the Qwen arch
branch. It matches only explicit minor versions and returns None for a bare
"Qwen3", so qwen3_next still resolves from the architecture string instead
of regressing to 3.0. scripts/validate_generation_scoring.py, which
documents itself as a mirror of the Rust logic, is updated to match.
Quality bonus is (generation - 1) * 3 clamped to 9, so Qwen3.6 models gain
+0.3 and Qwen3.8 lands at +8.4.
* bench: Muse-Glimmer-30B on amd-radeon-rx-7900-xt and apple-m4-pro
Two llama.cpp results for Meta's Muse-Glimmer-30B (released 2026-08-10), one per
existing hardware slug, measured with llmfit v1.1.9 and llama.cpp built at 84e908c
(Vulkan) and release b10375 (Metal).
Both runs are fully GPU-resident (53/53 layers offloaded) at ctx 4096, 3 runs each,
after a 5-minute machine preheat.
* Update llmfit-core/data/community/amd-radeon-rx-7900-xt/1786562074-7e61b3fb.json
fix(bench): align 7900 XT hardwareName with the existing slug entries
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
---------
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* data: community benchmark (intel-alder-lake-p-gt2-iris-xe-graphics-integrated)
* data: community benchmark (intel-alder-lake-p-gt2-iris-xe-graphics-integrated)
* data: community benchmark (intel-alder-lake-p-gt2-iris-xe-graphics-integrated)
* data: community benchmark (intel-alder-lake-p-gt2-iris-xe-graphics-integrated)
* fix(ollama): stop one sized install marking a whole model family installed
`build_installed_set` inserted the bare family stem alongside every tag, and
the heuristic half of `hf_name_to_ollama_candidates` offered that same bare
stem as a candidate for any model with no `OLLAMA_MAPPINGS` entry. The two met
in the middle: a single `qwen3:8b` marked 238 of the 9,250 catalog entries
installed — `Qwen3-235B-A22B` and hundreds of community fine-tunes among them.
Because "installed" gates the download action, those models became
undownloadable in the TUI (discussion #861).
Size is now the discriminator:
- A sized install contributes its tag and nothing else. `qwen3:8b` says exactly
which weights are on disk.
- Only an untagged / `:latest` install contributes a family stem, plus the
sized alias implied by the parameter count Ollama already reports in
`/api/tags` (`qwen3:latest` → "8.2B" → `qwen3:8b`), so it still resolves to
one model rather than a family.
- A candidate derived from a sized HF name no longer includes the bare family.
- Size-less candidates — `OLLAMA_MAPPINGS` tags like `phi-4` → `phi4`, or HF
names with no size to parse — now match any tag of that family, which is what
keeps `phi4:14b` detecting `microsoft/phi-4`.
The bare-family candidate came in with #492 (fixing #481, "installed flag
always false for models without explicit mapping"); this keeps that fix and
drops its blast radius. Same over-match seen from another angle in #619.
Regression cover: every one of the 134 `OLLAMA_MAPPINGS` entries is still
detected from its own tag, and the reported scenario asserts its siblings stay
uninstalled.
* fix(ollama): also alias the verbatim parameter size for `:latest` installs
`qwen2.5:14b` reports "14.8B", so a `:latest` install has to be aliased to the
truncated marketing size. But some families are tagged with the decimal itself
— `solar:10.7b`, `qwen3:1.7b`, `lfm2:1.2b`, 20 entries in `OLLAMA_MAPPINGS` —
and for those the truncated alias alone reports the model as absent.
Emit both forms. They stay inside the family that is genuinely installed, so
the extra alias cannot resurrect the cross-family match this branch removes;
one of the two is simply dead weight per install.
* fix(python): read the package readme through the metadata hook
`readme = "../README.md"` is rejected by current hatchling ("Readme path must
be within the project directory"), which fails `uv sync` and takes the Test
Suite job down on all three platforms — including on main, independently of
this branch.
The README belongs at the repository root and should not be duplicated or
symlinked into `llmfit-python` (a symlink would checkout as a text stub on
Windows runners). Hatchling accepts readme *contents* without a path
constraint, so the existing custom metadata hook now supplies them: `readme`
joins `version` and `license-expression` as dynamic metadata.
Verified the built metadata is unchanged in substance — `Description-Content-Type:
text/markdown` with the full README body.
* data: community benchmark (nvidia-rtx-5880-ada-generation)
* data: community benchmark (nvidia-rtx-5880-ada-generation)
* data: community benchmark (nvidia-rtx-5880-ada-generation)
* data: community benchmark (nvidia-rtx-5880-ada-generation)
* data: community benchmark (nvidia-geforce-rtx-5070)
* data: community benchmark (nvidia-geforce-rtx-5070)
* data: community benchmark (nvidia-geforce-rtx-5070)
* data: community benchmark (nvidia-geforce-rtx-5070)
* fix(share): strip absolute GGUF paths from the pending store model field
llama-server reports the value of its -m/--model argument, usually an
absolute filesystem path, as the model id in /v1/models. That path was
stored verbatim in the model field of every pending submission payload,
forcing contributors to hand-edit each stored file before opening a
community-benchmarks PR, and quietly publishing machine-specific paths
(often a username) when they did not.
Keep only the GGUF file name at the two store boundaries:
- build_submission: new payloads are written with the bare file name
- read_store: payloads written by older binaries are scrubbed at load
time, so the share listing, the dry-run preview and the upload agree
Ids that are not paths to a .gguf file (Ollama tags, HF-style org/model
ids from vLLM or MLX) pass through unchanged. Detection, the TUI and the
model field sent in benchmark requests are deliberately untouched.
Closes#819
* fix(share): only strip model ids that are absolute paths
Hub-style references such as hf.co/org/repo/file.gguf contain
separators and end in .gguf but carry nothing machine-specific;
stripping them would discard the org and repo context. Restrict the
strip to ids with a leading slash, backslash or Windows drive letter,
which is the only shape llama-server reports for a locally loaded GGUF.
* fix(share): use get_mut to avoid panicking on non-object pending payloads
Indexing through Value's IndexMut panics when a stored pending file's
top level is not a JSON object, and silently inserts `"results": null`
into object payloads that lack the key. Switch sanitize_stored_payload
to `get_mut("results").and_then(Value::as_array_mut)` so a stray
hand-edited file in pending/ cannot panic `llmfit share`.
Three tests added: absolute paths are still scrubbed, non-object top
levels are left untouched without panicking, and objects without a
`results` key are not polluted.
plan (and other read-only subcommands) auto-started a detached background
'serve' server because auto_dashboard treated every non-serve command as
interactive. On plan's error path, std::process::exit(1) skips the
DashboardGuard destructor, so the orphaned server survives, keeps listening
on 127.0.0.1:8787, and contradicts the documented 'SIDE EFFECTS: None' plan
contract. Exclude read-only informational subcommands from auto_dashboard so
no server is spawned at all. Fixes#837.