From a4190d7713c271b7a818f40e09ca86bf64071a6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=B8=D1=8F=20=D0=91=D0=B5=D1=80=D0=B4?= =?UTF-8?q?=D0=BD=D0=B8=D0=BA=D0=BE=D0=B2=D0=B0?= Date: Thu, 28 May 2026 05:44:17 +0000 Subject: [PATCH] =?UTF-8?q?Human-in-the-Loop=20=D1=87=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=B7=20middleware:=20README.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../README.md | 141 +++++++++--------- 1 file changed, 71 insertions(+), 70 deletions(-) diff --git a/solutions/69a86305c46fd26feae6bcaa_Human-in-the-Loop_через_middleware/README.md b/solutions/69a86305c46fd26feae6bcaa_Human-in-the-Loop_через_middleware/README.md index 5ce9acb..3b64602 100644 --- a/solutions/69a86305c46fd26feae6bcaa_Human-in-the-Loop_через_middleware/README.md +++ b/solutions/69a86305c46fd26feae6bcaa_Human-in-the-Loop_через_middleware/README.md @@ -1,139 +1,140 @@ -# Human‑in‑the‑Loop Agent via Middleware +# Human‑in‑the‑Loop Agent via Middleware (LangGraph) -This repository contains a minimal example of an LLM agent that pauses whenever it wants to call a tool and asks the user for approval before proceeding. -The core idea is to use **`HumanInTheLoopMiddleware`** from LangChain, which intercepts every tool invocation, prints a prompt with the action details, and waits for the user to respond (`approve`, `reject`, or optionally edit the request). +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. -> **Why this matters** – In many real‑world scenarios you want an LLM to ask for human confirmation before performing potentially sensitive actions (e.g., sending emails, accessing databases, calling external APIs). +> ⚠️ 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`. --- ## Table of Contents -- [Project Structure](#project-structure) +- [Features](#features) +- [Prerequisites](#prerequisites) - [Installation](#installation) - [Running the Agent](#running-the-agent) - - [Interactive Mode](#interactive-mode) - - [Scripted Example](#scripted-example) + - [Interactive Demo (`solution.py`)](#interactive-demo-solutionpy) + - [Unit Tests (`tests/test_solution.py`)](#unit-tests-test_solutionpy) - [Example Usage](#example-usage) -- [Extending the Agent](#extending-the-agent) +- [License](#license) --- -## Project Structure +## 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) + +```bash +export OPENAI_API_KEY="sk-..." ``` -├── solution.py # Main script with the agent implementation -└── README.md # This file -``` - -`solution.py` contains: - -1. **LLM configuration** – uses `ChatOpenAI`. -2. **A simple tool** (`get_weather`) that returns a fake weather string. -3. **Memory checkpoint** via `MemorySaver`. -4. **Agent creation** with `create_react_agent` and the middleware. -5. **Execution loop** that keeps asking for user input until the conversation ends. --- ## Installation -1. **Clone the repo** +1. **Clone the repository** ```bash - git clone https://github.com/your-username/human-in-the-loop-agent.git - cd human-in-the-loop-agent + 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 + source .venv/bin/activate # On Windows: .venv\Scripts\activate ``` 3. **Install dependencies** ```bash - pip install --upgrade pip - pip install langchain langgraph openai + pip install -r requirements.txt ``` -4. **Set your OpenAI API key** + *If you don’t have a `requirements.txt`, create one with the following content:* - ```bash - export OPENAI_API_KEY="sk-..." - # Windows: setx OPENAI_API_KEY "sk-..." + ```text + langchain-openai>=0.2.0 + langgraph>=0.1.0 ``` --- ## Running the Agent -### Interactive Mode +### Interactive Demo (`solution.py`) -Simply run the script: +The main script demonstrates how to start the agent and handle interruptions. ```bash python solution.py ``` -You will see a prompt like: +**What happens:** -``` -Agent wants to call tool `get_weather` with arguments: - city = "Moscow" - date = "2025-10-01" +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: -Please type one of: approve / reject (or edit ) -> -``` + ``` + Tool requested: get_weather + Arguments: {'city': 'Paris', 'date': '2024-12-01'} + ``` -Type **`approve`** to let the agent proceed, or **`reject`** to stop it. -If you want to modify the arguments before approval, use `edit city=London date=2025-12-25`. +4. You are prompted to type `approve` or `reject`. +5. After your decision, the agent resumes and prints the final answer. -The conversation continues until the user types `stop` or the agent finishes its plan. +--- -### Scripted Example +### Unit Tests (`tests/test_solution.py`) -You can also run a quick demo that automatically approves all calls: +Run the test suite to verify that the interruption logic works as expected: ```bash -python - <<'PY' -from solution import agent, llm, memory -# Override middleware to auto‑approve for demonstration -agent.middleware[0].interrupt_on = {"get_weather": False} -print(agent.run("What's the weather in New York tomorrow?")) -PY +pytest tests/test_solution.py ``` +The tests simulate a user approving the tool call automatically and check that the final output contains the weather string. + --- ## Example Usage -```bash -$ python solution.py -User: What's the weather in Paris next Friday? -Agent wants to call tool `get_weather` with arguments: - city = "Paris" - date = "2025-10-06" +Below is a quick snippet you can paste into a Python REPL or another script to see the agent in action: -Please type one of: approve / reject (or edit ) -> approve +```python +from solution import agent, memory # assuming solution.py defines them -Assistant: Погода в Париже на 2025‑10‑06: солнечно 25°C. -User: Thank you! +# 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"]) ``` ---- - -## Extending the Agent - -1. **Add more tools** – decorate any function with `@tool` and add it to the `tools` list in `create_react_agent`. -2. **Change the interrupt policy** – modify `interrupt_on` dict (e.g., `{ "get_weather": True, "send_email": False }`). -3. **Persist conversation state** – replace `MemorySaver()` with a database checkpoint if you need long‑term memory. -4. **Custom prompts** – tweak `system_prompt` or add a custom `description_prefix`. +When you run this, you’ll see the same interruption prompt as described above. --- -Happy hacking! 🚀 \ No newline at end of file +## License + +MIT © 2026. Feel free to fork and adapt for your own projects. \ No newline at end of file