Startseite / Artikel

LangGraph Persistenz: Zwischenstände, die das Wiederaufnehmen und HITL ermöglichen

Erklärung zur Persistenz von LangGraph: Wie Checkpoints den Zustand pro Thread speichern, sodass Unterbrechungen, menschliche Freigabe im Lauf des Prozesses, Wiederholungsversuche sowie Debugging durch Zeitreisen funktionieren.

Verlag: REACTAPP.TOP7 Min. Lesezeit1608 Wörter

Quellen: LangGraph Persistence: The Feature That Makes Everything Else Possible

Dieser Leitfaden erstellt erneut einen funktionsfähigen Weg für: LangGraph Persistence – die Funktion, die alles Weitere möglich macht. Konzentrieren Sie sich auf Verträge, Überprüfungen sowie Code, den Sie ohne Rätseln über die Absicht direkt in ein Repository einfügen können. Zur Übersicht sollten Sie vor dem Ändern des Codes die Eingaben, den Verantwortlichen für den Schritt sowie die Abbruchkriterien definieren. Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckten Zustände schließen zu müssen. Ziehen Sie kleine, testbare Einheiten vor großen Skripten. Wenn ein Schritt fehlschlägt, sollte der Fehler auf eine einzige Verantwortung hinweisen.

Kurze Zusammenfassung dessen, was wir bisher wissen

Zur schnellen Zusammenfassung dessen, was wir bisher wissen: Definieren Sie die Eingaben, den Verantwortlichen für den Schritt sowie die Abbruchkriterien, bevor Sie Code ändern. Die Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckten Zustände schließen zu müssen. Betrachten Sie diese Phase als Vertrag zwischen den Eingaben und den validierten Ausgaben. Benennen Sie die Artefakte, definieren Sie Erfolgskontrollen und lehnen Sie stille, unvollständige Abschlüsse ab. Führen Sie Checkpoints nach kostspieligen Schritten durch, damit Wiederholungen nicht denselben Modellaufruf erneut verrechnen.

Was Persistenz eigentlich ist

Für das, was tatsächlich unter Ausdauer zu verstehen ist, sollten vor der Codeänderung die Eingabedaten, der Verantwortliche für den Schritt sowie die Abbruchkriterien definiert werden. Die Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckte Zustände schließen zu müssen. Zeiten und Kosten sollten neben den funktionalen Ergebnissen aufgezeichnet werden. Frühzeitige Sichtbarkeit verhindert überraschende Rechnungen in gemeinsam genutzten Umgebungen. Führen Sie nach teuren Schritten einen Checkpoint durch, damit Wiederholungsversuche nicht denselben Modellaufruf erneut berechnen.

Wie es tatsächlich funktioniert: Checkpointer

Für die Funktionsweise: Definieren Sie vor dem Ändern des Codes Checkpoint-Pointer, die Eingaben, den Verantwortlichen für den Schritt sowie die Abbruchkriterien. Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckten Zuständen schließen zu müssen. Bewahren Sie die Konfiguration außerhalb des Anwendungscode auf. Umgebungsdateien, Geheimdatenspeicher und Feature-Flags sollten an einem Ort gesammelt sein, den Operator überprüfen können. Erstellen Sie Checkpointe nach teuren Schritten, damit Wiederholungen nicht denselben Modellaufruf erneut verrechnen. Für die Funktionsweise: Definieren Sie vor dem Ändern des Codes Checkpoint-Pointer, die Eingaben, den Verantwortlichen für den Schritt sowie die Abbruchkriterien. Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckten Zuständen schließen zu müssen. Ziehen Sie kleine, testbare Einheiten vor großen Skripten vor. Wenn ein Schritt fehlschlägt, sollte der Fehler auf eine einzige Verantwortungsbereich verweisen.

Threaden: Mehrere Ausführungen voneinander trennen

Zur Threadung – um mehrere Ausführungen voneinander zu trennen – sollten Eingaben, der Eigentümer des Schritts sowie die Abbruchkriterien vor dem Ändern des Codes definiert werden. Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckten Zustände schließen zu müssen. Betrachten Sie diese Phase als Vertrag zwischen Eingaben und validierten Ausgaben. Benennen Sie die Artefakte, definieren Sie Erfolgskontrollen und lehnen Sie stille, unvollständige Abschlüsse ab. Durch Persistenz werden Demos zu Systemen: Threads, menschliche Einflussfaktoren sowie Debugging-Methoden wie Zeitreise-Debugging hängen davon ab.

Der Code (er ist einfacher, als man denkt)

Für den Code (er ist einfacher, als man erwarten würde): Definieren Sie die Eingaben, den Verantwortlichen für den Schritt sowie die Abbruchkriterien, bevor Sie Code ändern. Die Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckte Zustände schließen zu müssen. Erfassen Sie die Laufzeiten und Kosten zusammen mit den funktionalen Ergebnissen. Frühzeitige Sichtbarkeit verhindert überraschende Rechnungen in gemeinsam genutzten Umgebungen. Durch Persistenz werden Demos zu Systemen – Threads, menschliche Beteiligung sowie Debugging mit Zeitreise-Methoden hängen davon ab.

