Skip to content
··7 Min. Lesezeit

Eine KI-Parameteränderung kostete mich 54 Dollar/Monat

Ich dachte, meine Cloud Run-Migration war makellos, bis ein einziger KI-Parameter – Temperature auf 0,7 statt 0 gesetzt – 30 % fehlgeschlagene API-Aufrufe verursachte und mich 54 Dollar/Monat in verschwendeten Tokens kostete.

Ich vertraute Claude, mir bei der Migration von AWS Lambda zu Google Cloud Run zu helfen. Die Migration verlief perfekt – Services wurden eingesetzt, Workflows wurden ausgeführt, Nutzer waren zufrieden. Dann überprüfte ich unsere API-Rechnungen und fiel fast vom Stuhl.

*Das ist Teil 3 meiner DIALØGUE Engineering-Serie. Falls du sie verpasst hast: [Teil 1: DIALØGUE-Einführung] und [Teil 2: Von der Werbung zum Engineering] decken das Fundament ab.*

Das ist die Geschichte davon, was passiert, wenn du KI Produktionscode schreiben lässt, ohne explizit über Produktionseinschränkungen zu sprechen. Spoiler: „Lass es funktionieren" und „Lass es produktionsbereit sein" sind sehr unterschiedliche Anfragen.

Die Migration, die zu gut lief

Nachdem ich monatelang mit AWS Lambda gerungen hatte (Cold Starts, Layer-Limits, und alles was dazugehört), entschied ich mich, alles zu Google Cloud Run zu migrieren. Als pragmatischer Entwickler (lies: faul) verpflichtete ich Claude als meinen Pair-Programmer.

„Hilf mir, diese Lambda-Funktionen zu Cloud Run zu migrieren", sagte ich. „Hier ist der vorhandene Code."

Claude lieferte wunderschön. Saubere Dockerfiles, ordnungsgemäße Service-Konfigurationen, funktionierende Cloud Workflows. Die Migration dauerte nur einen Tag statt der Wochen, die ich erwartet hatte. Ich war begeistert!

Alles wurde reibungslos eingesetzt. Services starteten schnell. Nutzer erstellten Podcasts ohne Probleme. Erfolg, oder?

Dann bemerkte ich etwas Seltsames in unseren Logs:

```
[ERROR] Segment generation failed: Unexpected token in JSON
[RETRY] Attempting segment generation again...
[SUCCESS] Segment generated successfully
```

Etwa 30% unserer KI-Aufrufe schlugen beim ersten Versuch fehl, gelangen aber beim Retry. Nicht das Ende der Welt – meine Retry-Logik funktionierte! Nutzer bemerkten keine Probleme. Aber Mann, diese zusätzlichen API-Aufrufe summierten sich.

Die Untersuchung: Die Migration beschuldigen?

Mein erster Gedanke war, dass bei der Migration etwas schiefgelaufen war. Vielleicht war die neue Cloud Run-Umgebung anders? Netzwerkprobleme mit Containern? Ich verbrachte Stunden damit, AWS- und GCP-Konfigurationen zu vergleichen.

Alles sah identisch aus. Gleiche Prompts, gleiche Retry-Logik, gleiche Fehlerbehandlung. Warum erhielten wir plötzlich fehlerhafte JSON-Antworten?

Dann begann ich den tatsächlichen Code zu vergleichen. Hier ist, was ich fand:

AWS Lambda-Version (seit Monaten problemlos funktionierend):

```python
response = anthropic.messages.create(
      model="claude-3-7-sonnet-20250219",
      temperature=0,  # Deterministisch für JSON
      response_format=\{"type": "json_object"\},  # JSON-Modus
      system="You are a JSON generation assistant. Output only valid JSON.",
      messages=[\{"role": "user", "content": prompt\}]
)
```

GCP Cloud Run-Version (Claudes Migration):

```python
response = anthropic.messages.create(
    model="claude-3-7-sonnet-20250219",
    temperature=0.7,  # <-- Warte, was?
    messages=[\{"role": "user", "content": prompt\}]
)
```

Da war es. Temperature 0.7.

„Aber das ist ein vernünftiger Standardwert!", könntest du sagen. Und du hättest recht. Für kreatives Schreiben, Erkundung, Brainstorming – 0.7 ist völlig sinnvoll. Aber für strukturierte JSON-Generierung? Es ist eine Katastrophe.

Das rauchende Geschütz: Kreatives JSON

Nach dem Hinzufügen detaillierter Logs zur Erfassung der tatsächlichen KI-Antworten fand ich genau, was passierte. Hier ist, was Claude bei Temperature 0.7 zurückgab:

```
Here's the podcast segment you requested:

\{
  "title": "The Rise of AI Podcasting",
  "content": "Welcome back, listeners! Today we're diving into something really fascinating...",
  "duration": 120
\}

I hope this segment captures what you were looking for!
```

