diff --git a/main.py b/main.py new file mode 100644 index 0000000..68491c9 --- /dev/null +++ b/main.py @@ -0,0 +1,89 @@ +import os +import json +from langchain_openai import ChatOpenAI +from langchain.agents import create_agent +from langchain.agents.middleware import HumanInTheLoopMiddleware +from langgraph.checkpoint.memory import MemorySaver +from langgraph.types import Command + +# 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, +) + +# Simple tool: get_weather +from langchain.tools import tool + +@tool +def get_weather(city: str, date: str = "сегодня") -> str: + """Return a mock weather description for the given city and date.""" + # In a real scenario, call an API. Here we return a deterministic string. + return f"Погода в {city} на {date}: солнечно, 25°C." + +# Agent with HumanInTheLoopMiddleware +memory = MemorySaver() + +agent = create_agent( + model=llm, + tools=[get_weather], + system_prompt="Ты полезный ассистент.", + middleware=[ + HumanInTheLoopMiddleware( + interrupt_on={"get_weather": True}, + description_prefix="Подтвердите вызов инструмента", + ), + ], + checkpointer=memory, +) + +# Helper to process interrupt and collect decisions + +def handle_interrupt(interrupt_value): + action_requests = interrupt_value["action_requests"] + decisions = [] + for idx, action in enumerate(action_requests, 1): + name = action.get("name") + args = action.get("args", {}) + description = action.get("description", "") + print(f"\n--- Подтверждение {idx} ---") + print(f"Инструмент: {name}") + print(f"Аргументы: {args}") + if description: + print(f"Описание: {description}") + while True: + choice = input("a = approve, r = reject: ").strip().lower() + if choice == "a": + decisions.append({"type": "approve"}) + break + elif choice == "r": + msg = input("Сообщение для агента (причина отказа): ") + decisions.append({"type": "reject", "message": msg}) + break + else: + print("Неверный ввод. Попробуйте снова.") + return decisions + +# Main interaction loop +if __name__ == "__main__": + config = {"configurable": {"thread_id": "сессия-1"}} + while True: + user_input = input("\nВы: ") + if user_input.lower() in {"exit", "quit"}: + print("Завершение.") + break + # Initial invoke + result = agent.invoke({"messages": [{"role": "human", "content": user_input}]}, config=config) + # Process interrupts + while "__interrupt__" in result: + interrupt = result["__interrupt__"][0].value + decisions = handle_interrupt(interrupt) + result = agent.invoke(Command(resume={"decisions": decisions}), config=config) + # Final answer + if result.get("messages"): + final_msg = result["messages"][-1].content + print(f"\nАгент: {final_msg}") + else: + print("\nАгент не вернул ответа.")