Главная / Статьи / Кэширование промптов делает self-consistency дешёвой для проверок LLM на длинном контексте

Кэширование промптов делает self-consistency дешёвой для проверок LLM на длинном контексте

Замеры на шести моделях: с кэшированием несколько прогонов одного длинного промпта стоят всего в 1,55–2,5 раза дороже одного вызова. Плюс формула, оговорки и рецепт оценки.

1942 слов

Почему проверка согласованности не обязана стоить вшестеро дороже

Дешёвый и переносимый способ поймать ненадёжную LLM известен давно. Задайте модели один и тот же вопрос несколько раз и сравните ответы. Если они расходятся, не верьте ни одному. Не нужны ни logprobs, ни разметка, ни модель-судья, и подходит любой API, который можно вызвать дважды. Но в продакшене этим пользуются редко, потому что все приводят одно и то же возражение: шесть сэмплов — шесть счетов.

Тесты на шести моделях показывают другую картину. Там, где работает кэширование промптов, шесть сэмплов обходятся в 1,55–2,5 цены одного вызова. Уточню, что это значит: цифры — это отношения, так что запрос с оценкой всё равно дороже обычного. Меняется размер надбавки: около 55% вместо воображаемых 500%. Абсолютные суммы в долларах есть в таблицах, их можно проверить.

Нагрузка, под которую кэширование и создавалось

Причина механическая. Запрос приходит в API единым потоком токенов: сначала контекст, в конце вопрос. Кэш сравнивает этот поток с предыдущими начиная с нулевого байта, и всё совпавшее тарифицируется примерно на 90% дешевле обычной цены за вход. Любое изменение в начале промпта выбивает всё, что идёт после него.

Сэмплирование ради согласованности ничего не меняет. Оно повторяет один и тот же промпт N раз. Первый вызов платит полную цену и наполняет кэш, а остальные пять переиспользуют контекст за десятую часть цены, так что новая работа — только генерация ответов, то есть ровно то, что вы и хотите сравнить. В RAG по длинным документам или у агентов с большим контекстом инструментов, то есть там, где доверие важнее всего, львиная доля стоимости приходится на входные токены, и шестикратная надбавка в основном исчезает.

Есть детали, которые всё усложняют. Запись в кэш Anthropic стоит разовую надбавку 1,25x, и из трёх провайдеров только Anthropic сообщает об этой записи. Gemini кэширует блоками по 8 192 токена, и в этих прогонах между примерно 9k и 17k токенов ничего не кэшировалось. Минимальные размеры тоже разные: 512 токенов у Claude Opus-5, 1024 у OpenAI и 4 096 у Gemini.

Как устроен тест и сколько он стоил

В тесте контекстом служили правила авиакомпании примерно на 21k токенов, а за ними шёл один вопрос; каждой модели он отправлялся шесть раз. После каждого вызова записывалось число закэшированных токенов по данным провайдера, и у четырёх провайдеров это поле называется четырьмя разными именами. Затем оценщик noncontradiction из UQLM оценивал шесть ответов, сравнивая каждый ответ с остальными пятью с помощью NLI-модели. Этот шаг выполняется локально постфактум и не добавляет вызовов API.

Народное поверье — 6x. С прогретым кэшем стоимость запроса с оценкой, делённая на стоимость запроса без неё, у большинства моделей вышла от 1,55x до 2,5x (замеры 31 июля 2026 года).

Два результата портят оптимизм. Qwen не показал ни одного попадания в кэш ни на одном из шести вызовов, так что у него ровно 6x, и для этой модели возражение верно в чистом виде. Llama закэшировала 99,4% промпта, но ничего не сэкономила, потому что Together указывает сниженную цену за кэш для некоторых моделей, но не для этой. Попадание в кэш — техническое событие, а скидка — бизнес-решение, и нужно, чтобы случилось и то и другое.

Длиннее контекст — меньше надбавка

