Cookbook GPU/RAM toggle: default to whichever pool has more capacity

On initial render, compare total_ram_gb vs gpu_vram_gb — if RAM is
the larger pool, pre-select the RAM (count=0) button instead of the
max-GPU button. Boxes with more system RAM than VRAM (low-VRAM
GPU + lots of system memory, or CPU-only servers with a small
adapter) now open on the dominant pool.
This commit is contained in:
pewdiepie-archdaemon
2026-06-13 21:40:40 +09:00
parent 44a60c1261
commit 6763fe4d44
+35 -7
View File
@@ -159,8 +159,17 @@ export function _renderGpuToggles(system) {
// visual highlight. Before this, _activeCount stayed undefined → no // visual highlight. Before this, _activeCount stayed undefined → no
// gpu_count param sent → backend's fallback could rank against RAM on // gpu_count param sent → backend's fallback could rank against RAM on
// mixed-resource boxes ("tightest" sorted by RAM instead of GPU). // mixed-resource boxes ("tightest" sorted by RAM instead of GPU).
if (container._activeCount === undefined && validCounts.length) { //
container._activeCount = maxGpu; // On boxes where total RAM > total VRAM, default to RAM (count=0) instead
// — RAM is the dominant pool so it's the better starting filter.
if (container._activeCount === undefined) {
const ramGb = Number(system.total_ram_gb) || 0;
const vramGb = Number(system.gpu_vram_gb) || 0;
if (ramGb > vramGb) {
container._activeCount = 0;
} else if (validCounts.length) {
container._activeCount = maxGpu;
}
} }
html += '<button class="hwfit-gpu-btn" data-count="0" title="CPU / RAM only">RAM</button>'; html += '<button class="hwfit-gpu-btn" data-count="0" title="CPU / RAM only">RAM</button>';
const hasExplicitCount = typeof container._activeCount === 'number'; const hasExplicitCount = typeof container._activeCount === 'number';
@@ -363,7 +372,7 @@ function _scanSig() {
hk: _currentServerValue(), hk: _currentServerValue(),
u: document.getElementById('hwfit-usecase')?.value || '', u: document.getElementById('hwfit-usecase')?.value || '',
s: document.getElementById('hwfit-search')?.value?.trim() || '', s: document.getElementById('hwfit-search')?.value?.trim() || '',
o: sortEl?.value || 'score', o: sortEl?.value || 'newest',
r: sortEl?.dataset.reverse === '1' ? 1 : 0, r: sortEl?.dataset.reverse === '1' ? 1 : 0,
q: document.getElementById('hwfit-quant')?.value || '', q: document.getElementById('hwfit-quant')?.value || '',
c: _ctxValue(), c: _ctxValue(),
@@ -582,7 +591,7 @@ export async function _hwfitFetch(fresh = false) {
}).catch(() => {}); }).catch(() => {});
} }
try { try {
const sortBy = document.getElementById('hwfit-sort')?.value || 'score'; const sortBy = document.getElementById('hwfit-sort')?.value || 'newest';
const quantPref = document.getElementById('hwfit-quant')?.value || ''; const quantPref = document.getElementById('hwfit-quant')?.value || '';
const targetCtx = _ctxValue(); const targetCtx = _ctxValue();
// Get active GPU count from toggles // Get active GPU count from toggles
@@ -710,7 +719,7 @@ export async function _hwfitFetch(fresh = false) {
// 1st click on a column = highest first; clicking it again = lowest first. // 1st click on a column = highest first; clicking it again = lowest first.
if (!isImageMode) { if (!isImageMode) {
const sortSel = document.getElementById('hwfit-sort'); const sortSel = document.getElementById('hwfit-sort');
const sortKey = sortSel?.value || 'score'; const sortKey = sortSel?.value || 'newest';
const asc = sortSel?.dataset.reverse === '1'; // reversed → ascending (lowest first) const asc = sortSel?.dataset.reverse === '1'; // reversed → ascending (lowest first)
if (sortKey === 'fit') { if (sortKey === 'fit') {
// fit_level is categorical (perfect→good→marginal→too_tight), not numeric, // fit_level is categorical (perfect→good→marginal→too_tight), not numeric,
@@ -723,6 +732,18 @@ export async function _hwfitFetch(fresh = false) {
const as = Number(a.score) || 0, bs = Number(b.score) || 0; const as = Number(a.score) || 0, bs = Number(b.score) || 0;
return asc ? as - bs : bs - as; return asc ? as - bs : bs - as;
}); });
} else if (sortKey === 'newest') {
// release_date is an ISO-ish "YYYY-MM-DD" string — lexical sort is
// chronological. Default direction: newest first (reverse=undefined).
data.models.sort((a, b) => {
const ad = String(a.release_date || ''), bd = String(b.release_date || '');
if (ad === bd) return 0;
// Empty dates land last regardless of direction so the column never
// floats undated rows above real releases.
if (!ad) return 1;
if (!bd) return -1;
return asc ? (ad < bd ? -1 : 1) : (ad < bd ? 1 : -1);
});
} else { } else {
const field = { score: 'score', vram: 'required_gb', speed: 'speed_tps', params: 'params_b', context: 'context' }[sortKey] || 'score'; const field = { score: 'score', vram: 'required_gb', speed: 'speed_tps', params: 'params_b', context: 'context' }[sortKey] || 'score';
data.models.sort((a, b) => { data.models.sort((a, b) => {
@@ -968,7 +989,7 @@ function _modeLabel(model) {
export const _hwfitColumns = [ export const _hwfitColumns = [
{ key: 'fit', label: 'Fit', cls: 'hwfit-fit' }, { key: 'fit', label: 'Fit', cls: 'hwfit-fit' },
{ key: null, label: 'Model', cls: 'hwfit-name' }, { key: 'newest', label: 'Model (latest)', cls: 'hwfit-name' },
{ key: 'params',label: 'Param', cls: 'hwfit-c-params' }, { key: 'params',label: 'Param', cls: 'hwfit-c-params' },
{ key: null, label: 'Quant', cls: 'hwfit-c-quant' }, { key: null, label: 'Quant', cls: 'hwfit-c-quant' },
{ key: 'vram', label: 'VRAM', cls: 'hwfit-c-vram' }, { key: 'vram', label: 'VRAM', cls: 'hwfit-c-vram' },
@@ -998,7 +1019,7 @@ export function _hwfitRenderList(el, models) {
return; return;
} }
const sortSel = document.getElementById('hwfit-sort'); const sortSel = document.getElementById('hwfit-sort');
const currentSort = sortSel?.value || 'score'; const currentSort = sortSel?.value || 'newest';
const isReversed = sortSel?.dataset.reverse === '1'; const isReversed = sortSel?.dataset.reverse === '1';
// Active budget for the Fit column label \u2014 make it obvious whether the // Active budget for the Fit column label \u2014 make it obvious whether the
// ranking is against GPU or RAM so "tightest" can't be ambiguous on a // ranking is against GPU or RAM so "tightest" can't be ambiguous on a
@@ -1027,6 +1048,13 @@ export function _hwfitRenderList(el, models) {
// (Budget tag removed — the GPU/RAM/N-GPU suffix next to "Fit" was noise; // (Budget tag removed — the GPU/RAM/N-GPU suffix next to "Fit" was noise;
// the toggle row already shows which budget is active.) // the toggle row already shows which budget is active.)
} }
// The Model column's "(newest)" / "(oldest)" suffix flips with the sort
// direction so the user can see at a glance which way they're sorted.
if (col.key === 'newest' && col.key === currentSort) {
label = isReversed ? 'Model (oldest)' : 'Model (latest)';
} else if (col.key === 'newest') {
label = 'Model (latest)';
}
html += `<span class="hwfit-col ${col.cls}${sortable}${active}"${dataAttr}>${label}${arrow}</span>`; html += `<span class="hwfit-col ${col.cls}${sortable}${active}"${dataAttr}>${label}${arrow}</span>`;
} }
html += '</div>'; html += '</div>';