Alle Projekte

KI-Gateway

pacod-gw

Ein Gateway vor jedem Modell — mit den Schlüsseln, Preisen, Kontingenten und Nutzungsdaten, die deine Anwendungen nicht selbst verwalten sollten.

pacod-gw sitzt zwischen deinen Anwendungen und den LLM-Anbietern. Ein Rust-Kern leitet jeden Aufruf weiter oder übersetzt ihn, hält Anbieterschlüssel aus deinen Apps heraus, setzt Kontingente durch, bepreist jede Anfrage und streamt Nutzungsdaten in ClickHouse-Analysen — alles verwaltet über eine SvelteKit-Konsole.

  • Apache-2.0
  • Version 0.1.0
  • Vorschau

Funktionen

  • Proxy oder Managed

    Die API eines Anbieters Byte für Byte weiterleiten — oder das Gateway Templates auflösen, Parameter zusammenführen und zwischen Dialekten übersetzen lassen.

  • Viele Dialekte, ein Vertrag

    OpenAI, Anthropic, Gemini und ein nativer Dialekt; live gegen DeepSeek und GLM geprüft, Kimi und Ollama werden vom Mock emuliert.

  • Schlüssel bleiben im Gateway

    Gespeicherte Anbieter-Zugangsdaten und Gateway-Schlüssel pro Workspace. Anwendungen sehen nie den Schlüssel eines Anbieters.

  • Kontingente und Limits

    Token- und Anfragelimits pro Organisation, Workspace und Schlüssel, durchgesetzt, bevor ein Aufruf das Gateway verlässt.

  • Jeder Aufruf bepreist

    Ein Nutzungsjournal mit den Kosten in der Antwort, sodass Teams sofort sehen, was jede Anfrage gekostet hat.

  • Analysen auf ClickHouse

    Events fließen in einen eigenen Analysedienst mit Reports und geplanten Jobs; Prometheus, Grafana und OpenTelemetry für den Betrieb.

  • Routing und Intent

    Routing-Schemata und -Regeln sowie ein Intent-Plugin mit LLM-, Jev- und Kaskaden-Engines, das für jede Anfrage das passende Modell wählt.

  • Lite-Modus

    Dieselbe Data Plane in einem Container — ohne Datenbank, ohne Konsole —, konfiguriert über eine einzige .env-Datei und mit Protokollierung jedes Aufrufs.

Einordnung

Diagramm: wie die pacod-Projekte zusammenpassen LLM-Aufrufe Tippe auf ein Projekt, um zu sehen, womit es verbunden ist.

Warum ein Gateway

Jedes Produkt, das mit einem Sprachmodell spricht, implementiert am Ende dieselben Dinge neu: Anbieterschlüssel speichern, zwischen APIs übersetzen, Tokens zählen, Limits durchsetzen und die Rechnung erklären. pacod-gw nimmt all das aus der Anwendung heraus. Die Anwendung ruft einen Endpunkt mit einem Gateway-Schlüssel auf; das Gateway entscheidet, welches Modell den Aufruf bedient, was er kosten darf und wer ihn bezahlt.

Das erste Ziel ist konkret: einen LiteLLM-Proxy vor einer Anwendung ersetzen, indem nur deren Basis-URL und Schlüssel geändert werden.

Zwei Modi, ein Kern

Der Kern ist ein Rust-Binary mit zwei Listenern: der Data Plane für Anwendungen und der Management-API für die Konsole und Skripte. Der Modus wird über das URL-Präfix gewählt und pro Schlüssel erlaubt.

  • Proxy-Modus (/proxy/{provider}/…) leitet die API des Anbieters Byte für Byte weiter und ergänzt Authentifizierung, Limits und Abrechnung. Ein Template kann trotzdem das Modell und seine Parameter setzen.
  • Managed-Modus bedient OpenAIs /v1/chat/completions, Anthropics /v1/messages, Geminis generateContent und das native /gw/v1/chat, dazu Embeddings und Sprachausgabe.

Im Managed-Modus bestimmen der Dialekt des Aufrufers und der Anbieter des Modells den Weg:

Aufrufer spricht Modell liegt bei Was passiert
OpenAI-Dialekt einem OpenAI-kompatiblen Anbieter (OpenAI, DeepSeek, GLM, Kimi, Ollama, …) Die Bytes des Aufrufers werden gepatcht; die Kosten kommen in usage hinzu.
Anthropic-Dialekt Anthropic Die Konversation erreicht Anthropic so, wie sie gesendet wurde; die Kosten kommen in einem Header zurück.
Jede andere Kombination und die native Schnittstelle jedem Anbieter Übersetzt über ein anbieterneutrales Modell und zurück, sodass ein Aufruf über Dialekte hinweg ausweichen kann.

