fix(models): Embedding-/Rerank-Modelle aus Dropdown filtern + nach Größe sortieren

nomic-embed-text & Co. nutzen /api/embeddings, nicht /api/generate — würden
beim Job-Start einen Ollama-400er werfen. Substring-Filter auf "embed"/"rerank"
im Modellnamen, Sortierung nach Größe absteigend macht das Dropdown sinnvoller.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
root 2026-05-16 16:50:03 +00:00
parent c6164d946c
commit 79d6cfec74

View File

@ -157,10 +157,18 @@ async def health() -> dict:
return r.json()
# Modelle, die unbrauchbar sind für /api/generate (Embeddings, Reranker, etc.) —
# Substring-Match, klein geschrieben. Sortiert nach Größe absteigend ausgeliefert,
# damit die wahrscheinlich-fähigeren Modelle oben im Dropdown stehen.
_NON_CHAT_HINTS = ("embed", "embedding", "rerank")
async def list_models() -> list[dict]:
"""Liefert die lokal gepullten Ollama-Modelle inkl. Größe und Mod-Zeit.
Antwort-Form pro Eintrag: {"name", "size", "modified_at"} (Größe in Bytes).
Embeddings-/Rerank-Modelle werden gefiltert, weil sie auf /api/generate
einen 400er werfen würden der User soll im UI nicht in diese Falle laufen.
"""
url = f"{settings.ollama_url.rstrip('/')}/api/tags"
async with httpx.AsyncClient(timeout=10) as c:
@ -169,9 +177,16 @@ async def list_models() -> list[dict]:
data = r.json()
out: list[dict] = []
for m in data.get("models", []):
name = m.get("name") or m.get("model") or ""
if not name:
continue
if any(h in name.lower() for h in _NON_CHAT_HINTS):
log.info("list_models: filtere Non-Chat-Modell heraus: %s", name)
continue
out.append({
"name": m.get("name") or m.get("model") or "",
"name": name,
"size": m.get("size", 0),
"modified_at": m.get("modified_at", ""),
})
return [m for m in out if m["name"]]
out.sort(key=lambda m: m["size"], reverse=True)
return out