from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph
from langgraph.checkpoint.memory import InMemorySaver
from typing import TypedDict

llm = ChatOpenAI()

class JokeState(TypedDict):
    topic: str
    joke: str
    explanation: str

def generate_joke(state: JokeState):
    response = llm.invoke(f"Generate a joke on the topic: {state['topic']}")
    return {"joke": response.content}

def generate_explanation(state: JokeState):
    response = llm.invoke(f"Explain this joke: {state['joke']}")
    return {"explanation": response.content}

# Build graph
graph = StateGraph(JokeState)
graph.add_node("generate_joke", generate_joke)
graph.add_node("generate_explanation", generate_explanation)
graph.add_edge("__start__", "generate_joke")
graph.add_edge("generate_joke", "generate_explanation")
graph.add_edge("generate_explanation", "__end__")

# Add persistence - this is the key line
checkpointer = InMemorySaver()
workflow = graph.compile(checkpointer=checkpointer)
config = {"configurable": {"thread_id": "1"}}

result = workflow.invoke(
    {"topic": "pizza"},
    config=config
)
# Get the final state
workflow.get_state(config)

# Get ALL intermediate states
workflow.get_state_history(config)
config_2 = {"configurable": {"thread_id": "2"}}
result_2 = workflow.invoke({"topic": "pasta"}, config=config_2)

Was Sie damit bauen können

Für das, was Sie damit bauen können, definieren Sie die Eingaben, den Verantwortlichen für den Schritt sowie die Abbruchkriterien, bevor Sie Code ändern. Operator:innen sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckten Zuständen schließen zu müssen. Bewahren Sie Konfigurationen außerhalb des Anwendungscode auf. Umgebungsdateien, Geheimdatenspeicher und Feature-Flags sollten an einem Ort zusammengefasst sein, den Operator:innen überprüfen können. Persistenz verwandelt Demos in Systeme: Threads, menschliche Einflüsse sowie Debugging-Methoden wie Zeitreise-Debugging hängen davon ab. Für das, was Sie damit bauen können, definieren Sie die Eingaben, den Verantwortlichen für den Schritt sowie die Abbruchkriterien, bevor Sie Code ändern. Operator:innen sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckten Zuständen schließen zu müssen. Ziehen Sie kleine, testbare Einheiten vor großen Skripten vor. Wenn ein Schritt fehlschlägt, sollte der Fehler auf eine einzige Verantwortungsbereich verweisen.

1. Kurzfristiges Gedächtnis in Chatbots

Für das Kurzzeitgedächtnis in Chatbots sollten vor dem Ändern des Codes die Eingaben, der Verantwortliche für den jeweiligen Schritt sowie die Abbruchkriterien definiert werden. Die Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckte Zustände schließen zu müssen. Betrachten Sie diese Phase als Vertrag zwischen den Eingaben und den validierten Ausgaben. Benennen Sie die Ergebnisdokumente, definieren Sie Erfolgskontrollen und lehnen Sie stille, unvollständige Abschlüsse ab. Halten Sie den Zustand des Graphen flach und typisiert. Verschachtelte Datenblöcke verbergen, welcher Knoten welches Feld geschrieben hat, und führen zu Unterbrechungen beim Wiederaufnehmen der Ausführung.

2. Fehlertoleranz

Zur Fehlertoleranz sollten Eingaben, der Verantwortliche für den Schritt sowie die Abbruchkriterien vor dem Codeändern definiert werden. Die Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckte Zustände schließen zu müssen. Zeiten und Kosten sollten neben den funktionalen Ergebnissen aufgezeichnet werden. Frühzeitige Sichtbarkeit verhindert überraschende Rechnungen in gemeinsam genutzten Umgebungen. Halten Sie den Graphenzustand einfach und typisiert – verschachtelte Datenblöcke verbergen, welcher Knoten welches Feld geschrieben hat, und führen zu Unterbrechungen beim Wiederaufnehmen der Ausführung.

import time

def step_two(state):
    print("Step 2 running...")
    time.sleep(30)  # simulating a slow operation
    return {"step_two": "done"}
workflow.invoke(None, config=config)

3. Mensch im Prozess

