diff --git a/app/main.py b/app/main.py index 71b5e86..d5d27c5 100644 --- a/app/main.py +++ b/app/main.py @@ -1949,6 +1949,7 @@ MODEL_VALUE_EMOJI = { "tinfoil": "🔒", # architecturally private (TEE) "greenpt": "🌱", # 100% renewable energy "publicai": "📖", # publicly developed, sovereign open models + "regolo": "⚡", # EU-hosted, zero data retention, renewable-powered } MODEL_FRIENDLY_NAMES = { "greenpt/deepseek-v4.1-flash": "DeepSeek V4.1", @@ -1959,6 +1960,9 @@ MODEL_FRIENDLY_NAMES = { "tinfoil/gpt-oss-120b": "GPT-OSS 120B", "publicai/apertus-v1.5-8b": "Apertus 8B", "publicai/apertus-v1.5-70b": "Apertus 70B", + "regolo/apertus-70b": "Apertus 70B (Regolo)", + "regolo/qwen3.5-122b": "Qwen 3.5 122B", + "regolo/qwen-image": "Qwen Image", } @@ -1994,6 +1998,10 @@ async def list_models(request: Request): audio_modes = {"audio_transcription", "audio_speech"} audio_name_hints = ("whisper", "voxtral", "tts") embedding_name_hints = ("embed",) + # Image-generation models are used through Open WebUI's image feature + # (Admin > Images), not as chat models — listing them in the picker + # would fail on chat completions. + image_modes = {"image_generation"} def is_audio_model(m) -> bool: mode = ((m.get("info") or {}).get("meta") or {}).get("mode") or "" @@ -2009,9 +2017,13 @@ async def list_models(request: Request): mid = (m.get("id") or "").lower() return any(h in mid for h in embedding_name_hints) + def is_image_model(m) -> bool: + mode = ((m.get("info") or {}).get("meta") or {}).get("mode") or "" + return mode in image_modes + payload["data"] = [ m for m in payload.get("data", []) - if not is_audio_model(m) and not is_embedding_model(m) + if not is_audio_model(m) and not is_embedding_model(m) and not is_image_model(m) ] for model in payload.get("data", []):