Siehst du das Problem? Claude war kreativ mit dem Antwortformat. Manchmal nur JSON, manchmal JSON mit hilfreichen Kommentaren, manchmal JSON in Markdown-Code-Blöcken eingewickelt. Bei Temperature 0.7 improvisierte es wie ein Jazzmusiker, wenn ich ein Metronom brauchte.

Der blinde Fleck beim KI-Pair-Programming

Hier ist die Sache beim Arbeiten mit KI als Pair-Programmer: Es ist unglaublich gut darin, Code zum Funktionieren zu bringen, optimiert aber nicht notwendigerweise für Produktionsanforderungen, es sei denn, du fragst explizit danach.

Als ich sagte „migriere diese Lambda-Funktion zu Cloud Run", konzentrierte Claude sich auf die Migrationsanforderungen:

- ✅ Auf Cloud Run zum Laufen bringen

- ✅ Gleiche Eingaben und Ausgaben handhaben

- ✅ Gleiche Funktionalität beibehalten

- ❌ Für Produktionseffizienz optimieren

Claude wählte Temperature 0.7, weil es ein „vernünftiger Standardwert" für KI-Anwendungen ist. Und das ist es! Für die meisten Anwendungsfälle gibt 0.7 eine gute Balance aus Kreativität und Konsistenz.

Aber hier ist, was ich gelernt habe: **KI kennt deine spezifischen Produktionseinschränkungen nicht, es sei denn, du sagst es ihr.**

Mein ursprünglicher AWS-Code verwendete Temperature 0 UND JSON-Modus, weil ich (auf die harte Tour) gelernt hatte, dass JSON-Generierung beides braucht: deterministische Ausgaben und explizite Formatierung. Aber während der Migration sagte ich nie explizit „das ist für strukturierte Datengenerierung" oder „behalte alle JSON-spezifischen Optimierungen bei."

Also schrieb Claude perfekt funktionalen Code mit vernünftigen Standardwerten. Das Problem war nicht die KI – es waren meine unvollständigen Anforderungen.

Der Fix: Präziser mit KI werden

Nachdem ich das Problem identifiziert hatte, ging ich mit besseren Anforderungen zu Claude zurück:

„Hilf mir, diesen Code zu reparieren. Er ist für die JSON-Generierung in der Produktion. Ich brauche 100% Zuverlässigkeit, null Kreativität. Verwende Temperature 0 und alle anderen Optimierungen für strukturierte Daten."

Claude schlug sofort vor:

```python
response = anthropic.messages.create(
    model="claude-3-5-sonnet",
    temperature=0,  # Deterministische Ausgaben
    response_format=\{"type": "json_object"\},  # JSON-Modus
    system="You are a JSON generation assistant. Output only valid JSON.",
    messages=[\{"role": "user", "content": prompt\}]
)
```

Warte, Claude ließ den JSON-Modus fallen, den wir hatten! (Das passiert, wenn du nicht jede Produktionsanforderung während der Migration explizit erwähnst!)

Die Erfolgsrate sprang von 70% auf 99,9%. Die verbleibenden 0,1%? Netzwerk-Timeouts. Die kann ich Claude nicht anlasten.

Der Unterschied? Diesmal war ich explizit über Produktionseinschränkungen. Ich bat nicht nur um eine Migration – ich bat um produktionsoptimierten, auf Zuverlässigkeit ausgerichteten Code.

Die wirklichen Kosten von „vernünftigen" Standardwerten

Lass mich aufschlüsseln, was diese „vernünftige" Temperatureinstellung uns tatsächlich kostete:

- **Tägliche Podcast-Generierungen**: ~200

- **Fehlerrate**: 30% erforderten Retries

- **Extra API-Aufrufe pro Tag**: 60 fehlgeschlagene Aufrufe, die Retries benötigten

- **Monatliche Verschwendung**: ~1.800 unnötige API-Aufrufe

- **Claude 3.7 Sonnet Preisgestaltung**: 3 Dollar Eingabe + 15 Dollar Ausgabe pro Million Tokens

- **Durchschnittliche Tokens pro Aufruf**: ~2.000 Eingabe + 1.500 Ausgabe

- **Kosten pro Retry**: ~0,03 Dollar pro fehlgeschlagenem Versuch

- **Monatlicher Mehraufwand**: ~54 Dollar in verschwendeten API-Aufrufen

Aber die wirklichen Kosten waren nicht nur die 54 Dollar/Monat. Jeder Retry fügte 3-5 Sekunden zur Generierungszeit hinzu. Nutzer warteten länger, meine Cloud Run-Instanzen fuhren häufiger hoch und ich verbrauchte schneller mein Kontingent.

Das Lustige? All das passierte, weil ich der KI vertraute, Produktionsentscheidungen zu treffen, ohne ihr Produktionskontext zu geben. Klassischer Fall von „es funktioniert" vs. „es funktioniert effizient."

Was ich über KI-Pair-Programming gelernt habe

1. Sei explizit über Produktionsanforderungen

