Саморефлексия агентов и автоматическое исправление ошибок

50 минут Урок 29

Урок: Саморефлексия агентов и автоматическое исправление ошибок

Добро пожаловать в один из самых захватывающих разделов курса по Gemini 3 API. Сегодня мы переходим от создания агентов, которые просто «выполняют команды», к агентам, которые умеют думать о собственном мышлении.

В когнитивной науке это называется метакогниция. В мире LLM мы называем это саморефлексией (Self-Reflection).

Почему это критически важно?

Даже самые мощные модели, включая Gemini 3, могут ошибаться. Они могут галлюцинировать, допускать синтаксические ошибки в коде или неверно интерпретировать сложные инструкции. В традиционном программировании ошибка ведет к падению программы. В агентных системах ошибка — это просто сигнал для обучения.

Если ваш агент выдал неверный ответ, а вы просто приняли его — система ненадежна. Но если агент:

  1. Выдал ответ.
  2. Проверил его (сам или с помощью инструментов).
  3. Обнаружил ошибку.
  4. Исправил её и выдал финальный результат.

...тогда вы получаете автономную систему промышленного уровня.

Архитектура цикла рефлексии (The Reflection Loop)

Базовая схема работы автономного агента обычно выглядит линейно: Ввод -> Модель -> Вывод. Для внедрения самокоррекции мы превращаем линию в цикл.

Существует несколько популярных паттернов для реализации этого:

  • ReAct (Reason + Act): Агент рассуждает, выполняет действие, наблюдает результат. Если результат не соответствует ожиданию, он генерирует новое рассуждение.
  • Reflexion: Более продвинутый фреймворк, где агент хранит «вербальную память» о прошлых ошибках, чтобы не повторять их в следующих попытках.
  • Actor-Critic (Актор-Критик): Использование двух разных промптов (или даже моделей). Один генерирует решение (Актор), второй жестко критикует его и ищет уязвимости (Критик).

Рассмотрим, как это выглядит на практике при работе с кодом. Это самый наглядный пример, так как код либо работает, либо нет — критерий успеха бинарен и объективен.

python
import google.generativeai as genai
import traceback
import io
import sys

# Настройка модели (предполагаем, что API ключ уже в окружении)
model = genai.GenerativeModel('gemini-3-pro')

def execute_generated_code(code_string):
    """
    Пытается выполнить Python-код и возвращает результат или текст ошибки.
    """
    # Перехват stdout для захвата вывода print()
    buffer = io.StringIO()
    sys.stdout = buffer
    
    try:
        # Внимание: exec() опасен в продакшене без песочницы!
        # Используем здесь только для демонстрации логики.
        exec(code_string, globals())
        output = buffer.getvalue()
        return True, output
    except Exception:
        # Если произошла ошибка, захватываем полный traceback
        error_msg = traceback.format_exc()
        return False, error_msg
    finally:
        sys.stdout = sys.__stdout__

# Пример того, как мы будем использовать это дальше
# code = "print(10 / 0)"
# success, result = execute_generated_code(code)
# print(f"Success: {success}, Result: {result}")

Паттерн «Самоисцеляющийся код» (Self-Healing Code)

Теперь, когда у нас есть инструмент для выполнения кода и получения текста ошибки (функция выше), мы можем замкнуть цикл обратной связи.

Алгоритм действий:

  1. Генерация: Просим Gemini написать функцию.
  2. Исполнение: Запускаем код через exec().
  3. Проверка:
    • Если код сработал успешно -> Возвращаем результат.
    • Если возникло исключение -> Берем текст ошибки (Traceback).
  4. Рефлексия и исправление: Отправляем модели историю диалога: «Вот твой код, а вот ошибка, которую он вызвал: [Traceback]. Проанализируй причину, исправь код и верни только исправленную версию».
  5. Повтор: Повторяем цикл до успеха или исчерпания лимита попыток.

Этот метод невероятно эффективен. Gemini 3 отлично понимает сообщения об ошибках интерпретатора Python и быстро находит пропущенные импорты, синтаксические ошибки или логические несостыковки.

