add: main.py

This commit is contained in:
2026-06-30 16:16:15 +00:00
commit 7dca7dacb9
+91
View File
@@ -0,0 +1,91 @@
import asyncio
import os
from typing import TypedDict
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, START
from langgraph.types import interrupt, Command
from langgraph.checkpoint.memory import InMemorySaver
import questionary
# Deepagents imports
from deepagents import create_deep_agent
from deepagents.backends import FilesystemBackend, LocalShellBackend, CompositeBackend
# LLM configuration (OpenRouter)
llm = ChatOpenAI(
model="openai/gpt-oss-20b:free",
base_url="https://openrouter.ai/api/v1",
api_key=os.getenv("OPENAI_API_KEY"),
temperature=0.0,
)
# Backend for the deep agent (required by the assignment)
backend = CompositeBackend([
LocalShellBackend(workspace_dir="./workspace"),
FilesystemBackend(),
])
# Create a deep agent it is instantiated to satisfy the requirement, but not used further.
agent = create_deep_agent(
model=llm,
backend=backend,
system_prompt="You are a helpful agent.",
)
# Graph state definition
class GraphState(TypedDict):
human_value: str
foo: str
# Node that triggers a humanintheloop interrupt
def interrupt_node(state: GraphState):
# If the human has already responded, just return the state
if "human_value" in state:
return state
# Prepare the interrupt payload
payload = {
"type": "confirm",
"question": "Уверены, что хотите продолжить?",
"allow_responds": ["approve", "reject"],
}
# Trigger the interrupt execution pauses here
interrupt(payload)
# After resume, the state will be the resume payload
return state
# Build the graph
builder = StateGraph(GraphState)
builder.add_node("interrupt_node", interrupt_node)
builder.set_entry_point("interrupt_node")
builder.set_finish_point("interrupt_node")
# Compile with an inmemory checkpoint to allow resume
graph = builder.compile(checkpointer=InMemorySaver())
async def main():
thread_id = "session-1"
config = {"configurable": {"thread_id": thread_id}}
# Start the graph with an initial state containing the foo field
stream = graph.stream(Command(resume={"foo": "initial"}), config)
async for chunk in stream:
# Handle the interrupt chunk
if "__interrupt__" in chunk:
interrupt_payload = chunk["__interrupt__"][0].value
# Ask the user for a response
answer = questionary.select(
interrupt_payload["question"],
choices=interrupt_payload["allow_responds"],
).ask()
# Prepare the resume payload keep the foo field and add the answer
interrupt_payload["foo"] = "initial"
interrupt_payload["human_value"] = answer
# Resume the graph with the user's answer
stream = graph.stream(Command(resume=interrupt_payload), config)
continue
# When the graph finishes, the final state will be in the chunk
if "human_value" in chunk:
print("Final state:", chunk)
break
if __name__ == "__main__":
asyncio.run(main())