add main.py

This commit is contained in:
2026-05-25 22:27:44 +00:00
parent 3acb7e5337
commit 962e965d81
+27 -39
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
# First run: will pause at interrupt async for chunk in graph.stream({"messages": [], "human_value": None}, config):
stream = graph.stream({}, config)
for chunk in stream:
if "__interrupt__" in chunk: if "__interrupt__" in chunk:
# Extract payload
payload = chunk["__interrupt__"][0].value payload = chunk["__interrupt__"][0].value
# Show question and get answer answer = questionary.select(payload["question"], choices=payload["options"]).ask()
answer = questionary.select( # resume with answer
payload["question"],
choices=payload["allow_responds"],
).ask()
# Add answer to payload
payload["answer"] = answer payload["answer"] = answer
# Resume graph # store answer in state
stream = graph.stream(Command(resume=payload), config) chunk["human_value"] = answer
continue await graph.stream(Command(resume=payload), config)
# Print normal output else:
print(chunk) print(chunk)
# After stream ends, print final state if __name__ == "__main__":
print("Final state:", stream.final_state) import asyncio
asyncio.run(main())