Human-in-the-Loop через middleware: README.md
This commit is contained in:
@@ -1,120 +1,109 @@
|
|||||||
# Human‑in‑the‑Loop Agent via Middleware
|
# Human‑in‑the‑Loop через Middleware
|
||||||
|
|
||||||
This repository contains a minimal example of an **LLM agent** that pauses every time it wants to call an external tool and asks the user for confirmation (`approve` or `reject`).
|
Пример реализации агента на LangGraph с встроенным `HumanInTheLoopMiddleware`.
|
||||||
The pause is implemented with LangChain’s built‑in `HumanInTheLoopMiddleware`, which automatically generates the prompt, captures the user input, and resumes execution via a `Command`.
|
При каждом вызове инструмента агент останавливается и выводит в терминал запрос
|
||||||
|
на подтверждение (`approve` / `reject`). После ответа пользователь может
|
||||||
> **Why use middleware?**
|
продолжить выполнение, а агент продолжит работу.
|
||||||
> Unlike the `interrupt_before=['tools']` approach that requires manual handling of interruptions, the middleware handles everything internally: it creates the confirmation request, processes the response, and resumes the agent with the chosen decision.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📦 Installation
|
## 📦 Установка зависимостей
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Create a virtual environment (optional but recommended)
|
# Создайте виртуальное окружение (рекомендуется)
|
||||||
python -m venv .venv
|
python -m venv .venv
|
||||||
source .venv/bin/activate # Windows: .venv\Scripts\activate
|
source .venv/bin/activate # Windows: .venv\Scripts\activate
|
||||||
|
|
||||||
# Install required packages
|
# Установите необходимые пакеты
|
||||||
pip install langchain langgraph openai rich
|
pip install langgraph langchain-core langchain-openai openai tqdm
|
||||||
```
|
```
|
||||||
|
|
||||||
> **OpenAI API key**
|
> **Важно**
|
||||||
> The example uses an OpenAI model. Set your key in the environment:
|
> Для работы с OpenAI API понадобится переменная окружения `OPENAI_API_KEY`.
|
||||||
|
> ```bash
|
||||||
|
> export OPENAI_API_KEY="sk-..."
|
||||||
|
> ```
|
||||||
|
|
||||||
```bash
|
---
|
||||||
export OPENAI_API_KEY="sk-…"
|
|
||||||
|
## 📁 Структура проекта
|
||||||
|
|
||||||
|
```text
|
||||||
|
.
|
||||||
|
├── solution.py # Основной скрипт, реализующий агент
|
||||||
|
└── README.md # Текущий файл
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📁 Project Structure
|
## ▶️ Запуск
|
||||||
|
|
||||||
| File | Purpose |
|
### 1. Запустите скрипт из командной строки
|
||||||
|------|---------|
|
|
||||||
| `solution.py` | Main script that creates the agent, defines a simple tool (`get_weather`), and runs an interactive loop. |
|
|
||||||
|
|
||||||
> The repository contains only one Python file for clarity.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 Running the Example
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python solution.py
|
python solution.py
|
||||||
```
|
```
|
||||||
|
|
||||||
You will see something like:
|
> Скрипт автоматически создаст агента, подключит middleware и начнет диалог с пользователем.
|
||||||
|
|
||||||
|
### 2. Взаимодействие в терминале
|
||||||
|
|
||||||
|
После каждого вызова инструмента вы увидите сообщение вида:
|
||||||
|
|
||||||
```
|
```
|
||||||
User: What's the weather in London?
|
⚠️ Инструмент: get_weather
|
||||||
Agent: (pauses) Подтвердите вызов инструмента get_weather
|
Запрос: "Какая погода в Москве на 2024‑06‑01?"
|
||||||
- approve
|
Нужно подтвердить действие (approve/reject):
|
||||||
- reject
|
|
||||||
Your choice:
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Type `approve` to let the agent call the tool, or `reject` to skip it.
|
- Введите `approve` – инструмент будет выполнен и результат вернётся агенту.
|
||||||
After your decision, the agent continues its reasoning and eventually returns a final answer.
|
- Введите `reject` – вызов инструмента отменяется, агент продолжит работу без него.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🛠️ Customizing
|
## 📄 Пример использования
|
||||||
|
|
||||||
### Changing the Tool
|
|
||||||
|
|
||||||
Replace the `get_weather` function with any other LangChain tool:
|
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
from langgraph.prebuilt import create_react_agent
|
||||||
|
from langchain.tools import tool
|
||||||
|
from langgraph.checkpoint.memory import MemorySaver
|
||||||
|
from langgraph.types import Command
|
||||||
|
from langgraph.moderation import HumanInTheLoopMiddleware
|
||||||
|
|
||||||
|
# 1. Определяем инструмент
|
||||||
@tool
|
@tool
|
||||||
def get_time() -> str:
|
def get_weather(city: str, date: str) -> str:
|
||||||
"""Return current UTC time."""
|
"""Возвращает погоду в городе на указанную дату."""
|
||||||
return datetime.utcnow().isoformat()
|
return f"Погода в {city} на {date}: солнечно 25°C."
|
||||||
|
|
||||||
|
# 2. Создаём агент с middleware
|
||||||
|
memory = MemorySaver()
|
||||||
|
agent = create_react_agent(
|
||||||
|
tools=[get_weather],
|
||||||
|
memory=memory,
|
||||||
|
middleware=[HumanInTheLoopMiddleware()],
|
||||||
|
)
|
||||||
|
|
||||||
|
# 3. Запускаем диалог
|
||||||
|
config = {"thread_id": "session-1"}
|
||||||
|
state = agent.invoke({"messages": [{"role": "user", "content": "Какая погода в Москве на 2024‑06‑01?"}]}, config=config)
|
||||||
|
print(state["messages"][-1]["content"])
|
||||||
```
|
```
|
||||||
|
|
||||||
Add it to the `tools` list when creating the agent.
|
> После запуска вы увидите запрос подтверждения и сможете взаимодействовать с агентом, как описано выше.
|
||||||
|
|
||||||
### Adjusting Middleware Settings
|
|
||||||
|
|
||||||
- **Interrupt on specific decisions**
|
|
||||||
```python
|
|
||||||
interrupt_on={
|
|
||||||
"get_weather": {"allowed_decisions": ["approve", "reject"]} # no edit option
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Custom prompt prefix**
|
|
||||||
```python
|
|
||||||
description_prefix="Please confirm the tool call:"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Using a Different LLM
|
|
||||||
|
|
||||||
Swap `llm` for any LangChain-compatible model (e.g., GPT‑4o, Claude, etc.):
|
|
||||||
|
|
||||||
```python
|
|
||||||
from langchain_openai import ChatOpenAI
|
|
||||||
llm = ChatOpenAI(model_name="gpt-4o-mini")
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📖 Example Interaction
|
## 📚 Полезные ссылки
|
||||||
|
|
||||||
```
|
- [Документация LangChain – Human‑in‑the‑Loop](https://docs.langchain.com/oss/python/langchain/human-in-the-loop)
|
||||||
User: Tell me the weather in Paris.
|
- [LangGraph GitHub репозиторий](https://github.com/run-llama/langgraph)
|
||||||
Agent: (pauses) Подтвердите вызов инструмента get_weather
|
|
||||||
- approve
|
|
||||||
- reject
|
|
||||||
Your choice: approve
|
|
||||||
Agent: The current temperature in Paris is 18°C with clear skies.
|
|
||||||
Final answer: It’s sunny and mild in Paris today.
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📜 License
|
## 🤝 Вклад
|
||||||
|
|
||||||
This project is provided under the MIT license. Feel free to adapt it for your own experiments.
|
Если вы нашли ошибки или хотите добавить новые инструменты, создайте pull request.
|
||||||
|
Пожалуйста, придерживайтесь стиля кода из `solution.py` и добавляйте комментарии.
|
||||||
|
|
||||||
---
|
---```
|
||||||
Reference in New Issue
Block a user