Auftragsbuch: 'wartung/gateway-modell-liste-aufraeumen' angenommen (Ein-Klick-Gate)

This commit is contained in:
Auftragsbuch
2026-07-09 19:44:42 +02:00
+13 -10
View File
@@ -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)