Мне хотелось проверить, сделает ли повторный запуск одного и того же вопроса 51 раз ответ более надежным. Я взял локальную LLM, скормил ей фрагмент рабочего кода и попросил провести ревью. Затем я повторил это снова. И снова. Всего пятьдесят один раз, используя мажоритарное голосование, чтобы выбрать «лучший» ответ. Идея была проста: если модель споткнется при одном запуске, возможно, «мудрость толпы» в 51 генерации позволит нивелировать шум и выявить правильный анализ. Но произошло не это. Эксперимент показал, что мажоритарное голосование не выбирает правильность. Оно выбирает то, в чем модель наиболее упряма.
Это различие важно, потому что мажоритарное голосование стало популярным приемом в пайплайнах LLM. Принцип работы прост: вы запускаете модель несколько раз с одним и тем же промптом, собираете ответы и оставляете тот, который встречается чаще всего. В таких областях, как медицинская визуализация или обнаружение спама, ансамблевые методы работают, потому что разные модели (или разные представления данных) создают независимые ошибки, которые действительно могут взаимно уничтожаться. Большие языковые модели не являются независимыми избирателями. Это единая система с одной историей обучения, одним набором весов и одной вселенной предвзятостей. Когда вы задаете одной и той же модели один и тот же вопрос пятьдесят один раз, вы не собираете комитет. Вы проводите опрос одного и того же респондента, находящегося в слегка разном настроении.
Проблема устойчивости
Основная проблема заключается в том, что ошибки LLM редко бывают случайными. Это паттерны, заложенные в обучающие данные и архитектуру. Модель, которая неверно интерпретирует конкретный декоратор Python при одном запуске, скорее всего, сделает то же самое и при следующем. Модель, которая галлюцинирует уязвимость безопасности из-за того, что имя переменной похоже на пароль, вероятно, снова совершит эту галлюцинацию на сорок седьмом запуске. Шум, который вы пытаетесь усреднить, обычно представляет собой поверхностные вариации в формулировках или форматировании. Фундаментальная же логика часто остается неизменной.
Рассмотрим конкретный пример. Представьте функцию, которая парсит лог-файлы с помощью регулярного выражения. Регулярное выражение строгое и безопасное. Но строка r'...' содержит символы, которые в другом контексте могут привести к инъекции. Попросите LLM проверить это. Если модель видела тысячи постов на Stack Overflow с предупреждениями об инъекциях через regex в парсерах логов, она может пометить этот безопасный фрагмент как рискованный. Запустите один раз — получите ложноположительный результат. Запустите 51 раз — и велика вероятность, что вы получите 51 ложноположительный результат или, по крайней мере, подавляющее большинство. Мажоритарное голосование теперь лишь закрепляет галлюцинацию. Модель устойчива в своих заблуждениях, поэтому и «консенсус» оказывается таким же устойчивым.
Это происходит потому, что трюки с температурой и сэмплированием не меняют того, что модель знает. Они лишь меняют манеру изложения. Высокая температура может сделать объяснение болтливым или кратким. Она может заменить синонимы. Но она не может внезапно научить модель тому, что регулярное выражение на самом деле безвредно. Вариации, по которым вы голосуете, косметичны. Ошибка же является структурной.
Что показывают 51 запуск
Когда я разложил эти 51 ответа на столе, закономерность стала очевидной. Модель не исследовала 51 различную интерпретацию кода. Она проигрывала одну и ту же интерпретацию слегка разными голосами. Несколько запусков отклонились от сценария, предлагая исправления для граничных случаев или замечая несвязанные проблемы со стилем. Но доминирующий кластер, явное большинство, раз за разом возвращался к одному и тому же неверному центральному утверждению. Это утверждение не было верным. Оно было просто знакомым.
Математика мажоритарного голосования опирается на независимые испытания Бернулли. Чтобы большинство превзошло индивидуальный результат, ошибки должны быть не связанными. В моем эксперименте ошибки были глубоко взаимосвязаны. У них была одна и та же первопричина: распределение обучающих данных модели переоценивает определенные шаблоны написания кода. Таким образом, мажоритарное голосование не уменьшило ошибку. Оно усилило смещение большинства. Оно придало ложное чувство уверенности ошибочному анализу.
Это особенно опасно при ревью кода, потому что разработчики воспринимают единогласный или почти единогласный вывод ИИ как авторитетный. Одиночное неуверенное предложение легко проигнорировать. Рекомендация, которая остается неизменной на протяжении пятидесяти одного запуска, воспринимается как истина в последней инстанции. Но это не так. Это замкнутый круг.
Где голосование действительно работает
Это вовсе не означает, что модель никогда не стоит запускать более одного раза. Голосование большинством может помочь в узких ситуациях, когда задача поверхностна, а ошибки носят чисто случайный характер. Просьба к модели выбрать один из двух синтаксических форматов, определить соглашение об именовании переменных или извлечь строку с датой из лога — такие незначительные задачи иногда выигрывают от многократных запусков. Вариативность здесь является чистым шумом, и быстрое голосование помогает его устранить.
Проблемы начинаются тогда, когда задача требует рассуждений о намерениях. Должна ли эта проверка авторизации находиться здесь? Безопасен ли этот асинхронный вызов? Является ли эта коллизия ключей кэша действительно эксплуатируемой? Эти вопросы требуют понимания контекста, а не простого сопоставления с шаблоном. Механизм сопоставления шаблонов модели детерминирован в своих смещениях. Она будет стремиться к наиболее частому ответу из своих обучающих данных, а не к наиболее точному ответу для вашего кодового базиса.
Более разумные способы использования вычислительных ресурсов
Пятьдесят один запуск локальной модели стоит реального времени и электроэнергии. Есть способы лучше инвестировать эти вычислительные мощности. Если вы хотите повысить надежность, разнообразие важнее объема. Запустите две разные модели с
