This commit is contained in:
2026-05-12 21:37:10 +00:00
parent 29cbf58de7
commit 60b2ad6e71
+46 -37
View File
@@ -1,57 +1,66 @@
import questionary
from langgraph.graph import StateGraph, START
from langgraph.types import interrupt, Command
from langgraph.checkpoint.memory import InMemorySaver
from typing import TypedDict, List
import sys
from typing import TypedDict, List, Dict, Any
class GraphState(TypedDict):
from langgraph.graph import StateGraph, START
from langgraph.constants import interrupt
from langgraph.types import Command
from langgraph.checkpoint.memory import InMemorySaver
import questionary
# Define state
class State(TypedDict):
human_value: str | None
foo: str | None
# Node that triggers interrupt
def interrupt_node(state: GraphState) -> GraphState:
# Trigger interrupt with payload
payload = {
def interrupt_node(state: State) -> State:
# Trigger interrupt with question and options
interrupt_payload = {
"type": "confirm",
"question": "Уверены, что хотите продолжить?",
"allow_responds": ["approve", "reject"],
}
# interrupt returns None; graph pauses until resumed
interrupt(payload)
# After resume, state will contain the answer in payload['answer']
answer = state.get("answer")
state["human_value"] = answer
# 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
return state
builder = StateGraph(GraphState)
builder.add_node("interrupt", interrupt_node)
builder.set_entry_point("interrupt")
builder.add_edge(START, "interrupt")
builder.add_edge("interrupt", "interrupt") # loop to finish
graph = builder.compile(checkpointer=InMemorySaver())
# 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
checkpoint = InMemorySaver()
compiled = graph.compile(checkpointer=checkpoint)
# Run graph with interrupt handling
config = {"configurable": {"thread_id": "demo"}}
# Initial state
state: GraphState = {"human_value": None, "foo": None}
# Stream execution
for chunk in graph.stream(state, config):
if __name__ == "__main__":
thread_id = "demo_thread"
config = {"configurable": {"thread_id": thread_id}}
# Start stream
stream = compiled.stream({}, config)
for chunk in stream:
if "__interrupt__" in chunk:
# Extract payload
payload = chunk["__interrupt__"][0].value
# Show question
# Extract interrupt payload
interrupt_obj = chunk["__interrupt__"][0]
payload = interrupt_obj.value
# Show question to user
answer = questionary.select(
payload["question"],
choices=payload["allow_responds"],
).ask()
# Resume with answer
payload["answer"] = answer
resume = Command(resume=payload)
for _ in graph.stream(resume, config):
pass
resume_payload = {"human_value": answer}
stream = compiled.stream(Command(resume=resume_payload), config)
for subchunk in stream:
if "human_value" in subchunk:
print("\nFinal state:", subchunk)
sys.exit(0)
else:
# Final state output
print("Final state:", chunk)
# Normal output (none expected here)
pass