Учебник по GPT-6 Sol API: создаём агента для миграции кодовой базы
Научитесь использовать GPT-6 Sol API в Python. Постройте агента миграции кодовой базы с инструментами репозитория, Structured Outputs, триажем на GPT-6 Luna, steering и pytest.
Здесь мы используем GPT-6 Sol, чтобы перенести Northstar Checkout, небольшой вымышленный Python‑сервис оформления заказов, с локального платежного адаптера v1 на v2.
Точнее, мы разберём, как:
Сделать первый вызов GPT-6 Sol API и прочитать его поля учёта использования
Определить контракт миграции до того, как модель увидит репозиторий
Выдать GPT-6 Sol ограниченные инструменты для работы с файлами и тестами и поэтапно открывать доступ с помощью allowed_tools
Использовать GPT-6 Luna для триажа и заставить GPT-6 Sol проверить короткий список
Вернуть структурированный план миграции и проверить его по файлам, уже прочитанным GPT-6 Sol
Запустить миграцию по WebSocket и управлять ею после начала правок
Повысить усилие рассуждений после провала независимой проверки деплоя
Посчитать зафиксированную стоимость по данным использования API
Что я понял по дороге
Четыре вывода изменили бы мой подход к следующей версии:
Пройти набор приёмочных тестов оказалось недостаточно. Отправка того же запроса оформления заказа на другой сервер всё ещё приводила к необработанному исключению из адаптера.
Повышение усилия имело реальный триггер. После провала пробы деплоя GPT-6 Sol нашёл баг в состоянии, хранимом одним процессом, и починил ретраи между серверами.
Steer не может отменить сделанную правку, но модель может. К моменту нового требования GPT-6 Sol уже переименовал публичный параметр, и затем откатил переименование.
Короткий список от GPT-6 Luna имел полную полноту, но экономия не доказана. GPT-6 Sol всё равно искал шире перед планированием.
Что такое GPT-6 Sol?
GPT-6 Sol — средний уровень в семействе GPT-6 от OpenAI, идентификатор модели в API — gpt-6-sol. Наш обзор уровней моделей GPT-6 описывает релиз и бенчмарки. В рекомендациях по GPT-6 OpenAI называет GPT-6 Astra старшей, GPT-6 Sol — средней, а GPT-6 Luna — самой дешёвой.
GPT-6 Sol имеет контекстное окно 1 050 000 токенов и возвращает до 128 000 выходных токенов. Усилие рассуждений варьируется от none до max и по умолчанию — medium. В Chat Completions вызов функций для GPT-6 Sol поддерживается только при none, поэтому все запросы здесь используют Responses API.
Цены и поддержка API определяют, как обвязка отправляет каждый запрос.
Сколько стоит GPT-6 Sol API?
GPT-6 Sol стоит $2 за миллион входных токенов и $10 за миллион выходных токенов для запросов до 272 000 входных токенов, согласно странице цен OpenAI. Кэшированный вход стоит $0.20 за миллион, запись в кэш — $2.50. Тарифы GPT-6 Luna для тех же четырёх категорий: $0.10, $0.01, $0.125 и $0.50.
Свыше 272 000 входных токенов весь запрос тарифицируется по двойной ставке на вход и кэш и по 1.5x на выход. В этом проекте ни один запрос не приблизился к этим порогам.
Какие возможности API используются в этом учебнике?
Обвязка — то есть Python‑код вокруг модели — использует такие настройки GPT-6:
Все четыре настройки остаются в одной цепочке ответов Responses API.
Что мы построим с GPT-6 Sol API?
Мы создадим агента, который переведёт Northstar Checkout с Payments Adapter v1 на v2. Оба адаптера — локальные заглушки, написанные для эксперимента, а не настоящие платёжные SDK. Полный код, фикстуры и запись прогона — в этом репозитории GitHub.
В репозитории платёжный код смешан с несвязанными модулями, поэтому GPT-6 Sol должен сам найти затронутые файлы. Версия v2 ломает четыре контракта адаптера:
Создание платежа переносится с client.charge(...) на client.payments.create(...)
Словари результатов становятся типизированными объектами с суммами типа Money
Отклонённые карты возвращают состояние вместо генерации исключения
Вебхуки меняют имена, конверт и заголовок подписи
Поиск и замена справится с переименованием метода. С поведенческими изменениями — нет.
Один цикл миграции, две модели GPT-6. Изображение автора.
GPT-6 Sol получает спецификацию, дерево файлов и ограниченные инструменты, которые поэтапно становятся доступными. Модель не знает, какие файлы требуют изменений, и не знает, что требования изменятся.
Почему эта миграция API сложная?
Две части спецификации — ловушки. Это не подложенные баги; они возникают из-за столкновения поведения v2 с существующим кодом:
Идемпотентность. v2 сравнивает параметры при повторном request_id, но checkout на каждой попытке кладёт новый order_id в метаданные, поэтому наивный ретрай отклоняется вместо дедупликации.
Итоги возвратов. Вебхук payment.refunded в v2 сообщает накопленную сумму возврата, а старый обработчик суммирует каждое значение с помощью +=.
Обе проблемы не ловятся типизацией. Их видно только при прогоне оформления и возвратов от начала до конца.
Изменения платежей затрагивают несколько модулей Northstar. Изображение автора.
Схема отделяет прямые импорты адаптера от модулей, зависящих от платёжного поведения. Эти косвенные связи — причина, по которой важен эталонный ответ для всего репозитория.
Как мы будем тестировать миграцию?
Итог решает отложенный набор приёмочных тестов, написанных до первого вызова модели. GPT-6 Sol их не видит; обвязка запускает их с pytest против мигрированной копии. Он проверяет, что:
Оформление проходит через v2, а ретрай с тем же ключом идемпотентности списывает один раз
Полный возврат, два частичных возврата и повторная доставка вебхука оставляют корректные итоги
CheckoutClient сохраняет неизменными сигнатуры методов
Не осталось ссылок на v1, vendor/ и MIGRATION.md не затронуты, и видимые тесты проходят
Исходный код уже проходит проверки на неизменность интерфейсов и защищённых файлов; оставшиеся проверки измеряют миграцию. Отдельный эталонный ответ перечисляет требуемые изменения, но читает его только обвязка.
Каталоги acceptance/ и probes/ находятся вне копии репозитория, открытой для обеих моделей. Эталон живёт под acceptance/, поэтому не может попасть во вход GPT-6 Luna, дерево файлов или инструменты репозитория.
Ворота чтения могут вернуть пути из собственного плана GPT-6 Sol. Покрытие эталоном записывается только для оценки; оно никогда не отправляет отсутствующие пути из ground truth обратно в GPT-6 Sol.
После этого набора запускается проба деплоя. Ни одна из проверок не принимает сообщение модели «готово» как доказательство.
Как настроить GPT-6 Sol API в Python
Вам нужен Python 3.10 или новее и API‑ключ с доступом к обеим моделям. В требованиях есть дополнительный пакет realtime, который нужен для steering:
git clone https://github.com/KhalidAbdelaty/gpt-6-sol-api.git
cd gpt-6-sol-api
python -m venv .venv
.venv\Scripts\Activate.ps1
pip install-r requirements.txt
Copy-Item .env.example .envРаботает на
На macOS или Linux используйте source .venv/bin/activate и cp .env.example .env, затем добавьте OPENAI_API_KEY=... в .env.
Если ключ уже работает с Responses API, пропустите следующий подраздел.
Сделайте первый вызов GPT-6 Sol API
Минимально полезный запрос подтверждает ключ, ID модели и поля учёта, нужные для раздела о стоимости:
from dotenv import load_dotenv
from openai import OpenAI
load_dotenv()
client = OpenAI()
response = client.responses.create(
model="gpt-6-sol",input="In one sentence, why is a breaking API migration harder than renaming a function?",)print(response.reasoning.effort, response.output_text)print(response.usage)Работает на
В ответе указано усилие medium, а usage включает cached_tokens и cache_write_tokens. Не используйте temperature и top_p — при усилии, отличном от none, они приводят к 400.
Первый запрос к GPT-6 Sol возвращает usage. Изображение автора.
С какого усилия рассуждений начинать?
Начинайте с medium, значения по умолчанию, и держите настройку на уровне запроса неизменной весь прогон. Большинство шагов миграции — чтение и небольшие правки. Позже проба деплоя даст повод повысить усилие.
Как добавить безопасные инструменты репозитория в кодирующего агента
Слой инструментов определяет права агента. GPT-6 Sol получает эти функциональные инструменты с strict: true:
list_files и search_code находят релевантный код
read_file возвращает один файл репозитория
edit_file меняет одно точное вхождение
run_tests запускает разрешённую цель pytest
Строгие схемы проверяют форму аргументов, а не безопасность путей, поэтому границу записи обеспечивает Python:
READ_ONLY =("vendor/","MIGRATION.md","conftest.py")if write:if rel_posix.startswith(READ_ONLY)or rel_posix in READ_ONLY:raise ToolError(f"{rel_posix} is read-only")# the spec and both adaptersifnot rel_posix.startswith(("northstar/","tests/"))ornot rel_posix.endswith(".py"):raise ToolError("writes are limited to Python files under northstar/ and tests/")Работает на
Путь сначала нормализуется, поэтому ../ и абсолютные пути не проходят. edit_file заменяет одно точное совпадение, а run_tests принимает только цели под tests/.
Обвязка возвращает заблокированный вызов как вывод инструмента с префиксом ERROR:, и цикл продолжается. Наш гид по инженерии обвязки агента объясняет, почему эти проверки должны быть в обвязке, а не в подсказке.
Как протестировать границы файлов
Вызовите каждый инструмент с входными данными, которые он обязан отклонить:
Путь, содержащий ..
Абсолютный путь
Запись под vendor/
Цель теста, содержащая shell‑команду
Ни один не должен пройти. Правка, совпадающая более чем с одним местом, должна запрашивать больше контекста, а хранение правил в пользовательских функциях собирает их в одном, легко тестируемом месте.
Как использовать GPT-6 Luna для триажа репозитория
Триаж репозитория — узкая задача классификации: оценить релевантность каждого файла и процитировать ссылки на v1. GPT-6 Luna получает эту задачу и только её, и запускается первой, до того как GPT-6 Sol что-либо ищет.
classFileVerdict(BaseModel):
path:str
relevance: Literal["high","medium","low","none"]
legacy_references:list[str]
triage = client.responses.parse(model="gpt-6-luna",input=spec_and_all_files,
text_format=TriageResult)# a list of FileVerdictРаботает на
Вход — это спецификация плюс каждый Python‑файл под northstar/ и tests/. Всё с рейтингом high или medium попадает в короткий список, который GPT-6 Sol получит дальше.
Как проверить короткий список GPT-6 Luna
Сверьте короткий список с эталоном из предыдущего раздела и сначала посмотрите на полноту. GPT-6 Luna удержала каждый затронутый файл и добавила несколько лишних.
GPT-6 Luna сужает 56 до 16. Изображение автора.
Короткий список — это подсказка, а не граница.
Как использовать allowed_tools для поэтапных разрешений
allowed_tools — это режим tool_choice, который ограничивает, какие инструменты модель может вызвать, при этом полный список инструментов остаётся на месте. Так первый проход GPT-6 Sol остаётся только для чтения: полный список задаётся в каждом запросе, но доступны только листинг и поиск.
defallowed(names):return{"type":"allowed_tools","mode":"auto","tools":[{"type":"function","name": n}for n in names]}
response = client.responses.create(
model="gpt-6-sol", instructions=INSTRUCTIONS, tools=TOOLS,# full list, every time
tool_choice=allowed(["list_files","search_code"]),
reasoning={"effort":"medium"},input=inspect_prompt, store=True,)Работает на
Изменение поля tools между фазами перезапишет кэшированный префикс. Гид по вызову функций рекомендует allowed_tools, когда меняется только множество вызываемых инструментов.
Зачем запускать кодирующего агента в режиме «только чтение»?
Проход «только чтение» разделяет диагностику и действие. GPT-6 Sol получил короткий список от GPT-6 Luna с прямым предупреждением, что он может быть неверным, и его поиски импортов v1, вызовов charge и имён вебхуков сами по себе выявили каждый затронутый файл.
Он также вышел за пределы списка, отметив модели заказов, хранилище заказов, сериализаторы и выгрузку в бухгалтерскую книгу как нижестоящие зависимости для проверки. В итоге правок там не потребовалось, но прочитать их — единственный способ это выяснить. Я бы сохранял allowed_tools для любого агента, который редактирует файлы.
Как использовать Structured Outputs для плана миграции
План миграции — момент, когда агент фиксирует конкретные файлы до получения прав записи. На этапе планирования добавляется read_file, а сам план возвращается через Structured Outputs при отключённых инструментах:
plan = client.responses.parse(
model="gpt-6-sol", instructions=INSTRUCTIONS, tools=TOOLS, tool_choice="none",
reasoning={"effort":"medium"}, previous_response_id=last_id,input=PLAN_REQUEST, text_format=MigrationPlan,# files, evidence, risks)Работает на
План охватил все требуемые изменения и предупредил, что новый идентификатор заказа изменит метаданные v2 при ретрае. Это предупреждение вернётся позже.
Как проверить структурированный план миграции
Перед выдачей прав записи обвязка проверяет структуру плана, доказательства и покрытие.
Три проверки тестируют один план миграции. Изображение автора.
План прошёл все ворота. Он также предложил переименовать публичный параметр в client.py под стиль v2, как рекомендовал раздел чистки в спецификации. Это предложение стало тестом для steering.
Как построить кодирующего агента GPT-6 Sol на Responses API
Кодирующий агент GPT-6 Sol работает в петле инструментов: ждёт ответ, выполняет его вызовы функций и возвращает выходы. Наш гид по OpenAI Responses API объясняет формат запросов и результатов инструментов. Эта миграция держит цикл на одном WebSocket‑подключении, потому что steering этого требует.
with client.responses.connect()as conn:
conn.response.create(**base, previous_response_id=plan_id,input=[start_message])for event in conn:if event.type=="response.incomplete":
reason =getattr(event.response.incomplete_details,"reason",None)if reason =="steered":continue# keep reading for the automatic successorraise RuntimeError(reason or"response incomplete")if event.type!="response.completed":continue
calls =[i for i in event.response.output if i.type=="function_call"]ifnot calls:break# GPT-6 Sol says it's done here; the held-out tests decide whether it is
outputs =[{"type":"function_call_output","call_id": c.call_id,"output": tools.run(c.name, c.arguments)}for c in calls]
conn.response.create(**base, previous_response_id=event.response.id,input=outputs)Работает на
base фиксирует модель, инструкции, инструменты и усилие medium для кэширования подсказок. GPT-6 Sol запускал видимые тесты по ходу работы, но также написал большинство новых тестов, поэтому они не могут служить независимой проверкой.
Как работает управление на середине хода (steering) в GPT-6 Sol?
Mid-turn steering добавляет инструкцию к ответу, который всё ещё генерируется, без его отмены. После response.created вы отправляете response.steer по тому же соединению с ID этого ответа, и сервер применяет инструкцию в ответе‑преемнике.
Новое требование пришло от команды витрины: сигнатуры CheckoutClient «должны остаться ровно такими, как сегодня», потому что их вызывает другой сервис. Я не хотел привязывать это к таймеру, поэтому обвязка следит за репозиторием. После каждого пакета вызовов инструментов она сравнивает публичные сигнатуры на диске с оригиналами, и первое расхождение приводит к отправке steer:
if steer_state =="idle"and signature_changes(repo):# CheckoutClient, compared with ast
steer_state ="armed"if event.type=="response.created"and steer_state =="armed":
conn.response.steer(previous_response_id=event.response.id,input=STEER_TEXT)
steer_state ="sent"Работает на
Это гарантирует, что steer приземлится после противоречащего ему переименования — именно такую ситуацию и стоит тестировать. Отправленный раньше — это просто более длинная подсказка.
Сервер затем сообщил жизненный цикл steering:
response.steer.accepted означает, что обновление поставлено в очередь, а не применено
response.incomplete завершил исходный ответ по причине steered
Ответ‑преемник response.created продолжил работу с новым требованием
Если ответ ждёт результата инструмента, сервер отправит response.steer.pending и придержит steer, пока обвязка не вернёт его. Продолжайте отвечать на вызовы инструментов, пока steer в ожидании.
Что остаётся неизменным при steering?
Steering меняет то, что модель сделает дальше. Гид OpenAI прямо говорит об остальном: steer не переписывает уже отправленный вывод, не отменяет ранние действия и не останавливает уже начатые инструменты.
Когда пришёл steer, переименование уже было на диске в client.py. GPT-6 Sol его откатил, а отложенная проверка сигнатур позже подтвердила окончательный интерфейс.
Правку можно откатить. Инструмент, уже обратившийся к внешней системе, может не оставить, что откатывать, поэтому записывайте состояние репозитория при каждом приходе steer.
Может ли GPT-6 Sol мигрировать кодовую базу на Python?
В этом репозитории — да, хотя и не за один проход. Первая миграция выполнила исходный контракт, затем проба деплоя выявила пропущенный случай.
Что показали отложенные тесты?
Когда GPT-6 Sol сообщил о завершении миграции, отложенный набор прошёл без этапа исправлений. Для возвратов GPT-6 Sol заменил суммирование на накопительное чтение, которое также игнорирует вебхуки вне порядка:
- order.refunded_cents += data["amount_refunded"]
+ order.refunded_cents = max(order.refunded_cents, refunded["cents"])Работает на
Для идемпотентности GPT-6 Sol сохранил свежий order_id на каждую попытку и добавил кэш запросов в хранилище заказов, который отвечает на повторные запросы до того, как они попадут в v2. Этот кэш живёт в памяти процесса, что скоро станет важным.
Могут ли Structured Outputs быть неверными?
Да. Первый отчёт назвал обновлённый тест вебхука регрессией и не упомянул риск ретраев между серверами, хотя план эту ловушку называл.
Structured Outputs валидирует схему, а не утверждения. Сверяйте поля отчёта с записанными доказательствами и не считайте пустой список рисков доказательством их отсутствия.
Что пропустили приёмочные тесты?
Набор пропустил ретрай, направленный на другой экземпляр приложения. Я добавил пробу деплоя с двумя клиентами, которые делят один платёжный процессор, но не память процессов.
Проба провалилась. Ретрай на втором экземпляре сгенерировал payments_adapter_v2.IdempotencyConflict — исключение адаптера, которое витрина не должна видеть.
Такой сбой проявляется только в деплое с более чем одним процессом и служит триггером для повышения усилия рассуждений.
Как менять усилие рассуждений в ходе разговора
Элемент входа configuration_update меняет усилие рассуждений для следующего ответа и всех последующих, пока не придёт новое обновление. Усилие на уровне запроса остаётся прежним, поэтому кэшированный префикс сохраняется. Когда проба провалилась, обвязка отправила этот запрос, следуя гайду по рассуждениям:
Запросы миграции используют store=True, поэтому после закрытия WebSocket обвязка может продолжить сохранённую цепочку ответов обычным запросом к Responses API.
response = client.responses.create(
model="gpt-6-sol", reasoning={"effort":"medium"},# unchanged, so the prefix survives
instructions=INSTRUCTIONS, tools=TOOLS, tool_choice=allowed(DIAGNOSE_TOOLS),
previous_response_id=last_id,input=[{"type":"configuration_update","reasoning":{"effort":"high"}},{"role":"user","content": probe_failure + DIAGNOSE_FIRST}],)
active_effort ="high"# the harness records it; the response won'tРаботает на
GPT-6 Sol получает информацию о сбое и схему деплоя, но без намёка на исправление.
DIAGNOSE_TOOLS разрешает чтение и тестирование, но не правки. Сохранение инструментов и text.format неизменными сохраняет кэшированный префикс.
Одна особенность API неудобна: response.reasoning.effort после обновления всё ещё показывает настройку на уровне запроса. Обвязка не может прочитать активное усилие из ответа, поэтому сама его записывает при отправке обновления и помечает им все последующие ответы.
Сработало ли исправление при усилии high?
Да. GPT-6 Sol отследил сбой до локального хранилища второго сервера, затем проследил свежий ID заказа в метаданные платежа. Общий процессор увидел разные параметры для одного и того же request_id.
Исправление сделало идентификатор заказа функцией идентификатора запроса, чтобы каждый сервер вычислял один и тот же:
GPT-6 Sol также добавил видимый тест на этот случай. Проба и приёмочный набор прошли, затем
configuration_update вернул усилие к medium. На этот раз финальный отчёт корректно описал реальный сбой.
Приложение Streamlit проекта воспроизводит сохранённый прогон без API‑вызовов. Видеозапись идёт от обзора к событиям steering, затем к результатам приёмочных тестов и пробы.
Streamlit воспроизводит миграцию и исправление. Видео автора.
Чего здесь не видно — нашёл бы то же место режим medium. Я запустил только путь с эскалацией, поэтому факты такие: high сработал здесь — не то, что он был необходим.
Сколько стоит кодирующий агент на GPT-6 Sol?
Этот записанный прогон стоил $0.7082: $0.7051 за GPT-6 Sol и $0.0031 за GPT-6 Luna. Каждый вызов Responses API возвращает четыре тарифицируемых счётчика токенов, поэтому считайте цену каждого ответа отдельно по указанным ранее ставкам.
details = usage.input_tokens_details
cached, written = details.cached_tokens, details.cache_write_tokens
ordinary = usage.input_tokens - cached - written # cache writes have their own rate
cost =(
ordinary * PRICE_INPUT
+ cached * PRICE_CACHED_INPUT
+ written * PRICE_CACHE_WRITE
+ usage.output_tokens * PRICE_OUTPUT
)/1_000_000Работает на
За весь прогон 91% входа GPT-6 Sol пришёл из кэша.
План и первый отчёт каждый добавили схему ответа и не читали из кэша. В гайде по кэшированию подсказок параметр text.format указан среди тех, что меняют префикс. В этом прогоне записи в кэш стоили дороже выхода, так что держите инструкции и инструменты постоянными и ожидайте, что запросы с добавлением схемы запишут новый префикс.
Сэкономила ли GPT-6 Luna работу?
Не доказуемо. GPT-6 Luna сузила 56 файлов до 16, тогда как GPT-6 Sol независимо открыл ещё 16. Без эталона «без GPT-6 Luna» нельзя утверждать, что короткий список сократил общее чтение.
Когда кодирующему агенту использовать GPT-6 Sol, а когда GPT-6 Luna?
Используйте GPT-6 Sol там, где цена ошибки высока — планирование, правки, чтение падений тестов, — а GPT-6 Luna для узкой классификации, которую можно проверить. В этой сборке GPT-6 Luna один раз сузила область поиска, а все решения, меняющие файлы, принимал GPT-6 Sol.
Промышленная миграция платежей требует большего контроля, чем этот локальный эксперимент. Большинство мер — в обвязке, а не в модели:
Запускайте каждую миграцию в одноразовой ветке, рабочем дереве или контейнере
Останавливайте цикл по фиксированному числу ходов и лимиту по стоимости
Тестируйте конфигурацию деплоя вместе с кодом: добавьте проверки между несколькими инстансами в отложенный набор
Уберите секреты и клиентские данные из подсказок и логов инструментов
Требуйте одобрения человеком итогового diff перед слиянием
Держите чистую стартовую ревизию доступной для отката
Проверка между несколькими инстансами — контроль, заработанный в этом прогоне тяжёлым путём. Тестовый контракт доказывает только то, что покрывает, и каждый пункт списка ограничивает ущерб, когда покрытие меньше ожидаемого.
Итоги
Сначала Northstar достиг выполнения контракта, хотя ретрай на другом сервере ещё ломал идемпотентность — риск, названный в плане миграции до любых правок. Провал пробы и точечное исправление привели к результату, который пропустил исходный контракт.
Я бы оставил шаг триажа GPT-6 Luna только там, где он реально сокращает чтение, держал GPT-6 Sol на medium на рутинных ходах и повышал усилие при провале независимой проверки. Прежде всего я бы включил проверки деплоя в контракт до первого прогона, а не после первого сюрприза.
Работает ли режим WebSocket с store=false или Zero Data Retention?⌄
Да. Соединение держит в памяти недавнее состояние ответов, поэтому previous_response_id работает с store=false на том же соединении. После переподключения это состояние теряется, и запрос вернёт previous_response_not_found.
Что происходит с поставленным в очередь steer, если WebSocket‑соединение падает?⌄
Считайте это неизвестным. Поставленный в очередь steer живёт только на текущем соединении, а соединения длятся до 60 минут, поэтому в документации OpenAI сказано не предполагать, что он пережил обрыв. Логируйте каждый отправленный steer и сравнивайте с историей ответов перед повторной отправкой.
Можно ли использовать встроенный инструмент OpenAI apply_patch с GPT-6 Sol?⌄
Да, на странице модели GPT-6 Sol указано, что поддерживается apply_patch. Ваше приложение всё равно применяет каждый патч локально, поэтому проверки путей ему всё равно нужны.
Делятся ли GPT-6 Sol и GPT-6 Luna состоянием разговора?⌄
Нет. Приложение передаёт короткий список GPT-6 Luna в следующий запрос GPT-6 Sol; API‑вызовы не делятся состоянием автоматически.
Стоит ли отправлять весь репозиторий в GPT-6 Sol вместо использования инструментов для файлов?⌄
Для такого небольшого репозитория, как Northstar, можно. Нюанс: вставленный в контекст репозиторий остаётся в контексте разговора через previous_response_id, поэтому каждый последующий ход всё ещё обрабатывает эти токены, в основном как кэшированный вход. Петля инструментов добавляет только файлы, запрошенные GPT-6 Sol, и делает каждую правку обозримым вызовом инструмента.
Начните путь в разработке приложений на базе ИИ с OpenAI API. Узнайте о функциональности, лежащей в основе популярных ИИ-приложений, таких как ChatGPT.
Здесь мы используем GPT-6 Sol, чтобы перенести Northstar Checkout, небольшой вымышленный Python‑сервис оформления заказов, с локального платежного адаптера v1 на v2.
Точнее, мы разберём, как:
Сделать первый вызов GPT-6 Sol API и прочитать его поля учёта использования
Определить контракт миграции до того, как модель увидит репозиторий
Выдать GPT-6 Sol ограниченные инструменты для работы с файлами и тестами и поэтапно открывать доступ с помощью
allowed_toolsИспользовать GPT-6 Luna для триажа и заставить GPT-6 Sol проверить короткий список
Вернуть структурированный план миграции и проверить его по файлам, уже прочитанным GPT-6 Sol
Запустить миграцию по WebSocket и управлять ею после начала правок
Повысить усилие рассуждений после провала независимой проверки деплоя
Посчитать зафиксированную стоимость по данным использования API
Что я понял по дороге
Четыре вывода изменили бы мой подход к следующей версии:
Что такое GPT-6 Sol?
GPT-6 Sol — средний уровень в семействе GPT-6 от OpenAI, идентификатор модели в API —
gpt-6-sol. Наш обзор уровней моделей GPT-6 описывает релиз и бенчмарки. В рекомендациях по GPT-6 OpenAI называет GPT-6 Astra старшей, GPT-6 Sol — средней, а GPT-6 Luna — самой дешёвой.GPT-6 Sol имеет контекстное окно 1 050 000 токенов и возвращает до 128 000 выходных токенов. Усилие рассуждений варьируется от
noneдоmaxи по умолчанию —medium. В Chat Completions вызов функций для GPT-6 Sol поддерживается только приnone, поэтому все запросы здесь используют Responses API.Цены и поддержка API определяют, как обвязка отправляет каждый запрос.
Сколько стоит GPT-6 Sol API?
GPT-6 Sol стоит $2 за миллион входных токенов и $10 за миллион выходных токенов для запросов до 272 000 входных токенов, согласно странице цен OpenAI. Кэшированный вход стоит $0.20 за миллион, запись в кэш — $2.50. Тарифы GPT-6 Luna для тех же четырёх категорий: $0.10, $0.01, $0.125 и $0.50.
Свыше 272 000 входных токенов весь запрос тарифицируется по двойной ставке на вход и кэш и по 1.5x на выход. В этом проекте ни один запрос не приблизился к этим порогам.
Какие возможности API используются в этом учебнике?
Обвязка — то есть Python‑код вокруг модели — использует такие настройки GPT-6:
Управление на середине хода (Mid-turn steering) обновляет ответ во время его генерации
configuration_updateменяет усилие рассуждений без перезаписи кэшированного префиксаallowed_toolsзадаёт подмножество доступных инструментов для запросаStructured Outputs определяет поля плана и отчёта
Все четыре настройки остаются в одной цепочке ответов Responses API.
Что мы построим с GPT-6 Sol API?
Мы создадим агента, который переведёт Northstar Checkout с Payments Adapter v1 на v2. Оба адаптера — локальные заглушки, написанные для эксперимента, а не настоящие платёжные SDK. Полный код, фикстуры и запись прогона — в этом репозитории GitHub.
В репозитории платёжный код смешан с несвязанными модулями, поэтому GPT-6 Sol должен сам найти затронутые файлы. Версия v2 ломает четыре контракта адаптера:
Создание платежа переносится с
client.charge(...)наclient.payments.create(...)Словари результатов становятся типизированными объектами с суммами типа
MoneyОтклонённые карты возвращают состояние вместо генерации исключения
Вебхуки меняют имена, конверт и заголовок подписи
Поиск и замена справится с переименованием метода. С поведенческими изменениями — нет.
Один цикл миграции, две модели GPT-6. Изображение автора.
GPT-6 Sol получает спецификацию, дерево файлов и ограниченные инструменты, которые поэтапно становятся доступными. Модель не знает, какие файлы требуют изменений, и не знает, что требования изменятся.
Почему эта миграция API сложная?
Две части спецификации — ловушки. Это не подложенные баги; они возникают из-за столкновения поведения v2 с существующим кодом:
Идемпотентность. v2 сравнивает параметры при повторном
request_id, но checkout на каждой попытке кладёт новыйorder_idв метаданные, поэтому наивный ретрай отклоняется вместо дедупликации.Итоги возвратов. Вебхук
payment.refundedв v2 сообщает накопленную сумму возврата, а старый обработчик суммирует каждое значение с помощью+=.Обе проблемы не ловятся типизацией. Их видно только при прогоне оформления и возвратов от начала до конца.
Изменения платежей затрагивают несколько модулей Northstar. Изображение автора.
Схема отделяет прямые импорты адаптера от модулей, зависящих от платёжного поведения. Эти косвенные связи — причина, по которой важен эталонный ответ для всего репозитория.
Как мы будем тестировать миграцию?
Итог решает отложенный набор приёмочных тестов, написанных до первого вызова модели. GPT-6 Sol их не видит; обвязка запускает их с pytest против мигрированной копии. Он проверяет, что:
Оформление проходит через v2, а ретрай с тем же ключом идемпотентности списывает один раз
Отклонённая карта по‑прежнему генерирует публичную ошибку
CheckoutDeclinedПолный возврат, два частичных возврата и повторная доставка вебхука оставляют корректные итоги
CheckoutClientсохраняет неизменными сигнатуры методовНе осталось ссылок на v1,
vendor/иMIGRATION.mdне затронуты, и видимые тесты проходятИсходный код уже проходит проверки на неизменность интерфейсов и защищённых файлов; оставшиеся проверки измеряют миграцию. Отдельный эталонный ответ перечисляет требуемые изменения, но читает его только обвязка.
Каталоги
acceptance/иprobes/находятся вне копии репозитория, открытой для обеих моделей. Эталон живёт подacceptance/, поэтому не может попасть во вход GPT-6 Luna, дерево файлов или инструменты репозитория.Ворота чтения могут вернуть пути из собственного плана GPT-6 Sol. Покрытие эталоном записывается только для оценки; оно никогда не отправляет отсутствующие пути из ground truth обратно в GPT-6 Sol.
После этого набора запускается проба деплоя. Ни одна из проверок не принимает сообщение модели «готово» как доказательство.
Как настроить GPT-6 Sol API в Python
Вам нужен Python 3.10 или новее и API‑ключ с доступом к обеим моделям. В требованиях есть дополнительный пакет
realtime, который нужен для steering:На macOS или Linux используйте
source .venv/bin/activateиcp .env.example .env, затем добавьтеOPENAI_API_KEY=...в.env.Если ключ уже работает с Responses API, пропустите следующий подраздел.
Сделайте первый вызов GPT-6 Sol API
Минимально полезный запрос подтверждает ключ, ID модели и поля учёта, нужные для раздела о стоимости:
В ответе указано усилие
medium, аusageвключаетcached_tokensиcache_write_tokens. Не используйтеtemperatureиtop_p— при усилии, отличном отnone, они приводят к 400.Первый запрос к GPT-6 Sol возвращает usage. Изображение автора.
С какого усилия рассуждений начинать?
Начинайте с
medium, значения по умолчанию, и держите настройку на уровне запроса неизменной весь прогон. Большинство шагов миграции — чтение и небольшие правки. Позже проба деплоя даст повод повысить усилие.Как добавить безопасные инструменты репозитория в кодирующего агента
Слой инструментов определяет права агента. GPT-6 Sol получает эти функциональные инструменты с
strict: true:list_filesиsearch_codeнаходят релевантный кодread_fileвозвращает один файл репозиторияedit_fileменяет одно точное вхождениеrun_testsзапускает разрешённую цель pytestСтрогие схемы проверяют форму аргументов, а не безопасность путей, поэтому границу записи обеспечивает Python:
Путь сначала нормализуется, поэтому
../и абсолютные пути не проходят.edit_fileзаменяет одно точное совпадение, аrun_testsпринимает только цели подtests/.Обвязка возвращает заблокированный вызов как вывод инструмента с префиксом
ERROR:, и цикл продолжается. Наш гид по инженерии обвязки агента объясняет, почему эти проверки должны быть в обвязке, а не в подсказке.Как протестировать границы файлов
Вызовите каждый инструмент с входными данными, которые он обязан отклонить:
Путь, содержащий
..Абсолютный путь
Запись под
vendor/Цель теста, содержащая shell‑команду
Ни один не должен пройти. Правка, совпадающая более чем с одним местом, должна запрашивать больше контекста, а хранение правил в пользовательских функциях собирает их в одном, легко тестируемом месте.
Как использовать GPT-6 Luna для триажа репозитория
Триаж репозитория — узкая задача классификации: оценить релевантность каждого файла и процитировать ссылки на v1. GPT-6 Luna получает эту задачу и только её, и запускается первой, до того как GPT-6 Sol что-либо ищет.
Вход — это спецификация плюс каждый Python‑файл под
northstar/иtests/. Всё с рейтингомhighилиmediumпопадает в короткий список, который GPT-6 Sol получит дальше.Как проверить короткий список GPT-6 Luna
Сверьте короткий список с эталоном из предыдущего раздела и сначала посмотрите на полноту. GPT-6 Luna удержала каждый затронутый файл и добавила несколько лишних.
GPT-6 Luna сужает 56 до 16. Изображение автора.
Короткий список — это подсказка, а не граница.
Как использовать
allowed_toolsдля поэтапных разрешенийallowed_tools— это режимtool_choice, который ограничивает, какие инструменты модель может вызвать, при этом полный список инструментов остаётся на месте. Так первый проход GPT-6 Sol остаётся только для чтения: полный список задаётся в каждом запросе, но доступны только листинг и поиск.Изменение поля
toolsмежду фазами перезапишет кэшированный префикс. Гид по вызову функций рекомендуетallowed_tools, когда меняется только множество вызываемых инструментов.Зачем запускать кодирующего агента в режиме «только чтение»?
Проход «только чтение» разделяет диагностику и действие. GPT-6 Sol получил короткий список от GPT-6 Luna с прямым предупреждением, что он может быть неверным, и его поиски импортов v1, вызовов charge и имён вебхуков сами по себе выявили каждый затронутый файл.
Он также вышел за пределы списка, отметив модели заказов, хранилище заказов, сериализаторы и выгрузку в бухгалтерскую книгу как нижестоящие зависимости для проверки. В итоге правок там не потребовалось, но прочитать их — единственный способ это выяснить. Я бы сохранял
allowed_toolsдля любого агента, который редактирует файлы.Как использовать Structured Outputs для плана миграции
План миграции — момент, когда агент фиксирует конкретные файлы до получения прав записи. На этапе планирования добавляется
read_file, а сам план возвращается через Structured Outputs при отключённых инструментах:План охватил все требуемые изменения и предупредил, что новый идентификатор заказа изменит метаданные v2 при ретрае. Это предупреждение вернётся позже.
Как проверить структурированный план миграции
Перед выдачей прав записи обвязка проверяет структуру плана, доказательства и покрытие.
Три проверки тестируют один план миграции. Изображение автора.
План прошёл все ворота. Он также предложил переименовать публичный параметр в
client.pyпод стиль v2, как рекомендовал раздел чистки в спецификации. Это предложение стало тестом для steering.Как построить кодирующего агента GPT-6 Sol на Responses API
Кодирующий агент GPT-6 Sol работает в петле инструментов: ждёт ответ, выполняет его вызовы функций и возвращает выходы. Наш гид по OpenAI Responses API объясняет формат запросов и результатов инструментов. Эта миграция держит цикл на одном WebSocket‑подключении, потому что steering этого требует.
baseфиксирует модель, инструкции, инструменты и усилиеmediumдля кэширования подсказок. GPT-6 Sol запускал видимые тесты по ходу работы, но также написал большинство новых тестов, поэтому они не могут служить независимой проверкой.Как работает управление на середине хода (steering) в GPT-6 Sol?
Mid-turn steering добавляет инструкцию к ответу, который всё ещё генерируется, без его отмены. После
response.createdвы отправляетеresponse.steerпо тому же соединению с ID этого ответа, и сервер применяет инструкцию в ответе‑преемнике.Новое требование пришло от команды витрины: сигнатуры
CheckoutClient«должны остаться ровно такими, как сегодня», потому что их вызывает другой сервис. Я не хотел привязывать это к таймеру, поэтому обвязка следит за репозиторием. После каждого пакета вызовов инструментов она сравнивает публичные сигнатуры на диске с оригиналами, и первое расхождение приводит к отправке steer:Это гарантирует, что steer приземлится после противоречащего ему переименования — именно такую ситуацию и стоит тестировать. Отправленный раньше — это просто более длинная подсказка.
Сервер затем сообщил жизненный цикл steering:
response.steer.acceptedозначает, что обновление поставлено в очередь, а не примененоresponse.incompleteзавершил исходный ответ по причинеsteeredОтвет‑преемник
response.createdпродолжил работу с новым требованиемЕсли ответ ждёт результата инструмента, сервер отправит
response.steer.pendingи придержит steer, пока обвязка не вернёт его. Продолжайте отвечать на вызовы инструментов, пока steer в ожидании.Что остаётся неизменным при steering?
Steering меняет то, что модель сделает дальше. Гид OpenAI прямо говорит об остальном: steer не переписывает уже отправленный вывод, не отменяет ранние действия и не останавливает уже начатые инструменты.
Когда пришёл steer, переименование уже было на диске в
client.py. GPT-6 Sol его откатил, а отложенная проверка сигнатур позже подтвердила окончательный интерфейс.Правку можно откатить. Инструмент, уже обратившийся к внешней системе, может не оставить, что откатывать, поэтому записывайте состояние репозитория при каждом приходе steer.
Может ли GPT-6 Sol мигрировать кодовую базу на Python?
В этом репозитории — да, хотя и не за один проход. Первая миграция выполнила исходный контракт, затем проба деплоя выявила пропущенный случай.
Что показали отложенные тесты?
Когда GPT-6 Sol сообщил о завершении миграции, отложенный набор прошёл без этапа исправлений. Для возвратов GPT-6 Sol заменил суммирование на накопительное чтение, которое также игнорирует вебхуки вне порядка:
Для идемпотентности GPT-6 Sol сохранил свежий
order_idна каждую попытку и добавил кэш запросов в хранилище заказов, который отвечает на повторные запросы до того, как они попадут в v2. Этот кэш живёт в памяти процесса, что скоро станет важным.Могут ли Structured Outputs быть неверными?
Да. Первый отчёт назвал обновлённый тест вебхука регрессией и не упомянул риск ретраев между серверами, хотя план эту ловушку называл.
Structured Outputs валидирует схему, а не утверждения. Сверяйте поля отчёта с записанными доказательствами и не считайте пустой список рисков доказательством их отсутствия.
Что пропустили приёмочные тесты?
Набор пропустил ретрай, направленный на другой экземпляр приложения. Я добавил пробу деплоя с двумя клиентами, которые делят один платёжный процессор, но не память процессов.
Проба провалилась. Ретрай на втором экземпляре сгенерировал
payments_adapter_v2.IdempotencyConflict— исключение адаптера, которое витрина не должна видеть.Такой сбой проявляется только в деплое с более чем одним процессом и служит триггером для повышения усилия рассуждений.
Как менять усилие рассуждений в ходе разговора
Элемент входа
configuration_updateменяет усилие рассуждений для следующего ответа и всех последующих, пока не придёт новое обновление. Усилие на уровне запроса остаётся прежним, поэтому кэшированный префикс сохраняется. Когда проба провалилась, обвязка отправила этот запрос, следуя гайду по рассуждениям:Запросы миграции используют
store=True, поэтому после закрытия WebSocket обвязка может продолжить сохранённую цепочку ответов обычным запросом к Responses API.GPT-6 Sol получает информацию о сбое и схему деплоя, но без намёка на исправление.
DIAGNOSE_TOOLSразрешает чтение и тестирование, но не правки. Сохранение инструментов иtext.formatнеизменными сохраняет кэшированный префикс.Одна особенность API неудобна:
response.reasoning.effortпосле обновления всё ещё показывает настройку на уровне запроса. Обвязка не может прочитать активное усилие из ответа, поэтому сама его записывает при отправке обновления и помечает им все последующие ответы.Сработало ли исправление при усилии
high?Да. GPT-6 Sol отследил сбой до локального хранилища второго сервера, затем проследил свежий ID заказа в метаданные платежа. Общий процессор увидел разные параметры для одного и того же
request_id.Исправление сделало идентификатор заказа функцией идентификатора запроса, чтобы каждый сервер вычислял один и тот же:
GPT-6 Sol также добавил видимый тест на этот случай. Проба и приёмочный набор прошли, затем
configuration_updateвернул усилие кmedium. На этот раз финальный отчёт корректно описал реальный сбой.Приложение Streamlit проекта воспроизводит сохранённый прогон без API‑вызовов. Видеозапись идёт от обзора к событиям steering, затем к результатам приёмочных тестов и пробы.