Zurück zum Blog

KostenoptimierungAnleitung

Chat-Historie kürzen, um Kosten zu senken: gleitendes Fenster oder Zusammenfassung

Begrenze, was du in jeder Runde erneut sendest: Behalte die letzten paar Nachrichten oder eine kurze Zusammenfassung. Token-Rechnung für einen 50-Runden-Chat und einen Python-Helfer.

Von CheapTokens TeamVeröffentlicht am 6 Min. Lesezeit

Cover: Einen langen Chat günstig halten, mit dem trim_history-Helfer
Auf dieser Seite
  1. Was Runde 50 tatsächlich sendet
  2. Option 1: ein gleitendes Fenster
  3. Option 2: eine Zusammenfassung alter Runden
  4. Was die drei Varianten kosten
  5. Welche Option du wählen solltest

Dein Support-Bot chattet seit 50 Runden, und jede neue Nachricht kostet mehr als die vorherige. Die API merkt sich nichts, also sendet dein Code die gesamte Konversation jedes Mal erneut. Die Lösung: begrenze, was du sendest – behalte den System-Prompt und die letzten paar Runden (ein gleitendes Fenster) oder ersetze alte Runden durch eine kurze Zusammenfassung. Unten findest du die Rechnung für einen 50-Runden-Chat und einen Helfer zum Kopieren.

DeepSeeks Leitfaden für mehrrundige Chats (api-docs.deepseek.com, geprüft am 1. November 2026) sagt es klar: Der Server speichert den Kontext früherer Anfragen nicht, also sendet der Client bei jedem Aufruf die vollständige messages-Liste. Das OpenAI-kompatible Format auf CheapTokens funktioniert genauso. Falls das neu für dich ist, beginne mit warum ein langer Chat mehr kostet und wie das messages-Array funktioniert.

Was Runde 50 tatsächlich sendet#

Angenommen, du betreibst einen Support-Bot mit einem System-Prompt von 400 Tokens. In einer typischen Runde schreibt der Nutzer etwa 60 Tokens und der Bot antwortet mit etwa 190. Eine vollständige Runde fügt der Historie 250 Tokens hinzu. Das sind Annahmen: Ersetze sie durch die Zahlen aus dem usage-Feld deiner eigenen Antworten.

In Runde 50 trägt die Anfrage den System-Prompt, 49 frühere Runden und die neue Nachricht: 400 + 49 × 250 + 60 = 12,710 Input-Tokens, um eine 190-Token-Antwort zu erhalten. Summiere den gesamten Chat. Der System-Prompt und die neue Nachricht werden jedes Mal gesendet: 50 × 460 = 23,000. Die wiederholte Historie fügt 250 × 1,225 = 306,250 hinzu. Zusammen: 23,000 + 306,250 = 329,250 Input-Tokens gegenüber 50 × 190 = 9,500 Output-Tokens.

Die Historie in jeder Anfrage wächst um eine Runde, also wächst die Summe mit dem Quadrat der Chat-Länge. Gehe von 50 auf 100 Runden und der Teil der wiederholten Historie vervierfacht sich ungefähr.

Probier es selbstProbier es aus: Wenn du nur den System-Prompt, die letzten 4 Runden und die neue Nachricht senden würdest, wie viele Input-Tokens würde Runde 50 dann tragen?Antwort anzeigen

1.460 (400 + 4 × 250 + 60), gegenüber 12.710 mit der vollständigen Historie. Gleiche Frage, gleiche Antwortlänge, ein Bruchteil des Inputs.

Option 1: ein gleitendes Fenster#

Die Idee: Sende immer den System-Prompt, verwerfe alles außer den letzten N Runden. Du behältst die vollständige Historie in deinem eigenen Speicher und kürzt nur die Kopie, die du sendest.

python
def trim_history(messages, keep_pairs=4):
    """System prompt + the last keep_pairs turns + the new user message."""
    system = [m for m in messages if m["role"] == "system"]
    rest = [m for m in messages if m["role"] != "system"]
    return system + rest[-(keep_pairs * 2 + 1):]

Rufe es auf, nachdem du die neue Nachricht des Nutzers angehängt hast. Mit keep_pairs=4 sind das 4 Nutzer/Assistent-Paare plus die neue Nachricht, 9 Nachrichten, und der Slice beginnt immer mit einer Nutzer-Nachricht. Hier ist es in einen echten Aufruf eingebunden:

