Human‑in‑the‑Loop через Middleware
Описание
В этом проекте реализован агент на базе LangChain с встроенным middleware HumanInTheLoopMiddleware.
При каждом вызове инструмента агент останавливается и выводит в терминал сообщение вида:
> Инструмент: get_weather
> Запрос: Какая погода сегодня в Москве?
> Выберите действие: [approve / reject]
Пользователь вводит approve или reject. После этого выполнение агента возобновляется, а результат инструмента (или отказ) возвращается в цепочку.
Мiddleware автоматически формирует запрос на подтверждение и обрабатывает ответ через Command(resume={"decisions": [...]}).
Важно: для корректной работы паузы нужен чекпоинтер (
MemorySaver). Без него агент не сможет сохранить состояние между остановками.
Структура проекта
├── agent.py # Создание агента с HumanInTheLoopMiddleware
├── run_agent.py # Запуск интерактивного диалога с пользователем
└── requirements.txt # Зависимости
Установка зависимостей
# 1. Клонируйте репозиторий (или скопируйте файлы)
git clone https://github.com/your-username/human-in-loop-middleware.git
cd human-in-loop-middleware
# 2. Создайте виртуальное окружение (рекомендовано)
python -m venv .venv
source .venv/bin/activate # Windows: .\.venv\Scripts\activate
# 3. Установите зависимости
pip install -r requirements.txt
requirements.txt содержит:
langchain==0.* # актуальная версия LangChain
langgraph==0.* # для MemorySaver и middleware
openai==1.* # если используете OpenAI LLM
python-dotenv==1.* # для загрузки переменных окружения (API‑ключи)
Примечание: Если вы хотите использовать другой LLM, замените
langchainна нужный пакет и настройтеllmвagent.py.
Запуск
1. Создание агента (agent.py)
python agent.py
Файл создаёт объект agent, но не запускает диалог. Он нужен для импорта при запуске основного скрипта.
2. Интерактивный запуск (run_agent.py)
python run_agent.py
После запуска вы увидите приглашение:
> Какой вопрос у вас есть? (напишите 'exit' чтобы выйти)
Пример взаимодействия:
> Какую погоду сегодня в Москве?
> Инструмент: get_weather
> Запрос: Какая погода сегодня в Москве?
> Выберите действие: [approve / reject] > approve
> Погода в Москве сегодня 22°C, ясно.
Если пользователь вводит reject, агент сообщает об отказе и предлагает задать другой вопрос.
Пример использования
from langchain.agents import create_agent
from langchain.agents.middleware import HumanInTheLoopMiddleware
from langgraph.checkpoint.memory import MemorySaver
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv() # загружает переменные из .env (OPENAI_API_KEY)
# Инициализация LLM
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.7)
# Пример инструмента
def get_weather(location: str) -> str:
"""Возвращает погоду в указанном месте."""
# В реальном проекте здесь будет запрос к API погоды
return f"Погода в {location} сегодня 22°C, ясно."
get_weather_tool = {
"name": "get_weather",
"description": "Получить текущую погоду по местоположению.",
"func": get_weather,
}
memory = MemorySaver()
agent = create_agent(
model=llm,
tools=[get_weather_tool],
system_prompt="Ты полезный ассистент, который может получать погоду.",
middleware=[
HumanInTheLoopMiddleware(
interrupt_on={"get_weather": True},
description_prefix="Подтвердите вызов инструмента",
),
],
checkpointer=memory,
)
# Запуск диалога
while True:
user_input = input("> Какой вопрос у вас есть? (exit) ")
if user_input.lower() == "exit":
break
response = agent.invoke({"input": user_input})
print(response["output"])
Что дальше?
- Добавить больше инструментов – просто расширьте список
toolsи настройтеinterrupt_on. - Настроить разрешённые решения – в
HumanInTheLoopMiddlewareможно указатьallowed_decisions=["approve", "reject"], чтобы убрать вариант редактирования. - Сохранить историю – используйте более продвинутый чекпоинтер (
SQLiteSaver) для долгосрочного хранения сессий.