mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-11-01 10:42:23 +01:00
fix(models): skip non-chat models when resolving chat defaults (#6907)
This commit is contained in:
@@ -659,7 +659,7 @@ _NON_CHAT_CONTAINS = (
|
|||||||
"gliner", "riva", "-parse", "-embedqa", "-nemoretriever",
|
"gliner", "riva", "-parse", "-embedqa", "-nemoretriever",
|
||||||
"topic-control", "calibration",
|
"topic-control", "calibration",
|
||||||
"ai-synthetic-video", "cosmos-reason2",
|
"ai-synthetic-video", "cosmos-reason2",
|
||||||
"bge", "llama-guard",
|
"bge", "llama-guard", "-embed", "rerank",
|
||||||
)
|
)
|
||||||
_NON_CHAT_EXACT_PREFIXES = (
|
_NON_CHAT_EXACT_PREFIXES = (
|
||||||
"gpt-audio", # gpt-audio, gpt-audio-mini etc. (not gpt-4o-audio-preview which is chat)
|
"gpt-audio", # gpt-audio, gpt-audio-mini etc. (not gpt-4o-audio-preview which is chat)
|
||||||
@@ -2846,11 +2846,12 @@ def setup_model_routes(model_discovery):
|
|||||||
return {"endpoint_id": "", "endpoint_url": "", "model": ""}
|
return {"endpoint_id": "", "endpoint_url": "", "model": ""}
|
||||||
base = _normalize_base(ep.base_url)
|
base = _normalize_base(ep.base_url)
|
||||||
chat_url = build_chat_url(base)
|
chat_url = build_chat_url(base)
|
||||||
|
if model and not _is_chat_model(model):
|
||||||
|
model = ""
|
||||||
if not model and (getattr(ep, "cached_models", None) or getattr(ep, "pinned_models", None)):
|
if not model and (getattr(ep, "cached_models", None) or getattr(ep, "pinned_models", None)):
|
||||||
try:
|
try:
|
||||||
visible = _visible_models(ep.cached_models, getattr(ep, "hidden_models", None), getattr(ep, "pinned_models", None))
|
visible = _visible_models(ep.cached_models, getattr(ep, "hidden_models", None), getattr(ep, "pinned_models", None))
|
||||||
if visible:
|
model = next((mid for mid in visible if _is_chat_model(mid)), "")
|
||||||
model = visible[0]
|
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
return {"endpoint_id": ep.id, "endpoint_url": chat_url, "model": model}
|
return {"endpoint_id": ep.id, "endpoint_url": chat_url, "model": model}
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
"""Issue #2137: never preselect an embedding or other non-chat model."""
|
||||||
|
|
||||||
|
import json
|
||||||
|
from types import SimpleNamespace
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from fastapi import FastAPI
|
||||||
|
from fastapi.testclient import TestClient
|
||||||
|
|
||||||
|
from core.database import ModelEndpoint
|
||||||
|
from routes import model_routes, prefs_routes
|
||||||
|
from tests.helpers.database import disposable_database
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def defaults_api(monkeypatch, tmp_path):
|
||||||
|
defaults = {}
|
||||||
|
with disposable_database(tmp_path) as factory:
|
||||||
|
monkeypatch.setattr(model_routes, "SessionLocal", factory)
|
||||||
|
monkeypatch.setattr(model_routes, "_load_settings", lambda: {})
|
||||||
|
monkeypatch.setattr(prefs_routes, "_load_for_user", lambda owner: defaults)
|
||||||
|
app = FastAPI()
|
||||||
|
app.state.auth_manager = SimpleNamespace(is_admin=lambda owner: False)
|
||||||
|
|
||||||
|
@app.middleware("http")
|
||||||
|
async def owner(request, call_next):
|
||||||
|
request.state.current_user = "alice"
|
||||||
|
return await call_next(request)
|
||||||
|
|
||||||
|
app.include_router(model_routes.setup_model_routes(model_discovery=None))
|
||||||
|
with TestClient(app) as client:
|
||||||
|
yield client, factory, defaults
|
||||||
|
|
||||||
|
|
||||||
|
def _endpoint(factory, *, cached=(), pinned=(), hidden=(), owner="alice", endpoint_id="ep"):
|
||||||
|
with factory() as db:
|
||||||
|
db.add(ModelEndpoint(
|
||||||
|
id=endpoint_id, name="Fixture", base_url="http://model.invalid/v1", owner=owner,
|
||||||
|
is_enabled=True, cached_models=json.dumps(cached),
|
||||||
|
pinned_models=json.dumps(pinned), hidden_models=json.dumps(hidden),
|
||||||
|
))
|
||||||
|
db.commit()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("non_chat", [
|
||||||
|
"text-embedding-3-small", "nomic-embed-text:latest", "jina-reranker-v2-base",
|
||||||
|
"tts-1", "whisper-1", "gpt-image-1",
|
||||||
|
])
|
||||||
|
def test_automatic_default_skips_non_chat_models(defaults_api, non_chat):
|
||||||
|
client, factory, _ = defaults_api
|
||||||
|
_endpoint(factory, cached=[non_chat, "chat-model"])
|
||||||
|
assert client.get("/api/default-chat").json()["model"] == "chat-model"
|
||||||
|
|
||||||
|
|
||||||
|
def test_non_chat_saved_default_falls_back_to_visible_pinned_chat(defaults_api):
|
||||||
|
client, factory, defaults = defaults_api
|
||||||
|
_endpoint(factory, cached=["text-embedding-3-small", "hidden-chat"],
|
||||||
|
pinned=["jina-reranker-v2-base", "pinned-chat"], hidden=["hidden-chat"])
|
||||||
|
defaults.update(default_endpoint_id="ep", default_model="text-embedding-3-small")
|
||||||
|
assert client.get("/api/default-chat").json()["model"] == "pinned-chat"
|
||||||
|
|
||||||
|
|
||||||
|
def test_no_chat_candidate_leaves_model_empty(defaults_api):
|
||||||
|
client, factory, defaults = defaults_api
|
||||||
|
_endpoint(factory, cached=["text-embedding-3-small", "hidden-chat"],
|
||||||
|
pinned=["jina-reranker-v2-base"], hidden=["hidden-chat"])
|
||||||
|
defaults.update(default_endpoint_id="ep", default_model="text-embedding-3-small")
|
||||||
|
result = client.get("/api/default-chat").json()
|
||||||
|
assert result == {"endpoint_id": "ep", "endpoint_url": "http://model.invalid/v1/chat/completions", "model": ""}
|
||||||
|
|
||||||
|
|
||||||
|
def test_valid_explicit_model_survives_stale_catalog(defaults_api):
|
||||||
|
client, factory, defaults = defaults_api
|
||||||
|
_endpoint(factory, cached=["text-embedding-3-small", "other-chat"])
|
||||||
|
defaults.update(default_endpoint_id="ep", default_model="my-custom-chat")
|
||||||
|
assert client.get("/api/default-chat").json()["model"] == "my-custom-chat"
|
||||||
|
|
||||||
|
|
||||||
|
def test_model_filter_preserves_owner_scope(defaults_api):
|
||||||
|
client, factory, defaults = defaults_api
|
||||||
|
_endpoint(factory, owner="bob", endpoint_id="bobs-endpoint", cached=["bobs-chat"])
|
||||||
|
_endpoint(factory, cached=["text-embedding-3-small", "alices-chat"])
|
||||||
|
defaults.update(default_endpoint_id="bobs-endpoint")
|
||||||
|
result = client.get("/api/default-chat").json()
|
||||||
|
assert result["endpoint_id"] == "ep"
|
||||||
|
assert result["model"] == "alices-chat"
|
||||||
Reference in New Issue
Block a user