python
def generate_and_fix_code(prompt, max_attempts=3):
    chat = model.start_chat(history=[])
    
    # Шаг 1: Первичный запрос
    response = chat.send_message(
        f"{prompt}\nВАЖНО: Ответ должен содержать ТОЛЬКО исполняемый код Python, без маркдауна и объяснений."
    )
    current_code = response.text.replace('```python', '').replace('```', '').strip()
    
    print(f"--- Попытка 1: Сгенерирован код ---\n{current_code}\n")

    for attempt in range(max_attempts):
        # Шаг 2: Исполнение
        success, output = execute_generated_code(current_code)
        
        if success:
            print(f"SUCCESS! Результат выполнения:\n{output}")
            return current_code
        else:
            print(f"ERROR на попытке {attempt + 1}:\n{output}")
            
            # Шаг 3: Рефлексия (обратная связь)
            feedback_prompt = (
                f"Код вызвал следующую ошибку:\n{output}\n"
                "Пожалуйста, проанализируй traceback, объясни причину ошибки "
                "(в мыслях) и напиши ИСПРАВЛЕННЫЙ код. Верни только код."
            )
            
            response = chat.send_message(feedback_prompt)
            current_code = response.text.replace('```python', '').replace('```', '').strip()
            print(f"--- Исправление от Gemini ---\n{current_code}\n")
            
    print("Не удалось исправить код за отведенное число попыток.")
    return None

# Запуск агента с заведомо сложной задачей или провокацией на ошибку
# Например, попросим использовать библиотеку, которой может не быть, или сложную логику
task = "Напиши функцию, которая считает факториал числа 5, но используй рекурсию без базового случая (ошибка глубины), а потом исправь это."
# В реальности мы даем нормальную задачу, но модель может ошибиться сама.

# generate_and_fix_code("Напиши код, который создает список из 5 элементов и пытается обратиться к 10-му элементу.")

Рефлексия без выполнения кода (Logical Reflection)

Что делать, если задача не связана с написанием кода? Например, написание аналитической записки или суммаризация текста. Здесь нет компилятора, который выдаст «Ошибку 404».

В этом случае мы используем технику «Двухшапочного мышления» (Two-Cap Thinking) или архитектуру Актор-Критик внутри одного чата.

Промпт для самокритики

Вместо того чтобы просить «Напиши статью», мы разбиваем процесс:

  • Шаг 1 (Черновик): «Напиши черновик статьи о квантовых компьютерах.»
  • Шаг 2 (Критика): «Теперь представь, что ты — строгий редактор научного журнала. Прочитай текст выше. Найди логические ошибки, повторения, слишком сложные термины без объяснений и 'воду'. Составь список из 3-5 пунктов для улучшения.»
  • Шаг 3 (Финализация): «Используя эту критику, перепиши статью начисто.»

Исследования показывают, что LLM значительно лучше находят ошибки в уже сгенерированном тексте, чем предотвращают их в процессе генерации. Разделение генерации и проверки — ключ к качеству.

Упражнение

Создайте агента 'JSON Validator'. <br><br>Задача:<br>1. Агент должен получать описание объекта (например, 'Создай профиль RPG-персонажа').<br>2. Агент должен генерировать JSON строку.<br>3. Ваш скрипт должен пытаться распарсить эту строку через json.loads().<br>4. Если парсинг падает (JSONDecodeError), скрипт должен автоматически отправить ошибку обратно агенту и попросить исправить JSON.<br>5. Если в JSON отсутствуют обязательные поля (например, 'hp' или 'inventory'), это тоже считается ошибкой логики, о которой нужно сообщить агенту.

Продвинутая стратегия: Self-Consistency (Самосогласованность)

Для задач, требующих сложных рассуждений (математика, логика), простой рефлексии может быть недостаточно. Агент может уверенно настаивать на неправильном решении.

В таких случаях используется метод Self-Consistency:

  1. Мы запускаем один и тот же промпт 3-5 раз (параллельно, выставив temperature > 0.5 для вариативности).
  2. Мы получаем 5 разных путей рассуждения.
  3. Агент анализирует все 5 ответов и выбирает тот, который встречается чаще всего (голосование большинством), либо синтезирует финальный ответ, объединяя лучшие части.

В Gemini 3 это можно реализовать через параметр candidate_count (если поддерживается API) или просто циклом запросов, а затем отправкой всех результатов новому инстансу модели с ролью «Судья» для вынесения вердикта.

Вопрос

Какая главная причина, по которой мы разделяем процесс генерации контента и процесс его критики (рефлексии) в разные шаги?

Заключение

Автоматическое исправление ошибок переводит взаимодействие с ИИ на новый уровень. Вы перестаете быть «нянькой» для модели, постоянно проверяющей её ответы, и становитесь архитектором системы, которая сама следит за своим качеством.

Ключевые выводы урока:

  • Ошибки агента — это нормальная часть процесса, а не конец работы.
  • Используйте внешние инструменты (интерпретаторы кода, валидаторы JSON) как источник объективной истины для рефлексии.
  • Для текстовых задач используйте ролевые модели (Актор-Критик), чтобы модель сама улучшала свой черновик.

В следующем модуле мы объединим эти знания для создания мультиагентной системы, где разные агенты будут специализироваться на разных задачах и проверять друг друга.