Чтобы проверить утверждение про «длинный контекст», прогон шёл от 1,4k до 440k токенов, по три вызова на каждый размер, и у каждого размера был свой холодный префикс, чтобы ничего не досталось от тёплого кэша предыдущего прогона.

Каждая кривая падает, а затем выходит на полку. Это настоящая асимптота, а не медленный спад. OpenAI даёт 1,51x, 1,51x, 1,50x и 1,50x от 55k до 440k токенов, то есть восьмикратный рост контекста сдвигает результат на сотую. Чтобы опуститься ниже полки, нужно меньше сэмплов (три сэмпла упираются в 1,20x) или большая скидка на кэш.

Два провайдера отклоняются каждый по-своему. Anthropic упирается в 1,75x, а не 1,50x, потому что каждый холодный вызов платит 1,25x за запись в кэш. Блоки Gemini по 8 192 токена заставляют его множитель скакать всякий раз, когда префикс пересекает границу блока: 2,07x на 28k, рост до 2,31x на 50k, затем 1,63x на 84k, и всё это стремится к той же полке.

Ниже примерно 7k токенов Gemini ничего не кэшировал и стабильно держался на 6,00x. Это и есть граница, где аргумент перестаёт работать: на маленьких промптах стандартное возражение просто верно.

Всё укладывается в одну формулу

Всё сводится к одной строке. Для N сэмплов одного и того же промпта:

C  cached context tokens
c  cached / input rate   (~0.1; 1.0 if no cached price)
Q  uncached input per call
w  write / input rate    (1.0; 1.25 on Anthropic)
O  output tokens
k  output / input price  (6 Terra · 5 Opus, Gemini · 2 DeepSeek)

В этой формуле f показывает, какая доля стоимости запроса может ехать на кэше, а M линейно от неё зависит: равно N, когда ничего не закэшировано, и полке, когда закэшировано всё. Все шесть моделей ложатся на эту прямую с точностью до 0,005.

Внимания заслуживает взвешивание по стоимости. Выходные токены входят в f после умножения на k, потому что стоят в k раз дороже и никогда не кэшируются. У Terra один выходной токен съедает кэшируемую долю так же быстро, как шесть токенов контекста её наращивают, и этим объясняется большая часть наблюдаемого разброса. DeepSeek доходит до 1,86x даже при 99% попаданий, потому что каждый ответ содержал 656 токенов рассуждений. Llama стоит ровно на 6,00x при f = 0,99: без цены за кэш c = 1, и формула не оставляет ей простора.

Практическое правило: закэшированный контекст C должен сильно превышать выход O, умноженный на k. Длинный контекст помогает, а длинные ответы вредят в k раз быстрее. Поверхность, построенная по длине контекста и длине вывода, ставит точку безубыточности 2x там, где эти две силы уравновешиваются.

Для вашего собственного стека это арифметика, а не бенчмарк:

# pip install r2c2 — Reuse Context, Recheck Consistency
from r2c2 import estimate, required_context
estimate(context_tokens=21_000, output_tokens=40, model="gpt-5.6-terra").multiplier
# 1.56 — matches the 1.55 measured
required_context(output_tokens=40, model="gpt-5.6-terra", threshold=1.8)
# 4060 — under ~4k context tokens, six samples cost more than 1.8x

Вторая функция считает формулу в обратную сторону. Дайте ей потолок стоимости, и она вернёт размер контекста, начиная с которого оценка в этот потолок укладывается. Она возвращает None, если такого размера нет, а это бывает, когда потолок не выше полки провайдера.

Что ловят дополнительные расходы

Дешёвое сэмплирование бессмысленно, если оценка ничего не выявляет, поэтому тестовый вопрос был трудным. Правила разрешают возврат денег за невозвратные тарифы в течение 24 часов после бронирования и не уточняют, кто отменил рейс. Сценарий: пассажир купил невозвратный билет 30 часов назад, а потом авиакомпания отменила рейс. Положен ли возврат?

На контрольном вопросе, на который правила отвечают прямо, все шесть моделей получили 0,99 и выше. Формулировки каждый раз меняются, а вывод — никогда: перефразирование — это и есть суть сэмплирования, и расхождением оно не считается.

