Nella lezione precedente abbiamo parlato di come sfruttare l'integrazione di ChatGPT su Terminale Linux per generare istruzioni da linea di comando e codice. Questa volta ragioneremo invece al contrario: il codice sarà scritto da noi per interrogare il chatbot di OpenAI. Nello specifico capiremo come inviare query al modello generativo della piattaforma da un semplice script PHP.
Requisiti per l'applicazione
Di seguito un breve elenco degli strumenti che saranno utilizzati per la realizzazione del progetto.
API key e Organization ID
Oltre ad un ambiente di sviluppo basato su PHP, per la nostra applicazione abbiamo bisogno delle API key di OpenAI. La procedura per richiederne una è presente in questa parte della guida ed è molto semplice. Anche in questo caso vale la pena di ripetere che il servizio fornisce gratuitamente un credito di 18 dollari per testare le sue interfacce di programmazione. Se la medesima API Key viene utilizzata da più organizzazioni è utile specificare anche l'ID dell'organizzazione che intende impiegarla. Tale informazione è disponibile accedendo al proprio account da questa pagina, per poi seguire il percorso di menu "Personal > Manage Account > Settings".
Librerie e modelli
Esistono diverse librerie PHP che permettono di interagire con le interfacce di programmazione di OpenAI, basti citare l'OpenAI API Client di Orhanerday disponibile tramite GitHub e installabile con Composer. In questo caso però utilizzeremo esclusivamente codice vanilla e la sintassi nativa del linguaggio, senza ricorrere a framework o client preconfezionati.
Un altro punto importante riguarda la scelta del modello da interrogare. Quest'ultimo influisce su diversi fattori tra cui la velocità con cui vengono generati gli output, il loro livello di precisione e il costo per l'utilizzo delle API. Vi sono inoltre modelli sviluppati per finalità particolari, come Whisper per la conversione di audio in testo. Nell'applicazione utilizzeremo un modello del set GPT-3.5 e nello specifico gpt-3.5-turbo
.
Quest'ultimo supporta fino a 4.096 token ed è stato addestrato con dati aggiornati al settembre 2021. Per interagire con esso utilizzeremo la libreria Open Source cURL. Essa permette di comunicare con servizi esterni tramite protocolli di rete, compresi quelli che richiedono autenticazione. Se si opera da Linux, ad esempio su Mint, l'estensione PHP per cURL potrebbe non essere installata di default. Il problema è risolvibile aggiornando i package presenti nel sistema:
sudo apt update
per poi installare la libreria cURL da linea di comando tramite l'istruzione:
sudo apt install curl
Il buon esito dell'operazione può essere verificato lanciando il comando curl
. Perché PHP possa utilizzare la libreria è però necessario abilitare la relativa estensione nel file di configurazione php.ini
. Apriamolo quindi con il nostro editor preferito e decommentiamo la riga corrispondente:
Salviamo la modifica effettuata e riavviamo il Web server in uso, ad esempio Apache:
sudo service apache2 restart
o nginx:
sudo service nginx restart
In questo modo avremo tutto quello che ci serve per completare il nostro progetto.
Il codice dell'applicazione
La prima parte dell'applicazione deve essere dedicata alla definizione di tutti i dati utili per la comunicazione con la piattaforma. Come anticipato tra questi ultimi vi sono l'API key di OpenAI, l'Organization ID (che è un dato opzionale ma utile se si gestiscono più progetti tra diverse realtà che fanno capo ad un unico account) e il modello GPT di riferimento (o "engine"). A questi si aggiunge l'URL per la chiamata alle API che consente di interloquire con il modello tramite queste ultime.
// API KEY per l'autenticazione
$api_key = "sk-xxxxxxxxxxxxxxxxxxxxxxxx";
// URL del servizio
$url = 'https://api.openai.com/v1/chat/completions';
// ID dell'organizzazione
$org_id = "org-xxxxxxxxxxxxxxxxxxxxxxxx";
// Modello generativo da utilizzare
$modello = "gpt-3.5-turbo";
Nella seconda parte del codice l'API key e l'Organizzation ID vengono passate come valori per i parametri di intestazione.
$headers = array(
"Authorization: Bearer {$api_key}",
"OpenAI-Organization: {$org_id}",
"Content-Type: application/json"
);
La parte più interessante di questo passaggio riguarda l'intestazione "Content-Type: application/json"
. Essa infatti indica che il corpo della richiesta HTTP sfrutta JSON (JavaScript Object Notation) per i dati. Tale formato viene utilizzato per l'interscambio di informazioni tra applicazioni Web e ne offre una rappresentazione strutturata. "Content-Type: application/json"
definisce quindi il tipo di contenuto del messaggio e permette a server e client di elaborare in modo corretto i dati contenuti nel corpo del messaggio.
Invio del messaggio al chatbot
Un volta definite le intestazioni, si passa all'impostazione del messaggio (prompt) da inviare al chatbot, cioè un qualsiasi tipo di quesito (content
) da parte dell'utente a cui il sistemo possa rispondere in linguaggio colloquiale.
// Richiesta al chatbot
$messages = array();
$messages[] = array("role" => "user", "content" => "Parlami di PHP");
Il messaggio viene memorizzato in un array ($messages
) che diventa a sua volta parte di un array multidimensionale ($data
) destinato a contenere i parametri per la restituzione dell'output. In $data
, oltre al messaggio abbiamo quindi il modello precedentemente indicato ($modello = "gpt-3.5-turbo";
) e i valori associati alle opzioni max_tokens e temperature
. Il primo indica il numero massimo di token utilizzabili per la generazione delle risposte. Se elevato max_tokens
può determinare una spesa maggiore per l'uso delle API ma risposte più approfondite, se basso permette un maggior controllo dei costi ma può dar luogo ad output incompleti. Il secondo accetta valori compresi tra 0 e 1: con valori vicini allo 0 si dovrebbero avere risposte più strutturate, man mano che ci si avvicina ad 1 esse tendono invece ad essere più creative.
// Parametri per la restituzione dell'output
$data = array();
$data["model"] = $modello;
$data["messages"] = $messages;
$data["max_tokens"] = 150;
$data["temperature"] = 0.7;
La sessione cURL
A questo punto raccogliamo intestazioni e parametri e, dopo aver inizializzato la sessione cURL, utilizziamoli per l'invio del messaggio alle API. Viene così creato un handle ($curl
) da passare a curl_exec()
, funzione PHP che esegue la richiesta HTTP e restituisce la risposta sotto forma di stringa. Eventuali errori durante questa fase verranno segnalati dall'applicazione, diversamente essa procederà con la stampa della stringa.
// Sessione cURL
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
// Esecuzione della richiesta HTTP e restituzione del risultato
$result = curl_exec($curl);
if (curl_errno($curl)) {
// Messaggio di errore
echo "Attenzione: " . curl_error($curl);
} else {
// Stampa del risutato
echo "<pre>";
var_dump($result);
echo "</pre>";
}
curl_close($curl);
Decodifica JSON e output del chatbot
La stampa del risultato permette di visualizzare la stringa JSON contenente la risposta e tutte le intestazioni di quest'ultima. A questo punto possiamo quindi decodificare tale stringa tramite la funzione json_decode()
ed estrarre ad esempio il conteggio dei token utilizzati per la richiesta e la generazione dell'output.
// Decodifica della risposta JSON
$json_response = json_decode($result, true);
// Report sui token utilizzati
echo "In questa chat sono stati utilizzati " . $json_response["usage"]["prompt_tokens"] . " token per il prompt.<br />";
echo $json_response["usage"]["completion_tokens"] . " token per l'output.<br />";
echo $json_response["usage"]["total_tokens"] . " token totali utilizzati.<br />";
Per ultima viene stampata la risposta del chatbot. Da notare come quest'ultima risulti tronca perché il sistema considera il valore di max_tokens
troppo basso per poter fornire una risposta completa.
// Estrazione della risposta
$risposta = $json_response["choices"][0]["message"]["content"];
// Stampa la risposta del modello di chat
echo $risposta;
Descrivere PHP come un "linguaggio di programmazione" non è forse la scelta più adatta, così come la definizione fornita di applicazione Open Source appare un po' restrittiva. La precisione del modello può essere quindi migliorata, anche riformulando il prompt, ma in ogni caso il nostro codice ha funzionato.
Il codice dell'applicazione
Per comodità dei lettori riporto di seguito il codice completo della nostra applicazione:
<?php
// API KEY per l'autenticazione
$api_key = "sk-xxxxxxxxxxxxxxxxxxxxxxxx";
// URL del servizio
$url = 'https://api.openai.com/v1/chat/completions';
// ID dell'organizzazione
$org_id = "org-xxxxxxxxxxxxxxxxxxxxxxxx";
// Modello generativo da utilizzare
$modello = "gpt-3.5-turbo";
$headers = array(
"Authorization: Bearer {$api_key}",
"OpenAI-Organization: {$org_id}",
"Content-Type: application/json"
);
// Richiesta al chatbot
$messages = array();
$messages[] = array("role" => "user", "content" => "Parlami di PHP?");
// Parametri per la restituzione dell'output
$data = array();
$data["model"] = $modello;
$data["messages"] = $messages;
$data["max_tokens"] = 150;
$data["temperature"] = 0.7;
// Sessione cURL
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
// Esecuzione della richiesta HTTP e restituzione del risultato
$result = curl_exec($curl);
if (curl_errno($curl)) {
// Messaggio di errore
echo "Attenzione: " . curl_error($curl);
} else {
// Stampa del risutato
echo "<pre>";
var_dump($result);
echo "</pre>";
}
curl_close($curl);
// Decodifica della risposta JSON
$json_response = json_decode($result, true);
// Report sui token utilizzati
echo "In questa chat sono stati utilizzati " . $json_response["usage"]["prompt_tokens"] . " token per il prompt.<br />";
echo $json_response["usage"]["completion_tokens"] . " token per l'output.<br />";
echo $json_response["usage"]["total_tokens"] . " token totali utilizzati.<br />";
// Estrazione della risposta
$risposta = $json_response["choices"][0]["message"]["content"];
// Stampa la risposta del modello di chat
echo $risposta;
?>
Conclusioni
Le API di OpenAI permettono di interrogare il modello generativo GPT sfruttando vari linguaggi. In precedenza abbiamo analizzato l'esempio di Python, in questa lezione abbiamo proposto invece un esempio basato su PHP. A breve scopriremo altre modalità per l'utilizzo di queste interfacce.