Adversarial verification (адверсариальная верификация)

25 июля 2026 · ~15 мин чтения

ai llm workflow верификация качество

Adversarial verification (адверсариальная верификация)

Adversarial verification — это инженерный паттерн для проверки утверждений LLM: одну и ту же гипотезу отдают N независимым «скептикам»-судьям, каждому явно велят попытаться её опровергнуть, и если минимум K из N сказали «неправда» — гипотеза отбрасывается. Задача — не подтвердить то, что и так хочется услышать, а специально искать причины, по которым это неправда.

История

Термин adversarial verification в узком «LLM-ном» смысле — молодой, ему буквально 2–3 года. Но идея старая и собрана из нескольких линий.

Первая линия — теория. 2018, США, OpenAI. Джеффри Ирвинг, Пол Кристиано, Дарио Амодей опубликовали работу «AI safety via debate». Идея: если два ИИ спорят друг с другом по одному вопросу, а человек-судья оценивает аргументы — то даже относительно слабому судье проще выбрать правильную сторону, чем самому разобраться в теме с нуля. Это не про LLM-агентов в проде, а про долгосрочную безопасность: как проверить систему, которая умнее тебя. Но именно оттуда пошла интуиция «противостояние → истина».

Вторая линия — эмпирика. 2022. Google Research, Xuezhi Wang и соавторы, статья «Self-Consistency Improves Chain of Thought Reasoning». Взяли одну и ту же задачу, прогнали через LLM K раз с ненулевой температурой (то есть с рандомом в ответах), взяли модальный ответ — точность на бенчмарках подскочила на 10–20 процентных пунктов. Оттуда пошла мысль: несколько независимых прогонов ловят больше правды, чем один.

Третья линия — Constitutional AI. 2022, Anthropic, Юньтао Бай и команда. Модель сначала пишет ответ, потом отдельным проходом сама себя критикует по списку принципов, потом переписывает. Это ещё не «adversarial verification» в чистом виде, но именно там появился шаг «отдельный проход = именно критика, а не порождение».

Четвёртая линия — Multi-Agent Debate. 2023, MIT + Google, Yilun Du и соавторы. Запустили несколько экземпляров LLM параллельно, дали каждому свой ответ, потом по кругу показали ответы соседей и попросили улучшить. Через 2–3 раунда точность выросла существенно; критично, что в промпте прямо велено ставить под сомнение чужие ответы.

Пятая линия — Chain-of-Verification (CoVe). 2023, Meta AI, Shehzaad Dhuliawala и команда. Модель порождает ответ, потом сама себе задаёт «а какие факты в этом ответе легко проверить?», отвечает на каждый отдельно и переписывает первоначальный ответ. Ключевое слово в статье — separation: чтобы критик не был предвзят, он не должен видеть исходную цепочку рассуждений.

2024–2026 — инженерная сборка. Практика собралась в узнаваемый паттерн: генератор кандидатов → N судей-скептиков с явной установкой «REFUTE, не confirm» → голосование → отбор. Именно в этой форме он живёт сейчас в проде RAG-систем, deep-research агентов, автомодерации, автоматических SRE-плейбуков, а также в скиллах Claude Code (например, встроенный deep-research workflow ставит 3-of-3 voters с порогом «≥2 refutations kill it»).

Что это такое

Adversarial verification — это три идеи, склеенные вместе.

  1. Отделение генерации от проверки. Тот, кто сгенерировал утверждение, — не тот, кто его проверяет. У LLM (как и у людей) есть встроенная склонность подтверждать собственные ответы: если попросить ту же модель «проверь, всё ли верно?» — она с высокой вероятностью просто добавит уверенности вместо реального аудита. Поэтому проверяющий инстанс запускается заново, желательно с чистым промптом.

  2. Явная установка на опровержение, а не подтверждение. В prompt-е критика написано что-то вроде «Be SKEPTICAL. Try to REFUTE this claim. Default to refuted=true if uncertain». Это принципиально: если сказать нейтрально «оцени», модель тяготеет к «выглядит нормально», потому что генерирование правдоподобного текста — её основной способ существования. Прямое указание «твоя работа — сломать это» смещает распределение выхода в сторону поиска дыр.

  3. Голосование, а не один судья. Один критик может ошибиться, поймать не то, промахнуться. Три-пять независимых критиков — уже статистика. Порог «K из N говорят refute → отбросить» выбирается под задачу: жёстче (2 из 3) — если цена ложного пропуска высока (медицина, юридические факты); мягче (3 из 5) — если цена ложного отбрасывания тоже большая (креативные задачи).

