TypeSafe AI SDK для PHP

September 17, 2026 · View on GitHub

PHP-клиент API System One от TypeSafe AI. Позволяет задавать вопросы «да/нет», выбирать категории и оценивать текст или структурированные данные, получая типизированные ответы.

Неофициальный пакет, поддерживаемый сообществом и не связанный с компанией TypeSafe AI.

English version

  • Вопросы Noul, Choice и Score, типизированные ответы и вероятности.
  • Синхронные и асинхронные запросы через Guzzle promises.
  • Список моделей, настраиваемые повторы, таймауты и PSR-3 логирование.

Требования

  • PHP 8.2 или новее в пределах PHP 8.
  • Расширения PHP cURL и JSON.
  • Composer 2 и API key TypeSafe для реальных запросов.

Установка

composer require butochnikov/typesafe-sdk-php:^0.1

Эта команда требует релиза, добавленного в Packagist. До публикации используйте локальную установку.

Задайте ключ в окружении:

export TYPESAFE_API_KEY='ваш-ключ'

SDK читает переменные окружения напрямую и не загружает .env автоматически.

Синхронное использование

<?php

use TypeSafe\{Choice, Noul, Score, TypeSafeClient};

require __DIR__ . '/vendor/autoload.php';

$client = new TypeSafeClient();
try {
    $result = $client->systemOne(
        state: ['document' => 'I was charged twice. Please help ASAP.'],
        questions: [
            'billing' => new Noul(instructions: 'Is this about billing?'),
            'tone' => new Choice(criteria: ['calm' => null, 'angry' => null], instructions: 'Tone?'),
            'urgency' => new Score(criteria: ['low', 'medium', 'high'], instructions: 'Urgency?'),
        ],
    );
    echo $result->choices['tone']->choice . PHP_EOL;
    echo $result->nouls['billing']->noul . PHP_EOL;
    echo $result->scores['urgency']->score . PHP_EOL;
} finally {
    $client->close();
}

В SDK есть три примитива:

  • Noul — вероятность ответа «да», а не boolean;
  • Choice — выбор одного из именованных вариантов;
  • Score — ожидаемая оценка по упорядоченной шкале с нуля; она может быть дробной.

Открытому клиенту можно передавать и обычные ассоциативные массивы вопросов. Это позволяет использовать дополнительные поля API:

$result = $client->systemOne('a support ticket', [
    'is_billing' => ['type' => 'noul', 'instructions' => 'Billing?'],
    'tone' => ['type' => 'choice', 'criteria' => ['calm' => null, 'angry' => null]],
    'priority' => ['type' => 'score', 'criteria' => ['low', 'high']],
]);

Асинхронность и параллельные запросы

AsyncTypeSafeClient возвращает GuzzleHttp\Promise\PromiseInterface, который разрешается типизированным ответом.

<?php

use TypeSafe\{AsyncTypeSafeClient, Noul};

require __DIR__ . '/vendor/autoload.php';

$client = new AsyncTypeSafeClient();
try {
    $models = $client->models->list();
    $answers = $client->systemOne('text', [
        'q' => new Noul(instructions: 'Relevant?'),
    ]);

    [$models, $answers] = [$models->wait(), $answers->wait()];
} finally {
    $client->close();
}

Guzzle/cURL может выполнять несколько запросов одновременно. Promise поддерживает then(), обработчики ошибок, wait() и cancel(). Закрытие async-клиента отменяет ожидающие операции и безопасно при повторном вызове.

Модели и конфигурация

$client->models->list() возвращает ListModelsResponse. Карточки моделей содержат поля name, description и releaseDate.

Значения по умолчанию:

  • URL API: https://api.typesafe.ai;
  • модель: jev-latest;
  • timeout HTTP-запроса: 10 секунд.

Явные значения конструктора и параметры конкретного вызова имеют приоритет над переменными окружения:

  • TYPESAFE_API_KEY;
  • TYPESAFE_BASE_URL;
  • TYPESAFE_DEFAULT_MODEL;
  • TYPESAFE_LOG_LEVEL (debug, info, warn/warning, error, off).

