mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-09-27 18:42:20 +02:00
fix(model-routing): keep selected models strict (#5801)
Co-authored-by: Alexandre Teixeira <111787685+alteixeira20@users.noreply.github.com>
This commit is contained in:
co-authored by
Alexandre Teixeira
parent
53869d194d
commit
b52296471b
@@ -443,28 +443,14 @@ def resolve_endpoint_by_id(
|
||||
|
||||
|
||||
def resolve_chat_fallback_candidates(owner: Optional[str] = None) -> list:
|
||||
"""Build the configured default-chat fallback chain as a list of
|
||||
(chat_url, model, headers) tuples, skipping any that can't resolve.
|
||||
"""Compatibility shim for the retired default-chat fallback chain."""
|
||||
|
||||
The primary model is NOT included — callers prepend their session's
|
||||
current (url, model, headers) so per-session model overrides are honored.
|
||||
"""
|
||||
return _resolve_fallback_candidates("default_model_fallbacks", owner=owner)
|
||||
del owner
|
||||
return []
|
||||
|
||||
|
||||
def resolve_utility_fallback_candidates(owner: Optional[str] = None) -> list:
|
||||
"""Configured fallback chain for the Utility model (`utility_model_fallbacks`)."""
|
||||
try:
|
||||
from src.settings import get_user_setting, load_settings
|
||||
settings = load_settings()
|
||||
utility_ep = (get_user_setting("utility_endpoint_id", owner or "", settings.get("utility_endpoint_id", "")) or "").strip()
|
||||
if not utility_ep:
|
||||
utility_chain = get_user_setting("utility_model_fallbacks", owner or "", settings.get("utility_model_fallbacks") or []) or []
|
||||
if utility_chain:
|
||||
return _resolve_fallback_candidates("utility_model_fallbacks", owner=owner)
|
||||
return _resolve_fallback_candidates("default_model_fallbacks", owner=owner)
|
||||
except Exception:
|
||||
pass
|
||||
return _resolve_fallback_candidates("utility_model_fallbacks", owner=owner)
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
"""Foreground Chat and Agent model-routing policy.
|
||||
|
||||
The selected session model is strict by default. Historical
|
||||
``default_model_fallbacks`` values remain stored for compatibility, but this
|
||||
policy intentionally does not read or migrate them.
|
||||
"""
|
||||
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
|
||||
def resolve_foreground_fallback_candidates(owner: Optional[str] = None) -> list:
|
||||
"""Return fallback candidates for a foreground Chat or Agent request.
|
||||
|
||||
Foreground routing is strict, so no alternate endpoint/model is eligible.
|
||||
``owner`` is accepted to keep this policy boundary owner-aware.
|
||||
"""
|
||||
|
||||
del owner
|
||||
return []
|
||||
|
||||
|
||||
def build_foreground_model_candidates(
|
||||
endpoint_url: str,
|
||||
model: str,
|
||||
headers: Optional[Dict[str, Any]] = None,
|
||||
owner: Optional[str] = None,
|
||||
) -> list:
|
||||
"""Build the ordered candidate list for a foreground request."""
|
||||
|
||||
primary = (endpoint_url, model, headers or {})
|
||||
return [primary] + resolve_foreground_fallback_candidates(owner=owner)
|
||||
+4
-5
@@ -1949,11 +1949,10 @@ def _dedupe_candidates(candidates):
|
||||
"""Filter malformed entries and drop a later repeat of an already-seen
|
||||
``(url, model)`` route, preserving order (first occurrence wins).
|
||||
|
||||
The chain is the primary target followed by the configured fallbacks, so a
|
||||
fallback that repeats the session's current model — a common misconfiguration,
|
||||
since callers prepend the live ``(url, model)`` to ``default_model_fallbacks``
|
||||
— would otherwise make the chain re-attempt the very route that just failed:
|
||||
a wasted round-trip plus a spurious ``fallback`` notice for a switch that did
|
||||
The chain is the primary target followed by any caller-authorized
|
||||
fallbacks. A fallback that repeats the session's current model would
|
||||
otherwise make the chain re-attempt the very route that just failed: a
|
||||
wasted round-trip plus a spurious ``fallback`` notice for a switch that did
|
||||
not happen. Headers are not part of the key; the first tuple (with its
|
||||
headers) is the one kept.
|
||||
"""
|
||||
|
||||
+6
-7
@@ -138,14 +138,13 @@ DEFAULT_SETTINGS = {
|
||||
# Email replies use email_writing_style instead because greetings,
|
||||
# signatures, and mailbox identity rules are medium-specific.
|
||||
"document_writing_style": "",
|
||||
# Ordered fallback chain for the default chat model. Each entry is
|
||||
# {"endpoint_id": "...", "model": "..."}. If the primary model fails
|
||||
# before producing output (endpoint offline / errors), the chat
|
||||
# dispatch retries the next entry in order.
|
||||
# Legacy ordered fallback chain for the default chat model. Values remain
|
||||
# stored for compatibility and rollback reference, but model routing no
|
||||
# longer reads this key.
|
||||
"default_model_fallbacks": [],
|
||||
# When True, non-admin users inherit global default model/endpoint/fallbacks
|
||||
# when they have no personal defaults. When False, users only use their
|
||||
# personal defaults (no global fallback). Default is False.
|
||||
# When True, non-admin users inherit the global default model/endpoint when
|
||||
# they have no personal defaults. When False, users only use their personal
|
||||
# defaults. Default is False.
|
||||
"share_defaults_with_users": False,
|
||||
"utility_endpoint_id": "",
|
||||
"utility_model": "",
|
||||
|
||||
@@ -32,7 +32,7 @@ def resolve_task_candidates(
|
||||
2. Utility endpoint/model
|
||||
3. Default endpoint/model
|
||||
4. Utility fallback chain
|
||||
5. Default fallback chain
|
||||
5. Retired default-fallback compatibility hook (currently empty)
|
||||
"""
|
||||
candidates = []
|
||||
|
||||
|
||||
Reference in New Issue
Block a user