This commit is contained in:
2026-05-12 21:57:44 +00:00
parent 66ef2b49ed
commit 293073ccfb
+40 -39
View File
@@ -1,66 +1,67 @@
import sys
from typing import TypedDict, List, Dict, Any
import questionary
from langgraph.graph import StateGraph, START
from langgraph.constants import interrupt
from langgraph.types import Command
from langgraph.checkpoint.memory import InMemorySaver
import questionary
from typing import TypedDict, List, Dict
# Define state
class State(TypedDict):
class GraphState(TypedDict):
human_value: str | None
foo: str | None
# Node that triggers interrupt
def interrupt_node(state: State) -> State:
# Trigger interrupt with question and options
interrupt_payload = {
def interrupt_node(state: GraphState) -> GraphState:
# Trigger interrupt with structured payload
payload = {
"type": "confirm",
"question": "Уверены, что хотите продолжить?",
"allow_responds": ["approve", "reject"],
}
# Raise interrupt; graph will pause until resumed
interrupt(interrupt_payload)
# After resume, the payload will be merged into state via resume
# We expect state to contain 'human_value' set by resume
# interrupt returns None, execution pauses until resume
interrupt(payload)
# After resume, the same payload will be passed back via state
# We expect the resume payload to contain 'answer'
answer = state.get("answer")
state["human_value"] = answer
return state
# Build graph
graph = StateGraph(State)
graph.add_node("interrupt", interrupt_node)
graph.set_entry_point(START)
graph.add_edge(START, "interrupt")
# No further nodes; graph ends after interrupt node
graph.set_finish_point("interrupt")
# Compile with checkpoint
builder = StateGraph(GraphState)
builder.add_node("interrupt_node", interrupt_node)
builder.set_entry_point("interrupt_node")
builder.set_finish_point("interrupt_node")
# Use InMemorySaver for checkpointing
checkpoint = InMemorySaver()
compiled = graph.compile(checkpointer=checkpoint)
graph = builder.compile(checkpointer=checkpoint)
# Run graph with interrupt handling
if __name__ == "__main__":
thread_id = "demo_thread"
config = {"configurable": {"thread_id": thread_id}}
# Start stream
stream = compiled.stream({}, config)
for chunk in stream:
config = {"configurable": {"thread_id": "thread-1"}}
# Initial state
state: GraphState = {"human_value": None, "foo": None}
# Start streaming
stream = graph.stream(state, config)
for chunk in stream:
if "__interrupt__" in chunk:
# Extract interrupt payload
interrupt_obj = chunk["__interrupt__"][0]
payload = interrupt_obj.value
# Extract payload
payload = chunk["__interrupt__"][0].value
# Show question to user
answer = questionary.select(
payload["question"],
choices=payload["allow_responds"],
).ask()
# Resume with answer
resume_payload = {"human_value": answer}
stream = compiled.stream(Command(resume=resume_payload), config)
# Add answer to payload and resume
payload["answer"] = answer
# Resume graph
stream = graph.stream(Command(resume=payload), config)
# Continue processing resumed stream
for subchunk in stream:
if "human_value" in subchunk:
print("\nFinal state:", subchunk)
sys.exit(0)
if "__interrupt__" in subchunk:
# Should not happen in this simple example
continue
print(subchunk)
else:
# Normal output (none expected here)
pass
print(chunk)
print("Final state:", state)