119 lines
3.5 KiB
Markdown
119 lines
3.5 KiB
Markdown
# Human‑in‑the‑Loop Middleware Demo
|
||
|
||
This repository contains a minimal **LangChain** agent that demonstrates how to pause execution at every tool call and ask the user for approval or rejection before continuing.
|
||
The core of this behaviour is provided by `HumanInTheLoopMiddleware`, which automatically injects a confirmation step into the agent’s workflow.
|
||
|
||
> ⚠️ The example uses the open‑source **Ollama** LLM backend.
|
||
> If you don’t have Ollama installed, follow the instructions in the *Prerequisites* section.
|
||
|
||
---
|
||
|
||
## Table of Contents
|
||
|
||
- [Description](#description)
|
||
- [Prerequisites](#prerequisites)
|
||
- [Installation](#installation)
|
||
- [Running the Demo](#running-the-demo)
|
||
- [Example Interaction](#example-interaction)
|
||
|
||
---
|
||
|
||
## Description
|
||
|
||
`solution.py` implements a LangChain agent that:
|
||
|
||
1. **Creates** an LLM chain using `ChatOllama`.
|
||
2. **Wraps** it with a `MemorySaver` checkpoint for state persistence.
|
||
3. **Adds** the `HumanInTheLoopMiddleware`, which:
|
||
- Intercepts every tool call,
|
||
- Prints the intended action to the terminal (via `rich`),
|
||
- Prompts the user for `"approve"` or `"reject"`,
|
||
- Resumes execution based on the response.
|
||
|
||
This pattern is useful when you want a human operator to supervise or validate each step of an automated workflow, without having to manually interrupt the agent.
|
||
|
||
---
|
||
|
||
## Prerequisites
|
||
|
||
| Item | Version | Notes |
|
||
|------|---------|-------|
|
||
| Python | ≥ 3.10 | Tested with 3.11 |
|
||
| pip | – | Standard package installer |
|
||
| **Ollama** | Latest | Install from https://ollama.ai/ and run `ollama serve` before starting the demo. |
|
||
| **OpenAI‑compatible model** | e.g., `llama2:7b` | Pull via `ollama pull llama2:7b`. |
|
||
|
||
> **Tip:** If you prefer a different LLM, replace `ChatOllama` with any LangChain-compatible LLM (e.g., OpenAI, Anthropic).
|
||
|
||
---
|
||
|
||
## Installation
|
||
|
||
```bash
|
||
# 1. Clone the repo
|
||
git clone https://github.com/your-username/human-in-the-loop-demo.git
|
||
cd human-in-the-loop-demo
|
||
|
||
# 2. Create a virtual environment (optional but recommended)
|
||
python -m venv .venv
|
||
source .venv/bin/activate # On Windows: .\.venv\Scripts\activate
|
||
|
||
# 3. Install dependencies
|
||
pip install --upgrade pip
|
||
pip install langchain langgraph langchain-ollama rich
|
||
```
|
||
|
||
> **Note:**
|
||
> `langgraph` is required for the checkpointing and middleware support.
|
||
|
||
---
|
||
|
||
## Running the Demo
|
||
|
||
```bash
|
||
# Make sure Ollama server is running:
|
||
# ollama serve
|
||
|
||
# Run the agent script
|
||
python solution.py
|
||
```
|
||
|
||
You will be prompted to enter a question. The agent will then:
|
||
|
||
1. Generate a plan.
|
||
2. For each tool call, pause and display the intended action.
|
||
3. Await your `"approve"` or `"reject"` input before proceeding.
|
||
|
||
---
|
||
|
||
## Example Interaction
|
||
|
||
```text
|
||
$ python solution.py
|
||
Enter your question: What is the capital of France?
|
||
|
||
[Agent] Thinking...
|
||
[HumanInTheLoopMiddleware] Tool call planned: "search" with query "capital of France"
|
||
Approve? (yes/no): yes
|
||
|
||
[Agent] Executing tool...
|
||
Result: Paris
|
||
|
||
[Agent] Continuing...
|
||
|
||
Final answer: The capital of France is Paris.
|
||
```
|
||
|
||
If you type `no` instead of `yes`, the agent will skip that tool call and attempt to continue with its plan, potentially leading to a different outcome.
|
||
|
||
---
|
||
|
||
## Customization
|
||
|
||
- **Different tools** – Add more tools via `@tool` decorators or by passing a list to `create_agent`.
|
||
- **Custom prompt** – Modify the middleware’s confirmation message by subclassing `HumanInTheLoopMiddleware`.
|
||
- **Persist state** – The `MemorySaver` checkpoint can be swapped for a database-backed store if you need long‑term persistence.
|
||
|
||
---
|
||
|
||
Happy experimenting! 🚀 |