Мультиагентность: Как заставить две нейросети спорить друг с другом

16.06.2026 21:00

Я помню ночь, когда окончательно разочаровался в одиночных LLM. Мы дебажили плавающий баг — состояние гонки в биллинговом микросервисе на Go. Я скормил логи GPT-4. Модель выдала уверенный ответ и кусок кода. Я задеплоил фикс на стейджинг, и сервис упал с дедлоком. Я откатил изменения, отправил те же логи в Claude 3.5 Sonnet. Клод предложил другой подход с мьютексами. Стейджинг снова упал, на этот раз из-за утечки горутин.

Модели галлюцинировали по очереди, уверенно предлагая нерабочие решения. Проблема одиночной генерации в том, что нейросеть страдает от предвзятости подтверждения (confirmation bias). Сгенерировав первый токен ответа, она становится заложницей выбранного пути. Она не может остановиться на середине абзаца, сказать "подождите, я несу чушь" и стереть написанное.

Тогда я написал короткий Python-скрипт. Я взял нерабочий код от GPT-4, отправил его Claude и добавил жесткий системный промпт: «Ты — Senior Go Developer. Твоя задача — разнести этот код в пух и прах. Найди все состояния гонки, дедлоки и утечки памяти. Не пиши исправленный код, только критикуй».

Claude моментально нашел потенциальный дедлок, который я упустил. Затем я взял эту критику и вернул её GPT-4 с инструкцией: «Вот критика твоего кода от ревьюера. Исправь архитектуру с учетом этих замечаний». Со второй итерации GPT-4 выдал идеальный, потокобезопасный код.

Так я на практике открыл для себя паттерн Reflexion и архитектуру дебатов. Экспертный совет ботов работает на порядок круче одной, даже самой умной модели.

Механика конфликта: Почему дебаты работают

Когда вы просите одну модель написать код и проверить саму себя, она редко находит серьезные архитектурные ошибки. Ее веса уже настроены на генерацию конкретного паттерна, и при самопроверке она идет по тем же нейронным путям.

Чтобы получить качественный результат, нам нужно когнитивное разнообразие. Модели от разных вендоров (OpenAI и Anthropic) обучались на разных датасетах, используют разные механизмы RLHF и имеют разные "характеры". GPT-4 склонен к структурному, иногда переусложненному коду. Claude 3.5 Sonnet пишет более лаконично и лучше держит контекст длинных файлов.

Сталкивая их лбами, мы получаем синергию. Архитектура мультиагентных дебатов состоит из трех ролей:

  1. Генератор (Proposer): Пишет черновик решения.
  2. Критик (Critic): Ищет уязвимости, баги, логические дыры.
  3. Резолвер (Resolver / Judge): Читает черновик, читает критику и выдает финальный результат.

Проблема интеграции и зоопарк API

Реализация такого пайплайна "в лоб" быстро превращается в ад инфраструктурщика. Вам нужно зарегистрировать аккаунты в OpenAI и Anthropic. Привязать карты. Настроить мониторинг лимитов. Написать обертки для двух разных SDK, потому что форматы запросов у них отличаются. А если завтра вы захотите добавить Google Gemini в качестве второго критика?

Здесь на сцену выходит единый шлюз. В нашем проекте мы используем RouterAPI. Это снимает всю инфраструктурную боль: один API-ключ, один эндпоинт, полностью совместимый с форматом OpenAI, и доступ ко всем топовым моделям.

Вместо того чтобы жонглировать клиентами, мы инициализируем один стандартный клиент OpenAI и просто меняем параметр model.

Архитектура дебатов: Код и Промпты

Давайте соберем рабочий скрипт. Нам потребуется библиотека openai (или aiohttp для асинхронности) и ключ от RouterAPI.

Сначала задаем системные промпты. Это фундамент. Если промпты будут слабыми, модели начнут соглашаться друг с другом, и дебаты превратятся в обмен любезностями.

PROMPT_GENERATOR = """Ты — Senior Software Engineer.
Твоя задача: написать оптимальный, чистый и рабочий код для решения задачи пользователя.
Выдай только код и краткое объяснение архитектурных решений."""

PROMPT_CRITIC = """Ты — строгий Staff Security & Performance Engineer.
Твоя задача: найти критические уязвимости, баги, состояния гонки и узкие места в производительности в предоставленном коде.
Будь безжалостен. Не пиши исправленный код. Выдай нумерованный список найденных проблем с доказательствами, почему этот код упадет в продакшене."""

