Files
task-69a474cdc46fd26feae69896/main.py
T
2026-05-26 10:39:01 +00:00

92 lines
3.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import os
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage, SystemMessage
from langchain.tools import tool
from langgraph.checkpoint.memory import MemorySaver
from langgraph.types import Command
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
from rich.console import Console
# LLM setup
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,
)
console = Console()
# Dummy tool can be replaced by real implementation
@tool
def get_price(query: str) -> str:
"""Return a fake price for demonstration."""
return f"Цена для {query} 100₽"
# State definition
class ChatState(dict):
messages: list = add_messages
location: str = "start"
inventory: list = []
# Agent graph
builder = StateGraph(ChatState)
# Node that runs the LLM and returns tool calls
async def llm_node(state: ChatState):
system = SystemMessage(content="You are a helpful assistant. Use the get_price tool if needed.")
response = await llm.ainvoke([system] + state["messages"], config={"configurable": {"thread_id": "chat-1"}})
return {"messages": [response]}
# Node that handles tool calls (only get_price)
async def tool_node(state: ChatState):
last_msg = state["messages"][-1]
if hasattr(last_msg, "tool_calls") and last_msg.tool_calls:
tool_call = last_msg.tool_calls[0]
name = tool_call["name"]
args = tool_call["args"]
if name == "get_price":
result = get_price(args)
# Append tool result to messages
state["messages"].append(HumanMessage(content=result))
return state
builder.add_node("llm", llm_node)
builder.add_node("tool", tool_node)
builder.add_edge(START, "llm")
builder.add_edge("llm", "tool")
builder.add_edge("tool", END)
chat = builder.compile(checkpointer=MemorySaver(), interrupt_before=["tool"])
# Main loop
while True:
user_input = console.input("\nВы: ")
if user_input.lower() in {"exit", "quit"}:
break
# Add user message
chat.add_state({"messages": [HumanMessage(content=user_input)]})
# Run graph with interrupt handling
state = chat.get_state({"configurable": {"thread_id": "chat-1"}})
while True:
result = await chat.ainvoke(state, {"configurable": {"thread_id": "chat-1"}})
# If interrupted before tool
if "__interrupt__" in result and result["__interrupt__"][0]["name"] == "tool":
console.print("\nАгент хочет вызвать инструмент: get_price")
ans = console.input("Разрешить? (Y/n): ")
if ans.lower() in {"", "y", "yes"}:
# resume
state = chat.get_state({"configurable": {"thread_id": "chat-1"}})
continue
else:
console.print("Отменено")
break
# Print assistant response
for msg in result["messages"]:
if msg.role == "assistant":
console.print(msg.content)
break
console.print("\nДо свидания!")