Für 3. Human-in-the-Loop: Definieren Sie die Eingaben, den Verantwortlichen für den Schritt sowie die Abbruchkriterien, bevor Sie Code ändern. Die Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckte Zustände schließen zu müssen. Bewahren Sie die Konfiguration außerhalb des Anwendungscode auf. Umgebungsdateien, Geheimdatenspeicher sowie Feature-Flags sollten an einem Ort gesammelt sein, den die Operator überprüfen können. Halten Sie den Zustand des Graphen flach und typisiert. Verschachtelte Strukturen verbergen, welcher Knoten welches Feld geschrieben hat, und führen zu Störungen bei Unterbrechungen. Für 3. Human-in-the-Loop: Definieren Sie die Eingaben, den Verantwortlichen für den Schritt sowie die Abbruchkriterien, bevor Sie Code ändern. Die Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckte Zustände schließen zu müssen. Ziehen Sie kleine, testbare Einheiten vor großen, komplexen Skripten. Wenn ein Schritt fehlschlägt, sollte der Fehler auf eine einzige Verantwortungsbereich verweisen.

4. Zeitreise

Für die Zeitreise-Funktion sollten vor dem Ändern des Codes die Eingaben, der Verantwortliche für den jeweiligen Schritt sowie die Abbruchkriterien definiert werden. Die Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckte Zustände schließen zu müssen. Betrachten Sie diese Phase als Vertrag zwischen den Eingaben und den validierten Ausgaben. Benennen Sie die Ergebnisdokumente, definieren Sie Erfolgskontrollen und lehnen Sie stille, unvollständige Abschlüsse ab. Erstellen Sie Checkpoints nach teuren Schritten, damit Wiederholungsversuche nicht denselben Modellaufruf erneut berechnen.

# Go back to a specific checkpoint and change the topic
workflow.update_state(
    {"configurable": {"thread_id": "1", "checkpoint_id": "<checkpoint_id>"}},
    {"topic": "samosa"}
)

# Re-run from that point
workflow.invoke(None, config={"configurable": {"thread_id": "1", "checkpoint_id": "<new_checkpoint_id>"}})

Das Gesamtbild

Für das Gesamtbild sollten vor dem Ändern des Codes die Eingaben, der Verantwortliche für den jeweiligen Schritt sowie die Abbruchkriterien definiert werden. Die Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckte Zustände schließen zu müssen. Erhalten Sie neben den funktionalen Ergebnissen auch Informationen zu Laufzeiten und Kosten. Frühzeitige Sichtbarkeit verhindert überraschende Rechnungen in gemeinsam genutzten Umgebungen. Erstellen Sie Checkpoints nach teuren Schritten, damit Wiederholungsversuche nicht denselben Modellaufruf erneut berechnen.

Gestütztes Lernen jenseits von Blogs

Für das gestützte Lernen jenseits von Blogs sollten Eingaben, der Verantwortliche für einen Schritt sowie die Abbruchkriterien vor dem Ändern des Codes definiert werden. Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckte Zustände schließen zu müssen. Die Konfiguration sollte außerhalb des Anwendungscode gespeichert werden. Umgebungsdateien, Geheimdatenspeicher und Feature-Flags sollten an einem Ort zusammengefasst sein, den Operator überprüfen können. Führen Sie Checkpoints nach kostspieligen Schritten durch, damit Wiederholungen nicht denselben Modellaufruf erneut verrechnen.

Kurse

Für Kurse sollten die Eingaben, der Verantwortliche für den Schritt sowie die Abbruchkriterien vor dem Ändern des Codes definiert werden. Die Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckte Zustände schließen zu müssen. Dokumentieren Sie den erfolgreichen Ablauf sowie den Notfallweg gemeinsam. Wiederholte Versuche und die Handhabung von Fehlern gehören zum Produkt. Erstellen Sie Checkpoints nach teuren Schritten, damit Wiederholversuche nicht denselben Modellaufruf erneut verrechnen.

Operative Checkliste

Für die operative Checkliste sollten die Eingaben, der Verantwortliche für den Schritt sowie die Abbruchkriterien vor dem Ändern des Codes definiert werden. Die Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckte Zustände schließen zu müssen.

Dokumentieren Sie den erfolgreichen Ablauf sowie den Notfallweg gemeinsam. Wiederholte Versuche und die Handhabung von Fehlern gehören zum Produkt.

Persistenz verwandelt Demos in Systeme: Threads, menschliche Einflussfaktoren sowie Debugging-Methoden, die Zeitreisen ermöglichen, hängen davon ab.

Fügen Sie bei ausreichendem Budget in CI mit Fixtures einen Smoke-Test für den kritischen Pfad hinzu.

Bevorzugen Sie kleine, testbare Einheiten vor umfangreichen Skripten. Wenn ein Schritt fehlschlägt, sollte der Fehler auf eine einzige Verantwortung hinweisen.

Persistenz verwandelt Demos in Systeme: Threads, menschliche Beteiligung sowie Zeitreise-Debugging hängen davon ab.

Vor der Einführung des Stack sollten Versionen eingefroren werden, ein „goldener“ Transkript für den kritischen Pfad aufgenommen sowie Rollback-Schritte bestätigt werden. Gemeinsame Umgebungen benötigen Rate Limits, Überprüfungen der Nutzerrechte sowie einen klaren Verantwortlichen für die Rotation von Geheimnissen.