diff --git a/solutions/69a86305c46fd26feae6bcaa_Human_in_the_Loop_через_middleware/README.md b/solutions/69a86305c46fd26feae6bcaa_Human_in_the_Loop_через_middleware/README.md new file mode 100644 index 0000000..a4ef75b --- /dev/null +++ b/solutions/69a86305c46fd26feae6bcaa_Human_in_the_Loop_через_middleware/README.md @@ -0,0 +1,161 @@ +# 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 # Зависимости +``` + +--- + +## Установка зависимостей + +```bash +# 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` содержит: + +```text +langchain==0.* # актуальная версия LangChain +langgraph==0.* # для MemorySaver и middleware +openai==1.* # если используете OpenAI LLM +python-dotenv==1.* # для загрузки переменных окружения (API‑ключи) +``` + +> **Примечание**: Если вы хотите использовать другой LLM, замените `langchain` на нужный пакет и настройте `llm` в `agent.py`. + +--- + +## Запуск + +### 1. Создание агента (`agent.py`) + +```bash +python agent.py +``` + +Файл создаёт объект `agent`, но не запускает диалог. Он нужен для импорта при запуске основного скрипта. + +### 2. Интерактивный запуск (`run_agent.py`) + +```bash +python run_agent.py +``` + +После запуска вы увидите приглашение: + +``` +> Какой вопрос у вас есть? (напишите 'exit' чтобы выйти) +``` + +Пример взаимодействия: + +``` +> Какую погоду сегодня в Москве? +> Инструмент: get_weather +> Запрос: Какая погода сегодня в Москве? +> Выберите действие: [approve / reject] > approve +> Погода в Москве сегодня 22°C, ясно. +``` + +Если пользователь вводит `reject`, агент сообщает об отказе и предлагает задать другой вопрос. + +--- + +## Пример использования + +```python +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`) для долгосрочного хранения сессий. + +--- + +## Ссылки + +- [Документация LangChain: Human‑in‑the‑Loop](https://docs.langchain.com/oss/python/langchain/human-in-the-loop) +- [GitHub репозиторий LangChain](https://github.com/langchain-ai/langchain) + +--- \ No newline at end of file