diff --git a/app/main.py b/app/main.py index 0daafbc..459dfd9 100644 --- a/app/main.py +++ b/app/main.py @@ -1828,13 +1828,15 @@ async def list_models(request: Request): payload = r.json() - # Chat-list filter: exclude audio-only models (STT/TTS). They are - # registered and callable via /v1/audio/* for API users, but they are - # not chat models — listing them in Open WebUI would just confuse - # members. The gateway's model_info carries `mode` for audio models; - # fall back to a name check for safety. + # Chat-list filter: exclude audio-only models (STT/TTS) and embedding + # models. They are registered and callable via their own routes + # (/v1/audio/* and /v1/embeddings) for API users, but they are not chat + # models — listing them in Open WebUI would just confuse members. The + # gateway's model_info carries `mode` for these; fall back to a name + # check for safety. audio_modes = {"audio_transcription", "audio_speech"} audio_name_hints = ("whisper", "voxtral", "tts") + embedding_name_hints = ("embed",) def is_audio_model(m) -> bool: mode = ((m.get("info") or {}).get("meta") or {}).get("mode") or "" @@ -1843,7 +1845,17 @@ async def list_models(request: Request): mid = (m.get("id") or "").lower() return any(h in mid for h in audio_name_hints) - payload["data"] = [m for m in payload.get("data", []) if not is_audio_model(m)] + def is_embedding_model(m) -> bool: + mode = ((m.get("info") or {}).get("meta") or {}).get("mode") or "" + if mode == "embedding": + return True + mid = (m.get("id") or "").lower() + return any(h in mid for h in embedding_name_hints) + + payload["data"] = [ + m for m in payload.get("data", []) + if not is_audio_model(m) and not is_embedding_model(m) + ] for model in payload.get("data", []): # Friendly display name: emoji value-tier + short name. The `id`