Как устроено сжатие контекста в Codex
В обычных моделях (не Codex) CLI сжимает контекст локально. Нейросеть сокращает диалог по промпту сжатия. Потом `responses.create()` подхватывает этот сжатый текст и добавляет промпт передачи — рамку для саммари. Оба промпта есть в открытом доступе.
С моделями Codex иначе: CLI обращается к API `compact()`, а в ответ получает зашифрованный блоб. Что внутри — загадка: есть ли там LLM, какие используются промпты и существует ли вообще «промпт передачи», мы не знаем.
Я провел простую промпт-инъекцию (2 запроса к API, 35 строк на Python) и выяснил: API всё-таки использует нейросеть для саммаризации. У неё свои промпты (сжатия и передачи), причем они почти не отличаются от тех, что выложены в опенсорс.
Шаг 1 — compact()
Вызываю `compact()` с подставным сообщением. Серверный LLM-компактор обрабатывает ввод по своей скрытой инструкции (системному промпту), которую я и хочу вытащить.
Судя по всему, сервер собирает контекст для компактора так:
Компактор видит свой системный промпт и наш текст как единое целое. А так как внутри нашего текста спрятана инъекция (красным на схеме), модель послушно включает свой системный промпт в ответ. Но этот ответ в открытом виде есть только на сервере OpenAI. Нам достается лишь шифрованный блоб:
Прочитать содержимое блоба сейчас невозможно. Это AES, ключи у OpenAI. Остается только надеяться, что инъекция сработала и компактор действительно слил свой промпт в саммари. Проверим это на втором шаге.
Шаг 2 — create()
Отправляю в `responses.create()` зашифрованный блоб и второе сообщение. Сервер расшифровывает данные и собирает контекст для модели.
Я отправляю:
А модель, скорее всего, видит это так:
Если на первом шаге всё прошло гладко, в расшифрованном блобе уже сидит промпт сжатия (мы его туда внедрили). Плюс сервер добавляет промпт передачи. Если теперь заставить модель повторить увиденное, она выдаст всё сразу: и системный промпт, и промпт передачи, и промпт сжатия.
Результат
Вот полный, сырой вывод скрипта `extract_prompts.py`. Желтый — системный промпт, зеленый — передачи, розовый — сжатия.
Точно ли это настоящие промпты, а не галлюцинации? Извлеченный текст почти один в один совпадает с открытыми промптами для обычных моделей в Codex CLI (prompt.md, summary_prefix.md). Вряд ли модель смогла бы случайно придумать настолько точное совпадение. К тому же, результаты немного меняются от запуска к запуску.
Вероятная схема работы
Если собрать факты воедино, работа `compact()` на сервере выглядит примерно так:
Скрипт
Вопрос
Зачем Codex CLI использует два разных пути сжатия (локальную LLM для обычных моделей и зашифрованный API для Codex), если промпты почти одинаковые? И к чему вообще шифровать саммари?
Сложно сказать. Возможно, в зашифрованном блобе спрятано что-то еще, чего мой простой тест не увидел — например, специфика сжатия результатов работы инструментов. Но копать глубже я не стал.
Комментарии (0)
Войдите, чтобы комментировать