Ein Aufruf, Schritt für Schritt

  1. Authentifizieren. Der Schlüssel wird per HMAC in einem In-Memory-Snapshot der Konfiguration nachgeschlagen.
  2. Lesen. Ein Scanner findet Modell und Stream-Flags, ohne den ganzen Body zu parsen; die Plugins des Workspaces sehen die Konversation.
  3. Auflösen. Ein Template (@name oder x-gw-template) oder eine freigegebene Modell-ID bestimmt das Modell und seine Parameter.
  4. Zulassen. Das Parallelitätslimit des Schlüssels und jedes anwendbare Limit müssen passen.
  5. Senden. Die gespeicherten Anbieter-Zugangsdaten ersetzen den Gateway-Schlüssel. Im Managed-Modus werden ein 429, ein 5xx oder eine verlorene Verbindung wiederholt oder an das nächste Modell weitergereicht, bevor der Aufrufer ein Byte erhält.
  6. Weiterleiten und abrechnen. Die Antwort streamt zurück, während ein Abgriff die Nutzung aus einer Kopie liest; danach werden Kosten und Zähler aktualisiert, und ein Usage-Event geht in einen Spool auf der Festplatte.

Die Antwort enthält x-gw-request-id, x-gw-delay-ms (die Zeit, die das Gateway selbst hinzugefügt hat), x-gw-model-served und bei nicht gestreamten Managed-Aufrufen x-gw-cost.

Die Konfiguration liegt in PostgreSQL, aber der Anfragepfad wartet nicht darauf: Eine Änderung tauscht innerhalb von etwa zwei Sekunden einen neuen Snapshot ein, und fällt ein Speicher aus, läuft der Verkehr mit dem letzten weiter.

Organisationen, Workspaces und Schlüssel

Eine Organisation ist ein Kunde oder eine große Einheit. Ein Workspace ist eine Anwendung, ein Projekt, eine Umgebung oder ein Team und besitzt seine Schlüssel, Templates, Limits, Einstellungen und Nutzung. Zwei Regeln decken jede Einschränkung ab: Allow-Listen werden geschnitten und numerische Obergrenzen nehmen das Minimum.

Anbieterschlüssel gehören der Installation, einer Organisation oder einem Workspace, und ein Aufruf nutzt den nächstliegenden: den eigenen des Workspaces, dann den seiner Organisation, dann den gemeinsamen der Installation. Einen Schlüssel, den das Gateway bereits speichert, kann man an eine Organisation oder einen Workspace darunter weitergeben, ohne ihn erneut einzugeben; das Geheimnis verlässt das Gateway nie.

Rollen stehen in einer Datei, authz/gw.yaml, aus der die Prüfungen des Kerns und der Konsole erzeugt werden:

Rolle Was sie abdeckt
Platform-Admin Anbieter, Zugangsdaten, Modelle, Preise, Organisationen, Personen
Organisations-Admin Ihre Einstellungen, Workspaces, Mitglieder und Freigaben
Workspace-Admin Templates, Schlüssel, Limits, Einstellungen und Audit-Modus eines Workspaces
Auditor Liest Konfiguration, Nutzung und Audit-Mode-Aufzeichnungen
Viewer Liest Konfiguration und Nutzung; keine Geheimnisse, keine Audit-Mode-Aufzeichnungen

Aufrufe tragen Zuordnungen — end_user, session_id, trace_id, deklarierte Tags, agent_id, task, complexity —, die Reports, Limits und Routing auswerten. Personen melden sich an der Konsole mit lokalen Konten an oder, mit PGW_AUTH=oidc, über pacod-id.

Limits und Kosten

Ein Limit gilt für eine Organisation, einen Workspace, einen Schlüssel oder einen Endnutzer. Es zählt Tokens, Anfragen oder Ausgaben pro Minute, Stunde, Tag, Woche, Monat oder insgesamt und lehnt Aufrufe entweder ab (429, 402) oder zählt und berichtet nur. Anwendungen können den Kontingentstand eines Nutzers über GET /gw/v1/quota abfragen. Die Zähler werden etwa einmal pro Sekunde über PostgreSQL zwischen den Instanzen zusammengeführt, sodass ein Limit um etwa eine Sekunde Verkehr überschritten werden kann.

