diff --git a/solutions/69a86305c46fd26feae6bcaa_Human-in-the-Loop_через_middleware/README.md b/solutions/69a86305c46fd26feae6bcaa_Human-in-the-Loop_через_middleware/README.md index 3b64602..a01fe2c 100644 --- a/solutions/69a86305c46fd26feae6bcaa_Human-in-the-Loop_через_middleware/README.md +++ b/solutions/69a86305c46fd26feae6bcaa_Human-in-the-Loop_через_middleware/README.md @@ -1,140 +1,86 @@ -# Human‑in‑the‑Loop Agent via Middleware (LangGraph) +# Human‑in‑the‑Loop Agent with LangGraph -This repository contains a minimal example of a **Human‑in‑the‑Loop** agent built on top of LangGraph. -The agent pauses whenever it needs to call an external tool, prints the tool request and waits for a user decision (`approve` or `reject`). After the decision is supplied, execution resumes automatically. +This repository contains a minimal example of a **Human‑in‑the‑Loop** (HITL) agent built on top of [LangGraph](https://github.com/langchain-ai/langgraph). +The agent pauses whenever it needs to call an external tool, presents the tool output to the user and waits for a decision (`approve` or `reject`). After the decision is made the conversation continues automatically. -> ⚠️ The example uses OpenAI’s API (or any compatible LLM). Make sure you have an API key set in the environment variable `OPENAI_API_KEY`. +> **⚠️ Prerequisites** – The example uses OpenAI‑compatible APIs. +> Make sure you have an API key set in the environment variable `OPENAI_API_KEY`. --- -## Table of Contents - -- [Features](#features) -- [Prerequisites](#prerequisites) -- [Installation](#installation) -- [Running the Agent](#running-the-agent) - - [Interactive Demo (`solution.py`)](#interactive-demo-solutionpy) - - [Unit Tests (`tests/test_solution.py`)](#unit-tests-test_solutionpy) -- [Example Usage](#example-usage) -- [License](#license) - ---- - -## Features - -| Feature | Description | -|---------|-------------| -| **Human‑in‑the‑Loop** | Agent stops before calling any tool, prints the request and waits for user input. | -| **Interrupts via `interrupt_before=["tools"]`** | Configurable interruption point in LangGraph. | -| **Tool Example** | Simple `get_weather(city, date)` function that returns a mock weather string. | -| **Checkpointing** | Uses an in‑memory checkpoint (`MemorySaver`) to preserve state across interruptions. | - ---- - -## Prerequisites - -- Python 3.10+ -- An OpenAI API key (or any compatible LLM endpoint) +## 📦 Installation ```bash -export OPENAI_API_KEY="sk-..." +# 1️⃣ Clone the repo (or copy solution.py into a new folder) +git clone https://github.com/your-username/hitl-langgraph.git +cd hitl-langgraph + +# 2️⃣ Create and activate a virtual environment (optional but recommended) +python -m venv .venv +source .venv/bin/activate # Windows: .\.venv\Scripts\activate + +# 3️⃣ Install dependencies +pip install --upgrade pip +pip install langchain-openai langgraph langchain-tools ``` ---- - -## Installation - -1. **Clone the repository** - - ```bash - git clone https://github.com/yourusername/human-in-loop-langgraph.git - cd human-in-loop-langgraph - ``` - -2. **Create a virtual environment (optional but recommended)** - - ```bash - python -m venv .venv - source .venv/bin/activate # On Windows: .venv\Scripts\activate - ``` - -3. **Install dependencies** - - ```bash - pip install -r requirements.txt - ``` - - *If you don’t have a `requirements.txt`, create one with the following content:* - - ```text - langchain-openai>=0.2.0 - langgraph>=0.1.0 - ``` +> **Tip** – If you want to use a different LLM (e.g., Anthropic, Gemini), replace the `ChatOpenAI` import with the appropriate wrapper and adjust the model name. --- -## Running the Agent +## 🚀 Running the Agent -### Interactive Demo (`solution.py`) - -The main script demonstrates how to start the agent and handle interruptions. +The main logic is in `solution.py`. +Run it directly: ```bash python solution.py ``` -**What happens:** +### What Happens? -1. The user enters a prompt (e.g., “What’s the weather in Paris on 2024‑12‑01?”). -2. The agent processes the request, decides it needs to call `get_weather`, and pauses. -3. The tool request is printed: - - ``` - Tool requested: get_weather - Arguments: {'city': 'Paris', 'date': '2024-12-01'} - ``` - -4. You are prompted to type `approve` or `reject`. -5. After your decision, the agent resumes and prints the final answer. +1. The agent starts a conversation. +2. When it decides to call the `get_weather` tool, the execution pauses. +3. The tool output (e.g., `"Погода в Москва на 2024-05-28: солнечно 25°C."`) is printed to the console. +4. You are prompted to type **approve** or **reject**: + - `approve`: the agent resumes with the tool result as normal input. + - `reject`: the agent receives a `ToolMessage` indicating rejection and can decide what to do next. --- -### Unit Tests (`tests/test_solution.py`) +## 🔧 Example Interaction -Run the test suite to verify that the interruption logic works as expected: - -```bash -pytest tests/test_solution.py +```text +$ python solution.py +Agent: Какую погоду вы хотите узнать? +User: Москва на 2024-05-28 +Agent (calling tool): get_weather(city='Москва', date='2024-05-28') +Tool output: Погода в Москва на 2024-05-28: солнечно 25°C. +Please type 'approve' or 'reject': approve +Agent: Спасибо! Как ещё могу помочь? ``` -The tests simulate a user approving the tool call automatically and check that the final output contains the weather string. +If you type `reject`, the agent will receive a rejection message and can, for example, ask for clarification. --- -## Example Usage +## 📁 Project Structure -Below is a quick snippet you can paste into a Python REPL or another script to see the agent in action: - -```python -from solution import agent, memory # assuming solution.py defines them - -# Start a new thread/session -config = {"configurable": {"thread_id": "demo-session"}} - -# Invoke with a user message -response = agent.invoke( - {"messages": [{"role": "user", "content": "What's the weather in Tokyo on 2025-01-15?"}]}, - config=config, -) - -print("\nFinal response:") -print(response["messages"][-1]["content"]) -``` - -When you run this, you’ll see the same interruption prompt as described above. +| File | Purpose | +|------|---------| +| `solution.py` | Full implementation of the HITL agent. | +| `README.md` | This documentation file. | --- -## License +## 🛠️ Customization -MIT © 2026. Feel free to fork and adapt for your own projects. \ No newline at end of file +- **Add more tools** – Decorate any function with `@tool` and add it to the `tools=[...]` list. +- **Change prompt** – Edit `system_prompt` in `create_react_agent`. +- **Persist memory** – Replace `MemorySaver()` with a file‑based or database checkpoint if you need persistence across runs. + +--- + +## 📜 License + +MIT © 2026. Feel free to fork and adapt for your own projects! \ No newline at end of file