{ "_doku": "Versionierte Quelle des llmrouter. Secrets kommen NUR aus der Umgebung: OPENROUTER_API_KEY, MISTRAL_API_KEY, KIRA_REASONING_KEY, KIRA_STT_KEY, KIRA_TTS_KEY, ARTIFICIALANALYSIS_API_KEY, ADMIN_KEY; Client-Keys aus KEYS_FILE (token -> name), Rechte aus key-acls.json (name -> aliasse). Port 4010 (4001 im LXC von nginx belegt); Caddy zeigt llm.lan auf 4010, LiteLLM bleibt auf 4000 und bekommt alles, was hier unbekannt ist (fallback). MODEL_BLOCKLIST zeigt auf die Sperrliste (Host: /srv/llmrouter/model-blocklist.json).", "port": 4010, "logDir": "./log", "refreshHours": 12, "aaRefreshDays": 7, "lasttest": true, "upstreams": { "openrouter": { "base": "https://openrouter.ai/api/v1", "keyEnv": "OPENROUTER_API_KEY" }, "qwen": { "base": "http://10.18.5.30:11507/v1", "maxParallel": 1 }, "voice": { "base": "http://10.18.5.30:8803/v1" }, "ollama": { "base": "http://10.18.5.30:11434/v1" }, "mistral": { "base": "https://api.mistral.ai/v1", "keyEnv": "MISTRAL_API_KEY" }, "kira-chat": { "base": "http://10.6.42.111:8000/v1", "keyEnv": "KIRA_REASONING_KEY" }, "kira-stt": { "base": "http://10.6.42.111:8001/v1", "keyEnv": "KIRA_STT_KEY" }, "kira-tts": { "base": "http://10.6.42.111:8002/v1", "keyEnv": "KIRA_TTS_KEY" } }, "aliases": { "42i/marvin-2609:low": { "art": "schwelle", "index": 25, "minContext": 256000 }, "42i/marvin-2609:medium": { "art": "schwelle", "index": 45, "minContext": 256000 }, "42i/marvin-2609:high": { "art": "schwelle", "index": 49, "minContext": 500000 }, "42i/marvin-2609:max": { "art": "schwelle", "index": 53, "minContext": 500000 }, "42i/marvin-free": { "art": "fest", "upstream": "openrouter", "model": "openrouter/free" }, "42i/marvin-2609-core:none": { "art": "fest", "upstream": "qwen", "model": "qwen36:35b", "body": { "chat_template_kwargs": { "enable_thinking": false } } }, "42i/marvin-2609-core:medium": { "art": "fest", "upstream": "qwen", "model": "qwen36:35b", "body": { "chat_template_kwargs": { "enable_thinking": true } } }, "deizo/kira-reasoning": { "art": "fest", "upstream": "kira-chat", "model": "kira-reasoning" }, "deizo/kira-stt": { "art": "fest", "upstream": "kira-stt", "model": "kira-stt" }, "deizo/kira-tts": { "art": "fest", "upstream": "kira-tts", "model": "kira-tts" }, "42i/marvin-tts": { "art": "fest", "upstream": "voice", "model": "tts-1" }, "42i/marvin-stt": { "art": "fest", "upstream": "voice", "model": "whisper-1" }, "42i/marvin-tts-turbo": { "art": "fest", "upstream": "openrouter", "model": "x-ai/grok-voice-tts-1.0", "body": { "voice": "ara" }, "_doku": "Hörtest 2026-09-06 (Andreas): Grok Voice beste Stimme im OpenRouter-Katalog; Erstbyte 0,6 s, 32 s Audio in 5,8 s, $15/1M Zeichen. Fish S2.1 (Pro/free) klingt gut, liest aber Daten und Beträge falsch; MAI Voice 2 Flash (de-DE-Klaus) am schnellsten. Vorher Voxtral (keine deutsche Stimme). Stimme fest 'ara' (Andreas, Hörtest der fünf Stimmen), Grok kennt eve/ara/rex/sal/leo." }, "42i/marvin-stt-turbo": { "art": "fest", "upstream": "openrouter", "model": "mistralai/voxtral-small-24b-2507-stt", "_doku": "STT-Vergleich 2026-09-06 über OpenRouter (20 Modelle, deutscher Testsatz mit Datum/Beträgen/PLZ/Telefon, Studio und simulierte Telefonstrecke): Voxtral Small 24B, gpt-4o(-mini)-transcribe und MAI Transcribe 1.5 fehlerfrei auch am Telefon; Whisper large-v3(-turbo) verliert am Telefon 3 von 10 Zahlenstellen (deckt sich mit Andreas' Eindruck von kira-stt). Voxtral Small $0,18/h, günstigstes fehlerfreies. Vorher: voxtral-mini-latest direkt bei Mistral (ohne Router-Kosten, außerhalb des ZDR-Guardrails)." }, "42i/marvin-embedding": { "art": "fest", "upstream": "ollama", "model": "bge-m3" }, "42i/marvin-embedding-turbo": { "art": "fest", "upstream": "openrouter", "model": "mistralai/mistral-embed-2312" }, "42i/inka-qwen": { "art": "fest", "upstream": "openrouter", "model": "qwen/qwen3.8-27b", "body": { "reasoning": { "effort": "none" }, "provider": { "order": [ "AkashML", "Parasail" ], "allow_fallbacks": false } }, "_doku": "Test-Hirn fuer Inka (2026-09-06): Qwen 3.8 27B OHNE Denkstufe und mit festen Providern (fp8, Cache-Treffer $0,05/1M, Uptime >99,6 %), damit der Prompt-Cache ueber die Zuege traegt. Erster Qwen-Anruf ohne das: 5,2 s je Zug, 700 Reasoning-Token, Cache in 3 von 8 Zuegen." }, "auto/mass": { "art": "fest", "upstream": "qwen", "model": "qwen36:35b", "body": { "chat_template_kwargs": { "enable_thinking": true } }, "ausweich": "auto/mass:fast", "_doku": "Massenarbeit ohne Latenzanspruch: Mail-Ingest, Triage, Zusammenfassungen, opencodes small_model. Laeuft auf der eigenen Karte und kostet nichts. Steht der Knoten oder ist die Karte belegt, weicht der Router einmal auf auto/mass:fast aus -- ohne das haengt sonst jede Titelzeile jedes Agenten (42i/intern#1252)." }, "auto/mass:fast": { "art": "schwelle", "index": 25, "minContext": 256000, "minOutput": 32768, "ausweich": "auto/coding:junior", "_doku": "Wie auto/mass, aber wenn es schnell gehen muss: billigstes Cloud-Modell ueber der Mindestschwelle. Andreas 2026-09-06: 'bei masse ist halt: brauchst du es schnell, nimm ling, ist geschwindigkeit nicht wichtig, nimm core'. Ausweich auf auto/coding:junior seit 2026-09-08 (Andreas): ling hat nachts Kapazitaets- und Ratengrenzprobleme (2026-09-07 23:20-23:52: 5x 502 nach ~270 s haengendem Upstream, 117x 429), und auto/mass:fast war als Endstation ohne Rueckfall. coding:junior erfuellt ling strukturell nie (Coding 50,6 / Agentic 21,1 gegen Coding>=68 / Agentic>=45) -- der Ausweich landet also garantiert auf einem tauglichen Modell, nicht auf ling selbst. minOutput 32768 seit 2026-09-09 (Andreas): Masse schreibt fast nur kleine Completion-Haeufchen (gemessen 09.09.: 1.146 von 1.415 Requests unter 100 Token), das 64K-Output-Gate trieb sie sonst unnoetig auf solar-pro4; Arbeitsmodelle behalten 65536." }, "auto/allround:junior": { "art": "schwelle", "index": 40, "minContext": 256000, "_doku": "Standard fuer alles ohne besondere Achse: Text, Service, Assistenz, Doku." }, "auto/allround:senior": { "art": "schwelle", "index": 49, "minContext": 256000, "_doku": "Wie allround, aber wenn der generalistische Index zaehlt -- begutachten und entwerfen statt Werkzeugschleife." }, "auto/coding:junior": { "art": "schwelle", "coding": 68, "agentic": 45, "minContext": 256000, "_doku": "Code schreiben und pruefen. Agentic als Untergrenze, weil der Werkzeug-Rundlauf (lesen, patchen, testen, Fehler deuten) sonst nicht traegt." }, "auto/coding:senior": { "art": "schwelle", "coding": 76, "agentic": 50, "minContext": 256000, "_doku": "Schwerere Code-Aufgaben. Ausdruecklich anfordern (/model auto/coding:senior); keine Rolle zeigt von sich aus hierher." }, "auto/leader:junior": { "art": "schwelle", "index": 45, "agentic": 50, "minContext": 256000, "_doku": "Fuehren und koordinieren: lange Schleifen ueber fremde Tickets, Subagenten ansetzen, fremde Fehler erkennen. Latte 50 (Andreas 2026-09-06): tiefer zu gehen laesst nur Schlechteres zu, nichts Billigeres." }, "auto/leader:senior": { "art": "schwelle", "coding": 74, "agentic": 53, "minContext": 256000, "_doku": "Die teure Stufe. Latte 53 statt 55 (Andreas 2026-09-06): damit erfuellt grok-4.6 das Profil, Opus 5 bleibt erreichbar, wird aber nicht mehr automatisch gewaehlt. Stand 2026-09-07 zeigt KEINE Rolle hierher." } }, "_stufen_doku": "Stufen als Index-Schwelle (Artificial-Analysis-Intelligence-Index, 0-100) mit Mindestkontext (Andreas 2026-09-05): low 25/256k, medium 45/256k, high 49/500k, max 53/500k. Die Art \"alternative\" mit Referenzmodell (z.B. anthropic/claude-opus-5:medium) bleibt möglich. Namen versioniert wie bei LiteLLM (2608): 42i/marvin-2609:*.", "_fallback_entfernt": "Bis 2026-09-07 gingen unbekannte Modellnamen (die 2608-Reihe) an LiteLLM durch. Mit der Abschaltung von LiteLLM ist der Weg weg: unbekannte Namen sind jetzt ein Fehler statt einer stillen Weiterleitung. Das ist Absicht -- eine Weiterleitung an einen toten Dienst waere ein Timeout ohne Hinweis, und seit Caddy auf :4000 auf den Router zeigt, waere es sogar eine Schleife auf sich selbst.", "_rollen_doku": "Rollen entkoppeln Agenten von Modellnamen: ein Agent ruft role/worker, welches Modell dahintersteht, stellt man HIER um -- aus der Ferne, ohne Container-Deploy. Seit 2026-09-07 zeigen die Rollen auf auto/-Profile (42i/intern#1252) statt direkt auf eine Index-Stufe: die Wahl haengt jetzt an der Achse, die zur Aufgabe passt. xo, teamleader und lead auf auto/leader:junior (Andreas 2026-09-07: keine Rolle mehr auf der teuren Stufe); worker, engineer, qa und perf auf auto/coding:junior; alles uebrige auf auto/allround:junior. role/inka bleibt fest auf Luna (Telefon-Hirn, Cache-Verhalten gemessen). Die 42i/marvin-2609:*-Stufen bleiben als eigene Namen bestehen, damit direkte Aufrufe weiter gehen. role/ops zeigt seit 2026-09-07 auf auto/mass (lokales Qwen, kostenlos) -- Andreas: 'lass buzz auf 42i/mass laufen, der macht nicht so viel, das muss ein qwen koennen'. Buzz ist der einzige ops-Agent, deshalb bleibt die Rolle der richtige Ort. Nachgemessen am selben Tag: Qwen MIT Denkstufe (auto/mass setzt enable_thinking) holt den Persona-Skill selbst -- der alte 0/9-Befund (live/live#1171) galt fuer Qwen OHNE Denken. AGENT_SKILL_EINBACKEN ist fuer buzz deshalb NICHT gesetzt. VERSUCH ab 2026-09-07 20:3x (Andreas: 'stellen wir die worker mal auf ling um und schauen was passiert'): role/worker -> auto/mass:fast (ling-3.0-flash) statt auto/coding:junior (glm-5.3-flash). Gegenargument steht in #1252 (ling Coding 50,6 / Agentic 21,1 gegen 71,5 / 51,5) -- deshalb ausdruecklich ein Versuch mit Rueckweg: eine Zeile hier. Zu beobachten ist nicht der Preis, sondern ob die Worker-Ergebnisse die Abnahme des Teamleiters bestehen.", "rollen": { "xo": "auto/leader:junior", "architect": "auto/allround:junior", "teamleader": "auto/leader:junior", "lead": "auto/leader:junior", "leader": "auto/leader:junior", "worker": "auto/mass:fast", "coder": "auto/coding:junior", "engineer": "auto/coding:junior", "po": "auto/allround:junior", "speaker": "auto/allround:junior", "support": "auto/allround:junior", "assistant": "auto/allround:junior", "privacy": "auto/allround:junior", "service": "auto/allround:junior", "ops": "auto/mass", "marketing": "auto/allround:junior", "qa": "auto/coding:junior", "perf": "auto/coding:junior", "i18n": "auto/allround:junior", "docs": "auto/allround:junior", "ar": "auto/allround:junior", "archivist": "auto/allround:junior", "inka": "openrouter/openai/gpt-5.6-luna" }, "_namen_doku": "Namensraeume: 42i/* = konfigurierte Aliasse (aliases); deizo/* = Modelle im Prod-RZ deizo (kira, fest); openrouter/[:effort] = 1:1 an OpenRouter, Effort als reasoning.effort; alt/[:effort] = guenstigste Alternative derselben Klasse (Intelligence, Coding, Agentic je >= 95 % der Referenz, Kontext >= 90 %, billiger), aufgeloest bei der ersten Anfrage und im 12h-Takt erneuert, OHNE Last-Probe; role/ = Rolle (rollen). Alles andere -> fallback (LiteLLM).", "anthropicModus": "alt", "_anthropic_doku": "Claude Code/Desktop schicken nackte IDs (claude-sonnet-5, claude-opus-5-20260723, claude-sonnet-4-5[1m]). Der Router normalisiert sie und bildet sie je anthropicModus auf alt/anthropic/ (Standard) oder openrouter/anthropic/ ab; ein Client-Effort (output_config.effort) wird als Stufe angehaengt. Rechte: die ACL prueft den abgebildeten Namen, also alt/* bzw. openrouter/*.", "altnamen": { "42i/marvin-2608:none": "42i/marvin-2609:low", "42i/marvin-2608:low": "42i/marvin-2609:low", "42i/marvin-2608:medium": "42i/marvin-2609:medium", "42i/marvin-2608:high": "42i/marvin-2609:high", "42i/marvin-2608:extra": "42i/marvin-2609:high", "42i/marvin-2608:ultra": "42i/marvin-2609:max", "42i/marvin-2608-core:none": "42i/marvin-2609-core:none", "42i/marvin-2608-core:medium": "42i/marvin-2609-core:medium", "42i/marvin-2608-auto": "auto/allround:junior", "42i/marvin-2608-mass:none": "auto/mass:fast", "42i/marvin-2608-mass:medium": "auto/mass:fast", "42i/marvin-2608-mass": "auto/mass:fast", "marvin-tts": "42i/marvin-tts", "marvin-stt": "42i/marvin-stt", "marvin-tts-turbo": "42i/marvin-tts-turbo", "marvin-stt-turbo": "42i/marvin-stt-turbo", "marvin-embedding": "42i/marvin-embedding", "kira-reasoning": "deizo/kira-reasoning", "kira-stt": "deizo/kira-stt", "kira-tts": "deizo/kira-tts" }, "_altnamen_doku": "Alte Modellnamen (LiteLLM-Zeit) auf heutige Aliasse. Eine laufende opencode- oder Claude-Sitzung traegt ihren Modellnamen bis zum Ende mit; verschwindet er waehrend des Laufs aus der Config, stirbt sie beim naechsten Zug. Am 2026-09-07 hat das fuenf Teamlaeufe gekostet (Lehre im Kommentar zu 42i/intern#1251). Die Uebersetzung greift VOR ACL-Pruefung und Aufloesung. Eintraege koennen weg, wenn sicher ist, dass niemand den alten Namen mehr traegt." }