NormaHub knowledge base

OpenAI SDK через NormaHub

Сохраните интерфейс привычного клиента: меняются base URL, ключ и model ID. Маршруты, таймауты, повторы и безопасность — ниже.

1. Три параметра переезда

Совместимость означает совпадение формата API, а не поведения всех моделей. Поэтому переезд — это замена трёх значений с проверкой, а не слепая подмена адреса. Начните с короткого текстового запроса без tools и большого контекста и зафиксируйте статус, фактическую модель и X-Request-Id.

base_url: https://api.normahub.cc/v1
api_key:  YOUR_API_KEY          # из личного кабинета, только сервер
model:    MODEL_ID              # точный ID из каталога или /v1/models

Model ID берите из актуального каталога или ответом GET /v1/models вашим ключом. ID из чужих README могли переименовать, отключить или закрыть для вашего ключа — каталог не чинится промптом.

2. Выбор маршрута

Один base_url обслуживает несколько маршрутов, но доступность каждого определяет выбранная модель. Chat Completions — маршрут диалогов с messages. Responses API — отдельный маршрут с input, доступный там, где заявлен. Anthropic-совместимые клиенты используют маршрут /v1/messages — его выбирайте по формату клиента, а не по названию модели.

from openai import OpenAI

client = OpenAI(
    api_key="YOUR_API_KEY",
    base_url="https://api.normahub.cc/v1",
)

# Chat Completions — классический маршрут диалогов
chat = client.chat.completions.create(
    model="MODEL_ID",
    messages=[{"role": "user", "content": "Привет"}],
)

# Responses API — там, где его заявляет модель
resp = client.responses.create(
    model="MODEL_ID",
    input="Привет",
)

Не смешивайте протоколы вслепую: наличие Claude или GPT в каталоге не означает, что любая модель принимает tools, streaming или одинаковую структуру ответа. Проверяйте endpoint и capabilities каждой модели перед переключением — детали в документации API.

3. Таймауты и повторы

Производственный клиент отличается от примера из README двумя вещами: у каждого запроса есть timeout, а повторы ограничены. SDK сам повторяет временные 429 и 5xx, но число попыток и дедлайн операции задаёте вы. Интерактивному UI чаще лучше быстро показать понятный отказ, чем держать пользователя в очереди повторов.

from openai import OpenAI

client = OpenAI(
    api_key="YOUR_API_KEY",
    base_url="https://api.normahub.cc/v1",
    timeout=30.0,       # секунд на запрос вместо бесконечного ожидания
    max_retries=2,      # повторы только временных сбоев делает SDK
)

response = client.chat.completions.create(
    model="MODEL_ID",
    messages=[{"role": "user", "content": "Привет"}],
    max_tokens=512,     # ограничивает и ответ, и счёт
)

Если соединение оборвалось после отправки запроса, результат неизвестен: upstream мог уже обработать операцию. Не повторяйте неидемпотентные действия без собственного ключа идемпотентности. Полные правила — в гайде по ошибкам.

4. SDK помимо OpenAI

Тот же base_url работает с любым OpenAI-совместимым клиентом: LangChain, LiteLLM, Cline и CLI-агенты принимают адрес и ключ в своей конфигурации. Правило одно для всех: ключ на сервере или в переменных окружения процесса, model ID из каталога, первый запрос — маленький. Примеры для конкретных инструментов — в гайде OpenCode и гайде Claude.

5. Безопасность

Вызывайте NormaHub с backend или из локального AI-агента. Не передавайте секретный ключ в браузерный JavaScript, мобильный bundle, публичные логи, CI-артефакты и docker history. Разделяйте ключи по окружениям и интеграциям с собственными лимитами: отзыв одного секрета не должен останавливать весь продукт. Создать и отозвать ключи можно в личном кабинете.

Частые вопросы

Что именно менять при переезде с прямого OpenAI?

Три строки: base_url на https://api.normahub.cc/v1, api_key на ключ NormaHub и model на ID из актуального каталога. Логика, SDK и структура запросов остаются без изменений.

Chat Completions или Responses API?

Chat Completions — универсальный маршрут диалогов. Responses API используйте там, где его заявляет выбранная модель в каталоге. Маршрут проверяйте до переключения: не каждая модель поддерживает каждый endpoint, tools и streaming.

Почему SDK сам повторяет не все ошибки?

SDK повторяет только временные сбои (429, 5xx). Ошибки 400, 401, 402, 403 и 413 требуют исправления запроса, ключа, баланса или размера payload — их повторять бессмысленно.

Как не светить ключ в логах?

Вызывайте API только с backend или локального агента, не кладите ключ в NEXT_PUBLIC_/VITE_-переменные и query string. В логи пишите время, endpoint, модель, статус и X-Request-Id — этого достаточно для диагностики.