Usiamo i cookie. Cookie e memoria del browser ti mantengono connesso e ricordano le tue preferenze. Con il tuo consenso misuriamo anche come viene usato il sito. Puoi in qualsiasi momento. Consulta la nostra cookie policy.

PHP

Guide agli SDK

PHP

Usa openai-php/client con api14 in PHP: configurazione con la factory, chat, streaming, strumenti, output strutturato, embeddings, errori e retry con backoff.

Usa openai-php/client con api14. Costruisci il client con la factory, imposta la base URI su api14 e usa gli id dei modelli nel formato provider/model.

Installazione

composer require openai-php/client guzzlehttp/guzzle
export API14_API_KEY="sk-api14-..."

Configurazione

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

$client = OpenAI::factory()
    ->withApiKey(getenv('API14_API_KEY'))
    ->withBaseUri(getenv('API14_BASE_URL') ?: 'https://api14.com/api/v1')
    ->withHttpClient(new \GuzzleHttp\Client(['timeout' => 120, 'connect_timeout' => 5]))
    ->make();

Tieni la chiave nell'ambiente (o nel .env del tuo framework), mai nel codice sorgente. Il timeout di Guzzle è in secondi e copre l'intera richiesta; aumentalo per le chiamate lunghe di reasoning o di streaming.

Chat

$result = $client->chat()->create([
    'model' => 'openai/gpt-5-mini',
    'messages' => [
        ['role' => 'user', 'content' => 'Explain vector databases in two sentences.'],
    ],
]);

echo $result->choices[0]->message->content;

Streaming

$stream = $client->chat()->createStreamed([
    'model' => 'anthropic/claude-sonnet-4.5',
    'messages' => [['role' => 'user', 'content' => 'Write a haiku about APIs.']],
]);

foreach ($stream as $response) {
    echo $response->choices[0]->delta->content;
}

Vedi Streaming.

Tool calling

$tools = [[
    'type' => 'function',
    'function' => [
        'name' => 'get_weather',
        'description' => 'Current weather for a city',
        'parameters' => [
            'type' => 'object',
            'properties' => ['city' => ['type' => 'string']],
            'required' => ['city'],
        ],
    ],
]];
$messages = [['role' => 'user', 'content' => "What's the weather in Istanbul?"]];

while (true) {
    $response = $client->chat()->create(['model' => 'openai/gpt-5-mini', 'messages' => $messages, 'tools' => $tools]);
    $message = $response->choices[0]->message;
    if (empty($message->toolCalls)) {
        echo $message->content;
        break;
    }
    $messages[] = $message->toArray();
    foreach ($message->toolCalls as $call) {
        $args = json_decode($call->function->arguments, true);
        $messages[] = [
            'role' => 'tool',
            'tool_call_id' => $call->id,
            'content' => json_encode(getWeather($args['city'])), // la tua funzione
        ];
    }
}

Vedi Tool calling.

Output strutturato

$result = $client->chat()->create([
    'model' => 'openai/gpt-5-mini',
    'messages' => [['role' => 'user', 'content' => 'Extract: Ada Lovelace, born 1815 in London.']],
    'response_format' => [
        'type' => 'json_schema',
        'json_schema' => [
            'name' => 'person',
            'strict' => true,
            'schema' => [
                'type' => 'object',
                'properties' => [
                    'name' => ['type' => 'string'],
                    'born' => ['type' => 'integer'],
                    'city' => ['type' => 'string'],
                ],
                'required' => ['name', 'born', 'city'],
                'additionalProperties' => false,
            ],
        ],
    ],
]);

$person = json_decode($result->choices[0]->message->content, true, flags: JSON_THROW_ON_ERROR);

Vedi Output strutturati.

Input di immagini

$image = base64_encode(file_get_contents('photo.png'));

$result = $client->chat()->create([
    'model' => 'google/gemini-2.5-flash',
    'messages' => [[
        'role' => 'user',
        'content' => [
            ['type' => 'text', 'text' => 'What is in this picture?'],
            ['type' => 'image_url', 'image_url' => ['url' => "data:image/png;base64,{$image}"]],
        ],
    ]],
]);

Vedi Visione e file.

Embeddings

$result = $client->embeddings()->create([
    'model' => 'openai/text-embedding-3-small',
    'input' => ['The quick brown fox', 'Lorem ipsum'],
]);

echo count($result->embeddings[0]->embedding);

Sintesi vocale

$audio = $client->audio()->speech([
    'model' => 'openai/gpt-4o-mini-tts',
    'input' => 'Hello from api14!',
    'voice' => 'alloy',
]);

file_put_contents('speech.mp3', $audio);

Errori

Gli errori del gateway usano il formato OpenAI, quindi il client genera OpenAI\Exceptions\ErrorException con lo stato e il codice leggibile da macchina:

use OpenAI\Exceptions\ErrorException;

try {
    $client->chat()->create([
        'model' => 'openai/gpt-5-mini',
        'messages' => [['role' => 'user', 'content' => 'Hi']],
    ]);
} catch (ErrorException $e) {
    match ($e->getStatusCode()) {
        402 => error_log('Balance too low, add funds: ' . $e->getErrorCode()), // insufficient_balance
        429 => error_log('Rate limited, retry in 60s: ' . $e->getErrorCode()),  // rate_limited
        default => throw $e,
    };
}

Il gateway invia Retry-After: 60 con rate_limited. Vedi Limiti di frequenza ed Errori.

Retry con backoff

openai-php/client non ripete le richieste da solo. Avvolgi le chiamate in un piccolo ciclo che riprova rate_limited e 5xx, e rinuncia per tutto il resto:

use OpenAI\Exceptions\ErrorException;
use OpenAI\Exceptions\TransporterException;

function withRetry(callable $fn, int $attempts = 5): mixed
{
    for ($i = 0; ; $i++) {
        try {
            return $fn();
        } catch (ErrorException $e) {
            $retryable = $e->getErrorCode() === 'rate_limited' || $e->getStatusCode() >= 500;
            if (!$retryable || $i + 1 >= $attempts) throw $e;
        } catch (TransporterException $e) { // errore di rete o timeout
            if ($i + 1 >= $attempts) throw $e;
        }
        usleep((min(60, 2 ** $i) * 1000 + random_int(0, 1000)) * 1000); // backoff + jitter
    }
}

$result = withRetry(fn () => $client->chat()->create([
    'model' => 'openai/gpt-5-mini',
    'messages' => [['role' => 'user', 'content' => 'Hi']],
]));

daily_limit_reached e insufficient_balance non vengono ripetuti, perché aspettare qualche secondo non li risolve.

Tutte le funzionalità

import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api14.com/api/v1",
  apiKey: process.env.API14_API_KEY,
});

const result = await client.chat.completions.create({
  "model": "openai/gpt-5-mini",
  "messages": [
    {
      "role": "user",
      "content": "Explain vector databases in two sentences."
    }
  ]
});
console.log(result.choices[0].message.content);