python
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://api.cheaptokens.dev/v1",
    api_key=os.environ["CHEAPTOKENS_API_KEY"],
)
MODEL = "deepseek-ai/DeepSeek-V4-Flash-0731"

history = [{"role": "system", "content": "You are a concise support assistant."}]

def ask(text):
    history.append({"role": "user", "content": text})
    resp = client.chat.completions.create(
        model=MODEL,
        messages=trim_history(history),
        max_tokens=500,
    )
    answer = resp.choices[0].message.content
    history.append({"role": "assistant", "content": answer})
    print(resp.usage.prompt_tokens, resp.usage.completion_tokens)
    return answer

Die Zeile print ist die nützliche: Beobachte die erste Zahl. Ohne Kürzung steigt sie jede Runde. Mit dem Fenster hört sie auf zu wachsen, sobald der Chat Runde 4 überschreitet.

Python-Helfer trim_history: System-Prompt, letzte 4 Runden, neue Nachricht
Der Kürzungs-Helfer aus diesem Artikel

In Zahlen: Ab Runde 5 sind jede Anfrage 400 + 4 × 250 + 60 = 1,460 Input-Tokens. Die ersten vier Runden wachsen noch normal und summieren sich auf 3.340. Der gesamte Chat: 3,340 + 46 × 1,460 = 70,500 Input-Tokens, etwa ein Fünftel der 329.250, die du mit vollständiger Historie sendest. Der Output bleibt bei 50 × 190 = 9,500.

Anfrage in Runde 50: vollständige Historie versus ein Fenster von 4 Runden
Token-Teile der Anfrage in Runde 50, gemäß den obigen Annahmen

Im Code ist die ganze Änderung ein Argument im Aufruf:

Vergleichen

Die Ein-Zeilen-Änderung

Vorher

python
messages=history

Nachher

python
messages=trim_history(history)

Der Haken: Ein Fenster vergisst. Wenn der Nutzer in Runde 40 fragt „Wie war meine Bestellnummer?" und die Nummer in Runde 3 stand, hat das Modell sie nie gesehen. Zwei günstige Lösungen. Ziehe stabile Fakten (Name, Bestellnummer, Tarif) in deinem eigenen Code aus dem Chat und hänge sie an den System-Prompt an, wo das Fenster sie nie abschneidet. Oder füge eine Zusammenfassung hinzu, das ist die nächste Option.

Option 2: eine Zusammenfassung alter Runden#

Statt alte Runden zu verwerfen, komprimierst du sie. Alle paar Runden sendest du die Runden, die gerade aus dem Fenster gefallen sind, plus die aktuelle Zusammenfassung an das Modell und bittest um eine neue, kurze Zusammenfassung. Dann setzt du diese Zusammenfassung in die System-Nachricht.

python
def summarize(summary, old_messages):
    transcript = "\n".join(f"{m['role']}: {m['content']}" for m in old_messages)
    prompt = (
        f"Summary so far:\n{summary}\n\nNew turns:\n{transcript}\n\n"
        "Rewrite the summary in under 200 words. "
        "Keep names, numbers, decisions and open questions."
    )
    resp = client.chat.completions.create(
        model=MODEL,
        messages=[{"role": "user", "content": prompt}],
        max_tokens=400,
    )
    return resp.choices[0].message.content

def build_messages(history, summary, keep_pairs=4):
    system = history[0]["content"]
    if summary:
        system += "\n\nEarlier in this chat: " + summary
    recent = history[1:][-(keep_pairs * 2 + 1):]
    return [{"role": "system", "content": system}] + recent

Die Zusammenfassung ist nicht kostenlos: Sie ist ein zusätzlicher Modellaufruf. Angenommen, eine Zusammenfassung von etwa 300 Tokens wird alle 5 Runden aktualisiert (9 Mal in 50 Runden), wobei jede Aktualisierung etwa 1.600 Tokens liest (die alte Zusammenfassung plus fünf Runden plus die Anweisung) und 300 schreibt. Um auf der sicheren Seite zu bleiben, zähle die Zusammenfassung ab Runde 5 in jeder Anfrage mit (in Wirklichkeit erscheint sie erst nach der ersten Aktualisierung, das ist also eine leichte Überschätzung): 400 + 300 + 4 × 250 + 60 = 1,760 Input-Tokens.