На том же вопросе, взятом из тех же шести вызовов, что и цифры стоимости, модели разошлись. Qwen чередовал «нет», «да», «нет», «да», «нет», «да» — по сути, подбрасывал монетку в вопросе о возврате денег — и получил 0,40. Gemini разделился 4 к 2, и в его ответах «да» упоминались «правила Министерства транспорта», о которых в промпте ни слова. Terra и DeepSeek разделились 5 к 1. Claude Opus 5 шесть раз из шести ответил «да», решив — правдоподобно, но без опоры на текст, — что правило 24 часов касается только отмен по инициативе пассажира. Llama получила идеальные 1,00, шесть раз дав одну и ту же уклончивую формулировку («может считаться исключением... может иметь право»). Стабильная уклончивость — тоже сигнал, но этот оценщик её не ловит.

Каждый из тридцати шести ответов звучит гладко и уверенно, и каждый ссылается на правила. Глядя на один ответ, вы никогда не узнаете, что следующий сэмпл может сказать обратное. Те самые 0,40 — единственное видимое предупреждение, и там, где доминирует вход, оно стоит примерно половину одного дополнительного вызова.

Расклады ещё и меняются от прогона к прогону. В другом прогоне Terra разделился 3 к 3, а Gemini все шесть раз отказался отвечать. Предварительное тестирование этого не исправит, и это аргумент за оценку вживую, а не за разовый офлайн-аудит.

Как применить

Если вы уже сэмплируете N ответов, сама оценка бесплатна: .score() запускается постфактум на уже полученных ответах:

from uqlm import BlackBoxUQ
# six answers you already collected; calls 2-6 hit the prompt cache
scorer = BlackBoxUQ(scorers=["noncontradiction"], use_best=False)
result = scorer.score(responses=[answers[0]], sampled_responses=[answers[1:]])
confidence = result.to_df()["noncontradiction"][0]  # 0.99 = agrees; 0.40 = coin flip

Оценщик запускает локальную NLI-модель (microsoft/deberta-large-mnli), так что платить модели-судье не нужно. Низкие оценки можно отправлять человеку, на повторный поиск или более крупной модели.

Три привычки решают, увидите ли вы реальные 1,55x. Отправляйте первый вызов отдельно, а остальные — веером, потому что запись в кэше нельзя прочитать, пока не начал стримиться первый ответ, а шесть одновременных одинаковых запросов промахнутся все. Держите сэмплы идентичными до байта и выносите всё изменчивое за контекст: одна вставленная метка времени портит всё, что идёт после неё. И наконец, сэмплируйте с температурой выше нуля, иначе шесть одинаковых ответов дадут идеальную оценку, которая ничего не говорит.

К чему это ведёт

Среди методов обнаружения галлюцинаций оценка неопределённости по принципу чёрного ящика всегда была самой простой во внедрении: не нужны ни logprobs, ни разметка, работает где угодно. Единственным серьёзным минусом была цена, и он поблёк, когда провайдеры ввели чтение из кэша со скидкой 90%, ведь сэмплирование ради согласованности по своей природе отправляет одни и те же байты. Цикл такой: закэшировать прочитанное, пересэмплировать ответ, оценить согласие и отправить низкие оценки человеку. На платформах, через которые идёт большая часть продакшен-трафика, это стоит примерно половину лишнего вызова.

Ничто из этого не переносится без изменений на любую конфигурацию. Цифры зависят от размера контекста, провайдера и цен на токены. Промпт на 2k токенов в Gemini не кэшируется вообще, а чат-бот с короткими промптами и длинными ответами до 1,55x не дойдёт. Формула за полминуты даёт ваш собственный множитель, а репозиторий для воспроизведения повторяет всё это с четырьмя API-ключами примерно за два доллара.

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

Код и данные: https://github.com/mohitcek/r2c2 (репозиторий для воспроизведения) и https://github.com/cvs-health/uqlm (UQLM).