diff --git a/tools/ui/src/lib/components/app/models/ModelSize.svelte b/tools/ui/src/lib/components/app/models/ModelSize.svelte
deleted file mode 100644
index 2b76a2d767..0000000000
--- a/tools/ui/src/lib/components/app/models/ModelSize.svelte
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-{label}
diff --git a/tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerModelSettings.svelte b/tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerModelSettings.svelte
index 89a71be3ea..571174c387 100644
--- a/tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerModelSettings.svelte
+++ b/tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerModelSettings.svelte
@@ -5,6 +5,7 @@
type ModelOverride,
modelQuantLabel,
modelSizeLabel,
+ resolveModelSize,
SAMPLING_DEFAULTS,
SPECULATIVE_OPTIONS
} from './utils';
@@ -79,6 +80,26 @@
let quant = $derived(modelQuantLabel(option));
let size = $derived(modelSizeLabel(option));
let stopStrings = $derived(draft.stopStrings ?? []);
+ let resolvedSize = $state(null);
+
+ // the router rarely reports a size, the repo tree does
+ $effect(() => {
+ const target = option;
+
+ let cancelled = false;
+
+ resolvedSize = null;
+
+ void resolveModelSize(target)
+ .then((value) => {
+ if (!cancelled) resolvedSize = value;
+ })
+ .catch(() => {});
+
+ return () => {
+ cancelled = true;
+ };
+ });
let infoRows = $derived([
{ label: 'Model', value: option.model },
{ label: 'File Path', value: serverProps?.model_path ?? null },
@@ -92,7 +113,7 @@
label: 'Training Context',
value: option.contextLength ? `${formatParameters(option.contextLength)} tokens` : null
},
- { label: 'Model Size', value: size },
+ { label: 'Model Size', value: resolvedSize ?? size },
{ label: 'Parameters', value: option.parsedId?.params ?? null },
{ isBadge: true, label: 'Quantization', value: quant },
{ isBadge: true, label: 'Architecture', value: (option.meta?.architecture as string) ?? null },
diff --git a/tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerModelsTable.svelte b/tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerModelsTable.svelte
index 3421b44490..d90ca6742b 100644
--- a/tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerModelsTable.svelte
+++ b/tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerModelsTable.svelte
@@ -7,7 +7,6 @@
ModelId,
ModelLoadControl,
ModelRowActions,
- ModelSize,
ModelsSection
} from '$lib/components/app';
import { Input } from '$lib/components/ui/input';
@@ -36,7 +35,7 @@
}: Props = $props();
let isEmpty = $derived(groups.every((group) => group.items.length === 0));
- const rowGrid = 'grid grid-cols-[minmax(0,1fr)_5.5rem_3rem_4.5rem] items-center gap-3';
+ const rowGrid = 'grid grid-cols-[minmax(0,1fr)_3rem_4.5rem] items-center gap-3';
function stateOf(option: ModelOption): ServerModelStatus | null {
const model = modelsStore.routerModels.find((m) => m.id === option.model);
@@ -83,8 +82,6 @@
/>
-
-
Model
- Size
-
State
Actions
diff --git a/tools/ui/src/lib/components/app/models/ModelsManager/utils.ts b/tools/ui/src/lib/components/app/models/ModelsManager/utils.ts
index 201cb4ea49..43da090581 100644
--- a/tools/ui/src/lib/components/app/models/ModelsManager/utils.ts
+++ b/tools/ui/src/lib/components/app/models/ModelsManager/utils.ts
@@ -1,4 +1,5 @@
import { LOCAL_BACKEND_ID, MODEL_OVERRIDES_LOCALSTORAGE_KEY } from '$lib/constants';
+import { HuggingFaceService } from '$lib/services';
import type { ModelOption } from '$lib/types/models';
import { getBackend } from '$lib/utils/api-base';
import { formatFileSize, formatParameters } from '$lib/utils/formatters';
@@ -129,6 +130,34 @@ export function modelQuantLabel(option: ModelOption): string | null {
return option.parsedId?.quantization ?? null;
}
+/**
+ * File size of the model's own quant. The router reports one for some backends;
+ * otherwise a local GGUF reads it from its repo tree, the same source the
+ * discovery details use. Returns null when neither knows.
+ */
+export async function resolveModelSize(option: ModelOption): Promise {
+ const reported = modelSizeLabel(option);
+
+ if (reported) return reported;
+
+ if (!isLocalOption(option)) return null;
+
+ const [repo, quant] = option.model.split(':');
+
+ if (!repo || !quant) return null;
+
+ const tree = await HuggingFaceService.getTree(repo);
+ const file = HuggingFaceService.collapseGgufShards(
+ HuggingFaceService.filterByExtension(tree, '.gguf')
+ ).find((entry) => {
+ const meta = HuggingFaceService.extractQuantMeta(entry.path);
+
+ return meta?.quant === quant && !meta.sidecar;
+ });
+
+ return file?.size ? formatFileSize(file.size) : null;
+}
+
/** Extra args the router applies when this model is loaded. */
export function loadExtraArgs(override?: ModelOverride): string[] {
const load = override?.load;
diff --git a/tools/ui/src/lib/components/app/models/index.ts b/tools/ui/src/lib/components/app/models/index.ts
index fed5646148..074e253b62 100644
--- a/tools/ui/src/lib/components/app/models/index.ts
+++ b/tools/ui/src/lib/components/app/models/index.ts
@@ -51,7 +51,6 @@ export { default as ModelId } from './ModelId.svelte';
export { default as ModelAvatar } from './ModelAvatar.svelte';
export { default as ModelLoadControl } from './ModelLoadControl.svelte';
export { default as ModelRowActions } from './ModelRowActions.svelte';
-export { default as ModelSize } from './ModelSize.svelte';
export { default as ModelsSection } from './ModelsSection.svelte';
/**