Открытый проект
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Внешняя ссылка, откроется в новой вкладке.