PROMPT_RESOLVER = """Ты — Principal Engineer.
Тебе предоставлен изначальный код и критика от ревьюера.
Твоя задача: объективно оценить критику. Если критика по делу — перепиши код, устранив все проблемы. Если критика ошибочна — объясни почему, и оставь код без изменений.
Выдай финальный, production-ready код."""

Теперь реализуем логику вызовов. Благодаря RouterAPI мы можем запускать запросы параллельно или последовательно, используя один и тот же интерфейс.

import asyncio
from openai import AsyncOpenAI

# Инициализируем клиент через шлюз RouterAPI
client = AsyncOpenAI(
 api_key="sk-routerapi-..",
 base_url="https://routerapi.net/v1"
)

async def run_debate(user_task: str):
 # Шаг 1: Генерация черновика (используем Claude 3.5 Sonnet за его навыки кодинга)
 print("Генератор пишет код..")
 draft_response = await client.chat.completions.create(
 model="claude-3-5-sonnet",
 messages=[
 {"role": "system", "content": PROMPT_GENERATOR},
 {"role": "user", "content": user_task}
 ],
 temperature=0.2
 )
 draft_code = draft_response.choices[0].message.content

 # Шаг 2: Критика (используем GPT-4o, он отлично находит логические дыры)
 print("Критик ищет баги..")
 critic_response = await client.chat.completions.create(
 model="gpt-4o",
 messages=[
 {"role": "system", "content": PROMPT_CRITIC},
 {"role": "user", "content": f"Задача: {user_task}\n\nКод:\n{draft_code}"}
 ],
 temperature=0.1
 )
 critique = critic_response.choices[0].message.content

 # Шаг 3: Резолюция (возвращаем задачу Claude, чтобы он исправил свой код с учетом критики GPT-4)
 print("Резолвер сводит результат..")
 final_response = await client.chat.completions.create(
 model="claude-3-5-sonnet",
 messages=[
 {"role": "system", "content": PROMPT_RESOLVER},
 {"role": "user", "content": f"Задача: {user_task}\n\nТвой изначальный код:\n{draft_code}\n\nКритика от ревьюера:\n{critique}"}
 ],
 temperature=0.2
 )
 
 return final_response.choices[0].message.content

# Запуск
task = "Напиши in-memory кэш на Python с поддержкой TTL и вытеснением по алгоритму LRU. Кэш должен быть потокобезопасным."
final_code = asyncio.run(run_debate(task))
print(final_code)

Prompt Chaining и контроль состояния

В реальном продакшене мы усложняем эту схему. Мы используем Prompt Chaining — разбиваем сложную задачу на цепочку мелких шагов, где выход одного агента становится входом для другого.

Вместо простой передачи текста мы заставляем агентов общаться через строгие JSON-схемы (Structured Outputs). Критик возвращает не просто текст, а массив объектов [{"line": 45, "severity": "high", "issue": "Race condition", "explanation": ".."}]. Резолвер парсит этот JSON и проходит по каждому пункту. Это исключает потерю контекста и заставляет модели фокусироваться на конкретных строках кода.

Если критик находит проблемы с severity: high, мы можем зациклить процесс (паттерн Reflexion), заставляя Генератора и Критика общаться до тех пор, пока Критик не вернет пустой массив ошибок, либо пока не сработает лимит итераций (обычно 3-4 цикла).

Экономика мультиагентности

Запускать три тяжелые модели на каждый чих — дорого. Здесь RouterAPI дает еще одно неочевидное преимущество — маршрутизацию по стоимости.

Для простых задач или первичной генерации мы можем использовать быстрые и дешевые модели, например gpt-4o-mini или claude-3-haiku. А вот на роль Критика, где требуется максимальная глубина анализа, мы ставим gpt-4o или claude-3-opus.

Вызов одной мощной модели стоит условные $0.03. Вызов связки "Дешевый Генератор + Дорогой Критик + Дешевый Резолвер" может обойтись в $0.015, при этом качество итогового кода будет выше, чем если бы всю работу делала одна дорогая модель. Мы платим за когнитивную работу именно там, где она нужна.

Итог

Инженерия программного обеспечения прямо сейчас переживает трансформацию. Мы перестаем писать код руками и начинаем проектировать когнитивные архитектуры. Мы собираем команды из виртуальных экспертов, настраиваем правила их взаимодействия и даем им инструменты.

Одиночные промпты уходят в прошлое. Будущее за системами, где модели спорят, проверяют друг друга и итеративно улучшают результат. И инструменты вроде RouterAPI делают сборку таких систем тривиальной задачей, убирая всю инфраструктурную сложность и оставляя нам чистую инженерию.

Теги

Ещё по теме