From 2c74079a330535067bec0430837f3bf658356407 Mon Sep 17 00:00:00 2001 From: danielhanchen Date: Tue, 28 Jul 2026 22:24:21 +0000 Subject: [PATCH] Treat a loaded standalone GGUF as resident despite its derived quant A loose .gguf keys its settings by the bare path with no variant, since the path already names the one file. The loader still derives a label from the filename and /status reports it, so the settings page compared a derived quant against a deliberate null, never matched, and withheld the live launch config from the very file that was loaded. Applying from that page could then write the saved values over what the resident model is running with. The variant equality is skipped for that case only. Every other target, a repo row or a directory, still has to agree on the quant, because there the variant is what tells two loaded copies apart. --- studio/frontend/src/features/hub/hub-page.tsx | 11 +++++++++- tests/studio/test_model_picker_contracts.py | 21 +++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/studio/frontend/src/features/hub/hub-page.tsx b/studio/frontend/src/features/hub/hub-page.tsx index ee310f6e62..bf20d68037 100644 --- a/studio/frontend/src/features/hub/hub-page.tsx +++ b/studio/frontend/src/features/hub/hub-page.tsx @@ -1446,6 +1446,14 @@ export function ModelsPage() { // can show the live launch config. A GGUF loaded from an inactive HF cache or // straight off disk loads by path but is reported by its clean public id, so the // row's path and its settings identity both have to be offered as aliases. + // A loose .gguf is one file, so its path already names the quant and its + // settings deliberately carry no variant. The loader still derives one from the + // filename and /status reports it, so requiring the two to agree would never + // hold and the page would withhold the live config from the resident file. + const settingsTargetIsStandaloneFile = + settingsTarget !== null && + settingsTarget.ggufVariant == null && + settingsTarget.id.toLowerCase().endsWith(".gguf"); const settingsTargetIsResident = settingsTarget !== null && residentModelIdMatches( @@ -1453,7 +1461,8 @@ export function ModelsPage() { settingsTarget.id, settingsTarget.configId, ) && - ggufVariantsMatch(activeGgufVariant, settingsTarget.ggufVariant); + (settingsTargetIsStandaloneFile || + ggufVariantsMatch(activeGgufVariant, settingsTarget.ggufVariant)); const handleSearchHub = useCallback( (next: string) => { const trimmed = next.trim(); diff --git a/tests/studio/test_model_picker_contracts.py b/tests/studio/test_model_picker_contracts.py index 13a722d3b1..69f42ea7dc 100644 --- a/tests/studio/test_model_picker_contracts.py +++ b/tests/studio/test_model_picker_contracts.py @@ -1047,3 +1047,24 @@ def test_a_standalone_gguf_has_one_settings_key(): # The rule this mirrors: a variant is derived only for a single scanned file. assert "extract_quant_label(gguf_files[0].name)" in common assert "if scan_path.is_file() and len(gguf_files) == 1" in common + + +def test_a_standalone_gguf_is_resident_despite_its_derived_quant(): + """A loose .gguf keys its settings by the bare path with no variant, but the + loader derives one from the filename (llama_cpp sets _hf_variant from + _extract_quant_label) and /status reports it, so an equality between the two + could never hold and the settings page withheld the live launch config from + the very file that was loaded.""" + hub = " ".join(_read("features/hub/hub-page.tsx").split()) + assert "const settingsTargetIsStandaloneFile =" in hub + assert 'settingsTarget.id.toLowerCase().endsWith(".gguf")' in hub + assert ( + "(settingsTargetIsStandaloneFile || ggufVariantsMatch(activeGgufVariant, settingsTarget.ggufVariant))" + in hub + ) + backend = ( + WORKDIR / "studio" / "backend" / "core" / "inference" / "llama_cpp.py" + ).read_text(encoding = "utf-8") + assert "self._hf_variant = _extract_quant_label(gguf_path)" in backend, ( + "the derived label this accounts for" + )