# Human‑in‑the‑Loop через Middleware ## Описание проекта В этом проекте реализован агент на базе LangChain, который использует **HumanInTheLoopMiddleware** для ручного подтверждения вызовов инструментов. Каждый раз, когда агент планирует использовать инструмент (например, `get_weather`), он останавливается и выводит в терминал сообщение с просьбой подтвердить действие. Пользователь вводит одно из решений (`approve`, `reject` или `edit`) и только после этого выполнение возобновляется. > **Преимущество**: Middleware сам формирует запрос на подтверждение, обрабатывает ответ и управляет переходом к следующему шагу через `Command(resume={…})`. Это упрощает интеграцию Human‑in‑the‑Loop по сравнению с ручным использованием `interrupt_before=['tools']`. ## Структура проекта ``` ├── solution.py # Основной скрипт, реализующий агента └── README.md # Текущий файл ``` --- ## Установка зависимостей ```bash # Создайте виртуальное окружение (рекомендуется) python -m venv .venv source .venv/bin/activate # Windows: .venv\Scripts\activate # Установите необходимые библиотеки pip install langchain langgraph langchain-community openai ``` > **Важно** > * Если у вас нет ключа OpenAI, замените `OpenAI` на любой другой LLM (например, `DummyLLM`, который возвращает фиксированный ответ). > * Для работы с `HumanInTheLoopMiddleware` требуется версия LangChain ≥ 0.2 и LangGraph ≥ 0.1. --- ## Запуск проекта ```bash python solution.py ``` ### Что происходит при запуске? 1. Инициализируется LLM (по умолчанию OpenAI). 2. Создаётся инструмент `get_weather`. 3. Агент создаётся с Middleware, который перехватывает вызовы инструмента и запрашивает подтверждение у пользователя. 4. В терминале выводятся сообщения вида: ``` [HumanInTheLoop] Подтвердите вызов инструмента: - get_weather Введите решение (approve/reject/edit): ``` 5. После ввода решения агент продолжает работу. --- ## Пример использования ```bash $ python solution.py > Какую погоду в Москве сегодня? [HumanInTheLoop] Подтвердите вызов инструмента: - get_weather Введите решение (approve/reject/edit): approve Ответ агента: Сегодня в Москве солнечно, температура 22°C. ``` Если пользователь введёт `reject`, агент отменит вызов и попытается найти другой способ ответа. В случае `edit` можно изменить параметры запроса к инструменту. --- ## Как добавить собственный инструмент 1. Определите функцию‑инструмент: ```python def get_time(location: str) -> str: # Возвращает текущее время в указанном месте ``` 2. Добавьте её в список `tools` при создании агента и настройте Middleware: ```python agent = create_agent( model=llm, tools=[get_weather, get_time], middleware=[ HumanInTheLoopMiddleware( interrupt_on={"get_time": True}, description_prefix="Подтвердите вызов инструмента", ), ], ) ``` --- ## Тестирование Для быстрой проверки можно использовать `DummyLLM`, который всегда возвращает один и тот же ответ. Это удобно, если у вас нет доступа к OpenAI. ```python class DummyLLM: def __call__(self, *args, **kwargs): return "dummy response" ``` --- ## FAQ | Вопрос | Ответ | |--------|-------| | Как отключить Human‑in‑the‑Loop? | Удалите Middleware из списка `middleware` при создании агента. | | Можно ли задать только `approve` и `reject`, без `edit`? | Да, передайте в `interrupt_on`: `{"get_weather": {"allowed_decisions": ["approve", "reject"]}}`. | | Что делать, если агент не сохраняет состояние после паузы? | Убедитесь, что вы передали `checkpointer=MemorySaver()` при создании агента. | --- ## Лицензия MIT © 2026