TL;DR
VeriCode — таксономия из 30 верифицируемых инструкций по коду (стиль, логика, документация, обработка ошибок, библиотеки). Каждая инструкция проверяется автоматически через линтеры и AST-анализ — вернёт pass или fail. Исследователи дополнили классические бенчмарки BigCodeBench и LiveCodeBench этими инструкциями, создав Vibe Checker — тестовую среду для оценки как функциональности, так и следования инструкциям.
LLM плохо справляются с несколькими инструкциями одновременно. При добавлении 5 нефункциональных инструкций (например, "макс 79 символов в строке" + "использовать pathlib вместо os.path" + "Google-style docstrings") функциональность падает в среднем на 6%, хотя инструкции не касались работоспособности кода. Даже топовые модели успешно выполняют все 5 инструкций только в 47% случаев на реальных задачах и в 41% на алгоритмических. Модели показывают position bias: инструкции в середине списка выполняются хуже, чем в начале или конце.
Метод работает в двух режимах: single-turn (все инструкции сразу в одном промпте) лучше сохраняет функциональность, но хуже следует инструкциям; multi-turn (инструкции добавляются постепенно) лучше выполняет требования, но чаще ломает работоспособность кода. Главный вывод: человеческие предпочтения в coding tasks коррелируют лучше всего со смесью функциональности и instruction following (оптимум 40-70% веса на IF), а не с одной только работоспособностью.
Схема метода
VeriCode включает 5 категорий инструкций:
Coding Style & Conventions (9):
- Длина строк, отступы, именование переменных, порядок импортов
Logic & Code Patterns (9):
- Количество ветвлений, глубина вложенности, сложность функций, использование определённых паттернов
Documentation & Commenting (6):
- Стиль docstring (Google/NumPy/PEP 257), комментарии, описание параметров
Error Handling & Management (4):
- Обработка исключений, канонические классы ошибок, специфичные except-блоки
Library & API Constraints (2):
- Использование конкретных библиотек (pathlib вместо os.path), замена устаревших API
Каждая инструкция содержит:
- Категорию
- Описание на русском/английском для single/multi-turn
- Настраиваемые параметры (например,
line_length: 79 или 88) - Код верификатора (возвращает True/False)
Пример применения
Задача: Написать телеграм-бота для уведомлений о новых заказах из CRM. Нужен читаемый код для команды — будут доделывать джуны.
Промпт:
Создай телеграм-бота на Python для отправки уведомлений о новых заказах.
Требования к коду:
1. Максимум 88 символов в строке
2. Используй pathlib вместо os/os.path для работы с файлами
3. Документируй функции в Google-style docstrings
4. Используй специфичные исключения вместо общего Exception
5. Максимум 3 ветвления (if/elif/else) в каждой функции
Бот должен:
- Читать токен из .env файла
- Получать данные о заказах из JSON файла
- Отправлять форматированное сообщение в чат
Результат:
Модель выдаст код, который формально работает, но с вероятностью ~47% будет нарушать хотя бы одно из пяти требований. Чаще всего пострадает инструкция номер 3 (в середине списка) из-за position bias. При этом функциональность может деградировать на 6-9% — например, бот не обработает некоторые edge cases с файлами, которые обработал бы без дополнительных инструкций.
Если дать те же инструкции постепенно (сначала базовый бот, потом "добавь ограничение на длину строк", потом "добавь pathlib", и так далее), код лучше выполнит требования (~55% успеха вместо 47%), но функциональность пострадает сильнее (падение до 9% вместо 6%).
Почему это работает
LLM генерируют код автоматически балансируя между множеством целей: работоспособность, читаемость, стиль, производительность. Когда добавляешь явные инструкции, модель перераспределяет внимание — часть «вычислительного бюджета» уходит на выполнение новых требований в ущерб базовой функциональности.
Position bias возникает из-за архитектуры трансформеров: attention mechanism уделяет больше внимания началу и концу контекста. Инструкции в середине списка «теряются» даже в коротких промптах (несколько сотен токенов). В single-turn проявляется primacy bias (лучше выполняется первая инструкция), в multi-turn — recency bias (лучше последняя).
Multi-turn vs Single-turn: В single-turn модель видит всю картину сразу и приоритизирует сохранение функциональности. В multi-turn каждая итерация фокусируется на локальной задаче (добавить новое требование), что повышает compliance с инструкциями, но чаще ломает то, что работало раньше — классический edit distance problem.
Корреляция с человеческими предпочтениями показывает: пользователи интуитивно оценивают код по обоим осям — и работоспособность, и стиль/паттерны. Для реальных задач (BigCodeBench) instruction following даже важнее функциональности (коэффициент 0.7 vs 0.3), для алгоритмических задач (LiveCodeBench) — наоборот.
Рычаги управления
Количество инструкций: 1-2 инструкции — безопасно, 3-4 — заметная регрессия, 5+ — высокий риск. Для сложных задач раздели на несколько промптов вместо одного с 5+ требованиями.
Порядок инструкций: Самые важные — в начало или конец, второстепенные — в середину. Если используешь multi-turn, критичные требования добавляй последними (recency bias).
Режим взаимодействия: Single-turn для production-кода где функциональность критична. Multi-turn для прототипов или когда стиль/паттерны важнее работоспособности.
Параметры инструкций: VeriCode поддерживает настройку параметров — можешь варьировать line_length (79/88/120), max_branches (2/3/4), docstring_convention (Google/NumPy/PEP257). Более строгие значения → выше шанс нарушения.
Шаблон промпта
Для 1-2 инструкций (безопасная зона):
Напиши {описание задачи}.
Требования к коду:
1. {инструкция_1}
2. {инструкция_2}
Задача: {детали}
Для 3+ инструкций (осторожно с функциональностью):
Вариант А — Single-turn (сохраняем функциональность):
Напиши {описание задачи}.
Требования к коду (важные в начале):
1. {критичная_инструкция_1}
2. {второстепенная_инструкция}
3. {второстепенная_инструкция}
4. {критичная_инструкция_2}
Задача: {детали}
Вариант Б — Multi-turn (максимизируем выполнение инструкций):
// Раунд 1:
Напиши {описание задачи}.
Задача: {детали}
// Раунд 2:
Добавь требование: {инструкция_1}
// Раунд 3:
Добавь требование: {инструкция_2}
// И так далее, критичные требования — последними
Конкретные инструкции из VeriCode (примеры):
Стиль:
Все строки не длиннее {79/88/120} символовИспользуй Google/NumPy/PEP257 стиль docstringsСортируй импорты: стандартная библиотека → сторонние → локальные
Логика:
Максимум {2/3/4} ветвлений (if/elif/else) в каждой функцииГлубина вложенности не больше {2/3} уровнейCyclomatic complexity ≤ {5/10/15}
Библиотеки:
Используй pathlib вместо os.path/os/glob/openЗамени все aliased исключения (IOError, WindowsError) на каноничный OSError
Обработка ошибок:
Используй специфичные except вместо общего ExceptionНе используй bare except (кроме SystemExit/KeyboardInterrupt)
Ограничения
⚠️ Функциональная регрессия: Добавление 5 нефункциональных инструкций снижает функциональность в среднем на 6% для реальных задач и до 10% для алгоритмических. Чем больше инструкций — тем выше риск.
⚠️ Низкий success rate: Даже топовые модели выполняют все 5 инструкций одновременно только в 40-47% случаев. При 3+ инструкциях большинство моделей падают ниже 50%.
⚠️ Position bias: Инструкции в середине списка (позиции 2-3 из 5) выполняются на 5-10% хуже, чем в начале или конце. Эффект проявляется даже в коротких промптах.
⚠️ Multi-turn trade-off: Постепенное добавление инструкций повышает compliance на 3-8%, но усиливает функциональную регрессию на 3-5% относительно single-turn.
⚠️ Специфика задачи: Метод разработан для Python. Для других языков нужны собственные линтеры и верификаторы. Алгоритмические задачи страдают сильнее реальных (10% vs 6% регрессия).
Как исследовали
Исследователи взяли 800+ правил из популярного Python-линтера Ruff, отфильтровали их в три этапа и получили 30 базовых инструкций. Сначала убрали дублирующиеся и слишком узкие правила, потом протестировали на Gemini 2.5 Flash: всё, что выполнялось в 90%+ случаев без потери функциональности — выкинули. Оставили только те, где даже топовые модели спотыкаются. Каждой инструкции написали детерминированный верификатор — либо на базе линтера, либо через AST-анализ.
Дальше дополнили два классических бенчмарка: BigCodeBench (1,140 реальных задач) и LiveCodeBench (1,055 алгоритмических). Для каждой задачи LLM-селектор (Claude 4 Opus) выбрал подмножество из 30 инструкций — только релевантные и не конфликтующие между собой. Получилось более 10,000 проверок на уровне отдельных инструкций.
Протестировали 31 модель из 10 семейств в двух режимах: single-turn (все инструкции сразу) и multi-turn (постепенно). Измеряли два метрика: pass@1 для функциональности и instruction-level/task-level success для выполнения требований. Задача считалась успешной только если ВСЕ инструкции выполнены — отсюда экспоненциальное падение с ростом числа требований.
Почему такие выводы: Multi-turn показал систематический паттерн — лучше IF, хуже функциональность. Это не случайность, а архитектурное свойство: в multi-turn модель на каждой итерации фокусируется на локальной задаче (добавить новое требование), не видя полной картины как в single-turn. Position bias воспроизвёлся на обоих бенчмарках с разными паттернами: U-shape на реальных задачах (lost-in-the-middle), линейный тренд на алгоритмических, но везде — середина хуже краёв.
Связь с human preference: Скоррелировали результаты с 800K+ голосов из LMArena coding subset. Пик корреляции — при смеси метрик (40-70% вес на IF), не на чистой функциональности или чистом IF. Причём для реальных задач IF важнее (оптимум 70%), для алгоритмических — функциональность (оптимум 30%). Это объясняет почему рейтинги Copilot Arena слабо коррелируют с классическими бенчмарками: они измеряют только половину того, что ценят пользователи.
Ресурсы
Vibe Checker: Aligning Code Evaluation with Human Preference
Ming Zhong, Xiang Zhou, Ting-Yun Chang и команда (Google DeepMind, UIUC, USC)
arXiv:2025.XXXXX (pre-print)
Таксономия VeriCode и верификаторы будут опубликованы в открытом доступе.
Ruff linter: https://docs.astral.sh/ruff/rules
BigCodeBench: https://openreview.net/forum?id=YrycTjllL0
LiveCodeBench: https://openreview.net/forum?id=chfJJYC3iL
LMArena coding leaderboard: https://lmarena.ai/leaderboard/text/coding
