Если в продакшене у вас работает интеграция с OpenAI и вы прикидываете трудоёмкость переезда на Claude, честный ответ такой: меньше, чем кажется. Большинству команд хватает одной строки с новым base_url и одной строки с новым именем модели. Остальное это оценка качества, а не инженерия.
Перед вами плейбук, по которому мы помогаем командам уходить с gpt-4o или gpt-4.1 на Claude Sonnet 5 через OpenAI-совместимый шлюз codexkey. В нём разобрано, зачем переезжать, что меняется в коде, где прячутся тонкие отличия в промптах и как безопасно прогнать A/B до финального переключения.
Зачем переезжать
Три причины повторяются почти в каждой реальной миграции:
- Экономика длинного контекста. Кэширование промптов в Claude и цена за длинный вход обычно выигрывают в агентских циклах, RAG по большим документам и ассистентах для кода, которые на каждом шаге заново шлют один и тот же системный промпт. Когда средний контекст переваливает за ~20K токенов и заметная часть повторяется, Sonnet с кэшем трудно обойти по цене за полезный ответ. (Расчёт по токенам смотрите в нашем разборе цен.)
- Качество кода и tool use. На реальных задачах по коду и в длинных многошаговых цепочках с инструментами Sonnet 5 держится стабильно сильно. Если ваш продукт это code-агент, пайплайн извлечения структурированных данных или что-то с цепочкой tool calls, разница проявляется как меньше ретраев и меньше передач человеку.
- Окупаемость кэширования промптов. Это самый мощный рычаг по стоимости, и большинство команд находят его уже после переезда. Стабильный системный промпт и стабильная схема инструментов в кэше срезают 80-90% input-стоимости на горячих путях. У OpenAI свой кэш тоже есть, но явные маркеры кэша у Claude проще понять и настроить.
Это не значит, что OpenAI плох. Просто Claude стал разумным выбором по умолчанию для заметной части нагрузок, а переезд стоит так мало, что правильный подход обычно звучит так: «попробуй обоих и выбери победителя под каждую задачу».
Переезд почти без правок кода
codexkey отдаёт OpenAI-совместимый эндпоинт: https://api.codexkey.ru/v1. Если код уже работает через OpenAI SDK, менять нужно только конфигурацию:
- Укажите в
base_urlадресhttps://api.codexkey.ru/v1. - Замените
OPENAI_API_KEYна ключ codexkey. - Поменяйте имя модели с
gpt-4o(или что у вас стоит) наclaude-sonnet-5.
На этом всё. Стриминг, function calling, JSON mode, vision и форма запроса chat completions работают. Примерно 90% возможностей OpenAI SDK проходят без изменений. Остальные 10% и есть причина дочитать статью до конца.
Diff для Python
from openai import OpenAI
client = OpenAI(
- api_key=os.environ["OPENAI_API_KEY"],
+ api_key=os.environ["CODEXKEY_API_KEY"],
+ base_url="https://api.codexkey.ru/v1",
)
response = client.chat.completions.create(
- model="gpt-4o",
+ model="claude-sonnet-5",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": user_input},
],
max_tokens=1024,
)
Diff для TypeScript
import OpenAI from "openai";
const client = new OpenAI({
- apiKey: process.env.OPENAI_API_KEY,
+ apiKey: process.env.CODEXKEY_API_KEY,
+ baseURL: "https://api.codexkey.ru/v1",
});
const response = await client.chat.completions.create({
- model: "gpt-4o",
+ model: "claude-sonnet-5",
messages: [
{ role: "system", content: SYSTEM_PROMPT },
{ role: "user", content: userInput },
],
max_tokens: 1024,
});
Вот и все правки в коде. Дальше сборка, деплой и прогон evals.
Что на самом деле меняется под капотом
На проводе формат выглядит одинаково, но по ту сторону сидит не GPT. Несколько поведений сдвигаются, и именно их игнорирование чаще всего делает «drop-in миграцию» хуже, чем она должна быть, уже в первый день.
Стиль промпта: Claude ценит структуру
GPT-модели спокойно переносят рыхлые разговорные системные промпты. Claude награждает за структуру. Если ваш системный промпт выглядит как стена императивных предложений, оберните секции в XML-теги, и качество обычно вырастает на 5-15%:
<role>Ты старший backend-инженер, ревьюишь pull request.</role>
<rules>
- Отклоняй любые изменения без тестов.
- Отмечай отсутствие обработки ошибок.
</rules>
<output_format>
Верни JSON с полями: verdict, reasons[], suggested_fixes[].
</output_format>
Claude воспринимает такие теги как мягкую схему и следует им надёжнее, чем свободным заголовкам. Делать это необязательно, но если вы сравниваете качество с GPT, сделайте это до того, как делать выводы.
Сообщения с ролью system
Оба API принимают сообщение с ролью system. В режиме OpenAI-совместимости codexkey корректно переносит его в верхнеуровневый параметр system у Claude, поэтому рефакторинг не нужен. Есть тонкое отличие: Claude строже игнорирует инструкции, противоречащие системному сообщению. Обычно это то, что нужно, но если ваше приложение рассчитывает, что пользователь посреди диалога переопределит системную персону, проверьте этот сценарий отдельно.
Структурированный вывод: response_format и JSON
response_format={"type": "json_object"} работает, и response_format={"type": "json_schema", "json_schema": {...}} тоже. Второй вариант шлюз реализует так: принудительно запускает ход tool_use на синтетическом инструменте, чья input-схема совпадает с вашей JSON-схемой, а затем разворачивает результат. Гарантии те же, что у structured outputs OpenAI, с одним нюансом: ошибки валидации приходят как несоответствие tool use, а не как отказ модели, и отлаживать такое обычно проще.
Function calling
Массив tools с записями function в формате OpenAI без проблем превращается в блоки tool_use у Claude. Работают оба направления: модель вызывает инструмент, а вы возвращаете сообщение с ролью tool и результатом. Код править не нужно. Если function calling у вас на OpenAI уже в проде, ждите нулевой diff.
Стриминг
Server-sent events с чанками choices[].delta.content приходят в том же виде. Фронтенд, который рисует стримы OpenAI, нарисует и стримы Claude. Менять ничего не надо.
Токены и max_tokens
У Claude другой токенизатор, поэтому промпт в 1 200 токенов OpenAI может превратиться в 1 350 токенов Claude, а может и наоборот. Не зашивайте в код соотношение «символы → токены». Если у вас есть защита по окну контекста, пересчитайте её на новой модели, прежде чем поднимать алерты.
Проверьте качество до переключения
Не переезжайте одним деплоем. Рабочая схема такая:
- Неделю зеркальте трафик. Отправляйте каждый продовый запрос обоим провайдерам и логируйте ответы. Ответ Claude пользователям пока не показывайте.
- Сравните офлайн. Прогоните evals (золотые задачи, LLM-as-judge, выборочная проверка человеком) по парам ответов. Считайте победы, ничьи, регрессии и стоимость запроса.
- Shadow, затем canary. Когда Claude выигрывает или не уступает по вашим метрикам, направьте на него 5% живого трафика, потом 25%, потом 100%. Путь на OpenAI держите прогретым ещё минимум две недели после полного перехода.
Почти у каждой команды находится хотя бы одна задача, где GPT всё ещё лучше: скажем, промпт извлечения, который месяцами тюнили под GPT-4o. Это нормально. Маршрутизируйте по задачам, а не по компании.
Фолбэк на случай сбоя
Даже после полного перехода держите запасной путь. Безопасный шаблон:
def chat(messages):
try:
return claude_client.chat.completions.create(
model="claude-sonnet-5",
messages=messages,
timeout=20,
)
except (TimeoutError, APIError):
return openai_client.chat.completions.create(
model="gpt-4o",
messages=messages,
)
В штатном режиме фолбэк почти не срабатывает, зато напоминает о риске единственного провайдера и даёт команде эксплуатации один рубильник на случай проблем.
Итог
Правка кода занимает пять минут: один base_url, одно имя модели, один API-ключ. Неделя уходит на evals, шлифовку промптов и включение кэширования. Переезд можно делать хоть в пятницу днём, а оценку качества проводите в рабочее время.