TL;DR
Оптимальное распределение бюджета повторных попыток (Test-Time Compute Allocation) — это система правил и проверок для ситуаций, когда у вас есть пакет задач (генерация кода под автотесты, решение сложных расчётов, прогон регрессионного набора) и ограниченный бюджет вызовов LLM. Исследование доказывает, что популярная интуиция «давать самым сложным задачам максимум попыток» на тяжёлых наборах задач теряет почти весь возможный выигрыш, а при наличии автопроверки успех зависит не от хитрого алгоритма распределения, а от истории прошлых запусков и защиты верификатора от ложных срабатываний.
Главная боль при пакетном запуске LLM и кодинг-агентов — слив бюджета в бездонную бочку безнадёжных задач. Когда модель в среднем решает задачу редко, правило «чем выше сложность, тем больше попыток» сжигает десятки вызовов API на задачи с околонулевым шансом успеха, отбирая попытки у задач средней сложности, которые модель решила бы со второго-третьего раза. В итоге каскадные и пропорциональные сложности схемы работают вхолостую или даже дают результат хуже обычного равномерного распределения.
Метод решает эту проблему разделением стратегии на два чётких режима: 1. Без автопроверки (статический бюджет) — распределять попытки по колоколообразной кривой (перевёрнутой U): вовремя «сдаваться» на безнадёжных задачах (оставляя им минимум) и отдавать основной бюджет задачам средней сложности. 2. С программным верификатором (автотесты, компилятор) — на новых задачах не тратить токены на дешёвые промпт-оценщики сложности, а крутить простой циклический обход (Round-Robin) нерешённых задач; а на повторяющихся прогонах (регрессии, бенчмарки, эпохи RL) подключать сэмплирование Томпсона с априорной историей прошлых запусков, что почти удваивает долю решённых тяжёлых задач.
Схема метода
ВХОД: Пакет из N задач + Общий бюджет S = u * N попыток генерации LLM
│
├─► РЕЖИМ А: Верификатора НЕТ (попытки назначаются заранее, например под мажоритарное голосование)
│ ├─ Оценить вероятность успеха p_i по прошлым прогонам родственной модели
│ ├─ Отбросить правило «сложным — больше»
│ └─ Назначить попытки по предельной пользе (перевёрнутая U):
│ k*(r_i) = max(1, ln(r_i / λ) / r_i), где r_i = -ln(1 - p_i)
│ (Безнадёжные и слишком лёгкие задачи получают по 1 попытке; максимум бюджета — середнякам)
│
└─► РЕЖИМ Б: Верификатор ЕСТЬ (юнит-тесты, проверка ответа; решённая задача сразу выбывает из пула)
├─ Проверка 1: Ложные срабатывания верификатора (False Acceptance) << средней решаемости?
│ └─ НЕТ (например, шумная LLM-судья на сложных задачах) → Адаптивное распределение НЕ работает
└─ ДА (программные тесты / точный чекер): есть ли история прогонов тех же задач (корреляция ρ > 0.55)?
├─ НЕТ (новые пользовательские задачи) → Простой циклический обход (Round-Robin) по нерешённым задачам
└─ ДА (регрессионные тесты, оценка релизов, RL) → Сэмплирование Томпсона (Thompson Sampling)
с умеренным историческим приором (tempered prior) по квинтилям прошлой решаемости
Вся логика работает как легковесный внешний диспетчер очереди запросов поверх API любой LLM или кодинг-агента.
Пример применения
Задача: Команда разработки в российской ИТ-компании (например, в Яндексе или Авито) каждую ночь гоняет кодинг-агента на пакете из 200 сложных задач по починке багов и миграции легаси-модулей с проверкой через pytest. Бюджет ограничен — в среднем по 16 попыток генерации патча на задачу (всего 3200 вызовов LLM). Раньше команда просила саму модель оценить сложность тикета от 1 до 5 и выделяла «пятёркам» по 45 попыток, но доля закрытых тикетов застряла на 14%.
Конфигурация пайплайна и промпт-инструкция для оркестратора агента:
## Правила диспетчеризации попыток кодинг-агента (по методу Give Up to Get More)
1. ЗАПРЕТ НА ОЦЕНКУ СЛОЖНОСТИ ПРОМПТОМ:
Не запрашивай у LLM предварительную оценку сложности тикета и не выделяй максимум попыток самым «тяжёлым» задачам — на сложных пакетах это сливает бюджет в задачи с нулевой решаемостью.
2. РЕЖИМ ДЛЯ НОВЫХ ТИКЕТОВ (истории прогонов нет):
Запускай строго циклический обход (Round-Robin) по всем нерешённым тикетам:
- Раунд 1: по 1 попытке на каждый из 200 тикетов → прогон `pytest` → прошедшие тест тикеты исключаются из пула.
- Раунд 2..K: по 1 попытке только на оставшиеся нерешённые тикеты, пока не исчерпан общий бюджет 3200 вызовов.
3. РЕЖИМ ДЛЯ НОЧНОГО РЕГРЕССИОННОГО ПРОГОНА (есть история pass_rate с прошлого релиза):
- Разбей задачи на 5 групп (квинтилей) по их доле успешных прохождений в прошлых прогонах.
- Смешай распределение квинтиля с общим распределением пакета (tempered prior с весом w) для защиты от перекосов на лёгких задачах.
- На каждом шаге выбирай следующий нерешённый тикет через Thompson Sampling: после каждой неудачной попытки апостериорная оценка тикета снижается, и если тикет «безнадёжен» на текущем бюджете, агент автоматически перестаёт жечь на него токены и переключается на решаемые задачи средней сложности.
4. ТРЕБОВАНИЕ К ВЕРИФИКАТОРУ:
Останавливать попытки только при прохождении строгих автотестов (`pytest` + линтер). Не использовать мягкую оценку LLM-судьи как сигнал остановки (доля ложных принятий должна быть строго ниже 1%, иначе выигрыш обнуляется).
Результат: Убрав каскад «сложным тикетам — максимум попыток» и переключившись на циклический обход для новых задач и сэмплирование Томпсона по истории прошлых релизов для регрессионного пакета, команда перестаёт сжигать сотни вызовов API на неберущихся тикетах. Высвободившийся бюджет автоматически уходит на задачи средней сложности, и доля успешно закрытых автотестами задач на том же бюджете токенов вырастает почти вдвое (в экспериментах автора — с 14% до 27%).
Почему это работает
Главная ошибка большинства существующих пайплайнов (автор нашёл её как минимум в 13–32 научных работах по адаптивному вычислению для LLM) — линейное мышление: «если задача сложная, дадим ей побольше попыток». На самом деле математическая ценность одной дополнительной попытки равна $\Delta(p, k) = p(1 - p)^k$. Если задача слишком простая ($p \approx 1$), она решается с первого раза и лишние попытки ей не нужны. Но если задача слишком сложная для текущей модели ($p \approx 0$), то и 1-я, и 16-я попытка дадут почти нулевой прирост. Пик пользы от дополнительной попытки всегда находится посередине — на задачах умеренной сложности ($p = 1/(k+1)$).
На лёгких бенчмарках (вроде GSM8K, где модель решает 80–90% задач с первой попытки) почти все задачи лежат на правом склоне этого «холма», поэтому правило «сложным — больше» случайно оказывается близким к оптимуму. Но как только вы переходите к реальным тяжёлым задачам (сложный код, олимпиадная математика, где решаемость падает ниже 10%), большинство задач оказывается на левом склоне, и попытка накачивать самые глухие задачи токенами приводит к провалу.
При наличии верификатора (автотестов) механика меняется ещё сильнее: - Каждая неудача снижает шансы задачи — если задача не решилась после нескольких попыток, в байесовском смысле она скользит в категорию «безнадёжных», и продолжать долбить её без сильного предварительного знания невыгодно. - Дешёвые угадыватели сложности слепы — попытки оценить сложность новой задачи по длине текста, промптом к самой LLM или парой пробных генераций маленькой модели дают ранговую корреляцию с реальной решаемостью ниже порога окупаемости ($\rho \le 0,3\text{--}0,55$). Поэтому на новых задачах честный Round-Robin по нерешённым примерам бесплатен и оптимален. - Асимметрия ошибок верификатора — если автотест случайно забракует верное решение (ложный отказ до 20%), алгоритм почти не теряет эффективности. Но если «мягкий» верификатор (например, нейросетевая модель награды) в 5% случаев примет неправильный ответ за верный, система досрочно снимет задачу с пробега с ошибкой, и весь выигрыш умрёт.
Шаблон промпта
Используй этот шаблон в качестве чек-листа и технического задания для кодинг-агента, когда нужно написать скрипт пакетного прогона LLM (Best-of-N, генерация кода под тесты, прогон датасета оценки):
Мне нужно написать скрипт-диспетчер для пакетного запуска LLM на наборе из {число_задач} задач по теме «{описание_задачи}» с общим бюджетом в среднем {бюджет_на_задачу} попыток на задачу.
Спроектируй диспетчер строго по следующим правилам из исследования Give Up to Get More:
1. Тип проверки ответа: {тип_верификатора: нет_верификатора | программный_тест | llm_судья}.
- Если выбран llm_судья на сложных задачах: добавь жёсткие программные проверки (схема, компиляция, инварианты), чтобы снизить вероятность ложного принятия (false acceptance) ниже 1%.
2. Наличие истории прошлых прогонов на этих же задачах: {есть_ли_история: нет_новые_задачи | да_есть_статистика_прошлых_запусков}.
- Если «нет_новые_задачи» и есть верификатор: реализуй чистый Round-Robin по пулу нерешённых задач без оценки сложности промптом.
- Если «да_есть_статистика_прошлых_запусков» и есть верификатор: реализуй Thompson Sampling с умеренным приором (tempered prior, вес смешивания w={вес_w_например_0.7}) по квинтилям исторического pass_rate.
- Если верификатора нет, но есть оценки решаемости p_i: распредели число попыток k_i статически по формуле предельной ценности k*(r_i) = max(1, ln(r_i / λ) / r_i), где r_i = -ln(1 - p_i), подобрав λ под общий бюджет.
Что подставлять в плейсхолдеры:
- {число_задач} и {бюджет_на_задачу} — размер вашего пакета и среднее число вызовов API на один пример (например, 100 задач по 8 попыток = 800 вызовов).
- {тип_верификатора} — чем проверяется успех попытки (юнит-тесты, парсер, точный ответ или отсутствие проверки).
- {есть_ли_история} — гоняете ли вы этот набор задач повторно (регрессионный стенд, бенчмарк при смене промпта/модели) или это разовый поток новых запросов.
🚀 Быстрый старт — вставь в чат:
Вот шаблон проектирования диспетчера попыток генерации LLM (Give Up to Get More). Адаптируй его и напиши готовый Python-скрипт под мою задачу: [опиши свой пайплайн пакетной генерации или тестирования].
Задавай вопросы, чтобы заполнить поля.
[вставить шаблон выше]
LLM уточнит, чем именно ты проверяешь правильность ответа в коде, какова примерная доля успешных ответов с первой попытки и сохранились ли логи прошлых прогонов — после чего выдаст код диспетчера без типичных ловушек «сложным — больше».
Ограничения
⚠️ Для новых разовых запросов умные политики не дают выигрыша: Если задачи приходят впервые и у вас нет статистики их прошлых прогонов, ни один из дешёвых способов заранее угадать сложность (оценка промптом, текстовые признаки, пробные запуски мелкой модели) не обгоняет обычный циклический обход Round-Robin.
⚠️ Уязвимость к ложным срабатываниям LLM-судьи: Если вместо строгих юнит-тестов или точного чекера использовать неточную модель награды (Reward Model), которая хотя бы в 5% случаев принимает неверный ответ за верный, весь прирост от умного распределения бюджета полностью исчезает.
⚠️ Только для независимых попыток с бинарным успехом: Выводы проверены на задачах, где ответ либо верен, либо нет (код, математика, доказательства), а попытки независимы. Схемы, где следующая попытка получает в промпт текст ошибки компилятора от предыдущей попытки, в этой математической модели не тестировались.
Как исследовали
Исследователь Джинхён Пэ из Университета иностранных языков Хангук сначала провёл строгий аудит 221 научной статьи по адаптивному распределению вычислений LLM (отобранных из 3016 работ) и сопоставил их с 12 классическими дисциплинами — от теории оптимального поиска Купмана (1957) и расписаний рестартов в SAT-солверах до краудсорсинга и отбора роллаутов в RL. Оказалось, что в классических областях давно отсекают безнадёжные задачи (правило перевёрнутой U), тогда как в 70% направленных работ по инференсу LLM авторы упорно отдают максимум бюджета самым сложным примерам. Чтобы измерить цену этой ошибки, автор прогнал масштабные симуляции на сохранённых пулах генераций (по 10 000 попыток на задачу из датасета Large Language Monkeys для MATH, GSM8K, CodeContests и MiniF2F на моделях Pythia, Gemma, Llama-3 8B/70B, плюс 1800 попыток на задачу из PRM800K для GPT-4 и выборки GPT-4o-mini) и отдельно воспроизвёл результаты на свежих генерациях моделей Qwen2.5. На лёгких задачах (GSM8K на Llama-3-8B и GPT-4o-mini, где средняя решаемость 77–93%) правило «сложным — больше» забирает 93–102% от идеального оракула. Но на сложных задачах (CodeContests и MATH на младших моделях, где средняя решаемость 1,3–9,3%) то же самое правило даже при знании истинных вероятностей успеха захватывает от 0% до 13% возможного прироста, а каскадное разбиение на уровни (21/30/45 попыток) вообще уводит результат в минус на 16–40% относительно равномерной раздачи! Зато при наличии верификатора и истории прошлых прогонов родственной модели (корреляция Спирмена $\rho = 0,66\text{--}0,93$) сэмплирование Томпсона поднимает долю решённых задач на самом тяжёлом пакете с 14% до 27% (+13 п.п.), тогда как дешёвые текстовые и LLM-приоры застревают на корреляции $\rho \le 0,3\text{--}0,55$ и дают не более +1,7 п.п.
Адаптации и экстраполяции
🔧 Техника: Быстрая диагностика своего бенчмарка перед выбором стратегии → защита от потери бюджета на каскадах
Прежде чем внедрять любую сложную схему маршрутизации попыток в своём пайплайне, посчитай по 1 пробному прогону среднюю долю успеха $\bar{p}$ и умножь на плановый бюджет попыток $u$ на задачу: - Если $\bar{p} > 0,5$ (модель решает больше половины задач с первой попытки): стандартные правила «давать сложным больше попыток до лимита» работают отлично и забирают 50–100% возможного выигрыша. - Если $\bar{p} < 0,15$ (тяжёлый пакет задач, код со сложными тестами): немедленно отключи любые правила, накидывающие попытки за «высокую сложность» или низкую уверенность модели — переключись на Round-Robin с автотестами или отсекай задачи, которые не решились после первых $k$ попыток.
Ресурсы
- Исследование: Give Up to Get More: Priors, Not Policies, Govern Test-Time Compute Allocation (arXiv:2611.06372v1, ноябрь 2026)
- Автор: Jinhyung Bae (Department of Industrial and Management Engineering, Hankuk University of Foreign Studies, Yongin, Republic of Korea)
- Ключевые отсылки и датасеты в работе: пулы многократного сэмплирования Large Language Monkeys (Brown et al., 2024), PRM800K (Lightman et al., 2024), Weaver (Saad-Falcon et al., 2025); классическая теория оптимального распределения поисковых усилий (Koopman, 1957; Stone, 1975); индексные политики для «ухудшающихся рук» (Gittins, 1979; Weitzman, 1979).
