From 43f022ac95a1324c0393b0ea53eaae528a0ff7a7 Mon Sep 17 00:00:00 2001 From: Danil Parunin 5f1b81b8-4f5d-11e8-9c2d-fa7ae01bbebc Date: Mon, 15 Jun 2026 12:29:38 +0000 Subject: [PATCH] add: main.py --- main.py | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 main.py diff --git a/main.py b/main.py new file mode 100644 index 0000000..d74fa8e --- /dev/null +++ b/main.py @@ -0,0 +1,95 @@ +import os +import asyncio +from langchain_openai import ChatOpenAI +from langchain_core.messages import HumanMessage +from langchain.tools import tool +from deepagents import create_deep_agent +from deepagents.backends import FilesystemBackend, LocalShellBackend, CompositeBackend +from langgraph.checkpoint.memory import MemorySaver +from rich.console import Console + +# ---------- LLM ---------- +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 ---------- +backend = CompositeBackend([ + LocalShellBackend(workspace_dir="./workspace"), + FilesystemBackend(), +]) + +# ---------- Tool ---------- +@tool +def get_price(query: str) -> str: + """Return a mock price for a city and date.""" + return f"Price for {query} is $42" + +# ---------- Memory ---------- +memory = MemorySaver() + +# ---------- Console ---------- +console = Console() + +# ---------- Agent ---------- +agent = create_deep_agent( + model=llm, + tools=[get_price], + backend=backend, + system_prompt="You are a helpful agent that can fetch prices.", + checkpointer=memory, + interrupt_before=["tools"], +) + +# ---------- Helper to display tool call ---------- +async def display_tool_call(state): + # Get the last tool call from the messages + messages = state.values.get("messages", []) + if not messages: + return + last_msg = messages[-1] + if hasattr(last_msg, "tool_calls") and last_msg.tool_calls: + tool_call = last_msg.tool_calls[0] + name = tool_call.get("name") + args = tool_call.get("args") + console.print(f"\n[bold cyan]Agent wants to call tool:[/bold cyan] {name}({args})") + +# ---------- Main loop ---------- +async def ask_and_run(user_input, config): + async for chunk in agent.stream(user_input, config=config, stream_mode=["messages", "updates"]): + chunk_type, chunk_data = chunk + state = agent.get_state(config) + + if chunk_type == "messages": + # Stream token output + console.print(chunk_data, end="") + + if chunk_type == "updates": + # Tool execution output + console.print(chunk_data, end="") + + # Handle interrupt before tool call + if "__interrupt__" in chunk_data and state.next == ("tools",): + await display_tool_call(state) + answer = input("Разрешить? (Y/n): ") + if answer.lower().strip() in ("", "y", "yes"): + # Resume by calling ask_and_run with None to continue + await ask_and_run(None, config) + else: + console.print("[red]Отменено[/red]") + break + +async def main(): + config = {"configurable": {"thread_id": "conversation-1"}} + console.print("[bold green]Добро пожаловать! Введите 'exit' для выхода.[/bold green]") + while True: + user_input = input("\nВы: ") + if user_input.lower() == "exit": + break + await ask_and_run({"messages": [{"role": "human", "content": user_input}]}, config) + +if __name__ == "__main__": + asyncio.run(main())