Jeder Aufruf wird beim Abschluss bepreist, aus einem versionierten Preis, der Cache-Lese- und -Schreibzugriffe, Reasoning, Batch-Varianten, Stufen nach Eingabegröße und Off-Peak-Fenster abdeckt. Einen Standardpreis gibt es nicht: Ein Modell braucht einen Preis oder ein ausdrückliches „kostenlos“, um aktiviert zu werden. Die Modellerkennung fragt jeden Anbieter, standardmäßig einmal täglich, nach seiner Modellliste und schlägt die Modelle vor, die dem Gateway fehlen; ein aus einem Vorschlag hinzugefügtes Modell bleibt ein Entwurf, bis es einen Preis hat. Ein geplanter Preis-Tracker liest die Preisliste von LiteLLM oder die Preisseite eines Anbieters und übernimmt Änderungen innerhalb einer festgelegten Grenze oder schlägt sie zur Freigabe vor. Solange er keine Quellen hat, schlägt die Konsole die Liste von LiteLLM für OpenAI, Anthropic, Gemini, DeepSeek und z.ai vor.

Routing und Intent

Ein Template kann einen Pool von Modellen mit Tiers, Gewichten und Prioritäten enthalten. Ohne weitere Einrichtung bedient das erste Modell, und das nächste übernimmt bei einem 429, einem 5xx oder einer verlorenen Verbindung. Ein Routing-Schema ergänzt Regeln auf das, was der Aufrufer angibt (complexity, task, Tags, Eingabegröße oder ein CEL-Ausdruck), und Algorithmen: Priorität, gewichtet, Round Robin, geringste Latenz und günstigster Preis, optional mit Session-Affinität, damit Prompt-Caches warm bleiben. Ein Circuit Breaker stellt ein fehlerhaftes Modell zurück, und jede Antwort nennt in x-gw-route die Regel, die sie geroutet hat.

Das Intent-Plugin beantwortet die Frage „Wofür ist dieser Aufruf?“ anhand eines Katalogs, den die Organisation oder der Workspace schreibt, mit einem LLM, der Jev-Engine oder einer Kaskade aus beiden. Sein Urteil kann einen Aufruf blockieren, routen, auf Limits pro Intent anrechnen oder zur Prüfung markieren; es kann zunächst im Schattenmodus laufen und verändert die Konversation nie.

Ein neuer Katalog beginnt mit einer eingebauten Vorlage, starter, mit den Intents eines allgemeinen Assistenten und Regeln, die markieren und blockieren. Ein neues Binding beginnt mit einer Vorlage, die das Gateway für seinen Geltungsbereich ausfüllt: Schattenmodus, dieser Katalog und das günstigste freigegebene Modell, das nach einem JSON-Schema antwortet, oder Jev, wenn es keines gibt. Die Panels zum Ausprobieren und Bewerten in der Konsole lassen die Engines auf Beispieltexten laufen, zuerst auf Demodaten, die für den Katalog erstellt werden, sodass sich die Engines vergleichen lassen, bevor ein Binding durchsetzt. Siehe den Routing-Leitfaden und das Plugin-Konzept.

Observability und Audit

Usage-Events erreichen den Analysedienst in Batches aus dem Spool jeder Instanz; die Zustellung erfolgt mindestens einmal, und ClickHouse entfernt Duplikate. Der Dienst erstellt Reports zu Nutzung, Fehlern, Gateway-Verzögerung, Rankings und Endnutzern, mit CSV-Export, und führt die geplanten Jobs aus. Die Konsole erreicht ihn nur über den Kern, der die Rolle des Aufrufers prüft und den Geltungsbereich erzwingt.

Prometheus, Grafana-Dashboards, Alertmanager-Regeln und OpenTelemetry-Traces decken den Betrieb ab; die Konsole zeigt Live-Kennzahlen, den Zustand der Anbieter und offene Alarme.

Der Audit-Modus speichert vollständige Aufrufe zur Fehlersuche: die Anfrage, jeden Versuch beim Anbieter und die Antworten. Er ist standardmäßig aus, eine Organisation kann ihn vorschreiben oder verbieten, Zugangsdaten werden vorher entfernt, und Aufzeichnungen laufen standardmäßig nach 14 Tagen ab.

Sicherheitsmodell

  • Anbieterschlüssel werden pro Zugangsdatensatz mit AES-256-GCM versiegelt, unter einem Key-Encryption-Key aus der Umgebung oder einer Datei, nie aus der Datenbank. Die API zeigt nur einen Fingerabdruck.
  • Gateway-Schlüssel (pgw_…) tragen 32 Zufallsbytes, werden als HMAC-SHA256 mit Pepper gespeichert und einmal angezeigt.
  • Mandantentrennung. Der Workspace ergibt sich aus dem Schlüssel, nie aus der Anfrage, und der Kern beschränkt Reports auf das, was die Rollen des Aufrufers erlauben.
  • Ausgehende Verbindungen zu Anbietern und Preisquellen werden nach der Namensauflösung geprüft: Private und Link-Local-Adressen werden abgelehnt, sofern ein Betreiber sie nicht freigibt.
  • Prompts bleiben aus Logs, Metriken und Traces heraus, die nur Metadaten enthalten; Bodies werden nur im Audit-Modus gespeichert.

Das Bedrohungsmodell nennt auch, was offen bleibt: Der Metrik-Port etwa hat keine Authentifizierung und trägt Mandanten-Labels, und im gemeinsamen Netzwerk erreicht jeder pacod-Container die Management-API, die sich dort allein auf ihre eigene Authentifizierung stützt.

Deployment und Betrieb

Der Kern läuft als all oder aufgeteilt in gateway-Instanzen und eine admin-Instanz. Die Instanzen teilen sich eine PostgreSQL und sonst nichts.

Layout Dateien
Ein Kern deploy/docker-compose.yml mit docker-compose.standalone.yml
Mehrere Gateways auf einem Host zusätzlich docker-compose.scale.yml
Gateways auf anderen Maschinen docker-compose.hub.yml zentral, deploy/node/ auf jeder Maschine
Kubernetes deploy/helm/pacod-gw
Minimales Gateway deploy/lite/docker-compose.yml

Wie jedes pacod-Projekt tritt das Gateway dem gemeinsamen Docker-Netzwerk pacod-net bei, in dem jeder Dienst einen eigenen Namen hat: Der Kern heißt pacod-gw, die übrigen Dienste gw-*. docker-compose.yml enthält die eigenen Dienste des Gateways; docker-compose.standalone.yml ergänzt seine Kopien der gemeinsamen Komponenten: PostgreSQL, pacod-id, Caddy und Monitoring. pacod-demo betreibt das Gateway zusammen mit den anderen pacod-Projekten unter demo.pacod.io. pacod-demo lädt nur die erste Datei und startet jede gemeinsame Komponente einmal; ClickHouse bleibt beim Gateway.

Caddy terminiert TLS und schickt jeden Aufruf an das bereite Gateway mit den wenigsten laufenden Aufrufen. Das Runbook behandelt Geheimnisse, Backup und Wiederherstellung, Schlüsselrotation, Upgrades und Fehlersuche; ein eingebauter Tester führt Testfälle und Lasttests aus der Konsole aus.

pacod-gw-lite behält Übersetzung, Streaming, Wiederholungen und Failover, mit Limits pro Schlüssel im Speicher und einer Logzeile pro Aufruf mit ihren Kosten. Seine Clients teilen sich die Anbieterschlüssel und sind beim Anbieter nicht voneinander getrennt. Im gemeinsamen Netzwerk heißt das minimale Gateway ebenfalls pacod-gw, daher läuft auf einem Host entweder es oder das vollständige Gateway (Details).

Was getestet ist

  • OpenAI, Anthropic, Gemini, DeepSeek und GLM werden mit Live-Aufrufen geprüft; Kimi, Ollama, xAI und Vertex AI nur gegen ihre Dokumentation und den Mock-Anbieter.
  • Das Designziel von 10.000 gleichzeitigen Streams im Proxy-Modus und 5.000 im Managed-Modus pro Instanz (2 CPUs, 1 GB) ist noch nicht durch einen Lasttest bestätigt.
  • Noch nicht erprobt: Let's-Encrypt-Zertifikate, ein Linux-Host, ein Upgrade zwischen Releases und das Helm-Chart auf einem echten Cluster.
  • Nicht im ersten Release: MCP- und Tool-Governance, Content-Guardrails und Response-Caching.

Die Seite zur Architektur zeigt, wie der Code aufgebaut ist und wo er vom Designkonzept abweicht.

Tech-Stack

Geschrieben in
  • Rust
  • TypeScript
  • Python
Tech-Stack
  • Rust
  • PostgreSQL
  • ClickHouse
  • SvelteKit
  • Caddy
  • Docker
  • Helm
  • Prometheus
  • OpenTelemetry

Schnellstart

Der komplette Stack mit einem Mock-Anbieter
make test-servicesmake verifymake dev-upmake smoke-mockopen http://localhost:13000
Das minimale Gateway
make lite-dev-upmake lite-smoke

Funktioniert mit

  • pacod-id

    Mit PGW_AUTH=oidc melden sich Personen über pacod-id an der Konsole an; Rollen und Workspaces stammen aus dessen Autorisierungs-Feed.

  • pacod-ap

    Jeder LLM-Aufruf eines Agenten läuft über das Gateway, das Modelle, Preise, Schlüssel und Nutzung verwaltet.

  • pacod-cms

    Die KI-Übersetzung im Studio ruft das Gateway auf, sodass das CMS nie einen Anbieterschlüssel hält.

  • pacod-kb

    Der optionale LLM-Bereinigungsschritt der Wissensdatenbank wird vom Gateway geroutet, bepreist und zugeordnet.

Lizenz

Apache-2.0