Техническое руководство
Версии контракта OpenAI-совместимого API: как обновлять клиент без скрытой поломки
Версии контракта OpenAI-совместимого API помогают команде отличить проверенное изменение своего адаптера от предположения, что любой похожий endpoint ведёт себя одинаково. Полезная версия описывает запрос, ответ, ошибки и границы именно вашего поддерживаемого сценария. Она не превращает RussiaAPI в официальный сервис разработчика модели и не гарантирует неизменность каталога, цены, лимита или дополнительных функций.
RUSSIAAPI_API_KEY; не передавайте внешние ключи, cookie, пароли, коды подтверждения или лишние персональные данные.Версия — это договорённость вашего приложения
Не начинайте с номера в URL, если вы ещё не описали, что меняется. Карточка контракта должна содержать базовый URL, зафиксированную версию SDK, разрешённый model ID, обязательные поля, нормализованные ошибки и ожидаемое действие клиента. Например, добавление необязательного telemetry-поля может быть совместимо, а изменение типа поля или правила обработки tool call — уже отдельный риск.
Разделите внешний контракт gateway и внутренний контракт вашего backend. Даже если запрос имеет знакомую форму, вы не обязаны передавать на клиент все upstream-поля. Стабильный собственный response DTO, allowlist полей и понятные прикладные коды снижают связанность. Перед изменением проверяйте текущий каталог и права конкретного проекта, потому что похожее имя модели не доказывает тот же набор функций.
Соберите матрицу совместимости
Для каждого клиента выпишите: старый адаптер, новый адаптер, обязательные поля, допустимые дополнительные поля и поведение при неизвестном поле. Отдельно обозначьте функции вне scope — streaming, tool calls, JSON Schema, изображения или асинхронные задачи. Эта матрица даёт разработчику честный ответ «не поддерживается в этом выпуске» вместо опасной попытки угадать совместимость в production.
Проверяйте вход и выход локальной схемой. Модельный текст, идентификаторы или порядок необязательных полей не должны быть единственным критерием теста. На интеграционном уровне достаточно небольшого обезличенного запроса и измеримых утверждений: HTTP-класс, наличие ожидаемого поля, нормализованный error code и отсутствие секрета в логах. Более широкий подход к проверке описан в контрактных тестах.
Делайте изменения аддитивными и наблюдаемыми
Самая безопасная последовательность: сначала backend умеет читать старый и новый допустимый вариант, затем небольшая доля контролируемого трафика использует новый путь, потом измеряется результат. Feature flag должен иметь владельца, дату пересмотра, критерий включения и простой rollback. Не связывайте rollout с обещанием лучшего качества модели или постоянной доступности: это гипотеза, которую проверяет ваша метрика.
Если изменение влияет на цену, очередь или хранение, интерфейс и документация должны сообщать об этом до запуска сценария. Сравнивайте стоимость успешной операции, долю безопасно обработанных ошибок и длительность, а не только HTTP 200. При обнаружении несовместимости отключите флаг, сохраните минимальный диагностический контекст и исправьте адаптер. Молчаливая подмена маршрута усложнит инцидент и аудит.
Пример совместимого нормализатора
Пример Node.js 18+ ниже показывает слой приложения, который принимает только ожидаемую форму ответа и возвращает стабильный результат клиенту. Он не утверждает, что конкретный модельный endpoint поддерживает все поля из примера. До реального вызова подтвердите свою модель и маршрут в каталоге, а в тестах подставляйте фикстуры без персональных данных и настоящих ключей.
export function normalizeCompletion(payload) {
const message = payload?.choices?.[0]?.message;
if (!message || typeof message.content !== 'string') {
return { ok: false, error: 'contract_mismatch' };
}
const finish = payload.choices[0].finish_reason;
if (finish !== null && typeof finish !== 'string') {
return { ok: false, error: 'invalid_finish_reason' };
}
return {
ok: true,
data: { text: message.content, finishReason: finish ?? 'unknown' }
};
}Синтаксис примера проверяется через node --check. Добавьте тесты для пустого choices, неизвестного finish reason и ответа с лишним полем. Так изменение не пройдёт только потому, что одна счастливая ветка вернула текст.
Отдельно планируйте rollback
Rollback — это не «вернём старый package.json когда-нибудь». Подготовьте возможность вернуть старый адаптер, переключатель маршрута и минимальный набор метрик до запуска. Для асинхронных задач определите, какая версия читает уже созданные operation ID; нельзя посылать одну и ту же дорогую задачу повторно лишь потому, что версия клиента изменилась.
После релиза сохраните короткий журнал решения: что изменилось, какая выборка была проверена, какие ошибки наблюдались и почему флаг оставлен включённым. Это даёт будущей команде проверяемую историю без хранения prompts, токенов доступа и чужих внутренних деталей. Для обновления SDK с проверкой базы и модели используйте также план миграции.
Минимальный операционный контур
Для любого сценария заранее определите владельца операции, внутренний идентификатор, допустимый срок ожидания и событие, после которого результат считается подтверждённым. В журнале достаточно хранить время, статус, безопасный request ID, тип операции и версию вашего адаптера. Полный prompt, ответ пользователя, заголовок Authorization и временные ссылки не нужны для базовой диагностики и часто создают лишний риск.
Проверяйте изменения на обезличенном тестовом наборе и с отдельным собственным ключом, ограниченным бюджетом и правами. Нельзя по единичному удачному вызову делать вывод, что все модели, параметры, цены или возможности доступны постоянно. Перед расширением трафика сверяйте текущий каталог, права проекта, условия обработки данных и фактические сигналы своего приложения.
Ошибки 400, 401, 403, 429, timeout и 5xx требуют разных действий. Не скрывайте их бесконечным retry, не меняйте модель молча и не используйте интеграцию для обхода законов, санкций, региональных или платформенных ограничений. Если состояние операции после timeout неизвестно, сначала проверьте своё внутреннее хранилище, а затем выполняйте только явно разрешённый и ограниченный шаг.
Проверьте сценарий в RussiaAPI
Создайте собственный тестовый ключ в консоли, сверьте текущий каталог моделей и выполните обезличенный server-side smoke test. Расширяйте нагрузку и доступ только после измеримой проверки.
FAQ
Нужно ли менять URL при каждом изменении контракта?
Нет. Сначала определите масштаб изменения и совместимость. Многие изменения безопаснее оформить внутренним адаптером и feature flag. Новый публичный путь нужен, когда старый клиент больше не может корректно понять обязательные поля или семантику.
Совместимый формат гарантирует поддержку всех параметров SDK?
Нет. Совместимость относится к документированному и проверенному сценарию. Модель, параметр, streaming, инструменты, цены и лимиты нужно подтверждать отдельно по текущему каталогу, документации и собственным тестам.
Что хранить после rollout?
Храните версию адаптера, безопасные агрегированные метрики, решение о включении флага и минимальный request ID для диагностики. Не добавляйте в журнал Authorization, полный prompt, ответы с личными данными или секреты из окружения.