add main.py

This commit is contained in:
2026-05-25 22:27:44 +00:00
parent 3acb7e5337
commit 962e965d81
+31 -43
View File
@@ -1,61 +1,49 @@
import questionary import sys
from langgraph.graph import StateGraph, START from langgraph.graph import StateGraph, START
from langgraph.types import interrupt, Command from langgraph.types import interrupt, Command
from langgraph.checkpoint.memory import InMemorySaver from langgraph.checkpoint.memory import InMemorySaver
from typing import TypedDict, Annotated from typing import TypedDict, Annotated
from langgraph.graph.message import add_messages
import questionary
# State definition
class GraphState(TypedDict): class GraphState(TypedDict):
human_value: Annotated[str | None, "value chosen by user"] messages: Annotated[list, add_messages]
foo: Annotated[str, "initial data placeholder"] human_value: str | None
# Node that triggers interrupt async def interrupt_node(state: GraphState) -> GraphState:
# Trigger interrupt asking user to confirm
def interrupt_node(state: GraphState) -> GraphState:
# Trigger interrupt with structured payload
payload = { payload = {
"type": "confirm", "type": "confirm",
"question": "Уверены, что хотите продолжить?", "question": "Do you want to continue?",
"allow_responds": ["approve", "reject"], "options": ["yes", "no"],
} }
# Call interrupt; execution pauses until resumed # interrupt returns None, graph pauses
interrupt(payload) interrupt(payload)
# After resume, payload will contain 'answer' # After resume, payload will have 'answer'
# The node receives the resumed payload as its return value answer = state.get("human_value")
# We store the answer in state return {"messages": state["messages"], "human_value": answer}
state["human_value"] = payload.get("answer")
return state
# Build graph
builder = StateGraph(GraphState) builder = StateGraph(GraphState)
builder.add_node("interrupt_node", interrupt_node) builder.add_node("interrupt_node", interrupt_node)
builder.add_edge(START, "interrupt_node") builder.add_edge(START, "interrupt_node")
builder.add_edge("interrupt_node", END) builder.add_edge("interrupt_node", START)
# Compile with checkpoint
graph = builder.compile(checkpointer=InMemorySaver()) graph = builder.compile(checkpointer=InMemorySaver())
# Run graph with stream and handle interrupt async def main():
config = {"configurable": {"thread_id": "demo"}} config = {"configurable": {"thread_id": "session-1"}}
# Start stream
async for chunk in graph.stream({"messages": [], "human_value": None}, config):
if "__interrupt__" in chunk:
payload = chunk["__interrupt__"][0].value
answer = questionary.select(payload["question"], choices=payload["options"]).ask()
# resume with answer
payload["answer"] = answer
# store answer in state
chunk["human_value"] = answer
await graph.stream(Command(resume=payload), config)
else:
print(chunk)
# First run: will pause at interrupt if __name__ == "__main__":
stream = graph.stream({}, config) import asyncio
for chunk in stream: asyncio.run(main())
if "__interrupt__" in chunk:
# Extract payload
payload = chunk["__interrupt__"][0].value
# Show question and get answer
answer = questionary.select(
payload["question"],
choices=payload["allow_responds"],
).ask()
# Add answer to payload
payload["answer"] = answer
# Resume graph
stream = graph.stream(Command(resume=payload), config)
continue
# Print normal output
print(chunk)
# After stream ends, print final state
print("Final state:", stream.final_state)