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);