Adversarial verification vs self-consistency. Self-consistency — это когда ты один и тот же вопрос задаёшь LLM K раз и берёшь модальный ответ. Adversarial verification — это когда ты берёшь готовое утверждение и отдельно спрашиваешь K раз «правда ли?», причём с установкой на опровержение. Первое хорошо там, где есть точный ответ (арифметика, код); второе — там, где нужно валидировать нарратив, факт, цитату, вывод.

Adversarial verification vs LLM-as-a-Judge. LLM-as-a-Judge — общий термин для «одна LLM оценивает выход другой». Это может быть про качество (насколько ответ хорош), про соответствие рубрике или про факт-чек. Adversarial verification — узкая подсемья: судья именно скептичен и голосует бинарно (real/refuted), плюс их несколько.

Adversarial verification vs debate. Debate по Ирвингу — это диалог, критики видят и парируют аргументы друг друга. В adversarial verification критики независимы, друг о друге не знают, чтобы не было каскадного согласия («якорения» на первом голосе). Это уменьшает точность одного голоса, но делает ансамбль честным.

Аналогии из жизни

Второе мнение у врачей.
Ты пришёл к терапевту, тебе диагностировали редкую болячку. Прежде чем начинать лечение, ты идёшь ещё к двум-трём независимым врачам — принципиально не рассказывая, что сказал первый. Если двое из трёх скажут «нет, это не оно» — ты первый диагноз отбрасываешь. Логика та же: несколько независимых экспертов, каждый смотрит свежим взглядом.
Где ломается: если все три врача учились у одного профессора и мыслят одинаково, независимость иллюзорна. Так же и с LLM: если ты крутанул 3 судей на одной и той же модели, они склонны разделять одни и те же слепые пятна (например, все три плохо знают события последних месяцев или все три легко ведутся на уверенный тон исходного текста). Хорошая практика — брать разных судей: одна и та же модель, но с разными системными промптами и/или разные модели (Sonnet + Opus + Haiku, скажем).

Peer review в науке.
Ты подал статью в журнал, редактор отправил её 2–3 независимым рецензентам, каждый в другой стране, ничего не знает про остальных. Пишут отдельные отзывы, редактор смотрит их вместе. Часто именно один из них ловит фундаментальную ошибку, которую пропустили автор, редактор и второй рецензент.
Где ломается: peer review работает только когда рецензенты реально пытаются найти дыры, а не подписывают отзыв «всё нормально» ради галочки. Знаменитый провал — реплицируемость в психологии и социологии: тысячи статей прошли рецензирование, потом оказалось, что 60% результатов не воспроизводятся. Так и с LLM-судьями: если промпт судьи звучит слишком дружелюбно, он превращается в такого же ленивого рецензента и штампует «looks correct».

Пробное фото на паспортном контроле.
На границе стоит офицер, у него твой паспорт и лицо. Он не обязан доказывать, что ты — это ты; его работа — попробовать найти основание тебя развернуть. Он смотрит на фото, на срок действия, на визы, на историю поездок, стучит по клавиатуре, ищет тебя в базах. Прямая установка — искать причину отказать. Если причин не нашёл — пропускает.
Где ломается: если офицер устал или ему платят по количеству пропущенных за час — он превращается в «резинку» и штампует всех. Именно поэтому важен третий и четвёртый голос: один устал, второй схалтурил, третий и четвёртый вытаскивают правду. Плюс: как только контроль превращается в формальность, реальные подделки проскакивают. Судьи в LLM «устают» из-за одинакового промпта — стоит хотя бы менять формулировку от голоса к голосу, чтобы не сработала кэш-подобная одинаковая реакция.

Как это работает

Разберём типовую реализацию, ту самую, которую можно увидеть в workflow-скиптах.

Шаг 1. Генерация кандидатов. На вход приходит задача — например, «сделай ресёрч про X». Первый агент (Source Extractor / Researcher / Bug Finder — в зависимости от домена) порождает набор утверждений: «в июле 2026 года Россия выпустила по Украине 419 ракет и дронов», «функция parseUser не проверяет длину входной строки», «в компонент Header.tsx протекает null при отсутствии сессии». Ключевое требование к утверждениям — они должны быть falsifiable (фальсифицируемыми): конкретное, проверяемое, а не «в целом безопасно» или «в среднем работает». Обычно это фиксируется через требование structured output — JSON-схема с полем claim, supporting_quote, source_url, centrality.

