Использование Python SDK
Guides and patterns for working with the TypeSafe Python SDK.
Руководства и паттерны работы с TypeSafe Python SDK.
Вызов System One API
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())
```
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):
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:
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
Выбор модели
Просмотр доступных моделей:
from typesafe_sdk import TypeSafeClient
print(TypeSafeClient().models.list())
Указание модели при инициализации клиента:
client = TypeSafeClient(model="jev")
Подробности см. в справочнике ресурса Models.
Настройка базового URL (base URL)
Чтобы использовать SDK с другим URL API, задайте параметр base_url при создании клиента или установите переменную окружения TYPESAFE_BASE_URL.
Например, подключение через AI-шлюз с использованием его API-ключа и идентификатора модели:
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)
```
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 во время создания клиента, еще до отправки какого-либо запроса или повторной попытки.
client = TypeSafeClient(retry=RetryPolicy(max_retries=3, backoff_max=0.2, timeout=1.0))
```
client.system_one(
state, questions, retry=RetryPolicy(max_retries=3, backoff_max=0.2, timeout=1.0)
)
```
Обработка ошибок
Обработка исключений, генерируемых SDK:
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:
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
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)
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, включая эти ответы:
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"]
Неизвестные поля ответа
Неизвестные дополнительные поля в распознанных ответах игнорируются.