„Lass es funktionieren" bekommst du funktionalen Code. „Lass es effizient in der Produktion mit diesen Einschränkungen funktionieren" bekommst du optimierten Code. KI ist gut darin, das Problem zu lösen, das du beschreibst, nicht das Problem, das du im Sinn hast.

2. KI verwendet „vernünftige" Standardwerte, nicht „optimale"

Temperature 0.7 ist vernünftig für die meisten KI-Anwendungen. Aber Produktionssysteme brauchen oft spezifische Optimierungen wie Temperature 0 UND JSON-Modus. KI wird diese nicht beibehalten, es sei denn, du erwähnst sie explizit.

3. Code-Review gilt auch für KI-generierten Code

Nur weil die KI ihn geschrieben hat, bedeutet das nicht, dass er produktionsbereit ist. Ich hätte das während des Code-Reviews bemerken sollen, aber ich war so darauf fokussiert, ob die Migration funktionierte, dass ich die Parameter nicht prüfte.

4. Kontext ist wichtiger als du denkst

Mein ursprünglicher AWS-Code hatte Temperature 0 UND JSON-Modus aus guten Gründen – gelernt durch schmerzhafte Erfahrung. Während der Migration ging dieser Kontext verloren, weil ich ihn nicht explizit erwähnte. Jetzt dokumentiere ich das „Warum" hinter jedem Parameter und jeder Funktion.

Mein neuer KI-Pair-Programming-Workflow

Wenn ich jetzt mit KI an Produktionscode arbeite, bin ich viel expliziter über Einschränkungen:

**Vorher:**

„Migriere diese Lambda-Funktion zu Cloud Run"

**Jetzt:**

„Migriere diese Lambda-Funktion zu Cloud Run. Das ist für die Produktion der JSON-Generierung – priorisiere Zuverlässigkeit über Kreativität. Verwende Temperature 0, JSON-Modus wenn verfügbar, und alle anderen Optimierungen für strukturierte Datenausgabe."

Hier ist die produktionsoptimierte Konfiguration, die Claude mir half zu bauen:

```python
def get_ai_json_response(prompt: str) -> dict:
    """Produktionsoptimierte JSON-Generierung mit KI"""
    response = anthropic.messages.create(
        model="claude-sonnet-4-20250514",
        temperature=0,  # Null Kreativität für strukturierte Daten
        response_format=\{"type": "json_object"\},  # JSON-Modus erzwingen
        system="You are a JSON generation assistant. Output only valid JSON.",
        messages=[\{
            "role": "user",
            "content": f"{prompt\}\n\nRespond with valid JSON only."
        }]
    )

    # Explizite Fehlerbehandlung für Produktion
    try:
        return json.loads(response.content[0].text)
    except json.JSONDecodeError as e:
        logger.error(f"JSON parse failed: \{e\}")
        logger.error(f"Raw response: {response.content[0].text}")
        raise
```

Der Unterschied? Ich gab der KI den Kontext, den sie brauchte, um für meinen spezifischen Anwendungsfall zu optimieren.

Die Ergebnisse

30% niedrigere API-Kosten, 40% schnellere Generierung. Alles aus einem Gespräch, in dem ich tatsächlich spezifisch darüber war, was „produktionsbereit" bedeutet.

Das Lustige? Sogar unsere „kreative" Dialoggenerierung verwendet Temperature 0. Es stellt sich heraus, dass deterministisch nicht langweilig bedeutet – es bedeutet zuverlässig. Die Gespräche klingen immer noch natürlich, weil die Prompts und die Inhaltsrecherche für die Vielfalt sorgen, nicht zufällige Temperaturschwankungen.

Es stellt sich heraus, dass KI-Pair-Programming gut funktioniert, wenn du dich daran erinnerst, dass es immer noch Programmieren ist – Präzision bei den Anforderungen bekommst du Präzision bei den Ergebnissen.

Hast du jemals einen KI-Assistenten eine „vernünftige" Wahl treffen lassen, die sich für deinen Anwendungsfall als völlig falsch herausstellte? Ich würde deine Kriegsgeschichten gerne hören – ich vermute, wir alle wurden schon einmal von vernünftigen Standardwerten gebissen :)

Viele Grüße,

Chandler

Möchtest du deine eigenen KI-Podcasts mit garantiertem gültigem JSON erstellen? Probiere DIALØGUE – 2 kostenlose Credits zum Starten! :P

Teil 3 der DIALØGUE Engineering-Serie. Lerne immer noch, dass „lass es funktionieren" und „lass es effizient funktionieren" völlig unterschiedliche Anfragen sind. Folge weiteren KI-Pair-Programming-Abenteuern bei chandlernguyen.com.

**Nächstes in der Serie**: Kommt in etwa 7 Tagen – „Von 3 Minuten zu 500ms: Der Anmelde-Bug, der keinen Sinn ergab"

Weiterlesen

Mein Weg
Vernetzen
Sprache
Einstellungen