# solution.py # -*- coding: utf-8 -*- """ Пример агента с Human-in-the-Loop через HumanInTheLoopMiddleware. При каждом вызове инструмента агент останавливается, выводит информацию и ожидает решения пользователя: approve / reject. """ from langchain_openai import ChatOpenAI from langchain.tools import tool from langchain.agents.middleware import HumanInTheLoopMiddleware from langgraph.prebuilt import create_react_agent from langgraph.checkpoint.memory import MemorySaver from langgraph.types import Command # 1. Модель LLM llm = ChatOpenAI( model="gpt-4o-mini", temperature=0, ) # 2. Простой инструмент @tool def get_weather(city: str, date: str) -> str: """Возвращает погоду в городе на указанную дату.""" return f"Погода в {city} на {date}: солнечно 25°C." # 3. Хранилище памяти memory = MemorySaver() # 4. Создание агента с HumanInTheLoopMiddleware agent = create_react_agent( model=llm, tools=[get_weather], system_prompt="Ты полезный ассистент, отвечай точно.", checkpointer=memory, middleware=[ HumanInTheLoopMiddleware( interrupt_on={ "get_weather": True, # прерывать на каждом вызове get_weather }, description_prefix="Подтвердите вызов инструмента", ), ], ) def main() -> None: """ Запускает чат-цикл с human-in-the-loop: пользователь вводит запрос, агент останавливается перед вызовом инструмента и ждёт подтверждения (approve / reject). """ config = {"configurable": {"thread_id": "session-1"}} print("Привет! Введите запрос или 'выход' для завершения.") while True: user_input = input("\nВы: ").strip() if user_input.lower() in {"выход", "exit", "quit"}: print("Завершение работы.") break # Первый вызов агента result = agent.invoke( {"messages": [{"role": "human", "content": user_input}]}, config=config, ) # Цикл обработки прерываний while "__interrupt__" in result: interrupt_payload = result["__interrupt__"][0].value action_requests = interrupt_payload.get("action_requests", []) review_configs = interrupt_payload.get("review_configs", {}) decisions = [] for req in action_requests: name = req.get("name", "неизвестный инструмент") args = req.get("args", {}) description = req.get("description", "") print("\n--- Подтверждение ---") print(f"Инструмент: {name}") if description: print(f"Описание: {description}") print(f"Аргументы: {args}") # Показываем разрешённые решения из review_configs allowed = review_configs.get(name, {}).get( "allowed_decisions", ["approve", "reject"] ) print(f"Разрешённые решения: {allowed}") choice = input("a=approve, r=reject: ").strip().lower() if choice == "r": reason = input("Причина отказа: ").strip() decisions.append({"type": "reject", "message": reason}) else: decisions.append({"type": "approve"}) # Возобновляем выполнение агента с решениями result = agent.invoke( Command(resume={"decisions": decisions}), config=config, ) # Финальный ответ агента final_answer = result["messages"][-1].content print(f"\nАгент: {final_answer}") if __name__ == "__main__": main()