Содержание статьи+
Оба API решают одну задачу, но устроены по-разному. Если просто заменить base_url в OpenAI SDK на Anthropic-совместимый endpoint, код сломается. Ниже — семь отличий, на которых чаще всего спотыкаются при миграции.
1. Системный промпт
В OpenAI system — это сообщение в массиве messages. В Anthropic system — отдельное поле верхнего уровня, а messages содержат только user и assistant. Если отправить system внутри messages, Anthropic вернёт ошибку.
# OpenAI
messages = [
{"role": "system", "content": "Ты — редактор."},
{"role": "user", "content": "Проверь текст."},
]# Anthropic
system = "Ты — редактор."
messages = [
{"role": "user", "content": "Проверь текст."},
]2. max_tokens обязателен
У Anthropic параметр max_tokens обязателен. Если его нет, запрос не пройдёт. У OpenAI он опционален, и многие клиенты его не передают. При миграции добавьте явное ограничение — это ещё и защита от неожиданно длинного ответа.
3. Content blocks
Anthropic возвращает content как массив блоков: [{type: "text", text: "..."}]. OpenAI — строку в message.content. Если ваш код делает response.content[0].text, он не заработает с OpenAI; если обращается к строке — не заработает с Anthropic.
def extract_text(response) -> str:
content = response.content
if isinstance(content, str):
return content
return "".join(
block.text for block in content if block.type == "text"
)4. Tool use
OpenAI описывает функции как {type: "function", function: {...}} и возвращает tool_calls. Anthropic использует input_schema и блоки tool_use. Схемы похожи, но обёртки разные. Универсального формата нет — нужен адаптер или отдельные ветки кода.
5. Стриминг
OpenAI присылает choices[0].delta.content. Anthropic — события content_block_delta с delta.text, а также отдельные события начала и конца блока. Если вы парсите SSE вручную, придётся учитывать типы событий. SDK это скрывают, но не все клиенты используют SDK.
6. Заголовки и версия
OpenAI: Authorization: Bearer. Anthropic: x-api-key и anthropic-version. CheApi принимает оба варианта авторизации, но версию Anthropic лучше передавать явно — 2023-06-01. Тогда поведение не изменится при обновлении upstream.
7. Ошибки
OpenAI возвращает {error: {message, type, code}}. Anthropic — {type: "error", error: {type, message}}. Коды HTTP совпадают, а структура нет. Если у вас есть обработчик ошибок, проверьте, что он понимает оба формата.
def error_message(payload):
if "error" in payload and isinstance(payload["error"], dict):
return payload["error"].get("message", "Unknown error")
return payload.get("message", "Unknown error")Что делать, если нужны обе модели
Есть три пути. Первый — использовать два SDK и нормализовать ответы. Второй — взять фреймворк вроде LangChain, который скрывает различия. Третий — ходить через один OpenAI-совместимый слой, если он поддерживает нужные модели.
CheApi поддерживает оба диалекта: /v1/chat/completions и /v1/responses для OpenAI, /v1/messages для Anthropic. Можно оставить существующие SDK и переключать модели одной строкой, не переписывая приложение.
Чек-лист миграции
- Вынесите системный промпт в отдельное поле для Anthropic.
- Добавьте max_tokens везде, где его не было.
- Нормализуйте извлечение текста из ответа.
- Проверьте формат tool_use и tool_result.
- Обновите парсер SSE, если он самодельный.
- Добавьте обработку обоих форматов ошибок.
- Прогоните 20 реальных задач и сравните не только ответы, но и стоимость.
Попробовать
5 млн токенов на тесты
Зарегистрируйтесь, получите ключ и проверьте модели на своих задачах. Карта не нужна.