Пустые и состоящие только из пробелов значения окружения игнорируются. Не храните API key в исходном коде или репозитории.

extraBody объединяется поверх стандартного тела запроса неглубоко, по принципу last-write-wins, и может заменить state, model или questions. extraHeaders действует только для конкретного вызова; заголовки авторизации и идентификации SDK защищены.

Для явного отключения общего ограничения времени используйте new Timeout(null). Объект Timeout также позволяет задать connect/read timeout. У Guzzle нет полного аналога фазовых timeout HTTPX для write/pool; поведение read timeout зависит от выбранного handler.

Повторные попытки и ошибки

По умолчанию RetryPolicy выполняет до двух повторных попыток для ответов 408, 429 и 5xx, сетевых ошибок и timeout. Доступны параметры maxRetries, backoffInitial, backoffMax, backoffJitter, httpStatuses, respectRetryAfter, apiConnectionError, apiTimeoutError, exceptions, predicate и общий budget timeout.

Политика, заданная для отдельного вызова, не изменяет настройки клиента.

Ошибки API преобразуются в следующие исключения:

TypeSafeBadRequestError, TypeSafeAuthenticationError, TypeSafePermissionDeniedError, TypeSafeNotFoundError, TypeSafeUnprocessableEntityError, TypeSafeRateLimitError и TypeSafeInternalServerError. Все они наследуют TypeSafeError. Сетевые ошибки представлены TypeSafeAPIConnectionError и TypeSafeAPITimeoutError.

Успешные ответы содержат типизированные DTO и доступны через $response->answers. Свойства requestId и rawHttpResponse доступны у ответа, созданного из HTTP-ответа; при отсутствии метаданных обращение к ним выбрасывает TypeSafeError. Сериализация DTO включает только wire-поля и сохраняет различие между JSON-объектами и массивами.

Логирование и собственный transport

Передайте любой PSR-3 LoggerInterface через параметр logger:. По умолчанию используется NullLogger; глобальное логирование приложения SDK не настраивает.

Debug-логи содержат wire-заголовки и body. Info-логи содержат метод, очищенный URL, статус, длительность, request id и номер retry. Значения заголовков авторизации, cookies, API keys, proxy authorization, а также заголовков с token или secret заменяются на ***.

Тела запросов и ответов намеренно не редактируются, как и в upstream SDK.

Параметр transport: принимает Guzzle handler или HandlerStack, а httpClient: — Guzzle ClientInterface. Эти параметры взаимоисключающие. Подключённые middleware, обычные headers, proxy и TLS-настройки сохраняются. SDK использует абсолютный URL, auth => null, http_errors => false и отключённые редиректы.

Если приложению нужно явно закрывать пользовательский ресурс, реализуйте CloseableTransportInterface или CloseableHttpClientInterface.

Разработка

composer validate --strict
composer install --no-interaction
composer test
composer analyse
composer check

Стандартный набор тестов работает без сети и проверяет отдельные контракты SDK. Совместимость с реальным API и полное соответствие Python SDK пока не проверены. Скрипты в examples/ выполняют реальные запросы при запуске; Composer autoload их не запускает.

Совместимость и версии

0.1.0 — первый релиз PHP-пакета на основе Python SDK 0.6.0. Версии этих пакетов независимы. Исходный commit и отличия PHP перечислены в таблице совместимости.

В серии 0.x несовместимые изменения будут повышать minor-версию, совместимые исправления — patch-версию. Ограничение ^0.1 оставляет приложение на серии 0.1.x. Изменения описываются в CHANGELOG.md, порядок выпуска — в инструкции по публикации.

Участие в разработке

К исправлениям ошибок и изменениям поведения добавляйте тест и выполняйте composer check перед отправкой pull request. Ошибки SDK обсуждаются в этом репозитории; вопросы использования сервиса — в документации TypeSafe.

Лицензия

MIT. Атрибуция Python SDK и его исходная лицензия сохранены в THIRD_PARTY_NOTICES.md.