Costruire un robusto backend per l’assistente AI!
Con il progredire della tecnologia AI, si prevede che gli assistenti AI svolgeranno un ruolo sempre più significativo nella gestione dell’assistenza clienti aziendale. La maggior parte delle aziende ha già integrato un qualche tipo di IA nei propri flussi di lavoro.
In questo articolo parleremo degli assistenti AI, evidenziandone gli incredibili vantaggi e i potenziali svantaggi.
Inoltre, forniremo una guida completa passo-passo sulla creazione di un assistente basato sull’intelligenza artificiale utilizzando OpenAI e Back4app.
Contents
Che cos’è un assistente AI?
Un assistente AI è un software che riceve una richiesta tramite testo o voce e genera una risposta.
Questa tecnologia utilizza, tra l’altro, l’elaborazione del linguaggio naturale (NLP) e l’apprendimento automatico.
Lo scopo degli assistenti AI è quello di imitare una conversazione simile a quella umana.
Nel corso dell’articolo, utilizzeremo le parole assistente AI e chatbot AI in modo intercambiabile. Tuttavia, alcuni potrebbero sostenere che un assistente è una versione più complessa di un chatbot, in grado di svolgere anche attività.
Alcuni esempi di assistenti AI popolari sono ChatGPT, Claude e Gemini.
Alcune applicazioni di assistente AI includono:
- Assistenza clienti (gli assistenti AI possono essere addestrati a rispondere alle domande dei clienti)
- Aiuto agli sviluppatori (gli assistenti AI possono generare codice e aiutare gli sviluppatori a lavorare in modo efficiente)
- Formazione (gli assistenti possono essere utilizzati per scopi didattici e per l’onboarding degli utenti)
- Marketing e analisi (gli assistenti possono generare materiale di marketing e analizzare i dati)
- Intrattenimento (i chatbot AI possono creare risposte divertenti o creative)
Vantaggi degli assistenti AI
Gli assistenti AI offrono una serie di vantaggi. Vediamoli!
Aumentare la produttività
Gli assistenti AI consentono di aumentare notevolmente la produttività aziendale.
Possono essere utilizzati per l’organizzazione dei compiti, le operazioni commerciali, l’assistenza ai clienti, il marketing, ecc.
Utilizzando l’intelligenza artificiale, è possibile creare un’assistenza clienti altamente scalabile e autonoma, disponibile 24 ore su 24, 7 giorni su 7.
Inoltre, gli sviluppatori possono sfruttare gli assistenti AI per scrivere, revisionare e documentare il codice. Esistono già diversi strumenti specializzati per questo scopo, tra cui GitHub Copilot, OpenAI Codex e CodePal.
Facilità d’uso
Gli assistenti AI sono tra i software più accessibili perché “capiscono” il testo umano. Quasi tutti, a prescindere dalla loro esperienza tecnologica, possono utilizzarli.
Tagliare i costi
Gli assistenti AI possono aiutarvi a ridurre significativamente i costi ottimizzando i processi di lavoro e automatizzando l’assistenza ai clienti. Alcuni studi hanno scoperto che l’IA aiuta le aziende a ridurre i costi fino al 20%.
Recupero delle informazioni
Uno dei vantaggi migliori degli assistenti AI è la loro capacità di reperire informazioni. Possono interrogare rapidamente diversi documenti e restituire una risposta semplice e leggibile per l’utente.
Inoltre, possono accompagnare le risposte con le fonti.
Grazie ai recenti progressi dell’API di OpenAI, è ora possibile addestrare i bot utilizzando i dati aziendali senza alcuno sforzo.
Personalizzazione e personalizzazione
Gli assistenti AI sono altamente personalizzabili. Per riproporre un assistente è sufficiente cambiare le istruzioni o la cosiddetta richiesta iniziale.
Inoltre, gli assistenti AI possono fornire risposte personalizzate in base all’interlocutore.
Ad esempio, possono rispondere alla domanda dell’utente nella sua lingua madre o considerare il contesto delle conversazioni precedenti.
Svantaggi degli assistenti AI
Nulla è privo di inconvenienti.
Allucinazioni
I chatbot AI a volte generano informazioni false o senza senso. Quando ciò accade, si dice che il chatbot ha avuto un’allucinazione.
Il motivo è che i bot non capiscono realmente ciò che dicono, ma generano solo la parola successiva più probabile in base alle parole precedenti.
Se siete curiosi di sapere come funzionano i chatbot AI come ChatGPT, date un’occhiata a questo articolo.
Non è in grado di eseguire operazioni complesse
Gli assistenti AI sono ottimi per le attività semplici e ripetitive, ma falliscono miseramente quando si chiede loro di svolgere compiti complessi.
Mancano di buon senso e di intelligenza umana in generale. Se la risposta non rientra nel materiale didattico del chatbot, è probabile che restituisca una risposta errata.
Inoltre, non garantiscono risultati ottimali.
Manutenzione
Per garantire che i chatbot addestrati sui documenti aziendali forniscano informazioni accurate e aggiornate, è necessario aggiornarli regolarmente con i documenti più recenti. Senza questa manutenzione continua, il chatbot potrebbe fornire risposte obsolete.
Problemi di privacy e sicurezza
Gli assistenti devono talvolta trattare informazioni aziendali riservate o dati personali degli utenti. Ciò solleva alcune questioni etiche e rende possibile la fuga di informazioni riservate da parte dell’assistente.
Come costruire un assistente AI?
In questa parte dell’esercitazione, creeremo un assistente virtuale alimentato da GPT.
Il nostro assistente virtuale sarà specializzato nel rispondere a domande di matematica. Utilizzerà i thread, consentendogli di rispondere alle domande successive.
Inoltre, il codice sarà progettato per essere facilmente riproposto e adattato ad altre applicazioni.
Per il backend utilizzeremo OpenAI e Back4app, mentre il frontend sarà realizzato con React (con TailwindCSS).
Prerequisiti
- Conoscenza di base di JavaScript ES6
- Esperienza con React e React Hooks
- Un account OpenAI con alcuni crediti
- Un account Back4app gratuito
Obiettivi
# | Backend | Frontend |
1 | Creare un’applicazione Back4app | Bootstrap di un nuovo progetto |
2 | Aggiornare la versione Node.js dell’applicazione | Installare TailwindCSS |
3 | Creare una chiave segreta OpenAI | Codice dell’interfaccia utente |
4 | Aggiungere la chiave segreta come variabile env | Installare e configurare Parse SDK |
5 | Creare le funzioni di Cloud Code | Connettersi al backend |
Iniziamo a codificare!
Backend
In questa fase del tutorial, ci occuperemo del backend. Creeremo un’applicazione Back4app, creeremo le chiavi segrete di OpenAI, le aggiungeremo come variabili ambientali e scriveremo le funzioni necessarie di Cloud Code.
Creare l’applicazione Back4app
Per prima cosa, accedete al vostro account Back4app o createne uno se non ne avete ancora uno.
Una volta effettuato l’accesso, si verrà reindirizzati all’elenco delle app. Fare clic su “Crea nuova app” per creare un’app.
La piattaforma Back4app consente di distribuire due tipi di applicazioni: Backend as a Service (BaaS) e Containers as a Service (CaaS). Stiamo costruendo un backend, quindi scegliete BaaS.
Quindi, date alla vostra applicazione un nome informativo, lasciate il database come NoSQL e fate clic su “Crea”.
Attendere circa tre minuti affinché la piattaforma crei l’applicazione. Back4app si occuperà di tutto, dalla creazione del livello dell’app all’impostazione del database, alla sicurezza, alla scalabilità e altro ancora.
Una volta fatto, si verrà reindirizzati all’interfaccia del database dell’applicazione.
Cambiare la versione del nodo
Per impostazione predefinita, le applicazioni di Back4app sono alimentate da Parse v4.10.4. Questa versione di Parse Server utilizza Node v14, che è incompatibile con la libreria di OpenAI, che richiede Node v18+.
Aggiorniamo la versione di Parse Server.
Per prima cosa, selezionare “Impostazioni del server” nella barra laterale, quindi navigare fino alle impostazioni di “Gestione del server Parse”, come illustrato nell’immagine seguente.
Cambiare la versione di Parse Server in 5.2.3
o più recente.
Fare clic su “Salva” e attendere qualche minuto affinché Back4app aggiorni la versione del server.
Per verificare la versione di Node.js, si può definire la seguente funzione di Cloud Code:
Parse.Cloud.define("getNodeVersion", async(request) => {
return process.version;
});
Quindi, attivarlo tramite l’API integrata > Console > REST, inviando una richiesta POST
a functions/getNodeVersion
.
Chiavi API OpenAI
Procediamo con la creazione di una chiave API OpenAI per connetterci a OpenAI dal nostro backend.
Accedere alla dashboard di OpenAI e creare un nuovo progetto facendo clic su “Progetto predefinito” e poi su “Crea progetto”.
Date al vostro progetto un nome descrittivo: io sceglierò “back4app”. Dopodiché, fate clic su “Crea”.
OpenAI dovrebbe passare automaticamente al progetto appena creato.
Quindi, accedere alla sezione “Chiavi API” selezionando “Dashboard” nella barra di navigazione e poi “Chiavi API” nella barra laterale. Fare clic su “Crea nuova chiave segreta” per avviare il processo di creazione della chiave API.
Lasciare tutte le impostazioni predefinite e fare clic su “Crea chiave segreta” per confermare la creazione della chiave.
Prendete nota della chiave segreta, perché potrete vederla solo una volta.
Trattate la vostra chiave segreta con la stessa sicurezza di una password. Se qualcun altro ne entra in possesso, potrebbe generare ingenti spese per OpenAI. Inoltre, suggerisco di fissare dei limiti di utilizzo.
Impostare le variabili ambientali
Per evitare di esporre la nostra chiave segreta nel codice sorgente, la aggiungeremo come variabile ambientale.
Andare a “Impostazioni del server > Variabili d’ambiente > Impostazioni”.
Quindi impostare la variabile ambientale OPENAI_API_KEY
come si farebbe in un file .env:
OPENAI_API_KEY=<your_openai_api_key>
Assicurati di sostituire <your_openai_api_key> con la chiave segreta OpenAI del passaggio precedente.
Infine, fare clic su “Salva” per salvare le variabili ambientali.
Ora è possibile accedere alla chiave segreta dalle funzioni di Cloud Code in questo modo:
const secretKey = process.env.OPENAI_API_KEY;
console.log(secretKey);
// sk-proj-...
Cloud Code
Per implementare la logica del backend, utilizzeremo le funzioni Cloud Code. Le funzioni Cloud Code sono una robusta funzionalità di Parse Server che consente agli sviluppatori di eseguire codice JavaScript personalizzato lato server.
Possono essere attivati tramite REST, utilizzando Parse SDK, o programmati su base temporale.
Per saperne di più sulle funzioni come servizio, consultate Che cosa sono le funzioni serverless?
Per prima cosa, selezionare “Cloud Code > Funzioni e Web Hosting” nella barra laterale per accedere a Cloud Code.
Si noterà che la schermata è divisa in due sezioni. A sinistra c’è la struttura delle cartelle e a destra l’editor del codice JavaScript. Per impostazione predefinita, ci sono due directory:
- cartella cloud utilizzata per distribuire le funzioni di Cloud Code e altro codice personalizzato
- cartella pubblica utilizzata per distribuire contenuti statici (ad esempio, immagini, video, icone)
Installare la libreria OpenAI
Per interagire con l’API OpenAI, installeremo la libreria OpenAI JavaScript.
Installare i pacchetti NPM usando Cloud Code è facile. Per farlo, si deve creare un file package.json nella cartella cloud, elencando i pacchetti che si desidera installare.
// cloud/package.json
{
"dependencies": {
"openai": "^4.51.0"
}
}
Per ottenere l’ultima versione del pacchetto
openai
, controllate la pagina dei pacchetti NPM.
Quindi fate clic su “Deploy” in alto a destra dello schermo.
Se l’installazione è andata a buon fine, si dovrebbe vedere un file package-lock.json appena generato nella cartella cloud. Il file di blocco dovrebbe contenere il pacchetto openai
.
Funzioni del Cloud Code
Quindi, occupiamoci delle funzioni di Cloud Code.
Creeremo le seguenti quattro funzioni:
setup()
creerà un assistente virtuale e salverà la sua configurazione nella base dati.createThread()
creerà un nuovo thread assistente virtualedeleteThread(threadId)
elimina un thread dell’assistente virtuale esistenteaddMessage(threadId, message)
aggiunge un messaggio alla discussione e genera una risposta.
Incollare il seguente codice in cloud/main.js:
// cloud/main.js
const OpenAI = require("openai");
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
const ASSISTANT_INITIAL_MESSAGE = "Hi, my name is Math Bot. How can I help you?";
const ASSISTANT_SETTINGS = {
name: "Math Bot",
instructions: "Very smart math bot that answers math questions.",
model: "gpt-3.5-turbo-0125",
tools: [],
};
Parse.Cloud.define("setup", async (request) => {
const Assistant = Parse.Object.extend("Assistant");
const query = await new Parse.Query(Assistant);
const count = await query.count();
// Check if virtual assistant already exists
if (count !== 0) {
throw new Parse.Error(
Parse.Error.VALIDATION_ERROR,
"A virtual assistant already exists!",
);
}
// Use OpenAI's API to create an assistant
const openAssistant = await openai.beta.assistants.create(
ASSISTANT_SETTINGS,
);
// Store the assistant in Back4app database
const assistant = new Assistant();
for (const key in ASSISTANT_SETTINGS) {
assistant.set(key, ASSISTANT_SETTINGS[key]);
}
assistant.set("initialMessage", ASSISTANT_INITIAL_MESSAGE);
assistant.set("assistantId", openAssistant.id);
await assistant.save();
return assistant.get("assistantId");
});
Parse.Cloud.define("createThread", async (request) => {
const thread = await openai.beta.threads.create();
return thread.id;
});
Parse.Cloud.define("deleteThread", async (request) => {
const _threadId = request.params.threadId;
return await openai.beta.threads.del(_threadId);
});
Parse.Cloud.define("addMessage", async (request) => {
const _threadId = request.params.threadId;
const _message = request.params.message;
// Verify all the parameters are provided
if (!_threadId || !_message) {
throw new Parse.Error(
Parse.Error.VALIDATION_ERROR,
"You need to provide: threadId & message.",
);
}
const Assistant = Parse.Object.extend("Assistant");
const query = await new Parse.Query(Assistant);
const count = await query.count();
// Check if a virtual assistant exists
if (count === 0) {
throw new Parse.Error(
Parse.Error.VALIDATION_ERROR,
"A virtual assistant does not exist!",
);
}
const assistant = await new Parse.Query(Assistant).first();
const assistantId = assistant.get("assistantId");
// Get the thread, add the message, and generate a response
let buffer = "";
const message = await openai.beta.threads.messages.create(
_threadId, {role: "user", content: _message},
);
let run = await openai.beta.threads.runs.createAndPoll(
_threadId, {assistant_id: assistantId},
);
// Add the last message to the buffer
if (run.status === "completed") {
const messages = await openai.beta.threads.messages.list(run.thread_id);
buffer += messages.data[0].content[0].text.value;
} else {
console.error("Failed to run the assistant.");
}
return buffer;
});
Panoramica del codice
- Il codice importa e inizializza la libreria OpenAI.
- Quindi definisce le impostazioni dell’assistente (ad esempio,
nome
,istruzioni
einitialMessage
). - Code fornisce quattro funzioni di Cloud Code, descritte in precedenza.
- In
setup()
, si recuperano l’assistente e il thread e si aggiunge un messaggio al thread. Si utilizza quindi un’esecuzione per generare una risposta utilizzando l’assistente.
Testare le funzioni di Cloud Code
Prima di passare al frontend, dobbiamo assicurarci che il backend funzioni come previsto.
Per i test, utilizzeremo la console integrata di Back4app. Andare su “API > Console > REST” nella barra laterale.
Innanzitutto, attivare la funzione setup()
:
- Che tipo di richiesta:
POST
- Quale endpoint:
functions/setup
- Usa chiave master:
false
- Esegui come: lasciare vuoto
- Parametri della query: lasciare vuoto
Questo creerà un nuovo assistente e lo salverà nel database. Se si naviga nella vista del database, si dovrebbe vedere che la classe Assistant
ha ora una riga.
Procediamo con la verifica degli endpoint di conversazione.
POST
afunctions/createThread
per creare una discussione. Prendere nota dell’ID del thread.POST
una domanda afunctions/addMessage
con i seguenti parametri{"threadId": "", "message": "Che cos'è 2+2?"}
. Verificare che la risposta generata sia corretta.POST
afunctions/deleteThread
con i seguenti parametri{"threadId": ""}
per cancellare la discussione.
Ottimo, il backend sembra funzionare bene!
Frontend
In questa sezione del tutorial, avvieremo un nuovo progetto React, installeremo TailwindCSS, implementeremo l’interfaccia utente, configureremo Parse SDK e implementeremo la logica necessaria.
Creare l’app Vite
Si inizia con il bootstrap di un nuovo progetto Vite utilizzando il modello React:
$ npm create vite@latest frontend -- --template react
Cambiare la directory nella cartella appena creata e installare le dipendenze:
$ cd frontend
$ npm install
Eseguire il server di sviluppo:
$ npm run dev
Aprite il vostro browser web preferito e navigate su http://localhost:5174/. Dovreste vedere la pagina di destinazione predefinita di Vite + React.
TailwindCSS
Per semplificare il nostro lavoro, utilizzeremo TailwindCSS, un framework CSS orientato all’utilità che consente di costruire rapidamente progetti personalizzati senza abbandonare l’HTML.
Il framework offre un approccio altamente personalizzabile e reattivo allo stile.
Per installare TailwindCSS, seguite la guida ufficiale.
Visualizzazioni
Procediamo con l’implementazione dell’interfaccia utente.
Per rendere il nostro codice più organizzato, creeremo prima alcuni componenti. Per prima cosa, creare una cartella components all’interno della cartella src e inserire i seguenti tre file:
Inoltre, aggiungere questo avatar.png alla cartella src/assets.
A questo punto la struttura della cartella dovrebbe essere simile a questa:
frontend/
└── src/
├── components/
│ ├── Spinner.jsx
│ ├── AssistantMessage.jsx
│ └── UserMessage.jsx
├── assets/
│ └── avatar.png
└── ...
Quindi, inserire il seguente codice in src/App.jsx:
// src/App.jsx
import {useEffect, useState} from "react";
import AssistantMessage from "./components/AssistantMessage.jsx";
import UserMessage from "./components/UserMessage.jsx";
import Spinner from "./components/Spinner.jsx";
function App() {
const [initialMessage, setInitialMessage] = useState(undefined);
const [loading, setLoading] = useState(true);
const [threadId, setThreadId] = useState(undefined);
const [message, setMessage] = useState("");
const [messages, setMessages] = useState([
{role: "assistant", content: "Welcome! How can I help you today?"},
{role: "user", content: "What is 2+2?"},
{role: "assistant", content: "2+2 is 4."},
]);
async function getInitialMessage() {
// TODO: get the initial message
}
async function reset(message) {
// TODO: create a new thread
}
useEffect(() => {
setLoading(false);
// TODO: get the initial message
}, []);
function onSubmit(event) {
// TODO: add the message to the thread and generate response
}
function onNewThread() {
// TODO: create a new thread
}
return (
<main className="container mx-auto py-8 px-8 md:px-32 lg:px-64 h-[100vh]">
<div className="pb-12 space-y-2">
<h1 className="text-3xl font-bold">
back4app-openai-virtual-assistant
</h1>
<p>
An AI-powered virtual assistant built using OpenAI + Back4app.
</p>
</div>
<div className="space-y-2">
{messages.map((message, index) => {
switch (message.role) {
case "assistant":
return <AssistantMessage key={index} content={message.content}/>;
case "user":
return <UserMessage key={index} content={message.content}/>;
default:
return <></>;
}
})}
{loading && <Spinner/>}
</div>
<form className="inline-block flex flex-row pt-12" onSubmit={onSubmit}>
<input
type="text"
className="w-full p-2 border border-gray-300 rounded-md outline-none"
placeholder="Type a message..."
value={message}
onChange={(event) => setMessage(event.target.value)}
/>
<button
type="submit"
className="bg-blue-500 hover:bg-blue-600 text-white p-2 px-3 rounded-md ml-2"
>
Send
</button>
<button
type="button"
className="bg-green-500 text-white p-2 px-3 rounded-md ml-2"
onClick={onNewThread}
>
New
</button>
</form>
</main>
);
}
export default App;
Questo codice crea una semplice interfaccia utente, che visualizza i messaggi dallo stato dei messaggi
. Inoltre, fornisce una casella di testo e un pulsante per inviare i messaggi all’assistente virtuale.
Avviate nuovamente il server di sviluppo e navigate su http://localhost:5174/. Dovreste essere in grado di vedere un’interfaccia utente simile a quella di ChatGPT.
Installare l’SDK Parse
Per collegarci al nostro backend basato su Back4app, useremo Parse SDK.
L’SDK di Parse consente agli sviluppatori di interagire senza problemi con i backend basati su Parse, consentendo interrogazioni efficienti dei dati, autenticazione degli utenti, notifiche, gestione dei dati in tempo reale e altro ancora.
Per prima cosa, installare Parse tramite npm:
$ npm install parse
Successivamente, accedere all’applicazione Back4app. Selezionare “Impostazioni app > Sicurezza e chiavi” nella barra laterale. Prendere nota di “Application ID” e “JavaScript Key”.
Invece di esporre le chiavi segrete nel codice sorgente, creare un file .env nella root del progetto:
VITE_BACK4APP_APPLICATION_ID=<your_back4app_application_id>
VITE_BACK4APP_JAVASCRIPT_KEY=<your_back4app_javascript_key>
Assicurarsi di sostituire le variabili con le chiavi reali.
Quindi, spostarsi in src/main.jsx e inizializzare Parse usando le variabili ambientali:
// src/main.jsx
// ...
import Parse from "parse/dist/parse.min.js";
// Initialize Parse SDK using the Back4app API keys
Parse.initialize(
import.meta.env.VITE_BACK4APP_APPLICATION_ID,
import.meta.env.VITE_BACK4APP_JAVASCRIPT_KEY,
);
Parse.serverURL = "https://parseapi.back4app.com/";
ReactDOM.createRoot(document.getElementById("root")).render(
// ...
);
Ora è possibile utilizzare l’istanza di Parse in tutte le viste, importandola:
import Parse from "parse/dist/parse.min.js";
Logica
Infine, sostituire gli hook di React in src/App.jsx con i seguenti:
// src/App.jsx
// ...
import Parse from "parse/dist/parse.min.js";
function App() {
// ...
async function getInitialMessage() {
const Assistant = Parse.Object.extend("Assistant");
const assistant = await new Parse.Query(Assistant).first();
return assistant.get("initialMessage");
}
async function reset(message) {
setMessages([
{role: "assistant", content: message},
]);
setMessage("");
const threadId = await Parse.Cloud.run("createThread");
setThreadId(threadId);
}
useEffect(() => {
(async () => {
const assistantInitialMessage = await getInitialMessage();
setInitialMessage(assistantInitialMessage);
await reset(assistantInitialMessage);
setLoading(false);
})();
}, []);
function onSubmit(event) {
event.preventDefault();
if (loading || !threadId || !message) return;
setMessages([
...messages,
{role: "user", content: message},
]);
setMessage("");
setLoading(true);
(async () => {
const response = await Parse.Cloud.run("addMessage", {threadId, message});
setMessages(messages => [
...messages,
{role: "assistant", content: response},
]);
setLoading(false);
})();
}
function onNewThread() {
if (loading || !threadId) return;
setLoading(true);
(async () => {
await reset(initialMessage);
setLoading(false);
})();
}
return (
// ...
);
}
export default App;
Questo codice gestisce il messaggio e lo invia al backend. Consente inoltre agli utenti di creare una nuova discussione facendo clic su un pulsante.
Voilà! Il frontend è ora completo.
Riavviare il server di sviluppo e testare l’applicazione per verificare che tutto funzioni.
Se si desidera distribuire il frontend dell’assistente, consultare Come ospitare un’applicazione React?
Conclusione
Questo articolo vi ha insegnato tutto quello che c’è da sapere per costruire assistenti personalizzati basati sull’intelligenza artificiale.
Ora dovreste essere in grado di utilizzare l’API Assistant di OpenAI e Back4app per creare e distribuire i vostri assistenti AI,
Il codice sorgente finale è disponibile nel repo GitHub di back4app-openai-virtual-assistant.