Summen für den Chat: Hauptanfragen 3,340 + 46 × 1,760 = 84,300 Input-Tokens, Zusammenfassungsaufrufe 9 × 1,600 = 14,400 Input und 9 × 300 = 2,700 Output. Insgesamt 84,300 + 14,400 = 98,700 Input- und 9,500 + 2,700 = 12,200 Output-Tokens.

Die Zusammenfassung kostet etwas mehr als das reine Fenster, und dafür weiß das Modell noch, was in Runde 3 passiert ist.

Was die drei Varianten kosten#

Hier ist derselbe 50-Runden-Chat auf DeepSeek-V4-Flash, live bepreist aus den obigen Summen:

Ein 50-Runden-Chat auf DeepSeek-V4-Flash
  • Vollständige Historie (329.250 in, 9.500 out)$0.0059
  • Fenster plus Zusammenfassung (98.700 in, 12.200 out)$0.0027
  • Gleitendes Fenster, 4 Runden (70.500 in, 9.500 out)$0.002

Die Preise stammen aus der Live-Preisliste, also aktualisieren sich die Zahlen, wenn sich der Tarif ändert. Die Reihenfolge nicht: Das Fenster sendet am wenigsten, die Zusammenfassung liegt dazwischen, die vollständige Historie ist am teuersten.

Für einen Chat wie diesen ist das CheapTokens-Modell zum Starten DeepSeek-V4-Flash. Es hat ein Kontextfenster von 380K (ein 50-Runden-Chat passt selbst ungekürzt hinein), bis zu 32.768 Output-Tokens pro Antwort, einen festen Preis zu jeder Tageszeit und ist insgesamt, Input und Output zusammengerechnet, günstiger als OpenRouter. Die Modell-ID ist deepseek-ai/DeepSeek-V4-Flash-0731. Wenn du Modelle für das Fenster-Setup vergleichen willst (durchschnittlich 1.410 Input-Tokens pro Anfrage, 190 Output, 50 Anfragen), hier ist die Live-Tabelle:

Modell Pro Anfrage 50 Anfragen OpenRouter, 50 Anfragen
GLM-5.3-Flash $0.000036 $0.0018 $0.0032
DeepSeek-V4-Flash $0.00004 $0.002 $0.0063
MiniMax-M2.7 $0.000099 $0.005 $0.0594

1.410 Input- und 190 Output-Tokens pro Anfrage. Die Preise pro 1 Mio. Tokens sind aktuell und ändern sich zusammen mit unseren Tarifen; die OpenRouter-Spalte zeigt Referenzpreise für dieselbe Arbeitslast.

GLM-5.3-Flash hat einen Kontext von 390K und MiniMax-M2.7 hat 180K, was für einen gekürzten Chat ausreicht. Aktuelle Preise stehen auf der Preisseite, und die Dokumentation zeigt, wie du die erste Anfrage sendest.

Welche Option du wählen solltest#

Ein Fenster ist der Standard: drei Zeilen Code, keine zusätzlichen Aufrufe, kein zusätzlicher Fehlermodus. Verwende es für Support-Bots, Tutoren und Rollenspiele, wo die letzten paar Runden das Gespräch tragen und der System-Prompt die Regeln. Füge die Zusammenfassung hinzu, wenn Nutzer auf Dinge verweisen, die vor langer Zeit gesagt wurden, wie bei einem persönlichen Assistenten mit einer endlosen Konversation. Halte das Fenster klein genug, dass das Modell noch den unmittelbaren Kontext sieht, und groß genug, um einen vollständigen Frage-Antwort-Austausch zu fassen. Wie viel überhaupt hineinpasst, ist eine separate Grenze, behandelt in was ein Kontextfenster ist.

Kurzer Check

Der Nutzer fragt in Runde 40 nach einer Bestellnummer, die in Runde 3 genannt wurde. Du verwendest ein 4-Runden-Fenster ohne Zusammenfassung. Was passiert?

Antwort anzeigen

Antwort: Das Modell kann sie nicht sehen, weil Runde 3 aus der Anfrage geschnitten wurde

Die API ist zustandslos. Das Modell sieht nur, was in der Anfrage steht, also müssen Fakten, die du noch brauchst, im System-Prompt oder in einer Zusammenfassung bleiben.