> 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-eng-zh/kai-fa-zhe/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-eng-zh/kai-fa-zhe/cli-guide.md).

***

## 认证

从 [Clore.ai 仪表板](https://clore.ai) → **API** 部分获取你的 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")
```

> ⚠️ **重要：** Clore.ai API 使用 `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"Server {s.id}: {s.gpu_model} — ${s.price_usd:.4f}/h")
```

***

## 同步客户端（`CloreAI`)

### 构造函数

```python
CloreAI(
    api_key: str | None = None,       # 回退到 CLORE_API_KEY 环境变量 / 配置
    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"  Deposit: {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 机组并配备大量内存
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` | 最小内存（GB）                  |
| `max_price_usd`  | `float \| None` | `None` | 每小时最高价格（美元）               |
| `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` | 内存（GB）                                      |
| `price_usd`      | `float \| None` | 按需价格（美元）                                    |
| `spot_price_usd` | `float \| None` | 竞价价格（美元）                                    |
| `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` | 内存（GB）                                                             |
| `status`     | `str`           | 可读的状态： `"Online"`, `"Offline"`, `"Disconnected"`，或 `"Not Working"` |
| `connected`  | `bool \| None`  | 服务器是否已连接                                                           |
| `online`     | `bool \| None`  | 服务器是否在线                                                            |
| `visibility` | `str \| None`   | `"public"` 或 `"private"`                                           |

***

### `server_config(server_name)`

获取你托管的特定服务器的配置。

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

print(f"Server: {config.name}")
print(f"GPU: {config.gpu_model}")
print(f"Min rental: {config.mrl}h")
print(f"On-demand: ${config.on_demand_price}")
print(f"Spot: ${config.spot_price}")
```

**参数：**

| 参数            | 类型    | 描述    |
| ------------- | ----- | ----- |
| `server_name` | `str` | 服务器名称 |

**返回：** `ServerConfig`

| 属性                | 类型                    | 描述                       |
| ----------------- | --------------------- | ------------------------ |
| `name`            | `str \| None`         | 服务器名称                    |
| `gpu_model`       | `str \| None`         | 主 GPU 描述                 |
| `mrl`             | `int \| None`         | 最短租期（小时）                 |
| `on_demand_price` | `float \| None`       | 可用的首个按需美元价格              |
| `spot_price`      | `float \| None`       | 可用的首个竞价美元价格              |
| `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 {order.id}: {order.type} — {order.status}")
    if order.pub_cluster:
        print(f"  IP: {order.pub_cluster}")
    if order.tcp_ports:
        print(f"  Ports: {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"Order {offer.order_id}: ${offer.price}/day (server {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` | 以美元计的货币汇率                                |

***

### `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 created: {order.id}")
print(f"Connect: {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 笔记本令牌（最多 32 个字符）                     |
| `command`            | `str`   | 否    | 容器启动后要运行的 shell 命令                           |
| `spot_price`         | `float` | 仅限竞价 | 竞价订单的每日价格                                    |
| `required_price`     | `float` | 否    | 锁定特定价格（仅限按需）                                 |
| `autossh_entrypoint` | `str`   | 否    | 使用 Clore.ai SSH 入口点                          |

**返回：** `订单`

> **速率限制：** `create_order` 在调用之间有一个特殊的 5 秒冷却时间。SDK 会自动强制执行。

***

### `cancel_order(order_id, issue)`

取消活动订单或竞价报价。可选地报告服务器问题。

```python
# 简单取消
client.cancel_order(order_id=38)

# 带问题报告的取消
client.cancel_order(
    order_id=38,
    issue="GPU #1 was overheating and throttling"
)
```

**参数：**

| 参数         | 类型    | 必需 | 描述                       |
| ---------- | ----- | -- | ------------------------ |
| `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` | 否  | 最低竞价每日价格   |

**返回：** `Dict[str, Any]`

***

### `set_spot_price(order_id, price)`

更新你在竞价市场报价的价格。

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

**参数：**

| 参数         | 类型      | 描述         |
| ---------- | ------- | ---------- |
| `order_id` | `int`   | 竞价订单/报价 ID |
| `price`    | `float` | 新的每日价格     |

**返回：** `Dict[str, Any]`

> **注意：** 你只能每 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())
```

### 并发操作

使用 `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)} available, cheapest ${cheapest:.4f}/h")
            else:
                print(f"{name}: none available")

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) |
| `获取竞价市场报价`  | await create\_order(...)            |
| `创建新订单`     | await cancel\_order(...)            |
| `取消订单`      | await set\_server\_settings(...)    |
| `更新服务器设置`   | await set\_spot\_price(...)         |

***

## 更新竞价价格

错误处理

```python
from clore_ai import CloreAI
SDK 为每个 API 错误代码提供结构化的异常类。
    from clore_ai.exceptions import (
    CloreAPIError,      # 所有 API 错误的基类
    AuthError,          # 代码 3 — 无效的 API 密钥
    RateLimitError,     # 代码 5 — 超出速率限制
    InvalidInputError,  # 代码 2 — 错误的请求数据
    DBError,            # 代码 1 — 数据库错误（DBError）或数据库相关错误）
    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` 响应中的 field） |

所有异常类都继承自 `CloreAPIError` 并包含：

* `e.code` — 数字错误代码
* `e.response` — 完整的 API 响应字典（如可用）

***

## 速率限制

SDK 包含内置速率限制器，会自动强制执行 Clore.ai 的限制：

| 端点             | 限制              |
| -------------- | --------------- |
| 大多数端点          | **每秒 1 次请求**    |
| `create_order` | **每 5 秒 1 次请求** |

当 API 返回速率限制错误（代码 5）时，SDK 会应用 **指数退避** 并重试最多 `max_retries` 次（默认：3）。您无需在调用之间添加 `time.sleep()` 。

### 工作原理

1. 在每次请求之前，速率限制器会等待直到最小间隔过去。
2. `create_order` 调用会强制额外的 5 秒冷却期。
3. 在速率限制错误时，SDK 会以指数方式退避：1s → 2s → 4s → ...
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-eng-zh/kai-fa-zhe/cli-guide.md) — 从终端使用 Clore.ai
* [**REST API**](/clore.ai/clore.ai-eng-zh/zhen-dui-zhu-ji/api.md) — 用于自定义集成的原始 API 文档
* [**按需与抢占式**](/clore.ai/clore.ai-eng-zh/zhen-dui-zu-yong-zhe/on-demand-vs-spot.md) — 了解定价模型
* [**可用的 Docker 镜像**](/clore.ai/clore.ai-eng-zh/zhen-dui-zu-yong-zhe/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:

```
GET https://docs.clore.ai/clore.ai/clore.ai-eng-zh/kai-fa-zhe/python-sdk.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
