# OpenAI SDK

Используйте официальные SDK OpenAI для Python и Node.js с Nodul Router, включая поля, которые есть только в роутере.

Роутер поддерживает OpenAI Chat Completions API: укажите в официальном SDK его base URL и используйте ключ Router.

## Установка

```bash
pip install openai
```

```bash
npm install openai
```

## Настройка клиента

```python
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://router.nodul.ru/api/v1",
    api_key=os.environ["NODUL_ROUTER_API_KEY"],
)
```

```js
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://router.nodul.ru/api/v1",
  apiKey: process.env.NODUL_ROUTER_API_KEY,
});
```

Многие библиотеки на основе SDK читают те же настройки из окружения: `OPENAI_BASE_URL=https://router.nodul.ru/api/v1` и `OPENAI_API_KEY=$NODUL_ROUTER_API_KEY`.

## Поля роутера

`provider`, `models` и другие поля, которых нет в типах OpenAI, в Python передаются в `extra_body`, а в Node.js добавляются в объект запроса.

```python
completion = client.chat.completions.create(
    model="openai/gpt-4o-mini",
    messages=[{"role": "user", "content": "Hello"}],
    max_tokens=200,
    extra_body={
        "models": ["google/gemma-3-4b-it"],
        "provider": {"zdr": True},
    },
)
print(completion.choices[0].message.content)
print("cost, PnP:", completion.usage.cost)
```

```js
const completion = await client.chat.completions.create({
  model: "openai/gpt-4o-mini",
  messages: [{ role: "user", content: "Hello" }],
  max_tokens: 200,
  // @ts-expect-error: router fields, not part of the OpenAI types
  models: ["google/gemma-3-4b-it"],
  provider: { zdr: true },
});
console.log(completion.choices[0].message.content);
```

`usage.cost` тоже нет в типах SDK: в Python это все равно атрибут `usage`, а в TypeScript читайте его как `(completion.usage as any).cost`.

## Потоковая передача

```python
stream = client.chat.completions.create(
    model="google/gemma-3-4b-it",
    messages=[{"role": "user", "content": "Write a haiku."}],
    stream=True,
)
for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)
```

```js
const stream = await client.chat.completions.create({
  model: "google/gemma-3-4b-it",
  messages: [{ role: "user", content: "Write a haiku." }],
  stream: true,
});
for await (const chunk of stream) process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
```

## Ошибки и повторные запросы

SDK выбрасывает `openai.APIStatusError` (Python) или `OpenAI.APIError` (Node.js) со `status` и сообщением роутера. По умолчанию SDK дважды повторяет `408`, `409`, `429` и `5xx`; чтобы это изменить, задайте `max_retries` / `maxRetries`. Помните: каждый повтор `POST` — это новый запрос, который оплачивается отдельно. Подробнее — в разделе [Ошибки](/docs/ru/errors).

## Что не поддерживается

Доступны только chat completions: Responses API, эмбеддинги, изображения, аудио и Assistants API из SDK не поддерживаются. `client.models.list()` работает и возвращает каталог.