Шаг 2. Постановка задачи скептикам. Для каждого утверждения формируется отдельный промпт критика, примерно такой:

You are Adversarial Claim Verifier (voter 1/3).
Be SKEPTICAL. Try to REFUTE this claim. ≥2/3 refutations kill it.

Claim under review: "..."
Source: <url>
Supporting quote: "..."

Checklist:
1. Is the claim actually supported by the quote, or is it an overreach?
2. WebSearch for contradicting evidence.
3. Is the source primary and credible?
4. Default to refuted=true if uncertain.

Return: {"refuted": true|false, "reason": "..."}

Шаг 3. Параллельный запуск N судей. Обычно N = 3 или 5. Все запускаются одновременно, друг о друге не знают, у каждого свежий контекст. Если критики видят чужие ответы — теряется независимость, начинается каскадное согласие. Технически это делается либо через parallel([...]) в workflow-скрипте (см. [[workflow-orchestration]]), либо через прямые параллельные вызовы LLM API.

Шаг 4. Каждый судья возвращает бинарное решение. Строго через structured output — не свободный текст «мне кажется, скорее да, но с оговорками…», а именно {refuted: bool, reason: string}. Свободный текст трактовать трудно и он мешает голосованию. reason нужен для логов и разбора — если утверждение убито, ты хочешь понимать почему.

Шаг 5. Агрегация голосов. Простое большинство или заданный порог. Порог 2 из 3 (>= 2/3 refute) — жёсткий, отсекает почти всё сомнительное. Порог 3 из 5 (>= 3/5 refute) — мягче, оставляет больше. Тип «единогласие» (3 из 3) редко используется — слишком много ложно-отвергнутых. Правильная точка настраивается на реальных данных: прогоняешь верификатор на выборке, где ты сам знаешь правильные ответы, смотришь precision/recall и подкручиваешь.

Шаг 6. Отчёт. Выжившие утверждения идут в финальный синтезатор («N claims survived K-vote adversarial verification, merge and synthesize»). Отвергнутые — либо совсем выкидываются, либо помечаются как «слабые» и включаются в отчёт с disclaimer-ом. Обязательно логируется: сколько утверждений отсеяно, по каким причинам, сколько голосов ушло на каждое. Иначе невозможно откалибровать.

Псевдокод (упрощённо):

def verify_claim(claim, N=3, kill_threshold=2):
    votes = parallel([
        judge(claim, voter_id=i, N=N) for i in range(N)
    ])
    refuted_count = sum(1 for v in votes if v.refuted)
    return refuted_count < kill_threshold  # True = survived

Тонкость: судьи должны иметь право сомневаться. Классическая ошибка — промпт «is this claim TRUE or FALSE?». Модель под давлением бинарности выбирает то, что «выглядит правдоподобно». Промпт «try to refute, default to refuted=true if uncertain» смещает распределение в противоположную сторону — а именно это и нужно, потому что цена ложного пропуска обычно выше цены ложного отвержения (лучше отбросить хорошее утверждение, чем оставить галлюцинацию в финальном отчёте).

Где встречается в обычной жизни

Где встречается в IT и бизнесе

Кто пользуется

Точных публичных цифр по эффективности мало (это ноу-хау), но в открытых бенчмарках рост точности от 5 до 25 процентных пунктов на задачах с фактами — типичный порядок.

Альтернативы и конкуренты

На практике лучший вариант — комбинация: adversarial verification для массового отсева + human-in-the-loop на топе (человек смотрит только survived-утверждения, а не все подряд).

Когда НЕ стоит использовать

Связанные понятия

Литература и источники

Где встретилось у меня

Вчера гонял deep-research workflow по вопросу «свежие новости июля 2026 в подаче украинских и российских СМИ». Из логов видно: workflow параллельно вытащил ~30 утверждений из 15+ источников, потом каждое утверждение прогнал через 3 независимых Adversarial Claim Verifier с явным промптом «Be SKEPTICAL. Try to REFUTE. ≥2/3 refutations kill it». В итоге 21 утверждение пережило голосование и ушло в финальный синтез — остальное молча отсеялось. Это ровно тот паттерн, разобранный выше, и именно он делает подобный ресёрч пригодным к чтению, а не «10 галлюцинаций подряд с уверенным тоном».

Краткое резюме