feat(diagnostic): Modell per HuggingFace-Link in den Katalog — mit GGUF-Vorschlaegen
Bisher kamen Modelle nur ueber "Von HuggingFace aktualisieren" und die Trends in den Katalog. Jetzt: Feld "HuggingFace-Link oder org/name". Hat das Repo kein GGUF (z.B. nur safetensors wie Virtue-AI-HUB/VulnLLM-R-7B oder fdtn-ai/Foundation-Sec-8B), sucht der Server GGUF-Fassungen desselben Modells (HF-Suche, filter=gguf, nach Downloads) und bietet sie mit "Diese nehmen" an. Hinzugefuegte stehen danach gefiltert in der Liste. Getestet gegen HuggingFace: beide Beispiele ohne GGUF erkannt, je 5 ladbare GGUF-Fassungen gefunden (Q4_K_M ~4,7–4,9 GB). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -960,6 +960,12 @@
|
||||
den Fortschritt. Danach ist es im Modell-Dropdown oben waehlbar.
|
||||
<span style="color:#FFD60A;">Achte auf den VRAM der Box (Spalte VRAM).</span>
|
||||
</p>
|
||||
<div style="display:flex;gap:6px;flex-wrap:wrap;margin:0 0 8px;">
|
||||
<input id="llm-catalog-add" type="text" placeholder="HuggingFace-Link oder org/name hinzufügen …" onkeydown="if(event.key==='Enter')addCatalogByLink()"
|
||||
style="flex:1;min-width:240px;background:#1E1E2E;border:1px solid #333;border-radius:4px;padding:6px 8px;color:#E0E0F0;font-size:12px;">
|
||||
<button class="btn secondary" onclick="addCatalogByLink()" style="padding:4px 10px;font-size:11px;">Hinzufügen</button>
|
||||
</div>
|
||||
<div id="llm-catalog-add-result" style="font-size:12px;margin:0 0 8px;"></div>
|
||||
<input id="llm-catalog-search" type="search" placeholder="🔍 Modell suchen … (z.B. coder, qwen3, 30b)" oninput="filterLlmCatalog()"
|
||||
style="display:none;width:100%;max-width:360px;box-sizing:border-box;margin:0 0 8px;background:#1E1E2E;border:1px solid #333;border-radius:4px;padding:6px 8px;color:#E0E0F0;font-size:12px;">
|
||||
<div id="llm-catalog-list" style="font-size:12px;color:#8888AA;overflow-x:auto;">(lade Katalog…)</div>
|
||||
@@ -10206,6 +10212,35 @@
|
||||
'<td style="' + td + 'text-align:right;white-space:nowrap;">' + act + '</td></tr>';
|
||||
}).join('') + '</table></div>';
|
||||
}
|
||||
// Modell per Link/Repo in den Katalog. Ohne GGUF: GGUF-Fassungen vorschlagen.
|
||||
async function addCatalogByLink(repo) {
|
||||
const inp = document.getElementById('llm-catalog-add');
|
||||
const out = document.getElementById('llm-catalog-add-result');
|
||||
const val = repo || (inp.value || '').trim();
|
||||
if (!val) return;
|
||||
out.innerHTML = '<span style="color:#8888AA;">Prüfe ' + escapeHtml(val) + ' auf HuggingFace …</span>';
|
||||
try {
|
||||
const j = await (await fetch('/api/llm-catalog/add', { method: 'POST', headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ hfRepo: val, manual: true }) })).json();
|
||||
if (j.ok) {
|
||||
_llmCatalog = j.models || _llmCatalog;
|
||||
renderLlmCatalog();
|
||||
inp.value = '';
|
||||
out.innerHTML = '<span style="color:#34C759;">✓ ' + escapeHtml(j.id) + (j.existed ? ' war schon im Katalog' : ' ist jetzt im Katalog') + ' — unten Ziel-Karte wählen und laden.</span>';
|
||||
const s = document.getElementById('llm-catalog-search');
|
||||
if (s) { s.value = j.id; filterLlmCatalog(); }
|
||||
return;
|
||||
}
|
||||
const alts = j.alternatives || [];
|
||||
out.innerHTML = '<span style="color:#FF9F0A;">⚠ ' + escapeHtml(j.error || 'Fehler') + '</span>'
|
||||
+ (alts.length ? '<div style="color:#9a9ab5;margin-top:4px;">GGUF-Fassungen desselben Modells:</div>' + alts.map(a =>
|
||||
`<div style="display:flex;gap:8px;align-items:center;margin-top:3px;">
|
||||
<a href="https://huggingface.co/${escapeHtml(a.repo)}" target="_blank" rel="noopener noreferrer" style="color:#E0E0F0;">${escapeHtml(a.repo)}</a>
|
||||
<span style="color:#555570;">↓ ${Number(a.downloads).toLocaleString('de')}</span>
|
||||
<button class="btn secondary" onclick="addCatalogByLink('${escapeHtmlAttr(a.repo)}')" style="padding:1px 8px;font-size:11px;">Diese nehmen</button></div>`).join('')
|
||||
: '');
|
||||
} catch (e) { out.innerHTML = '<span style="color:#FF6B6B;">✗ ' + escapeHtml(e.message) + '</span>'; }
|
||||
}
|
||||
async function addTrendingToCatalog(btn, repo) {
|
||||
btn.disabled = true; btn.textContent = '…';
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user