> For the complete documentation index, see [llms.txt](https://docs.clore.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.clore.ai/clore.ai/clore.ai-ru/razrabotchikam/python-sdk.md).

# Python SDK (clore-ai)

Этот **clore-ai** пакет является официальным Python SDK для [Clore.ai](https://clore.ai) маркетплейса GPU. Он оборачивает весь REST API в чистый, типобезопасный интерфейс со встроенным ограничением частоты запросов, автоматическими повторными попытками и структурированной обработкой ошибок — так что вы можете сосредоточиться на аренде GPU, а не на HTTP-обвязке.

***

## Установка

```bash
pip install clore-ai
```

**Требования:** Python 3.9+

Пакет устанавливает как Python SDK, так и [`clore` CLI](/clore.ai/clore.ai-ru/razrabotchikam/cli-guide.md).

***

## Аутентификация

Получите ваш API-ключ в [панели управления Clore.ai](https://clore.ai) → **API** разделе.

### Вариант 1: переменная окружения (рекомендуется)

```bash
export CLORE_API_KEY=your_api_key_here
```

SDK читает `CLORE_API_KEY` автоматически — изменения кода не требуются.

### Вариант 2: конфигурационный файл CLI

```bash
clore config set api_key YOUR_API_KEY
```

Это сохраняет ключ в `~/.clore/config.json`.

### Вариант 3: передайте напрямую в коде

```python
from clore_ai import CloreAI

client = CloreAI(api_key="your_api_key_here")
```

> ⚠️ **Важно:** API Clore.ai использует `auth` заголовок для аутентификации, **не** `Authorization: Bearer`. SDK обрабатывает это автоматически.

***

## Быстрый старт

```python
from clore_ai import CloreAI

client = CloreAI()
servers = client.marketplace(gpu="RTX 4090", max_price_usd=5.0)
for s in servers:
    print(f"Сервер {s.id}: {s.gpu_model} — ${s.price_usd:.4f}/ч")
```

***

## Синхронный клиент (`CloreAI`)

### Конструктор

```python
CloreAI(
    api_key: str | None = None,       # Берет CLORE_API_KEY из env / config
    base_url: str | None = None,       # По умолчанию: https://api.clore.ai/v1
    timeout: float = 30.0,             # Таймаут запроса в секундах
    max_retries: int = 3               # Попытки повторного запроса при ограничении частоты / сетевых ошибках
)
```

Клиент поддерживает контекстные менеджеры для автоматической очистки:

```python
with CloreAI() as client:
    wallets = client.wallets()
    # client.close() вызывается автоматически
```

***

### `wallets()`

Получите балансы ваших кошельков и адреса для пополнения.

```python
wallets = client.wallets()

for wallet in wallets:
    print(f"{wallet.name}: {wallet.balance:.8f}")
    if wallet.deposit:
        print(f"  Пополнение: {wallet.deposit}")
```

**Возвращает:** `List[Wallet]`

| Поле             | Тип             | Описание                                                                          |
| ---------------- | --------------- | --------------------------------------------------------------------------------- |
| `name`           | `str`           | Название валюты (например, `"bitcoin"`, `"CLORE-Blockchain"`, `"USD-Blockchain"`) |
| `balance`        | `float \| None` | Текущий баланс                                                                    |
| `deposit`        | `str \| None`   | Адрес пополнения                                                                  |
| `withdrawal_fee` | `float \| None` | Комиссия за вывод                                                                 |

***

### `marketplace()`

Поиск по GPU-маркетплейсу с необязательными фильтрами на стороне клиента.

```python
# Все доступные серверы
servers = client.marketplace()

# Фильтр по модели GPU и максимальной цене
servers = client.marketplace(
    gpu="RTX 4090",
    max_price_usd=5.0
)

# Много-GPU сборки с большим объемом RAM
servers = client.marketplace(
    min_gpu_count=4,
    min_ram_gb=128.0
)
```

**Параметры:**

| Параметр         | Тип             | По умолчанию | Описание                                                           |
| ---------------- | --------------- | ------------ | ------------------------------------------------------------------ |
| `gpu`            | `str \| None`   | `None`       | Фильтр по модели GPU (регистронезависимое совпадение по подстроке) |
| `min_gpu_count`  | `int \| None`   | `None`       | Минимальное количество GPU                                         |
| `min_ram_gb`     | `float \| None` | `None`       | Минимальный объем RAM в ГБ                                         |
| `max_price_usd`  | `float \| None` | `None`       | Максимальная цена в час в USD                                      |
| `available_only` | `bool`          | `True`       | Возвращать только серверы, доступные для аренды                    |

**Возвращает:** `List[MarketplaceServer]`

Каждый `MarketplaceServer` предоставляет удобные свойства для наиболее распространенных полей, а также доступ к полным вложенным данным:

| Свойство         | Тип             | Описание                                                         |
| ---------------- | --------------- | ---------------------------------------------------------------- |
| `id`             | `int`           | Уникальный ID сервера                                            |
| `gpu_model`      | `str \| None`   | Описание основной GPU (например, `"1x NVIDIA GeForce RTX 4090"`) |
| `gpu_count`      | `int`           | Количество GPU (из `gpu_array`)                                  |
| `ram_gb`         | `float \| None` | RAM в ГБ                                                         |
| `price_usd`      | `float \| None` | Цена по требованию в USD                                         |
| `spot_price_usd` | `float \| None` | Спотовая цена в USD                                              |
| `available`      | `bool`          | Доступен ли сервер (не арендован)                                |
| `location`       | `str \| None`   | Код страны из сетевых характеристик                              |

Для продвинутых сценариев вы можете получить доступ к полной вложенной структуре:

| Поле          | Тип                    | Описание                                                                                                     |
| ------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------ |
| `specs`       | `ServerSpecs \| None`  | Полные аппаратные характеристики (`specs.gpu`, `specs.ram`, `specs.cpu`, `specs.disk`, `specs.net`, и т. д.) |
| `price`       | `ServerPrice \| None`  | Полный объект цены (`price.usd.on_demand_usd`, `price.usd.spot`, `price.on_demand`, и т. д.)                 |
| `rented`      | `bool \| None`         | Находится ли сервер сейчас в аренде                                                                          |
| `reliability` | `float \| None`        | Оценка надежности сервера                                                                                    |
| `rating`      | `ServerRating \| None` | Рейтинг сервера (`rating.avg`, `rating.cnt`)                                                                 |

> **Примечание:** Этот `marketplace()` эндпоинт открыт — он работает без API-ключа.

***

### `my_servers()`

Список серверов, которые вы предоставляете на маркетплейс Clore.ai.

```python
my_servers = client.my_servers()

for server in my_servers:
    print(f"{server.name}: {server.gpu_model} [{server.status}]")
```

**Возвращает:** `List[MyServer]`

| Свойство     | Тип             | Описание                                                                   |
| ------------ | --------------- | -------------------------------------------------------------------------- |
| `id`         | `int`           | ID сервера                                                                 |
| `name`       | `str \| None`   | Имя сервера                                                                |
| `gpu_model`  | `str \| None`   | Описание основной GPU                                                      |
| `ram_gb`     | `float \| None` | RAM в ГБ                                                                   |
| `status`     | `str`           | Читаемый статус: `"Онлайн"`, `"Офлайн"`, `"Отключен"`, или `"Не работает"` |
| `connected`  | `bool \| None`  | Подключен ли сервер                                                        |
| `online`     | `bool \| None`  | В сети ли сервер                                                           |
| `visibility` | `str \| None`   | `"public"` или `"private"`                                                 |

***

### `server_config(server_name)`

Получите конфигурацию конкретного сервера, который вы хостите.

```python
config = client.server_config("MyGPU")

print(f"Сервер: {config.name}")
print(f"GPU: {config.gpu_model}")
print(f"Минимальная аренда: {config.mrl}h")
print(f"По требованию: ${config.on_demand_price}")
print(f"Спот: ${config.spot_price}")
```

**Параметры:**

| Параметр      | Тип   | Описание    |
| ------------- | ----- | ----------- |
| `server_name` | `str` | Имя сервера |

**Возвращает:** `ServerConfig`

| Свойство          | Тип                   | Описание                                  |
| ----------------- | --------------------- | ----------------------------------------- |
| `name`            | `str \| None`         | Имя сервера                               |
| `gpu_model`       | `str \| None`         | Описание основной GPU                     |
| `mrl`             | `int \| None`         | Максимальная длительность аренды в часах  |
| `on_demand_price` | `float \| None`       | Первая доступная цена по требованию в USD |
| `spot_price`      | `float \| None`       | Первая доступная спотовая цена в USD      |
| `specs`           | `ServerSpecs \| None` | Полные аппаратные спецификации            |
| `connected`       | `bool \| None`        | Подключен ли сервер                       |
| `visibility`      | `str \| None`         | `"public"` или `"private"`                |

***

### `my_orders(include_completed)`

Получите ваши текущие заказы, при необходимости включая выполненные/истекшие.

```python
# Только активные заказы
orders = client.my_orders()

# Включить выполненные заказы
all_orders = client.my_orders(include_completed=True)

for order in orders:
    print(f"Заказ {order.id}: {order.type} — {order.status}")
    if order.pub_cluster:
        print(f"  IP: {order.pub_cluster}")
    if order.tcp_ports:
        print(f"  Порты: {order.tcp_ports}")
```

**Параметры:**

| Параметр            | Тип    | По умолчанию | Описание                             |
| ------------------- | ------ | ------------ | ------------------------------------ |
| `include_completed` | `bool` | `False`      | Включать выполненные/истекшие заказы |

**Возвращает:** `List[Order]`

| Поле          | Тип             | Описание                           |
| ------------- | --------------- | ---------------------------------- |
| `id`          | `int`           | Уникальный ID заказа               |
| `server_id`   | `int \| None`   | ID сервера                         |
| `type`        | `str`           | `"on-demand"` или `"spot"`         |
| `status`      | `str \| None`   | Статус заказа                      |
| `image`       | `str \| None`   | Docker-образ                       |
| `currency`    | `str \| None`   | Валюта оплаты                      |
| `price`       | `float \| None` | Цена заказа в день                 |
| `pub_cluster` | `str \| None`   | Публичное имя хоста/IP для доступа |
| `tcp_ports`   | `dict \| None`  | Сопоставления TCP-портов           |

***

### `spot_marketplace(server_id)`

Просмотрите спотовые предложения рынка для конкретного сервера.

```python
spot = client.spot_marketplace(server_id=6)

if spot.offers:
    for offer in spot.offers:
        print(f"Заказ {offer.order_id}: ${offer.price}/день (сервер {offer.server_id})")

if spot.currency_rates_in_usd:
    for coin, rate in spot.currency_rates_in_usd.items():
        print(f"  {coin}: ${rate}")
```

**Параметры:**

| Параметр    | Тип   | Описание                |
| ----------- | ----- | ----------------------- |
| `server_id` | `int` | ID сервера для проверки |

**Возвращает:** `SpotMarket`

| Поле                    | Тип                        | Описание                                                          |
| ----------------------- | -------------------------- | ----------------------------------------------------------------- |
| `offers`                | `List[SpotOffer] \| None`  | Список спотовых предложений (`order_id`, `price`, `server_id`)    |
| `server`                | `SpotServerInfo \| None`   | Информация о сервере (минимальная цена, видимость, статус онлайн) |
| `currency_rates_in_usd` | `Dict[str, float] \| None` | Курсы обмена валют в USD                                          |

***

### `create_order(...)`

Создайте новый заказ по требованию или спотовый заказ. Так вы арендуете GPU.

#### Заказ по требованию

```python
order = client.create_order(
    server_id=123,
    image="cloreai/ubuntu22.04-cuda12",
    type="on-demand",
    currency="bitcoin",
    ssh_password="MySecurePass123",
    ports={"22": "tcp", "8888": "http"}
)

print(f"Заказ создан: {order.id}")
print(f"Подключение: {order.pub_cluster}")
```

#### Спотовый заказ

```python
order = client.create_order(
    server_id=123,
    image="cloreai/pytorch",
    type="spot",
    currency="bitcoin",
    spot_price=0.000005,
    ssh_password="MySecurePass123",
    ports={"22": "tcp"}
)
```

**Параметры:**

| Параметр             | Тип         | Обязательно      | Описание                                                                                                                                                                           |
| -------------------- | ----------- | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `server_id`          | `int`       | Да               | ID сервера для аренды                                                                                                                                                              |
| `image`              | `str`       | Да               | Docker-образ (например, `"cloreai/ubuntu22.04-cuda12"`)                                                                                                                            |
| `type`               | `str`       | Да               | `"on-demand"` или `"spot"`                                                                                                                                                         |
| `currency`           | `str`       | Да               | Валюта оплаты (например, `"bitcoin"`)                                                                                                                                              |
| `ssh_password`       | `str`       | Нет              | Пароль SSH (буквенно-цифровой, максимум 32 символа)                                                                                                                                |
| `ssh_key`            | `str`       | Нет              | Публичный ключ SSH (максимум 3072 символа)                                                                                                                                         |
| `ports`              | `dict`      | Нет              | Сопоставления портов, например, `{"22": "tcp", "8888": "http"}`                                                                                                                    |
| `env`                | `dict`      | Нет              | Переменные окружения                                                                                                                                                               |
| `jupyter_token`      | `str`       | Нет              | Токен Jupyter Notebook (максимум 32 символа)                                                                                                                                       |
| `command`            | `str`       | Нет              | Команда shell для выполнения после запуска контейнера                                                                                                                              |
| `spot_price`         | `float`     | Только для спота | Цена в день для спотовых заказов                                                                                                                                                   |
| `required_price`     | `float`     | Нет              | Зафиксировать конкретную цену (только по требованию)                                                                                                                               |
| `autossh_entrypoint` | `str`       | Нет              | Использовать SSH entrypoint Clore.ai                                                                                                                                               |
| `gpu_count`          | `int`       | Нет              | Арендуйте только N GPU на серверах с [частичной арендой](/clore.ai/clore.ai-ru/dlya-arendatorov/partial-gpu-rental.md) (только по требованию); опустите, чтобы арендовать весь риг |
| `gpu_indices`        | `list[int]` | Нет              | Точные слоты GPU из `partial_gpu_rental.free_indices`; длина должна равняться `gpu_count`; опустите для автоматического выбора                                                     |

**Возвращает:** сырой ответ API (`{"code": 0}` при успехе); получите созданный заказ через `my_orders()`

> **Ограничение частоты запросов:** `create_order` имеет специальную 5-секундную паузу между вызовами. SDK обеспечивает это автоматически.

***

### `cancel_order(order_id, issue)`

Отменить активный заказ или spot-предложение. При желании сообщите о проблеме с сервером.

```python
# Простая отмена
client.cancel_order(order_id=38)

# Отмена с сообщением о проблеме
client.cancel_order(
    order_id=38,
    issue="GPU #1 перегревался и снижал частоты"
)
```

**Параметры:**

| Параметр   | Тип   | Обязательно | Описание                                                    |
| ---------- | ----- | ----------- | ----------------------------------------------------------- |
| `order_id` | `int` | Да          | ID заказа для отмены                                        |
| `issue`    | `str` | Нет         | Причина отмены / сообщение о проблеме (макс. 2048 символов) |

**Возвращает:** `Dict[str, Any]`

***

### `set_server_settings(...)`

Обновить настройки сервера, который вы размещаете на маркетплейсе.

```python
client.set_server_settings(
    name="MyGPU",
    availability=True,
    mrl=96,
    on_demand=0.0001,
    spot=0.00000113
)
```

**Параметры:**

| Параметр       | Тип     | Обязательно | Описание                                 |
| -------------- | ------- | ----------- | ---------------------------------------- |
| `name`         | `str`   | Да          | Имя сервера                              |
| `availability` | `bool`  | Нет         | Может ли сервер быть арендован           |
| `mrl`          | `int`   | Нет         | Максимальная длительность аренды в часах |
| `on_demand`    | `float` | Нет         | Цена по требованию в день                |
| `spot`         | `float` | Нет         | Минимальная spot-цена в день             |

**Возвращает:** `Dict[str, Any]`

***

### `set_spot_price(order_id, price)`

Обновить цену вашего spot-предложения на рынке.

```python
client.set_spot_price(order_id=39, price=0.000003)
```

**Параметры:**

| Параметр   | Тип     | Описание                   |
| ---------- | ------- | -------------------------- |
| `order_id` | `int`   | ID spot-заказа/предложения |
| `price`    | `float` | Новая цена в день          |

**Возвращает:** `Dict[str, Any]`

> **Примечание:** Вы можете понижать spot-цены только раз в 600 секунд и только на ограниченный шаг. API возвращает `code: 6` с подробностями, если вы превысите эти лимиты.

***

## Асинхронный клиент (`AsyncCloreAI`)

Этот `AsyncCloreAI` клиент предоставляет те же методы, что и `CloreAI`, но все они возвращают корутины. Используйте его, когда вам нужны параллельные вызовы API или вы работаете в асинхронном приложении.

### Базовое использование

```python
import asyncio
from clore_ai import AsyncCloreAI

async def main():
    async with AsyncCloreAI(api_key="your_key") as client:
        wallets = await client.wallets()
        for w in wallets:
            print(f"{w.name}: {w.balance:.8f}")

asyncio.run(main())
```

### Параллельные операции

Запускайте несколько вызовов API параллельно с `asyncio.gather`:

```python
import asyncio
from clore_ai import AsyncCloreAI

async def compare_gpus():
    async with AsyncCloreAI() as client:
        # Одновременно ищем несколько моделей GPU
        rtx4090, rtx3090, a100 = await asyncio.gather(
            client.marketplace(gpu="RTX 4090"),
            client.marketplace(gpu="RTX 3090"),
            client.marketplace(gpu="A100"),
        )

        for name, servers in [("RTX 4090", rtx4090), ("RTX 3090", rtx3090), ("A100", a100)]:
            if servers:
                cheapest = min(s.price_usd or float('inf') for s in servers)
                print(f"{name}: {len(servers)} доступно, самое дешёвое ${cheapest:.4f}/ч")
            else:
                print(f"{name}: нет доступных")

asyncio.run(compare_gpus())
```

### Доступные методы

`AsyncCloreAI` поддерживает все те же методы, что и `CloreAI`:

| Метод                               | Описание                           |
| ----------------------------------- | ---------------------------------- |
| `await wallets()`                   | Получить балансы кошельков         |
| `await marketplace(...)`            | Поиск на маркетплейсе              |
| `await my_servers()`                | Список ваших размещённых серверов  |
| `await server_config(name)`         | Получить конфигурацию сервера      |
| `await my_orders(...)`              | Список ваших заказов               |
| `await spot_marketplace(server_id)` | Получить spot-предложения на рынке |
| `await create_order(...)`           | Создать новый заказ                |
| `await cancel_order(...)`           | Отменить заказ                     |
| `await set_server_settings(...)`    | Обновить настройки сервера         |
| `await set_spot_price(...)`         | Обновить spot-цену                 |

***

## Обработка ошибок

SDK предоставляет структурированные классы исключений для каждого кода ошибки API.

```python
from clore_ai import CloreAI
from clore_ai.exceptions import (
    CloreAPIError,      # Базовый класс для всех ошибок API
    AuthError,          # Код 3 — неверный API-ключ
    RateLimitError,     # Код 5 — превышено ограничение частоты запросов
    InvalidInputError,  # Код 2 — неверные данные запроса
    DBError,            # Код 1 — ошибка базы данных
    InvalidEndpointError,  # Код 4 — неверная конечная точка
    FieldError,         # Код 6 — ошибка в конкретном поле
)

client = CloreAI()

try:
    order = client.create_order(
        server_id=123,
        image="cloreai/ubuntu22.04-cuda12",
        type="on-demand",
        currency="bitcoin",
    )
except AuthError:
    print("Неверный API-ключ. Проверьте ваш CLORE_API_KEY.")
except RateLimitError:
    print("Ограничение частоты запросов. SDK повторяет автоматически, но вы достигли максимального числа повторов.")
except InvalidInputError as e:
    print(f"Неверный запрос: {e}")
except FieldError as e:
    # Ошибки кода 6 включают подробности в ответе
    print(f"Ошибка поля: {e} (подробности: {e.response})")
except CloreAPIError as e:
    print(f"Ошибка API: {e} (код: {e.code})")
```

### Коды ошибок

| Код | Исключение             | Описание                                             |
| --- | ---------------------- | ---------------------------------------------------- |
| 0   | —                      | Успех                                                |
| 1   | `DBError`              | Ошибка базы данных                                   |
| 2   | `InvalidInputError`    | Неверные входные данные                              |
| 3   | `AuthError`            | Неверный API-токен                                   |
| 4   | `InvalidEndpointError` | Неверная конечная точка                              |
| 5   | `RateLimitError`       | Превышено ограничение частоты запросов               |
| 6   | `FieldError`           | Ошибка в конкретном поле (см. `error` поле в ответе) |

Все классы исключений наследуются от `CloreAPIError` и включают:

* `e.code` — числовой код ошибки
* `e.response` — полный словарь ответа API (если доступен)

***

## Ограничение частоты запросов

SDK включает встроенный ограничитель частоты запросов, который автоматически соблюдает лимиты Clore.ai:

| Конечная точка             | Лимит                 |
| -------------------------- | --------------------- |
| Большинство конечных точек | **1 запрос/секунду**  |
| `create_order`             | **1 запрос/5 секунд** |

Когда API возвращает ошибку ограничения частоты запросов (код 5), SDK применяет **экспоненциальную задержку** и повторяет попытку до `max_retries` раз (по умолчанию: 3). Вам не нужно добавлять `time.sleep()` между вызовами.

### Как это работает

1. Перед каждым запросом ограничитель частоты ждёт, пока истечёт минимальный интервал.
2. `create_order` вызовы имеют дополнительную 5-секундную паузу.
3. При ошибках ограничения частоты SDK делает экспоненциальный откат: 1с → 2с → 4с → ...
4. После `max_retries` неудачных попыток `RateLimitError` вызывается

### Настроить поведение повторных попыток

```python
client = CloreAI(
    max_retries=5,    # Больше повторов для долгих скриптов
    timeout=60.0      # Более долгий таймаут для медленных соединений
)
```

***

## Конфигурация

### Файл конфигурации

CLI хранит конфигурацию в `~/.clore/config.json`:

```json
{
  "api_key": "your_api_key_here"
}
```

### Порядок разрешения

SDK определяет API-ключ в следующем порядке:

1. `api_key` аргумент, переданный конструктору
2. `CLORE_API_KEY` переменная окружения
3. `api_key` поле в `~/.clore/config.json`

### Переменные окружения

| Переменная      | Описание                    |
| --------------- | --------------------------- |
| `CLORE_API_KEY` | API-ключ для аутентификации |

***

## Дальше

* [**Справочник CLI**](/clore.ai/clore.ai-ru/razrabotchikam/cli-guide.md) — Используйте Clore.ai из вашего терминала
* [**REST API**](/clore.ai/clore.ai-ru/dlya-khostov/api.md) — Сырая документация API для кастомных интеграций
* [**On-Demand vs Spot**](/clore.ai/clore.ai-ru/dlya-arendatorov/on-demand-vs-spot.md) — Поймите модели ценообразования
* [**Доступные Docker-образы**](/clore.ai/clore.ai-ru/dlya-arendatorov/docker-images.md) — Предсобранные образы для GPU-нагрузок


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.clore.ai/clore.ai/clore.ai-ru/razrabotchikam/python-sdk.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
