Открытый проект

audit-prompt-caching

Скилл для Codex, который помогает найти причины промахов кэша в LLM-запросах.

Стабильный релиз
v0.1.15
Лицензия
MIT

Два запроса могут решать одну и ту же задачу и почти целиком совпадать. Но если в начало попала текущая дата или поменялся порядок описаний инструментов, общий префикс обрывается раньше, чем мы рассчитывали.

audit-prompt-caching помогает найти такое место. Скилл разбирает код сборки запроса, инструкции, инструменты, историю диалога и настройки маршрутизации. Локальные Python-скрипты сравнивают готовые запросы и разбирают сохранённые данные об использовании кэша.

Начать можно с кода проекта. Если для вывода нужны логи или метрики, скилл подскажет, какие именно собрать.

Как попробовать

Установите скилл:

npx skills add https://github.com/sernote/audit-prompt-caching --skill audit-prompt-caching

Откройте новую сессию Codex в своём проекте и дайте ему задачу:

Проверь этот проект с $audit-prompt-caching.
Начни с кода, который собирает и отправляет LLM-запросы.
Объясни, нужны ли изменения префикса, инструментов или маршрутизации.
Укажи, по каким данным проверить результат.
Если изменений не нужно, объясни почему.
Если данных не хватает, назови следующее конкретное наблюдение.

Скилл ищет меняющиеся поля в начале промпта, перестановки инструментов и схем, изменения истории между шагами. Затем проверяет настройки провайдера и роутера: одинаковые запросы могут попадать на разные реплики, каждая со своим кэшем.

В короткой инструкцииВнешняя ссылка, откроется в новой вкладке описано, как выбрать вопрос для аудита и проверить один его вывод. Ниже есть пример сравнения двух запросов. Код и остальные способы установки лежат на GitHubВнешняя ссылка, откроется в новой вкладке.

Пример: дата перед инструкциями

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

До:    дата, номер обращения, сообщение → инструкции
После: инструкции → дата, номер обращения, сообщение

Содержание запросов осталось прежним. В этом примере их общее начало выросло с 43 до 254 байт.

Чтобы повторить сравнение, нужны Git и Python 3.10 или новее:

git clone --depth 1 https://github.com/sernote/audit-prompt-caching.git
cd audit-prompt-caching
python3 audit-prompt-caching/scripts/prefix_stability_check.py --json \
  examples/first-audit/before-a.txt examples/first-audit/before-b.txt
python3 audit-prompt-caching/scripts/prefix_stability_check.py --json \
  examples/first-audit/after-a.txt examples/first-audit/after-b.txt

В выводе смотрите на stable_prefix_bytes:

До:    43
После: 254

Обе команды возвращают код 1: полные запросы всё ещё различаются, так и задумано. Числа показывают длину общего начала файлов в байтах UTF-8. Чтобы узнать, сработал ли кэш, нужны данные самого вызова.

Полные запросы и вывод скриптаВнешняя ссылка, откроется в новой вкладке можно посмотреть отдельно. Для своей задачи запустите скилл в проекте или сравните скриптом два готовых запроса одного сценария. Время и пользовательский ввод должны различаться так же, как в обычной работе приложения.

Как проверить результат

Проверьте один вывод аудита. Если предложена правка, сравните готовые запросы до и после. Если начало уже стабильно, оставьте его как есть и проверьте фактическое чтение кэша.

Повторите вызовы и посмотрите, сколько входных токенов провайдер прочитал из кэша. Если API отдельно показывает создание кэша, проверьте и чтение в следующих вызовах. Названия полей и условия зависят от API; в репозитории есть справки для OpenAIВнешняя ссылка, откроется в новой вкладке, AnthropicВнешняя ссылка, откроется в новой вкладке и BedrockВнешняя ссылка, откроется в новой вкладке.

Затем сравните время до первого токена и стоимость вызовов на той же нагрузке. Это отвечает на главный вопрос: помогло ли изменение приложению. Бывает, что кэш читается, а ответ всё равно задерживается в очереди. Такой случай разбираю в статье «Тёплый кэш — ещё не быстрый ответ».

Если проблема в маршрутизации

Проверьте, куда попал повторный запрос, что роутер знал о кэше выбранной реплики и сколько времени запрос провёл в очереди.

Экспериментальный скрипт analyze_routing_logs.py связывает решение роутера и результат попытки по run_id, request_id и attempt_id. Данные из своих логов нужно привести к формату JSONL для анализатораВнешняя ссылка, откроется в новой вкладке. Как их собрать и подготовить, разобрано в инструкции по наблюдению за роутеромВнешняя ссылка, откроется в новой вкладке.

Что видно в лабораторном примере

В сохранённом прогонеВнешняя ссылка, откроется в новой вкладке vllm-router отправляет три запроса тестовому серверу. В этой версии и на этом HTTP-пути видно две вещи:

  • Chat-запросы содержат текст в messages, но не содержат session_id. Политика получает пустую строку и показывает input_chars=0. Этот счётчик не измеряет входные токены модели.
  • Два ответа приходят целиком, а в третьем сервер намеренно пропускает завершающие события. У всех трёх HTTP 200, и счётчик circuit breaker отмечает три успешных обращения. Завершение ответа нужно проверять на стороне клиента.

События и устройство стендаВнешняя ссылка, откроется в новой вкладке можно разобрать без сборки; при желании там же есть инструкция повторного запуска. Сервер имитирует ответы без модели и KV-кэша. Механику разбираю в статье «Что кэш-роутер знает о кэше».

Обратная связь

После проверки можно оставить отзыв через формуВнешняя ссылка, откроется в новой вкладке: что проверяли, что помогло или запутало и удалось ли подтвердить результат. Это по желанию. Перед публикацией примеров удалите ключи доступа, персональные данные и внутренние адреса.

Механику повторного использования KV разбираю в главе «Префиксный кэш».

Claude for Open Source

В августе 2026 года проект приняли в программу Claude for Open SourceВнешняя ссылка, откроется в новой вкладке. Мне дали бесплатный Claude Max 20x на шесть месяцев, чтобы дальше заниматься проектом.

Забавно, что в описании проекта на первом месте всё равно skill для Codex.

Проект распространяется по лицензии MITВнешняя ссылка, откроется в новой вкладке.

Связанные материалы