studio: sort GGUF dropdown client-side -- recommended first, OOM last, rest by size descending
Move the sort logic from the backend to the frontend GgufVariantExpander component where GPU VRAM info is available. The backend now does a simple size-descending sort. The frontend pins the recommended variant at the top, pushes OOM variants to the bottom, and sorts the rest by file size descending (largest/best quality first).
This commit is contained in:
parent
dd2d979b40
commit
3c1b8d7ab7
2 changed files with 23 additions and 14 deletions
|
|
@ -962,18 +962,10 @@ def list_gguf_variants(
|
|||
)
|
||||
)
|
||||
|
||||
# Sort: recommended first, then UD variants by size, then non-UD by size.
|
||||
best_file = _pick_best_gguf([v.filename for v in variants])
|
||||
best_quant = _extract_quant_label(best_file) if best_file else None
|
||||
|
||||
def _sort_key(v: GgufVariantInfo) -> tuple:
|
||||
is_recommended = v.quant == best_quant
|
||||
is_ud = v.quant.startswith("UD-")
|
||||
# (0, ...) recommended | (1, 0, -size) other UD | (1, 1, -size) non-UD
|
||||
# Negative size so largest (best quality) appears first.
|
||||
return (0 if is_recommended else 1, 0 if is_ud else 1, -v.size_bytes)
|
||||
|
||||
variants.sort(key = _sort_key)
|
||||
# Sort by size descending (largest = best quality first).
|
||||
# Recommended pinning and OOM demotion are handled client-side
|
||||
# where GPU VRAM info is available.
|
||||
variants.sort(key = lambda v: -v.size_bytes)
|
||||
|
||||
return variants, has_vision
|
||||
|
||||
|
|
|
|||
|
|
@ -206,7 +206,24 @@ function GgufVariantExpander({
|
|||
);
|
||||
}
|
||||
|
||||
if (!variants || variants.length === 0) {
|
||||
const sortedVariants = useMemo(() => {
|
||||
if (!variants) return variants;
|
||||
return [...variants].sort((a, b) => {
|
||||
const aIsRec = a.quant === defaultVariant;
|
||||
const bIsRec = b.quant === defaultVariant;
|
||||
if (aIsRec !== bIsRec) return aIsRec ? -1 : 1;
|
||||
|
||||
const aGb = a.size_bytes / (1024 ** 3);
|
||||
const bGb = b.size_bytes / (1024 ** 3);
|
||||
const aOom = gpuGb != null && gpuGb > 0 && aGb > 0 && checkVramFit(aGb, gpuGb) === "exceeds";
|
||||
const bOom = gpuGb != null && gpuGb > 0 && bGb > 0 && checkVramFit(bGb, gpuGb) === "exceeds";
|
||||
if (aOom !== bOom) return aOom ? 1 : -1;
|
||||
|
||||
return b.size_bytes - a.size_bytes;
|
||||
});
|
||||
}, [variants, defaultVariant, gpuGb]);
|
||||
|
||||
if (!sortedVariants || sortedVariants.length === 0) {
|
||||
return (
|
||||
<div className="px-5 py-2 text-xs text-muted-foreground">
|
||||
No GGUF variants found.
|
||||
|
|
@ -224,7 +241,7 @@ function GgufVariantExpander({
|
|||
<span className="text-[9px] font-medium text-blue-400">Vision</span>
|
||||
)}
|
||||
</div>
|
||||
{variants.map((v) => {
|
||||
{sortedVariants.map((v) => {
|
||||
const sizeGb = v.size_bytes / (1024 ** 3);
|
||||
const fitStatus = gpuGb != null && gpuGb > 0 && sizeGb > 0
|
||||
? checkVramFit(sizeGb, gpuGb)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue