KI-Kosten sind kein Nebenaspekt, sondern die Zahl, die über den Nutzen einer Anwendung entscheidet. Die gute Nachricht: Bei den meisten Anwendungen lassen sich die Kosten um 60 bis 90 Prozent senken, ohne die Qualität zu verschlechtern. Ein Token ist nicht gleich ein Token.
Die Bestandteile
Die Kosten einer Anfrage bestehen aus drei Posten:
1. Eingabe-Token (Prompt, Kontext, Dokumente)
2. Ausgabe-Token (Antwort)
3. Zwischenspeicher (bei Treffer nur ein Bruchteil)
Warum das wichtig ist:
Ausgabe-Token kosten meist 3-5x so viel wie Eingabe
-> Lange Antworten sind der teuerste Teil
-> "Bitte ausfuehrlich erklaeren" ist teuer
Zwischenspeicher-Treffer kosten oft 10 % oder weniger
-> Wiederkehrender Prompt-Anfang (Systemanweisung,
Few-Shot-Beispiele) kann fast kostenlos werden
Zusatzkosten, die oft vergessen werden:
- Vektorsuche (Embeddings bei jeder Anfrage!)
- Zwischenspeicher-Speicher (Aufbewahrung des Cache!)
- Auswertung, Protokollierung, Bewertungslaeufe
- Werkzeugaufrufe (jeder Aufruf ist eine eigene Anfrage!)
- Wiederholungen bei Fehlern
Beispielrechnung (grobes Modell - eigene Preise einsetzen):
10.000 Anfragen/Tag
je Anfrage: 4.000 Eingabe-Token, 600 Ausgabe-Token
Eingabe $3 / 1 Mio Token -> 40 Mio -> $120/Tag
Ausgabe $15 / 1 Mio Token -> 6 Mio -> $90/Tag
Summe $210/Tag = $6.300/Monat
-> Mit Zwischenspeicher auf 70 % Eingabeersparnis:
Eingabe $36/Tag -> Gesamt $126/Tag = $3.780/Monat
Ersparnis 40 % durch EINE Massnahme.
Die wirksamsten Maßnahmen
1) ZWISCHENSPEICHER (Ersparnis 30-70 %)
Feste Systemanweisungen und Beispiele AN DEN ANFANG.
Alles, was sich je Anfrage aendert, NACH HINTEN.
# FALSCH: Zeitstempel/Anfrage-ID zuerst -> Cache nie getroffen
prompt = f"Aktuelle Zeit: {now}. Frage: {frage}"
# RICHTIG: fester Anfang, veraenderliches Ende
prompt = (
SYSTEM_ANWEISUNG + # immer identisch -> Cache!
FEW_SHOT_BEISPIELE + # immer identisch -> Cache!
f"Frage: {frage}" # veraenderlich
)
# Treffer kosten oft nur 10 % des Eingabepreises.
# Kurze Cache-Gueltigkeit (1-5 min) reicht bei Anwendungen:
# parallele Anfragen und Wiederholungen treffen trotzdem.
2) KUERZERER KONTEXT (Ersparnis 20-50 %)
Nicht "alles ins Fenster" - nur das Relevante.
RAG mit 3 guten Abschnitten statt 20 mittelmaessigen:
billiger UND besser.
3) KLEINERES MODELL, WO ES GENUEGT (Ersparnis 60-95 %)
Die haeufigsten 80 % der Anfragen sind einfach:
Formatierung, Klassifizierung, Extraktion, Zusammenfassung.
Dafuer ein kleines Modell, fuer die schwierigen Faelle
das grosse.
def beantworten(frage):
if ist_einfach(frage): # Klassifizierung
return kleines_modell(frage)
return grosses_modell(frage)
# Mit Bewertungssatz pruefen, dass die Qualitaet haelt!
4) AUSGABE BEGRENZEN (Ersparnis 20-60 %)
max_tokens setzen! Ohne Grenze kann eine Antwort
endlos werden und man zahlt das Doppelte.
Kurze, gezielte Antworten erzeugen statt Aufsaetze.
5) EINFRIEREN SELTENER ANTWORTEN (Ersparnis bis 90 %)
Was sich nicht aendert, muss nicht berechnet werden:
Einfrieren im Zwischenspeicher (Redis, Dateisystem).
FAQ, Stammdaten, kurze Erklaerungen.
# Invaliderung mitdenken: Schluessel = Hash der Anfrage,
# Gueltigkeit setzen.
6) WENIGER WERKZEUGAUFRUFE
Jeder Aufruf ist eine eigene Anfrage mit vollem Kontext.
Ein Agent mit 10 Werkzeugen und 5 Runden kostet das
10- bis 20-fache einer einzelnen Anfrage.
# Werkzeugdefinitionen schlank halten (sie sind
# Eingabe-Token bei JEDEM Aufruf!)
# Schleifen begrenzen (max_iterations)
7) VERARBEITUNG OFFLINE (Ersparnis bis 95 %)
Was laenger als 5 Sekunden dauern darf, muss nicht
in die Anfrage. Ueber Nacht verarbeiten, wo
Rabatte oder Batchpreise gelten (oft 50 %).
# Stapelverarbeitung nutzen, wo verfuegbar.
# Kuerzen statt Echtzeit.
8) KONFIDENZ-BASIERTE ESKALATION
Erst ein kleines Modell, nur bei Unsicherheit das grosse.
Der beste Kompromiss aus Kosten und Qualitaet.
Messen statt schätzen
# Ohne Messung gibt es keine Optimierung - nur Vermutungen.
# 1) Kosten je Funktion erfassen (nicht nur insgesamt!)
# Ein Durchschnitt verdeckt, dass eine Funktion
# 80 % der Kosten verursacht.
kosten = {
"funktion": name,
"eingabe_token": antwort.usage.prompt_tokens,
"ausgabe_token": antwort.usage.completion_tokens,
"cache_treffer": getattr(antwort.usage, "cached_tokens", 0),
"kosten_eur": berechne_kosten(antwort.usage),
}
# Taeglich/woechentlich aggregieren:
# SELECT funktion,
# SUM(kosten_eur) AS summe,
# SUM(kosten_eur) / COUNT(*) AS je_anfrage,
# SUM(cache_treffer) / SUM(eingabe_token) AS cachequote
# FROM ki_aufrufe GROUP BY funktion;
#
# Die wichtigsten drei Kennzahlen:
# Kosten je erfolgreicher Anfrage
# Zwischenspeicher-Trefferquote (Ziel: > 50 %)
# Anteil der Werkzeugaufrufe an den Kosten
# 2) Vor der Optimierung: MESSEN
# Sonst optimiert man die falsche Stelle.
# 3) Ueberwachung
# - Tageskosten mit Schwellenwert (Ausreisser!)
# - Kosten je Funktion im Verlauf
# - Fehlerquote (Wiederholungen kosten!)
# - Cachequote
# Ein Warnhinweis bei "Tageskosten > 150 % des Ueblichen"
# ist die einfachste wirksame Absicherung.
# Ohne Grenze kann eine Schleife in einem Agenten
# innerhalb von Stunden Monatsbudgets verbrauchen!
# 4) Harte Obergrenzen
# - max_tokens je Aufruf
# - Aufrufzahlen je Nutzer/Tag
# - Obergrenze fuer Werkzeugrunden
# - Gesamtbudget mit Abschaltung
Qualität halten: der Bewertungssatz
Jede Kostenoptimierung muss gegen die Qualitaet geprueft werden.
# 1) Bewertungssatz anlegen: 50-200 echte Faelle
# mit erwartetem Ergebnis (Goldstandard).
# Aus dem Produktivbetrieb ziehen, nicht erfinden!
# 2) Vor der Optimierung messen
# Qualitaet: 78 % korrekt, $0,34 je Anfrage
# 3) Nach der Optimierung messen
# Qualitaet: 77 % korrekt, $0,09 je Anfrage
# -> 74 % guenstiger bei 1 % Qualitaetsverlust: gut.
# ODER
# Qualitaet: 62 % korrekt, $0,09 je Anfrage
# -> NICHT akzeptabel, egal wie guenstig.
# 4) Mit jeder Aenderung neu messen (automatisiert!)
# Ohne das optimiert man ins Ungewisse.
# Auch bewerten:
# - Halluzinationsrate (erfundene Fakten)
# - Ablehnungsrate (Antworten "ich weiss nicht")
# - Formatfehler (JSON ungueltig)
# - Wiederholungsrate (Fehler -> neuer Versuch = doppelte Kosten)
Prüfliste
- Sind die Kosten je Funktion bekannt (nicht nur insgesamt)?
- Sind feste Prompt-Bestandteile an den Anfang gestellt (Zwischenspeicher)?
- Ist die Zwischenspeicher-Trefferquote gemessen?
- Ist
max_tokensbei jedem Aufruf gesetzt? - Läuft der einfache Teil der Anfragen über ein kleineres Modell – qualitätsgeprüft?
- Ist die Zahl der Werkzeugrunden begrenzt (Agenten)?
- Gibt es einen Bewertungssatz und wird er nach jeder Änderung ausgeführt?
- Gibt es eine Warnung bei Kostenausreißern und ein Gesamtbudget mit Abschaltung?
- Werden Offline-Aufgaben tatsächlich offline verarbeitet?
Häufige Fehler
- Zeitstempel oder Kennung am Prompt-Anfang. Zerstört jeden Zwischenspeicher-Treffer. Der teuerste einzelne Fehler.
- Kein
max_tokens. Eine entgleisende Antwort kostet das Doppelte oder Dreifache. - Optimieren ohne Messen. Meist wird an der billigsten Stelle gespart und der teuerste Posten übersehen.
- Werkzeugdefinitionen aufblähen. Sie stehen in jedem Aufruf. 20 Werkzeuge mit langen Beschreibungen kosten bei jeder Anfrage deutlich.
- Agenten ohne Rundengrenze. Eine Schleife kann in Stunden dreistellige Beträge verbrennen. Rundengrenze und Budget sind Pflicht.
- Nur Gesamtkosten betrachten. Ein Durchschnitt verdeckt, wo das Geld hingeht.
- Qualität nicht nachmessen. Die Hälfte der Ersparnis kommt oft daher, dass das System schlechter antwortet – und niemand merkt es.
- Zwischenspeicher-Aufbewahrung nicht bedacht. Der Speicher des Zwischenspeichers kostet ebenfalls. Kurze Gültigkeit ist meist ausreichend.
- Embeddings bei jeder Anfrage neu berechnen. Der teuerste und einfachste Fehler bei RAG: Sie ändern sich nie und gehören eingefroren.
Verwandte Grundlagen: RAG-Praxis, LLM, RAG in der Praxis, Vektordatenbank.