ДокументацияTypeSafe Python SDKИспользование Python SDK

Использование Python SDK

Guides and patterns for working with the TypeSafe Python SDK.

Руководства и паттерны работы с TypeSafe Python SDK.

Вызов System One API

```python theme={null} import asyncio
PLAINTEXT api.wedstack.ru/v1
from typesafe_sdk import AsyncTypeSafeClient, Choice, Noul, Score


async def main() -> None:
    async with AsyncTypeSafeClient() as client:
        result = await client.system_one(
            "I was charged twice. Please help ASAP.",
            {
                "billing": Noul(instructions="Is this about billing?"),
                "tone": Choice(
                    instructions="What is the tone?",
                    criteria={"calm": None, "angry": None},
                ),
                "urgency": Score(
                    instructions="How urgent is this?",
                    criteria=["low", "medium", "high"],
                ),
            },
        )
        print(
            result.nouls["billing"].noul,
            result.choices["tone"].choice,
            result.scores["urgency"].score,
        )


asyncio.run(main())
```
```python theme={null} from typesafe_sdk import Choice, Noul, Score, TypeSafeClient
PLAINTEXT api.wedstack.ru/v1
client = TypeSafeClient()
state = "I was charged twice. Please help ASAP."
questions = {
    "billing": Noul(instructions="Is this about billing?"),
    "tone": Choice(
        instructions="What is the tone?", criteria={"calm": None, "angry": None}
    ),
    "urgency": Score(
        instructions="How urgent is this?", criteria=["low", "medium", "high"]
    ),
}
result = client.system_one(state, questions)
print(
    result.nouls["billing"].noul,
    result.choices["tone"].choice,
    result.scores["urgency"].score,
)
```

Типизированные ответы system\_one

Вы можете передать модель ответа в system_one, чтобы сделать работу с результатом более строго типизированной (type-safe):

PYTHON THEME={NULL} api.wedstack.ru/v1
from typesafe_sdk import Noul, NoulAnswer, SystemOneResponse, TypeSafeClient


class BillingResponse(SystemOneResponse):
    billing: NoulAnswer


with TypeSafeClient() as client:
    result = client.system_one(
        "I was charged twice.",
        {"billing": Noul(instructions="Is this about billing?")},
        response_model=BillingResponse,
    )
    assert 0 <= result.billing.noul <= 1
    assert result.billing == result.nouls["billing"]
    print(result.request_id)

Пользовательские типы ответов

Также можно определить полностью новую модель ответа без наследования от SystemOneResponse:

PYTHON THEME={NULL} api.wedstack.ru/v1
from pydantic import BaseModel

from typesafe_sdk import Noul, NoulAnswer, TypeSafeClient


class BillingAnswers(BaseModel):
    billing: NoulAnswer


class BillingResponse(BaseModel):
    answers: BillingAnswers


result = TypeSafeClient().system_one(
    "I was charged twice.",
    {"billing": Noul(instructions="Is this about billing?")},
    response_model=BillingResponse,
)
assert 0 <= result.answers.billing.noul <= 1

Выбор модели

Просмотр доступных моделей:

PYTHON THEME={NULL} api.wedstack.ru/v1
from typesafe_sdk import TypeSafeClient

print(TypeSafeClient().models.list())

Указание модели при инициализации клиента:

PYTHON THEME={NULL} api.wedstack.ru/v1
client = TypeSafeClient(model="jev")

Подробности см. в справочнике ресурса Models.

Настройка базового URL (base URL)

Чтобы использовать SDK с другим URL API, задайте параметр base_url при создании клиента или установите переменную окружения TYPESAFE_BASE_URL.

Например, подключение через AI-шлюз с использованием его API-ключа и идентификатора модели:

Использование API-ключа OpenRouter и [идентификатора модели OpenRouter](https://openrouter.ai/~typesafe/jev-latest/):
PLAINTEXT api.wedstack.ru/v1
skip: next

```python theme={null}
import os

from typesafe_sdk import Noul, TypeSafeClient

with TypeSafeClient(
    api_key=os.environ["OPENROUTER_API_KEY"],
    base_url="https://openrouter.ai/api",
    model="~typesafe/jev-latest",
) as client:
    result = client.system_one(
        "I was charged twice.",
        {"billing": Noul(instructions="Is this about billing?")},
    )
    print(result.nouls["billing"].noul)
```
Также с SDK можно использовать [TypeSafe-совместимый API от Vercel](https://vercel.com/docs/ai-gateway/sdks-and-apis/typesafe):
PLAINTEXT api.wedstack.ru/v1
skip: next

```python theme={null}
import os

from typesafe_sdk import Noul, TypeSafeClient

with TypeSafeClient(
    api_key=os.environ["AI_GATEWAY_API_KEY"],
    base_url="https://ai-gateway.vercel.sh/typesafe",
    model="typesafe-ai/jev",
) as client:
    result = client.system_one(
        "I was charged twice.",
        {"billing": Noul(instructions="Is this about billing?")},
    )
    print(result.nouls["billing"].noul)
```

Для этого сторонний API должен соответствовать спецификации OpenAPI TypeSafe.

Повторные попытки (Retries)

Передайте пользовательскую политику RetryPolicy в аргументе retry на уровне клиента или для отдельного вызова. Некорректные API-ключи вызывают исключение TypeSafeError во время создания клиента, еще до отправки какого-либо запроса или повторной попытки.

```python theme={null} from typesafe_sdk import RetryPolicy, TypeSafeClient
PLAINTEXT api.wedstack.ru/v1
client = TypeSafeClient(retry=RetryPolicy(max_retries=3, backoff_max=0.2, timeout=1.0))
```
```python theme={null} from typesafe_sdk import RetryPolicy
PLAINTEXT api.wedstack.ru/v1
client.system_one(
    state, questions, retry=RetryPolicy(max_retries=3, backoff_max=0.2, timeout=1.0)
)
```

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

Обработка исключений, генерируемых SDK:

PYTHON THEME={NULL} api.wedstack.ru/v1
from typesafe_sdk import TypeSafeAPIError

try:
    client.system_one(state, questions)
except TypeSafeAPIError as error:
    print(error.status, error.request_id)

Логирование

SDK записывает логи через логгер typesafe_sdk. Настройте его в соответствии со стандартным руководством по logging:

PYTHON THEME={NULL} api.wedstack.ru/v1
import logging

logging.getLogger("typesafe_sdk").setLevel(logging.DEBUG)

Или задайте для переменной TYPESAFE_LOG_LEVEL одно из значений: debug, info, warning, error или off перед импортом SDK.

Уровень info записывает одну сводную строку на запрос; debug дополнительно логирует заголовки и тела запросов и ответов. Конфиденциальные заголовки — авторизация, API-ключи, cookies и любые заголовки, имя которых содержит token или secret — скрываются (маскируются) в выводе логов. Тела запросов и ответов не маскируются.

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

SDK считывает и использует следующие переменные окружения:

Переменная Назначение Значение по умолчанию
TYPESAFE_API_KEY API-ключ (обязательный)
TYPESAFE_BASE_URL Базовый URL API https://api.typesafe.ai
TYPESAFE_DEFAULT_MODEL Модель по умолчанию jev-latest
TYPESAFE_LOG_LEVEL Уровень логгера typesafe_sdk, применяется один раз при импорте не задано

Значения по умолчанию в SDK см. в справочнике констант.

У API-ключей, переданных через параметр api_key или переменную TYPESAFE_API_KEY, удаляются начальные и конечные пробельные символы, включая переносы строк из файлов ключей. Пустые ключи, пробелы внутри ключа, управляющие символы и символы, не входящие в ASCII, отклоняются до отправки запроса. Если явно передан пустой ключ, значение из переменных окружения не подставляется.

Прямая совместимость (Forward compatibility)

SDK сохраняет работоспособность по мере развития TypeSafe API, позволяя использовать новые возможности API еще до того, как в релизе SDK появится их первоклассная поддержка.

Дополнительные поля запроса

Передавайте дополнительные поля запроса к API с помощью extra_body. Поле beam_width в примере ниже приведено лишь для иллюстрации; отправляйте только те поля, которые поддерживаются API.

skip: next

PYTHON THEME={NULL} api.wedstack.ru/v1
from typesafe_sdk import Noul, TypeSafeClient

with TypeSafeClient() as client:
    client.system_one(
        "I was charged twice.",
        {"billing": Noul(instructions="About billing?")},
        extra_body={"beam_width": 4},
    )

Словари вопросов в исходном виде (raw)

PYTHON THEME={NULL} api.wedstack.ru/v1
from typesafe_sdk import TypeSafeClient

with TypeSafeClient() as client:
    client.system_one(
        "I was charged twice.",
        {"billing": {"type": "noul", "instructions": "About billing?", "weight": 2}},
    )
**Совет**

Неизвестные поля служат запасным выходом для обеспечения прямой совместимости. Игнорируйте ошибки проверки типов при их использовании и своевременно обновляйте SDK.

Неизвестные виды ответов

SDK регистрирует предупреждение в логах и пропускает нераспознанные типы ответов. Используйте raw_http_response, чтобы изучить полный ответ API, включая эти ответы:

PYTHON THEME={NULL} api.wedstack.ru/v1
from typesafe_sdk import Noul, TypeSafeClient

result = TypeSafeClient().system_one(
    "I was charged twice.",
    {"billing": Noul(instructions="Is this about billing?")},
)
raw_answers = result.raw_http_response.json()["answers"]

Неизвестные поля ответа

Неизвестные дополнительные поля в распознанных ответах игнорируются.