98 lines
5.6 KiB
Markdown
98 lines
5.6 KiB
Markdown
# Самокорректирующийся агент (LangGraph)
|
||
|
||
## Описание
|
||
Проект демонстрирует реализацию **самокорректирующегося агента** на базе `LangGraph`.
|
||
Агент получает задачу, выполняет её через ненадёжный инструмент (`unreliable_tool`), затем LLM‑as‑judge проверяет результат. Если проверка не прошла и количество попыток меньше `max_attempts`, агент повторяет выполнение. Цикл продолжается до получения статуса `success` или исчерпания лимита попыток.
|
||
|
||
### Состояние графа (`AgentState`)
|
||
```python
|
||
class AgentState(TypedDict):
|
||
task: str # исходная задача
|
||
result: str # результат выполнения инструмента
|
||
attempts: int # текущая попытка (начинается с 0)
|
||
status: str # pending | success | failed | max_attempts
|
||
error: Optional[str] # текст ошибки, если возникла
|
||
max_attempts: int # лимит попыток
|
||
```
|
||
|
||
### Узлы графа
|
||
| Узел | Роль |
|
||
|-----------------|----------------------------------------------------------------------|
|
||
| `execute_task` | Вызывает `unreliable_tool` (с ~30% вероятностью бросает `ValueError`). |
|
||
| `verify_result` | LLM‑as‑judge оценивает результат и возвращает строго `"success"` или `"failed"`. |
|
||
| `handle_error` | Увеличивает `attempts`, сохраняет ошибку и готовит к повторному выполнению. |
|
||
|
||
### Граф
|
||
```
|
||
START → execute_task → verify_result
|
||
↓ success → END
|
||
↓ failed & attempts < max → handle_error → execute_task
|
||
↓ max_attempts → END
|
||
```
|
||
|
||
## Установка зависимостей
|
||
```bash
|
||
# Рекомендуется использовать виртуальное окружение
|
||
python -m venv venv
|
||
source venv/bin/activate # Windows: venv\Scripts\activate
|
||
|
||
# Установить необходимые пакеты
|
||
pip install langgraph langchain-openai langchain-ollama
|
||
```
|
||
|
||
> **Важно:** Для работы с OpenAI необходимо задать переменную окружения `OPENAI_API_KEY`.
|
||
> Если вы предпочитаете Ollama, установите локальную модель и используйте `ChatOllama` вместо `ChatOpenAI` (см. комментарии в коде).
|
||
|
||
## Запуск
|
||
В проекте единственный исполняемый файл — `main.py`.
|
||
|
||
```bash
|
||
python main.py
|
||
```
|
||
|
||
При запуске скрипт выводит:
|
||
- номер текущей попытки,
|
||
- результат выполнения инструмента,
|
||
- вердикт LLM‑as‑judge,
|
||
- финальный статус (`success`, `failed` или `max_attempts`).
|
||
|
||
### Пример вывода
|
||
```
|
||
Attempt 0: Result = 42, Judge = failed
|
||
Attempt 1: Result = 42, Judge = success
|
||
Final status: success
|
||
```
|
||
|
||
Если все попытки исчерпаны:
|
||
```
|
||
Attempt 0: Result = Error: ..., Judge = failed
|
||
Attempt 1: Result = Error: ..., Judge = failed
|
||
Attempt 2: Result = Error: ..., Judge = failed
|
||
Final status: max_attempts
|
||
```
|
||
|
||
## Как работает пример
|
||
1. **`unreliable_tool`** – простая функция, которая с вероятностью ~30% бросает `ValueError`, иначе возвращает фиксированный результат (например, `"42"`).
|
||
2. **LLM‑as‑judge** – запрос к модели (OpenAI GPT‑3.5‑turbo или локальная Ollama) с промптом, требующим ответить **только** словом `success` или `failed` в зависимости от того, совпадает ли результат с ожидаемым значением.
|
||
3. Граф построен через `StateGraph` и скомпилирован в исполняемый объект, который запускается в цикле до достижения терминального узла.
|
||
|
||
## Настройка
|
||
- Изменить `task` и ожидаемый результат в функции `unreliable_tool` внутри `main.py`.
|
||
- Подстроить `max_attempts` в начальном состоянии (по умолчанию `3`).
|
||
- Переключиться между OpenAI и Ollama, заменив импорт и инициализацию LLM:
|
||
```python
|
||
# Для OpenAI
|
||
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
|
||
|
||
# Для Ollama (убедитесь, что модель запущена: ollama run <model>)
|
||
# from langchain_ollama import ChatOllama
|
||
# llm = ChatOllama(model="llama3", temperature=0)
|
||
```
|
||
|
||
## Требования
|
||
- Python 3.10+
|
||
- Доступ к интернету (для OpenAI) **или** запущенный локальный Ollama сервер.
|
||
|
||
---
|
||
|
||
*Это README охватывает только основной файл проекта `main.py`. При добавлении новых файлов достаточно дополнить разделы «Запуск» и «Пример использования» соответствующими инструкциями.* |