1. Установка и ключ
Работайте в виртуальном окружении и храните ключ в переменных окружения процесса, а не в коде. Для локальной разработки добавьте файл .env в .gitignore и читайте его через python-dotenv — так ключ не попадёт в репозиторий.
python -m venv .venv
source .venv/bin/activate
python -m pip install openai python-dotenv
export NORMAHUB_API_KEY="ваш_api_ключ"Создайте API-ключ в личном кабинете NormaHub. Скопируйте значение сразу: повторно оно не показывается. Для скриптов и агентов заводите отдельные ключи с лимитом расходов — тогда утечка одного ключа не опустошит общий баланс.
2. Первый запрос
Клиент OpenAI SDK совместим с NormaHub полностью: меняется только base_url и ключ. Модель указывайте точным ID из актуального каталога, а длину ответа ограничивайте max_tokens, чтобы контролировать стоимость каждого вызова.
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["NORMAHUB_API_KEY"],
base_url="https://api.normahub.cc/v1",
)
response = client.chat.completions.create(
model="gpt-5.6-sol",
messages=[{"role": "user", "content": "Привет"}],
max_tokens=512,
)
print(response.choices[0].message.content)Проверьте ответ глазами и зафиксируйте фактическую модель и usage. Если SDK возвращает ошибку, не гадайте по тексту сообщения — смотрите HTTP-статус: разбор всех кодов собран в гайде по ошибкам API.
3. Streaming ответов
Для чатов и агентов показывайте ответ по мере генерации: пользователь видит первые слова через доли секунды, а не ждёт весь ответ. Поток гарантированно работает только через Responses API — для /v1/chat/completions и /v1/messages отправляйте stream: false.
stream = client.responses.stream(
model="gpt-5.6-sol",
input="Объясни коротко",
)
for event in stream:
print(event, flush=True)При обрыве соединения сохраняйте уже полученный префикс и решайте отдельно, считать ли операцию завершённой — сервер мог успеть закончить работу. Перед включением сверьтесь с возможностями модели в каталоге.
4. Обработка ошибок
Делите ошибки на постоянные и временные. Постоянные — 400 (неверный запрос), 401 (ключ), 402 (баланс), 403 (модель недоступна ключу): их повтор не лечит, исправляйте причину. Временные — 429 и 5xx: их повторяйте с задержкой и верхним пределом попыток, сохраняя X-Request-Id для поддержки.
from openai import APIError, AuthenticationError, RateLimitError
try:
response = client.chat.completions.create(
model="gpt-5.6-sol",
messages=[{"role": "user", "content": "Привет"}],
timeout=30,
)
except AuthenticationError:
print("401: проверьте ключ NORMAHUB_API_KEY — он неверен или отозван")
except RateLimitError:
print("429: превышен лимит ключа, подождите и повторите позже")
except APIError as e:
print(f"HTTP {e.status_code}: смотрите разбор ошибок API")Задавайте timeout каждому запросу (по умолчанию SDK может ждать долго) и не повторяйте неидемпотентные операции без проверки состояния. Полный разбор кодов, retry-политик и дедлайнов — в гайде по ошибкам.
5. Контроль стоимости
Каждый запрос стоит input + output по тарифу модели. Дороже всего обходятся длинные истории диалога (контекст пересылается целиком) и неограниченный max_tokens. Режьте контекст до необходимого, кэшируйте системные инструкции и считайте стоимость полной операции, а не одного вызова.
Формула и примеры расчёта — в гайде по стоимости токенов, финальная сумма каждого запроса — в истории личного кабинета. При возникновении ошибок проверяйте баланс и доступные модели в личном кабинете.