Gateway: Modell-Liste aufgeraeumt - Router-Lanes + rohe Doppel-IDs raus
Die /v1/models-Liste zeigte Router-Lanes (coding/chat), Rollen-Aliase und rohe llama-swap-IDs durcheinander (verwirrte coding-vs-coder im Hermes-Desktop-Waehler). Jetzt nur noch die Klarnamen-Aliase: Router-Lanes nicht mehr gelistet (Routing bleibt, /chat/completions nimmt coding/chat weiter an), rohe Doppel-IDs ausgeblendet wenn ein Alias sie schon zeigt, tote Konstanten LANES/_LANE_LABELS entfernt. fast/scout/heavy unangetastet (tragend). py_compile gruen. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -5,7 +5,7 @@ from fastapi.responses import JSONResponse, StreamingResponse
|
|||||||
|
|
||||||
from config import LLAMA_SWAP_URL
|
from config import LLAMA_SWAP_URL
|
||||||
from services.gateway_stream import record_stream_chunk, record_usage
|
from services.gateway_stream import record_stream_chunk, record_usage
|
||||||
from services.router_logic import LANES, choose_for_lane
|
from services.router_logic import choose_for_lane
|
||||||
from services.routing_policy import load_policy
|
from services.routing_policy import load_policy
|
||||||
|
|
||||||
router = APIRouter(prefix="/v1")
|
router = APIRouter(prefix="/v1")
|
||||||
@@ -36,18 +36,14 @@ def _inject_language(body: dict, alias: str) -> None:
|
|||||||
elif isinstance(first_sys.get("content"), list):
|
elif isinstance(first_sys.get("content"), list):
|
||||||
first_sys["content"].append({"type": "text", "text": _LANG_DIRECTIVE})
|
first_sys["content"].append({"type": "text", "text": _LANG_DIRECTIVE})
|
||||||
|
|
||||||
# Virtuelle Lanes, die der Gateway zusätzlich zu den echten Modellen als „Modell" anbietet.
|
|
||||||
_LANE_LABELS = {"coding": "Coding (Router → coder/heavy/fast)", "chat": "Chat (Router → fast/heavy)"}
|
|
||||||
|
|
||||||
|
|
||||||
@router.get("/models")
|
@router.get("/models")
|
||||||
async def models(request: Request):
|
async def models(request: Request):
|
||||||
client = request.app.state.gw_client # geteilter Keep-Alive-Client (siehe app.py lifespan)
|
client = request.app.state.gw_client # geteilter Keep-Alive-Client (siehe app.py lifespan)
|
||||||
r = await client.get(f"{LLAMA_SWAP_URL}/v1/models", timeout=10.0)
|
r = await client.get(f"{LLAMA_SWAP_URL}/v1/models", timeout=10.0)
|
||||||
data = r.json()
|
data = r.json()
|
||||||
# Lanes ganz oben einblenden, damit IDEs einfach „coding"/„chat" wählen können.
|
# Aufgeräumt (07/2026): Die Router-Lanes (coding/chat) werden NICHT mehr als „Modell"
|
||||||
lanes = [{"id": lane, "object": "model", "owned_by": "mc2-router",
|
# angeboten — sie verwirrten (coding vs. coder) und seit dem Zed-Aus wählt sie niemand
|
||||||
"description": _LANE_LABELS.get(lane, lane)} for lane in LANES]
|
# mehr. Das Routing bleibt erhalten (siehe _proxy), sie stehen nur nicht mehr in der Liste.
|
||||||
# Kontextlänge je Modell mitliefern (aus der llama-swap-Config geparst). Ohne sie
|
# Kontextlänge je Modell mitliefern (aus der llama-swap-Config geparst). Ohne sie
|
||||||
# budgetieren Clients blind — Hermes-Subagents nahmen 256k an, schickten passende
|
# budgetieren Clients blind — Hermes-Subagents nahmen 256k an, schickten passende
|
||||||
# max_tokens und rissen damit den echten Server-Kontext (Radar-Lauf 02.07.).
|
# max_tokens und rissen damit den echten Server-Kontext (Radar-Lauf 02.07.).
|
||||||
@@ -55,6 +51,7 @@ async def models(request: Request):
|
|||||||
# Clients fragen aber genau damit an → als eigene Einträge einblenden.
|
# Clients fragen aber genau damit an → als eigene Einträge einblenden.
|
||||||
ctx_map: dict[str, int] = {}
|
ctx_map: dict[str, int] = {}
|
||||||
alias_entries: list[dict] = []
|
alias_entries: list[dict] = []
|
||||||
|
aliased_raw: set[str] = set() # rohe Modellnamen, die ein Klarnamen-Alias schon zeigt
|
||||||
try:
|
try:
|
||||||
from services import llamaswap
|
from services import llamaswap
|
||||||
for m in llamaswap.list_models():
|
for m in llamaswap.list_models():
|
||||||
@@ -69,7 +66,10 @@ async def models(request: Request):
|
|||||||
if ctx:
|
if ctx:
|
||||||
for api_id in m.get("api_ids", []):
|
for api_id in m.get("api_ids", []):
|
||||||
ctx_map[api_id] = ctx
|
ctx_map[api_id] = ctx
|
||||||
for alias in m.get("aliases", []):
|
aliases = m.get("aliases", [])
|
||||||
|
if aliases:
|
||||||
|
aliased_raw.add(m["name"])
|
||||||
|
for alias in aliases:
|
||||||
entry = {"id": alias, "object": "model", "owned_by": "mc2-alias",
|
entry = {"id": alias, "object": "model", "owned_by": "mc2-alias",
|
||||||
"description": f"Alias für {m['name']}"}
|
"description": f"Alias für {m['name']}"}
|
||||||
if ctx:
|
if ctx:
|
||||||
@@ -81,7 +81,10 @@ async def models(request: Request):
|
|||||||
for entry in data["data"]:
|
for entry in data["data"]:
|
||||||
if (ctx := ctx_map.get(entry.get("id"))):
|
if (ctx := ctx_map.get(entry.get("id"))):
|
||||||
entry.setdefault("context_length", ctx)
|
entry.setdefault("context_length", ctx)
|
||||||
data["data"] = lanes + alias_entries + data["data"]
|
# Rohe Doppel-IDs ausblenden, wenn ein Klarnamen-Alias sie schon zeigt → in der
|
||||||
|
# Liste erscheinen nur die freundlichen Rollen-Namen. Routing per roher ID bleibt.
|
||||||
|
raw = [e for e in data["data"] if e.get("id") not in aliased_raw]
|
||||||
|
data["data"] = alias_entries + raw
|
||||||
return JSONResponse(data, status_code=r.status_code)
|
return JSONResponse(data, status_code=r.status_code)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user