Resolve a local quant folder's variants by its path
A local row carries a repo id only inside the HF cache: getLocalHubId returns null unless the source is hf_cache. A plain folder of quants, under the models dir, a custom folder or LM Studio, therefore has none, while the backend still marks it as needing one, since requires_variant is scan_path.is_dir(), and leaves format_variant null because a directory is not the single-file case. settingsGgufVariantForRow then returns null, the guard is entered, the lookup is skipped for want of an id, and the toast is all that is left. The row menu offers Settings on every non-dataset row, so for these folders it could never do anything. The listing takes a path in that position and scans it, before the repo-id validation that would otherwise reject one, and that is already the request the on-device card makes: its fetch state is keyed on the model id, which for a local row without a hub id is the load path. So both surfaces now choose from the same quant set, and the settings key, the row's load id, does not move.
This commit is contained in:
parent
fc15f635ac
commit
0174461632
2 changed files with 31 additions and 1 deletions
|
|
@ -1343,7 +1343,14 @@ export function ModelsPage() {
|
||||||
// the server mirror is wrong too. Resolve it as the on-device card does.
|
// the server mirror is wrong too. Resolve it as the on-device card does.
|
||||||
let ggufVariant = settingsGgufVariantForRow(row);
|
let ggufVariant = settingsGgufVariantForRow(row);
|
||||||
if (!ggufVariant && row.isGguf && row.capabilities.requiresVariant) {
|
if (!ggufVariant && row.isGguf && row.capabilities.requiresVariant) {
|
||||||
const repoId = row.kind === "cache" ? row.repoId : (row.repoId ?? null);
|
// A local row only carries a repo id when it sits in the HF cache, so a
|
||||||
|
// plain folder of quants (the models dir, a custom folder, LM Studio) has
|
||||||
|
// none while still being marked as needing one. The listing takes a path
|
||||||
|
// in the same position and scans it, which is exactly what the on-device
|
||||||
|
// card already does for these rows, so without the fallback this menu
|
||||||
|
// entry could only ever reach the "couldn't determine which quant" toast.
|
||||||
|
const repoId =
|
||||||
|
row.kind === "cache" ? row.repoId : (row.repoId ?? row.path ?? null);
|
||||||
if (repoId) {
|
if (repoId) {
|
||||||
try {
|
try {
|
||||||
const [res] = await Promise.all([
|
const [res] = await Promise.all([
|
||||||
|
|
|
||||||
|
|
@ -1389,6 +1389,29 @@ def test_settings_open_reads_status_before_resolving_the_quant():
|
||||||
assert "refreshResidentModelStatus(), ]);" in page
|
assert "refreshResidentModelStatus(), ]);" in page
|
||||||
|
|
||||||
|
|
||||||
|
def test_a_local_quant_folder_resolves_its_variants_by_path():
|
||||||
|
"""A local row carries a repo id only inside the HF cache, so a plain folder of
|
||||||
|
quants has none while still being marked as needing one, and the row menu's
|
||||||
|
Settings could then only reach the error toast."""
|
||||||
|
hub = " ".join(_read("features/hub/hub-page.tsx").split())
|
||||||
|
assert (
|
||||||
|
'const repoId = row.kind === "cache" ? row.repoId : (row.repoId ?? row.path ?? null);'
|
||||||
|
in hub
|
||||||
|
)
|
||||||
|
# The on-device card already lists by path for the same rows; this is the
|
||||||
|
# request it makes, so both surfaces choose from one set of quants.
|
||||||
|
card = " ".join(_read("features/hub/catalog/local-on-device-card.tsx").split())
|
||||||
|
assert "repoId: modelId, hfToken, preferLocalCache: true, localPath: localGgufPath," in card
|
||||||
|
# The backend takes a path in the repo_id position and scans it, before the
|
||||||
|
# repo-id validation that would otherwise 400 on a path.
|
||||||
|
variants = (
|
||||||
|
WORKDIR / "studio" / "backend" / "hub" / "services" / "models" / "gguf_variants.py"
|
||||||
|
).read_text(encoding = "utf-8")
|
||||||
|
scan = variants.split("if is_local_path(repo_id):", 1)
|
||||||
|
assert len(scan) == 2, "the local-path branch this leans on"
|
||||||
|
assert "_is_valid_repo_id(repo_id)" in scan[1], "the branch has to come first"
|
||||||
|
|
||||||
|
|
||||||
def test_cached_repo_settings_key_follows_the_row_not_the_view():
|
def test_cached_repo_settings_key_follows_the_row_not_the_view():
|
||||||
"""A repo in an inactive HF cache loads by snapshot path while its settings are keyed
|
"""A repo in an inactive HF cache loads by snapshot path while its settings are keyed
|
||||||
by repo id."""
|
by repo id."""
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue