Esperienza utente elevata Implementazione dell’API di OpenAI Assistant per chatbot interattivi

Massima esperienza utente Implementazione dell'API di OpenAI Assistant per chatbot interattivi

Introduzione

Con l’introduzione di ChatGPT e dei modelli GPT 3 di OpenAI, il mondo si è orientato verso l’utilizzo di applicazioni integrate con l’IA. In tutte le applicazioni che utilizziamo quotidianamente, dal commercio elettronico alle applicazioni bancarie, l’IA integra alcune parti dell’applicazione, in particolare i Large Language Models. Uno di questi è l’OpenAI Assistant API, ossia i chatbot. OpenAI ha recentemente rilasciato Assistants API in versione beta, uno strumento progettato per migliorare l’esperienza dell’utente.

Obiettivi di apprendimento

  • Apprendere il processo di creazione di assistenti AI specifici mediante istruzioni specifiche.
  • Esplorare il concetto di fili persistenti e infinitamente lunghi nell’API Assistants.
  • Dimostrare la creazione di un assistente AI utilizzando la libreria OpenAI, specificando parametri come nome, istruzioni, modello e strumenti.
  • Apprendere il processo di creazione di esecuzioni per eseguire assistenti AI su fili specifici.
  • Comprendere la struttura dei prezzi dell’API Assistants, considerando fattori come i token del modello di linguaggio, le sessioni dell’interprete di codice e l’uso dello strumento di recupero.

Questo articolo è stato pubblicato come parte del Data Science Blogathon.

Cos’è Assistants API? Cosa può fare?

OpenAI ha recentemente lanciato l’Assistants API, attualmente in fase beta. Questa API ci consente di costruire e integrare assistenti AI nelle nostre applicazioni utilizzando i Large Language Models e gli strumenti di OpenAI. Le aziende personalizzano questi assistenti per uno scopo specifico e forniscono loro i dati pertinenti per quell’uso particolare. Esempi di questa assistenza includono un assistente AI per il meteo che fornisce informazioni relative al meteo o un assistente AI per i viaggi che risponde a domande relative ai viaggi.

Questi assistenti sono costruiti con la continuità in mente. Cioè, mantengono in gran parte le conversazioni precedenti, permettendo ai sviluppatori di non preoccuparsi della gestione dello stato e di lasciarlo all’OpenAI. Il flusso tipico è il seguente:

  • Creazione di un Assistente, dove selezioniamo i dati da inserire, quale modello utilizzare, istruzioni per l’Assistente e quali strumenti utilizzare.
  • Quindi creiamo un Fili. Un filo memorizza i messaggi dell’utente e le risposte di LLM. Questo filo è responsabile della gestione dello stato dell’Assistente e OpenAI si occupa di questo.
  • Dopo la creazione del Filo, aggiungiamo messaggi ad esso. Questi sono i messaggi che l’utente digita per l’AI Assistant o le risposte dell’Assistente.
  • Infine, eseguiamo l’Assistente su quel filo. In base ai messaggi su quel filo, l’AI Assistant chiama gli LLM di OpenAI per fornire una risposta adatta e può anche contattare alcuni strumenti intermedi, di cui parleremo nella sezione successiva.

Tutti questi assistente, filo, messaggio e esecuzione sono chiamati Oggetti nell’API Assistant. Oltre a questi oggetti, c’è un altro oggetto chiamato Passo di esecuzione, che ci fornisce i passi dettagliati che l’Assistente ha compiuto nella esecuzione, fornendo così una visione interna del suo funzionamento.

Strumenti – L’arsenale dell’Assistants API

Abbiamo costantemente menzionato la parola strumento, quindi cosa ha a che fare con l’OpenAI Assistant API? Gli strumenti sono come armi, che consentono all’API Assistants di svolgere compiti aggiuntivi. Questi includono gli strumenti ospitati da OpenAI come il recupero di conoscenze e l’interprete di codice. Possiamo anche definire strumenti personalizzati utilizzando la chiamata di funzione, di cui non parleremo in questo articolo.

Quindi, esaminiamo dettagliatamente gli strumenti rimanenti.

  • Interpretazione del codice: Questo interpreta il codice Python all’interno di un ambiente sandbox, consentendo all’API Assistants di eseguire script Python personalizzati. Utile per scenari come l’analisi dei dati, in cui l’Assistente può generare codice per analizzare dati CSV, eseguirlo e fornire una risposta all’utente.
  • Chiamata di funzioni: Gli sviluppatori possono definire strumenti personalizzati, consentendo all’Assistente di costruire iterativamente risposte utilizzando questi strumenti e i loro output.
  • Recupero: Essenziale per gli assistenti AI, implica fornire dati per l’analisi. Ad esempio, quando si crea un assistente per un prodotto, le informazioni pertinenti vengono suddivise, incorporate e archiviate in un archivio di vettori. L’Assistente recupera questi dati dalla base di conoscenza quando risponde alle domande degli utenti.

Costruzione del nostro assistente

In questa sezione, passeremo alla creazione di un assistente, all’aggiunta di messaggi a un thread e all’esecuzione dell’assistente su quel thread. Inizieremo scaricando la libreria OpenAI.

# installa la libreria openai che contiene l'API Assistants!pip install openai

Assicurati di utilizzare l’ultima versione (v.1.2.3 è la versione più recente al momento della stesura di questo articolo). Iniziamo creando il nostro cliente.

# importa la libreria os per leggere le variabili d'ambienteimport os# importa la libreria openai per interagire con l'API degli assistentifrom openai import OpenAI# memorizza la OPENAI API KEY in una variabile d'ambienteos.environ["OPENAI_API_KEY"] = "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"# crea il nostro client OpenAI fornendo la chiave APIclient = OpenAI(api_key = os.environ['OPENAI_API_KEY'])

Creazione di un assistente

Importiamo quindi la classe OpenAI dalla libreria openai. Successivamente, memorizziamo il nostro token API di OpenAI nella variabile d’ambiente. E quindi, istanziamo una classe OpenAI con la chiave API come variabile. La variabile client è l’istanza della classe OpenAI. Ora è il momento di creare il nostro assistente.

# creazione di un assistente assistant = client.beta.assistants.create(    name="PostgreSQL Expert",    instructions="Sei un esperto di PostgreSQL e puoi rispondere a qualsiasi domanda in modo semplice con un esempio",    model="gpt-4-1106-preview",    tools=[{"type":"retrieval"}])
  • Per creare un assistente, chiamiamo il metodo create() della classe assistants e passiamo i seguenti parametri
  • name: Questo è il nome del nostro assistente. In questo esempio, lo chiamiamo PostgreSQL Expert
  • instructions: Questo è il contesto/informazioni aggiuntive fornite all’assistente.
  • model: Il modello che l’assistente userà per generare le risposte. In questo caso, stiamo utilizzando un nuovo modello di anteprima GPT-4
  • tools: Questi sono gli strumenti di cui abbiamo parlato nella sezione precedente, che l’assistente utilizzerà per generare le risposte. Passiamo gli strumenti come una lista di dizionari. Qui, stiamo utilizzando lo strumento di recupero per l’assimilazione dei dati

Carica i documenti

Abbiamo quindi creato e assegnato un assistente alla variabile assistente. Il passo successivo sarà caricare i documenti.

# carica il filefile = client.files.create(    file=open(        "/content/LearnPostgres.pdf",        "rb",    ),    purpose="assistants",)# aggiorna l'assistenteassistant = client.beta.assistants.update(    assistant.id,    file_ids=[file.id],)
  • Il codice precedente serve a creare e incorporare un documento nell’assistente. Qui, ho un PDF (clicca qui per scaricare il PDF) che contiene informazioni di apprendimento su PostgreSQL.
  • Utilizziamo la classe files di OpenAI per crearne un file utilizzando il metodo create() e passiamo “assistants” come valore della variabile purpose in quanto questo deve essere aggiunto all’assistente.
  • Nel secondo passaggio, aggiorniamo il nostro assistente con il file creato. Per fare ciò, chiamiamo il metodo update() e passiamo l’ID dell’assistente (abbiamo già creato un oggetto assistente e quest’ultimo contiene un ID univoco) e gli ID dei file (ogni file creato avrà il proprio ID univoco).

Poiché abbiamo incluso lo strumento di recupero nella configurazione del nostro assistente, si occupa di suddividere il nostro LearnPostres.pdf, convertirlo in embed e reperire le informazioni rilevanti da esso.

Creazione di un thread e memorizzazione dei messaggi

In questa sezione, creeremo un Thread e aggiungeremo dei Messaggi ad esso. Inizieremo creando un nuovo Thread.

# creazione di un threadthread = client.beta.threads.create()

Il metodo create() della classe threads viene utilizzato per creare un Thread. Un Thread rappresenta una sessione di conversazione. Similmente agli assistenti, l’oggetto Thread avrà anche un ID unico associato ad esso. Inoltre, notate che non abbiamo passato alcun ID Assistente, implicando che il Thread è isolato e non accoppiato all’assistente. Ora, aggiungiamo un messaggio al nostro Thread appena creato.

# aggiunta del nostro primo messaggio al threadmessage = client.beta.threads.messages.create(thread_id=thread.id, role="user", content="Come creare una tabella in PostgreSQL")
  • I messaggi sono i blocchi di conversazione che contengono le query e le risposte dell’utente. Per aggiungere un messaggio a un Thread, utilizziamo il metodo create() della classe messages, e richiede i seguenti parametri
  • thread_id: Un ID unico associato ad ogni Thread creato. Qui, passiamo l’ID thread del Thread che abbiamo creato in precedenza.
  • role: Chi è il mittente / invia questo messaggio? Nel nostro caso, è l’utente.
  • content: Questa è la query dell’utente. Nel nostro esempio, la impostiamo su “Come creare una tabella in PostgreSQL.”

Esecuzione del nostro Assistente

Ora, eseguiamo l’Assistente creando una Run sul Thread su cui vogliamo che il nostro Assistente si esegua.

# Creazione di una Runrun = client.beta.threads.runs.create(thread_id=thread.id, assistant_id=assistant.id)
  • Per creare una Run, utilizziamo il metodo create() della classe runs. E gli passiamo l’ID del Thread, ovvero su quale Thread (ovvero, quale sessione di conversazione) vogliamo che l’Assistente si esegua e l’ID dell’Assistente (cioè, quale Assistente eseguire) e lo passiamo alla variabile run.
  • La creazione di una Run non produrrà la risposta. Invece, dobbiamo attendere finché la Run è completata. Una Run può essere considerata un’attività asincrona, dove dobbiamo controllare se la Run è stata completata o meno.

Creazione di una Funzione

L’oggetto fornisce una variabile chiamata status, che indica se una particolare Run è in coda / in corso / completata. Per fare ciò, creiamo la seguente funzione.

import time# creazione di una funzione per verificare se la Run è completata o nondef poll_run(run, thread):    while run.status != "completed":        run = client.beta.threads.runs.retrieve(            thread_id=thread.id,            run_id=run.id,        )        time.sleep(0.5)    return run    # attendiamo il completamento della runrun = poll_run(run, thread)
  • Qui, creiamo una funzione chiamata poll_run(). Questa funzione prende come argomenti i nostri oggetti Run e Thread creati in precedenza.
  • Una Run viene considerata elaborata quando il suo status è “completed”. Pertanto, controlliamo la Run per verificare se il suo stato è stato completato o meno in un ciclo.
  • In questo ciclo, chiamiamo il metodo retrieve() della classe runs e gli passiamo l’ID Run e l’ID Thread. Il metodo retrieve restituirà lo stesso oggetto Run con uno stato aggiornato.
  • Ora, controlliamo se lo stato è stato aggiornato a completato recuperando l’oggetto Run ogni 0.5 secondi e verificando il completamento.
  • Se lo status della Run diventa completato, allora restituiamo la Run.

In questo passaggio di Run, l’Assistente che abbiamo creato utilizzerà lo strumento di Recupero per recuperare le informazioni rilevanti relative alla query dell’utente dai dati disponibili chiamando il modello che abbiamo specificato con i dati applicabili e generare una risposta. Questa risposta generata viene memorizzata nel Thread. Ora, il nostro thread ha due messaggi: uno è la query dell’utente e l’altro è la risposta dell’Assistente.

Come Archiviare i Messaggi nel Thread?

Prendiamo i messaggi archiviati nel nostro Thread.

# estrazione dei messagemessages = client.beta.threads.messages.list(thread_id=thread.id)for m in messages:    print(f"{m.role}: {m.content[0].text.value}")
  • Nel primo passaggio, estraiamo tutti i messaggi nel Thread chiamando il metodo list() della classe messages. A questo scopo, passiamo l’ID del Thread per estrarre i messaggi del Thread desiderato
  • Successivamente, iteriamo su tutti i messaggi nella lista e li stampiamo. Il messaggio che abbiamo caricato nel Thread e i messaggi generati dall’Assistente sono archiviati in message.content[0].text.value dell’oggetto del messaggio

L’immagine sopra mostra la Risposta dell’Assistente nella parte superiore e la Query dell’Utente nella parte inferiore. Ora, diamo un secondo messaggio e testiamo se l’Assistente può accedere alla conversazione precedente.

# creazione di un secondo messaggio message2 = client.beta.threads.messages.create(    thread_id=thread.id,    role="user",    content="Aggiungi del valore alla tabella che hai creato")# creazione di un Runrun = client.beta.threads.runs.create(    thread_id=thread.id,    assistant_id=assistant.id)# attesa che il metodo Run sia completato run = poll_run(run, thread)# estrazione dei messagemessages = client.beta.threads.messages.list(thread_id=thread.id)for m in messages:    print(f"{m.role}: {m.content[0].text.value}")
  • Qui, creiamo un altro messaggio chiamato message2, e questa volta, stiamo passando la query “Aggiungi del valore alla tabella che hai creato.” Questa query si riferisce alla conversazione precedente e quindi la passa al nostro Thread.
  • Poi procediamo con lo stesso processo di creazione di un Run, esecuzione con l’Assistente e polling.

Infine, stiamo recuperando e stampando tutti i messaggi dal Thread.

L’Assistente può effettivamente accedere alle informazioni dalla conversazione precedente e utilizzare anche lo strumento di Recupero per generare una risposta alla query fornita. Pertanto, attraverso l’API dell’Assistente OpenAI, possiamo creare Assistenti personalizzati e poi integrarli in qualsiasi forma nelle nostre applicazioni. OpenAI sta anche pianificando di rilasciare molti strumenti che l’API dell’Assistente può utilizzare.

Tariffe dell’API dell’Assistente

L’API dell’Assistente viene addebitata in base al modello selezionato e agli strumenti utilizzati. Gli strumenti come il Recupero e l’Interprete di Codice hanno ciascuno un costo separato. Iniziamo con il modello, ogni modello in OpenAI ha il suo costo separato in base al numero di token utilizzati per l’input e al numero di token di output generati. Pertanto, per le tariffe del modello, clicca qui per controllare tutte le tariffe del Linguaggio Modello Grande di OpenAI.

Per quanto riguarda l’Interprete di Codice, ha un costo di $0,03 per sessione, con le sessioni attive per un’ora di default. Una sessione è associata a un Thread, quindi se hai N Threads in esecuzione, il costo sarà N * $0,03.

D’altra parte, il Recupero ha un costo di $0,20 per GB per assistente al giorno. Se N Assistenti accedono a questo strumento, il prezzo sarà N * $0,2 / Giorno. Il numero di Thread non influisce sul prezzo del recupero.

Privacy dei Dati e Preoccupazioni Etiche

Riguardo alle Preoccupazioni Etiche e all’uso dei Dati dell’Utente, OpenAI mette la Privacy dei Dati al primo posto. L’utente sarà il solo proprietario dei dati inviati all’API OpenAI e dei dati ricevuti da essa. Inoltre, OpenAI non si allena sui dati dell’utente e la longevità dei dati è sotto il controllo dell’utente. Anche i modelli personalizzati formati in OpenAI appartengono solo all’utente che li ha creati.

OpenAI segue rigide regole di conformità. Consente la crittografia dei dati a riposo (tramite AES-256) e durante il trasferimento (TLS 1.2+). OpenAI è stata sottoposta ad un’audit per la conformità SOC 2, il che significa che OpenAI si impegna rigorosamente per la privacy e la sicurezza dei dati. OpenAI permette un rigoroso controllo di accesso su chi può accedere ai dati all’interno dell’organizzazione.

Conclusioni

La API degli Assistants di OpenAI offre un nuovo approccio per creare e integrare assistenti AI nelle applicazioni. Questi assistenti sono stati sviluppati per affrontare uno scopo o un compito specifico. Come abbiamo esplorato le funzionalità e gli strumenti di questa API, inclusi l’interprete di codice, il recupero dei dati e la creazione di strumenti personalizzati, diventa evidente che gli sviluppatori hanno a disposizione un potente arsenale. La natura persistente degli assistenti, gestita in modo fluido tramite i Threads, riduce l’onere degli sviluppatori, consentendo loro di concentrarsi sulla creazione di esperienze AI personalizzate.

Punti Chiave

  • La API degli Assistants permette lo sviluppo di assistenti AI specifici per scopi particolari.
  • L’inclusione di strumenti come l’interprete di codice e il recupero dei dati amplia le possibilità di ciò che gli assistenti AI possono realizzare, dalla gestione di codice Python personalizzato all’accesso a conoscenze esterne.
  • La API introduce threads persistenti e infinitamente lunghi, semplificando la gestione dello stato e offrendo flessibilità agli sviluppatori.
  • I threads e gli assistenti sono isolati, consentendo agli sviluppatori di utilizzare thread duplicati ed eseguire altri assistenti.
  • Lo strumento di chiamata di funzione permette agli sviluppatori di utilizzare strumenti personalizzati che l’assistente può utilizzare durante il processo di generazione delle risposte.

Domande Frequenti

Riferimenti

Ecco la documentazione ufficiale riguardante la API degli Assistants di OpenAI

  • https://platform.openai.com/docs/assistants/overview
  • https://platform.openai.com/docs/api-reference/assistants

I media mostrati in questo articolo non sono di proprietà di Analytics Vidhya e vengono utilizzati a discrezione dell’autore.