Condividi tramite


Agenti di intelligenza artificiale in Azure Cosmos DB

Gli agenti IA sono progettati per eseguire attività specifiche, rispondere a domande e automatizzare i processi per gli utenti. Questi agenti variano notevolmente nella complessità. Si variano da chatbot semplici, a copiloti, a assistenti avanzati di intelligenza artificiale sotto forma di sistemi digitali o robotici che possono eseguire flussi di lavoro complessi in modo autonomo.

Questo articolo fornisce panoramiche concettuali ed esempi dettagliati di implementazione per gli agenti IA.

Che cosa sono gli agenti di intelligenza artificiale

A differenza dei modelli di linguaggio di grandi dimensioni (LLM) autonomi o dei sistemi software/hardware basati su regole, l'agente IA hanno le funzionalità comuni seguenti:

  • Pianificazione: gli agenti IA possono pianificare e sequenziare le azioni per raggiungere obiettivi specifici. L'integrazione degli LLM ha rivoluzionato le funzionalità di pianificazione.
  • Uso di strumenti: gli agenti IA avanzati possono usare vari strumenti, ad esempio l'esecuzione del codice, la ricerca e le funzionalità di calcolo, per eseguire in modo efficace le attività. Gli agenti IA usano spesso strumenti tramite chiamate di funzione.
  • Percezione: gli agenti IA possono percepire ed elaborare informazioni dal proprio ambiente, per renderle più interattive e consapevoli del contesto. Queste informazioni includono dati visivi, uditivi e altri dati sensoriali.
  • Memoria: gli agenti IA hanno la possibilità di ricordare le interazioni passate (utilizzo e percezione degli strumenti) e i comportamenti (utilizzo e pianificazione degli strumenti). Archiviano queste esperienze ed eseguono anche la riflessione automatica per informare le azioni future. Questo componente di memoria consente la continuità e il miglioramento delle prestazioni dell'agente nel tempo.

Nota

L'utilizzo del termine memoria nel contesto degli agenti IA è diverso dal concetto di memoria del computer ( ad esempio volatile, non volatile, non volatile e memoria persistente).

Copiloti

I copiloti sono un tipo di agente IA. Lavorano insieme agli utenti anziché operare in modo indipendente. A differenza degli agenti completamente automatizzati, i copiloti forniscono suggerimenti e consigli per aiutare gli utenti a completare le attività.

Ad esempio, quando un utente scrive un messaggio di posta elettronica, un copilota può suggerire espressioni, frasi o paragrafi. L'utente potrebbe anche chiedere al copilota di trovare informazioni pertinenti in altre email o file per supportare il suggerimento (vedere generazione aumentata di recupero). L'utente può accettare, rifiutare o modificare i passaggi suggeriti.

Agenti autonomi

Gli agenti autonomi possono operare in modo più indipendente. Quando si configurano agenti autonomi per facilitare la composizione dei messaggi di posta elettronica, è possibile abilitarli per eseguire le attività seguenti:

  • Consultare email, chat, file e altre informazioni interne e pubbliche correlate all'argomento.
  • Eseguire analisi qualitative o quantitative sulle informazioni raccolte e trarre conclusioni pertinenti all'email.
  • Scrivere l'email completa in base alle conclusioni e incorporare le prove di supporto.
  • Allegare file pertinenti all'email.
  • Esaminare l'email per assicurarsi che tutte le informazioni incorporate siano effettivamente accurate e che le asserzioni siano valide.
  • Selezionare i destinatari appropriati per A, CC e/o CCN e cercare i relativi indirizzi email.
  • Pianificare un orario appropriato per inviare l'email.
  • Eseguire le operazioni di completamento se le risposte sono previste ma non ricevute.

È possibile configurare gli agenti per eseguire ognuna delle attività precedenti con o senza approvazione umana.

Sistemi multi-agente

Una strategia comune per ottenere agenti autonomi efficienti è l'uso di sistemi multi-agente. Nei sistemi multi-agente, più agenti autonomi, in forma digitale o robotica, interagiscono o collaborano per raggiungere obiettivi individuali o collettivi. Gli agenti nel sistema possono operare in modo indipendente e possedere le proprie conoscenze o informazioni. Ogni agente può anche avere la capacità di percepire il proprio ambiente, prendere decisioni ed eseguire azioni in base ai propri obiettivi.

I sistemi multi-agente hanno queste caratteristiche chiave:

  • Autonomo: ogni agente funziona in modo indipendente. Prende le proprie decisioni senza l'intervento umano diretto o il controllo da parte di altri agenti.
  • Interattivo: gli agenti comunicano e collaborano tra loro per condividere informazioni, negoziare e coordinare le azioni. Questa interazione può verificarsi tramite vari protocolli e canali di comunicazione.
  • Orientato agli obiettivi: gli agenti in un sistema multi-agente sono progettati per raggiungere obiettivi specifici, che possono essere allineati ai singoli obiettivi o un obiettivo comune condiviso tra gli agenti.
  • Distribuito: i sistemi multi-agente operano in modo distribuito, senza un singolo punto di controllo. Questa distribuzione migliora l'affidabilità, la scalabilità e l'efficienza delle risorse del sistema.

Un sistema multi-agente offre i vantaggi seguenti rispetto a un copilota o a una singola istanza dell'inferenza LLM:

  • Ragionamento dinamico: rispetto alle richieste di tipo chain-of-thought o tree-of-thought, i sistemi multi-agente consentono la navigazione dinamica attraverso vari percorsi di ragionamento.
  • Capacità sofisticate: i sistemi multi-agente possono gestire problemi complessi o su larga scala eseguendo processi decisionali accurati e distribuendo attività tra più agenti.
  • Memoria avanzata: i sistemi multi-agente con memoria possono superare le finestre di contesto dei moduli APM per consentire una migliore comprensione e conservazione delle informazioni.

Implementazione degli agenti di intelligenza artificiale

Ragionamento e pianificazione

Ragionamento complesso e pianificazione sono il segno distintivo di agenti autonomi avanzati. I framework più diffusi per gli agenti autonomi incorporano una o più delle metodologie seguenti (con collegamenti alle pagine di archivio arXiv) per ragionamento e pianificazione:

  • Porsi domande

    Migliorare la catena di pensiero facendo in modo che il modello si chieda da solo esplicitamente (e si risponda) domande di follow-up prima di rispondere alla domanda iniziale.

  • Ragionare a agire (ReAct)

    Usare gli LLM per generare tracce di ragionamento e azioni specifiche per l'attività in modo interlacciato. Le tracce di ragionamento consentono al modello di indurre, tenere traccia e aggiornare i piani di azione, insieme alla gestione delle eccezioni. Le azioni consentono al modello di connettersi a origini esterne, ad esempio knowledge base o ambienti, per raccogliere informazioni aggiuntive.

  • Pianificare e risolvere

    Ideare un piano per dividere l'intera attività in sottoattività più piccole e quindi eseguire le sottoattività in base al piano. Questo approccio attenua gli errori di calcolo, gli errori di passaggi mancanti e gli errori di incomprensione semantica che sono spesso presenti nelle richieste CoT (Chain of Thought) zero-shot.

  • Riflettere/Autocritica

    Usare agenti riflessivi che riflettono verbalmente sui segnali di feedback delle attività. Questi agenti mantengono il proprio testo riflessivo in un buffer di memoria episodica per indurre un processo decisionale migliore nelle prove successive.

Framework

Vari framework e strumenti possono facilitare lo sviluppo e la distribuzione degli agenti IA.

Per l'utilizzo e la percezione degli strumenti che non richiedono una pianificazione e una memoria sofisticate, alcuni framework dell'agente di orchestrazione LLM più diffusi sono LangChain, LlamaIndex, Prompt Flow e Semantic Kernel.

Per i flussi di lavoro avanzati e autonomi di pianificazione ed esecuzione, AutoGen ha generato l'onda multi-agente iniziata alla fine del 2022. L'API Assistants di OpenAI consente agli utenti di creare agenti in modo nativo all'interno dell'ecosistema GPT. Gli agenti LangChain e gli agenti LlamaIndex sono emersi nello stesso momento.

Suggerimento

L'esempio di implementazione più avanti in questo articolo illustra come creare un semplice sistema multi-agente usando uno dei framework più diffusi e un sistema di memoria dell'agente unificato.

Sistema di memoria dell'agente IA

La pratica prevalente per sperimentare applicazioni avanzate con intelligenza artificiale dal 2022 fino al 2024 usa sistemi di gestione di database autonomi per vari flussi di lavoro o tipi di dati. Ad esempio, si può usare un database in memoria per la memorizzazione nella cache, un database relazionale per i dati operativi (inclusi i log di traccia/attività e la cronologia delle conversazioni LLM) e un database vettoriale puro per la gestione dell'incorporamento.

Tuttavia, questa pratica di usare una rete complessa di database autonomi può compromettere le prestazioni di un agente IA. L'integrazione di tutti questi database diversi in un sistema di memoria coeso, interoperabile e resiliente per gli agenti di intelligenza artificiale è la propria sfida.

Inoltre, molti dei servizi di database usati di frequente non sono ottimali per la velocità e la scalabilità necessari ai sistemi dell'agente IA. I singoli punti deboli dei database sono esacerbati nei sistemi multi-agente.

Database in memoria

I database in memoria sono eccellenti per la velocità, ma possono avere difficoltà con la persistenza dei dati su larga scala richiesta dall'agente IA.

Database relazionali

I database relazionali non sono ideali per le varie modalità e gli schemi fluidi dei dati gestiti dagli agenti. I database relazionali richiedono attività manuali e persino tempi di inattività per gestire il provisioning, il partizionamento e il partizionamento orizzontale.

Database vettoriali puri

I database vettoriali puri tendono a essere meno efficaci per le operazioni transazionali, gli aggiornamenti in tempo reale e i carichi di lavoro distribuiti. I database vettoriali puri più diffusi oggi offrono in genere:

  • Nessuna garanzia sulle operazioni di lettura e scrittura.
  • Velocità effettiva di inserimento limitata.
  • Disponibilità bassa (inferiore al 99,9% o un'interruzione annuale di 9 ore o più).
  • Un livello di coerenza (eventuale).
  • Un indice vettoriale a elevato utilizzo di risorse in memoria.
  • Opzioni limitate per la multi-tenancy.
  • Sicurezza limitata.

Caratteristiche di un sistema di memoria affidabile dell'agente di intelligenza artificiale

Così come sistemi efficienti di gestione dei database sono fondamentali per le prestazioni delle applicazioni software, è fondamentale fornire agli agenti LLM informazioni pertinenti e utili per favorire la loro inferenza. I sistemi di memoria affidabili consentono di organizzare e archiviare vari tipi di informazioni che gli agenti possono recuperare in fase di inferenza.

Attualmente, le applicazioni basate su LLM usano spesso la generazione aumentata di recupero che si serve della ricerca semantica di base o della ricerca vettoriale per recuperare passaggi o documenti. La ricerca vettoriale può essere utile per trovare informazioni generali. Tuttavia, la ricerca vettoriale potrebbe non acquisire il contesto, la struttura o le relazioni specifiche rilevanti per una determinata attività o dominio.

Ad esempio, se l'attività consiste nello scrivere codice, la ricerca vettoriale potrebbe non essere in grado di recuperare l'albero della sintassi, il layout del file system, i riepiloghi del codice o le firme API importanti per la generazione di codice coerente e corretto. Analogamente, se l'attività deve usare dati tabulari, la ricerca vettoriale potrebbe non essere in grado di recuperare lo schema, le chiavi esterne, le procedure memorizzate o i report utili per l'esecuzione di query o l'analisi dei dati.

Mettere insieme una rete di database autonomi, relazionali e vettoriali in memoria ( come spiegato in precedenza) non è una soluzione ottimale per i diversi tipi di dati. Questo approccio potrebbe funzionare per i sistemi di agenti prototipici. Tuttavia, aggiunge colli di bottiglia di complessità e prestazioni che possono ostacolare le prestazioni degli agenti autonomi avanzati.

Un sistema di memoria solido deve avere le caratteristiche seguenti.

Multimodale

I sistemi di memoria degli agenti IA devono fornire raccolte che archiviano metadati, relazioni, entità, riepiloghi o altri tipi di informazioni che possono essere utili per attività e domini diversi. Queste raccolte possono essere basate sulla struttura e sul formato dei dati, ad esempio documenti, tabelle o codice. Oppure possono essere basati sul contenuto e sul significato dei dati, ad esempio concetti, associazioni o passaggi procedurali.

I sistemi di memoria non sono essenziali solo per gli agenti di intelligenza artificiale. Sono anche importanti per gli esseri umani che sviluppano, gestiscono e usano questi agenti.

Ad esempio, gli esseri umani potrebbero dover supervisionare i flussi di lavoro di pianificazione ed esecuzione degli agenti quasi in tempo reale. Durante la supervisione, gli esseri umani possono intervenire con indicazioni o modificare in linea i dialoghi o i monologhi degli agenti. Gli esseri umani possono anche dover controllare il ragionamento e le azioni degli agenti per verificare la validità dell'output finale.

Le interazioni umani/agenti sono probabilmente in linguaggi naturali o di programmazione, mentre gli agenti "pensano", "imparano" e "ricordano" tramite incorporamenti. Questa differenza pone un altro requisito sulla coerenza dei sistemi di memoria tra le modalità dei dati.

Operativo

I sistemi di memoria devono fornire banche di memoria che archiviano informazioni rilevanti per l'interazione con l'utente e l'ambiente. Tali informazioni possono includere cronologia chat, preferenze utente, dati sensoriali, decisioni prese, fatti appresi o altri dati operativi aggiornati con frequenza elevata e a volumi elevati.

Queste banche di memoria possono aiutare gli agenti a ricordare informazioni a breve e a lungo termine, evitare di ripetersi o contraddirsi e mantenere la coerenza dell'attività. Questi requisiti devono essere validi anche se gli agenti eseguono una moltitudine di attività non correlate in successione. Nei casi avanzati, gli agenti possono anche testare numerosi piani di diramazione che divergono o convergono in punti diversi.

Condivisibile ma anche separabile

A livello di macro, i sistemi di memoria devono consentire a più agenti IA di collaborare su un problema o elaborare diversi aspetti del problema fornendo memoria condivisa accessibile a tutti gli agenti. La memoria condivisa può facilitare lo scambio di informazioni e il coordinamento delle azioni tra gli agenti.

Allo stesso tempo, il sistema di memoria deve consentire agli agenti di preservare la propria persona e le proprie caratteristiche, ad esempio le raccolte uniche di richieste e ricordi.

Creazione di un sistema di memoria solido dell'agente IA

Le caratteristiche precedenti richiedono che i sistemi di memoria degli agenti IA siano altamente scalabili e rapidi. La trama accuratamente insieme a diversi database in memoria, relazionali e vettoriali (come descritto in precedenza) potrebbe funzionare per le applicazioni abilitate per l'intelligenza artificiale in fase iniziale. Tuttavia, questo approccio aggiunge colli di bottiglia di complessità e prestazioni che possono ostacolare le prestazioni degli agenti autonomi avanzati.

Al posto di tutti i database autonomi, Azure Cosmos DB può fungere da soluzione unificata per i sistemi di memoria degli agenti IA. La sua robustezza ha permesso al servizio ChatGPT di OpenAI di ridimensionare dinamicamente con un'elevata affidabilità e una manutenzione ridotta. Basato su un motore atom-record-sequence, è il primo servizio di database vettoriale e relazionale NoSQL distribuito a livello globale che offre una modalità serverless. Gli agenti IA basati su Azure Cosmos DB offrono velocità, scalabilità e semplicità.

Velocità

Azure Cosmos DB offre una latenza in millisecondi a cifra singola. Questa funzionalità lo rende adatto per i processi che richiedono l'accesso rapido ai dati e la gestione. Questi processi includono la memorizzazione nella cache (memorizzazione nella cache tradizionale e semantica, transazioni e carichi di lavoro operativi.

La bassa latenza è fondamentale per gli agenti IA che devono eseguire ragionamenti complessi, prendere decisioni in tempo reale e fornire risposte immediate. Inoltre, l'uso dell'algoritmo DiskANN offre una ricerca vettoriale accurata e veloce con un consumo minimo di memoria.

Ridimensiona

Azure Cosmos DB è progettato per la distribuzione globale e la scalabilità orizzontale. Offre supporto per L'I/O in più aree e la multi-tenancy.

Il servizio consente di garantire che i sistemi di memoria possano espandersi senza problemi e mantenere il passo con agenti in rapida crescita e i dati associati. La garanzia di disponibilità nel contratto di servizio (SLA) si traduce in meno di 5 minuti di tempo di inattività all'anno. I servizi di database vettoriali puri, al contrario, sono dotati di 9 ore o più di tempi di inattività. Questa disponibilità offre una solida base per i carichi di lavoro cruciali. Allo stesso tempo, i vari modelli di servizio in Azure Cosmos DB, ad esempio capacità riservata o serverless, possono contribuire a ridurre i costi finanziari.

Semplicità

Azure Cosmos DB può semplificare la gestione e l'architettura dei dati integrando più funzionalità di database in una singola piattaforma coesa.

Le funzionalità integrate del database vettoriale possono archiviare, indicizzare ed eseguire query sugli incorporamenti insieme ai dati corrispondenti in linguaggi naturali o di programmazione. Questa funzionalità consente una maggiore coerenza, scalabilità e prestazioni dei dati.

La sua flessibilità supporta le diverse modalità e schemi fluidi dei metadati, delle relazioni, delle entità, dei riepiloghi, della cronologia delle chat, delle preferenze utente, dei dati sensoriali, delle decisioni, dei fatti appresi o di altri dati operativi coinvolti nei flussi di lavoro degli agenti. Il database indicizza automaticamente tutti i dati senza richiedere la gestione dello schema o dell'indice, che consente agli agenti IA di eseguire query complesse in modo rapido ed efficiente.

Azure Cosmos DB è completamente gestito, eliminando così il sovraccarico delle attività di amministrazione del database, ad esempio il ridimensionamento, l'applicazione di patch e i backup. Sena questo sovraccarico, gli sviluppatori possono quindi concentrarsi sulla creazione e l'ottimizzazione degli agenti IA senza preoccuparsi dell'infrastruttura dati sottostante.

Funzionalità avanzate

Azure Cosmos DB incorpora funzionalità avanzate, ad esempio il feed di modifiche, che consente di tenere traccia e rispondere alle modifiche dei dati in tempo reale. Questa funzionalità è utile per gli agenti IA che devono reagire tempestivamente alle nuove informazioni.

Inoltre, il supporto integrato per le scritture multimaster consente disponibilità elevata e resilienza, garantendo un funzionamento continuo degli agenti IA anche a seguito di errori a livello di area.

I cinque livelli di coerenza disponibili (da forte a eventuale) possono anche soddisfare diversi carichi di lavoro distribuiti a seconda dei requisiti dello scenario.

Suggerimento

È possibile scegliere tra due API di Azure Cosmos DB per compilare il sistema di memoria dell'agente di intelligenza artificiale:

  • Azure Cosmos DB for NoSQL, che offre una garanzia di disponibilità del 99,999% e fornisce tre algoritmidi ricerca vettoriale: IVF, HNSW e DiskANN
  • Azure Cosmos DB for MongoDB basato su vCore, che offre una garanzia di disponibilità del 99,995% e fornisce due algoritmi di ricerca vettoriale: IVF e HNSW (DiskANN è imminente)

Per informazioni sulle garanzie di disponibilità per queste API, vedere i contratti di servizio del servizio.

Esempio di implementazione

Questa sezione illustra l'implementazione di un agente autonomo per elaborare le richieste e le prenotazioni dei viaggiatori in un'applicazione di viaggio per una compagnia di crocera.

I chatbot sono un concetto di lunga data, ma gli agenti di intelligenza artificiale stanno avanzando oltre la conversazione umana di base per eseguire attività basate sul linguaggio naturale. Queste attività richiedono tradizionalmente la logica codificata. L'agente di viaggio di intelligenza artificiale in questo esempio di implementazione usa il framework dell'agente LangChain per la pianificazione, l'utilizzo degli strumenti e la percezione degli agenti.

L'agente di viaggio di intelligenza artificiale sistema di memoria unificato usa le funzionalità di database vettoriali e archivio documenti di Azure Cosmos DB per risolvere le richieste dei viaggiatori e facilitare le prenotazioni di viaggi. L'uso di Azure Cosmos DB a questo scopo consente di garantire velocità, scalabilità e semplicità, come descritto in precedenza.

L'agente di esempio opera all'interno di un back-end FastAPI Python. Supporta le interazioni utente tramite un'interfaccia utente JavaScript React.

Prerequisiti

  • Una sottoscrizione di Azure. Se non è disponibile, è possibile provare gratuitamente Azure Cosmos DB per 30 giorni senza creare un account Azure. La versione di valutazione gratuita non richiede una carta di credito e nessun impegno segue il periodo di valutazione.
  • Un account per l'API OpenAI o il Servizio OpenAI di Azure.
  • Un cluster vCore in Azure Cosmos DB for MongoDB. È possibile crearne uno seguendo questa guida introduttiva.
  • Un ambiente di sviluppo integrato, ad esempio Visual Studio Code.
  • Python 3.11.4 installato nell'ambiente di sviluppo.

Scaricare il progetto

Tutto il codice e i set di dati di esempio sono disponibili in questo repositoryGitHub. Il repository include queste cartelle:

  • caricatore: questa cartella contiene codice Python per caricare documenti di esempio e incorporamenti vettoriali in Azure Cosmos DB.
  • api: questa cartella contiene il progetto FastAPI Python per l'hosting dell'agente di viaggio di intelligenza artificiale.
  • web: questa cartella contiene il codice per l'interfaccia Web React.

Caricare documenti di viaggio in Azure Cosmos DB

Il repository GitHub contiene un progetto Python nella directory del caricatore. È destinato al caricamento dei documenti di viaggio di esempio in Azure Cosmos DB.

Configurare l'ambiente

Configurare l'ambiente virtuale Python nella directory caricatore eseguendo i comandi seguenti:

python -m venv venv

Attivare l'ambiente e installare le dipendenze nella directory caricatore:

venv\Scripts\activate
python -m pip install -r requirements.txt

Creare un file denominato .env nella directory caricatore per archiviare le variabili di ambiente seguenti:

OPENAI_API_KEY="<your OpenAI key>"
MONGO_CONNECTION_STRING="mongodb+srv:<your connection string from Azure Cosmos DB>"

Caricare documenti e vettori

Il file Python main.py funge da punto di ingresso centrale per il caricamento dei dati in Azure Cosmos DB. Questo codice elabora i dati di viaggio di esempio dal repository GitHub, incluse informazioni sulle navi e sulle destinazioni. Il codice genera anche pacchetti di itinerari di viaggio per ogni nave e destinazione, in modo che i viaggiatori possano prenotarli usando l'agente di intelligenza artificiale. Lo strumento CosmosDBcaricatore è responsabile della creazione di raccolte, incorporamenti vettoriali e indici nell'istanza di Azure Cosmos DB.

Ecco il contenuto di main.py:

from cosmosdbloader import CosmosDBLoader
from itinerarybuilder import ItineraryBuilder
import json

cosmosdb_loader = CosmosDBLoader(DB_Name='travel')

#read in ship data
with open('documents/ships.json') as file:
        ship_json = json.load(file)

#read in destination data
with open('documents/destinations.json') as file:
        destinations_json = json.load(file)

builder = ItineraryBuilder(ship_json['ships'],destinations_json['destinations'])

# Create five itinerary packages
itinerary = builder.build(5)

# Save itinerary packages to Cosmos DB
cosmosdb_loader.load_data(itinerary,'itinerary')

# Save destinations to Cosmos DB
cosmosdb_loader.load_data(destinations_json['destinations'],'destinations')

# Save ships to Cosmos DB, create vector store
collection = cosmosdb_loader.load_vectors(ship_json['ships'],'ships')

# Add text search index to ship name
collection.create_index([('name', 'text')])

Caricare documenti e vettori e creare indici eseguendo il comando seguente dalla directory caricatore:

python main.py

Ecco l'output di main.py:

--build itinerary--
--load itinerary--
--load destinations--
--load vectors ships--

Creare l'agente di viaggio di intelligenza artificiale usando Python FastAPI

L'agente di viaggio di intelligenza artificiale è ospitato in un'API back-end tramite Python FastAPI, che facilita l'integrazione con l'interfaccia utente front-end. Il progetto API elabora le richieste dell'agente basando le richieste LLM sul livello dei dati, in particolare i vettori e i documenti in Azure Cosmos DB.

L'agente usa vari strumenti, in particolare le funzioni Python fornite a livello di servizio API. Questo articolo è incentrato sul codice necessario per gli agenti IA all'interno del codice API.

Il progetto API nel repository GitHub è strutturato come segue:

  • I componenti di modellazione dei dati usano modelli Pydantic.
  • I componenti del livello Web sono responsabili dell'instradamento delle richieste e della gestione delle comunicazioni.
  • I componenti del livello di servizio sono responsabili della logica di business primaria e dell'interazione con il livello dati; LangChain Agent e Agent Tools.
  • I componenti del livello dati sono responsabili dell'interazione con l'archiviazione dei documenti e la ricerca vettoriale di Azure Cosmos DB for MongoDB.

Configurare l'ambiente per l'API

Python versione 3.11.4 è stata usata per lo sviluppo e il test dell'API.

Configurare l'ambiente virtuale Python nella directory api:

python -m venv venv

Attivare l'ambiente e installare le dipendenze usando il file dei requisiti nella directory api:

venv\Scripts\activate
python -m pip install -r requirements.txt

Creare un file denominato .env nella directory api per archiviare le variabili di ambiente:

OPENAI_API_KEY="<your Open AI key>"
MONGO_CONNECTION_STRING="mongodb+srv:<your connection string from Azure Cosmos DB>"

Dopo aver configurato l'ambiente e configurato le variabili, eseguire il comando seguente dalla directory api per avviare il server:

python app.py

Il server FastAPI viene avviato sul loopback localhost 127.0.0.1 porta 8000 per impostazione predefinita. È possibile accedere ai documenti di Swagger usando l'indirizzo localhost seguente: http://127.0.0.1:8000/docs.

Usare una sessione per la memoria dell'agente IA

È fondamentale che l'agente di viaggio sia capace di fare riferimento alle informazioni fornite in precedenza all'interno della conversazione in corso. Questa capacità è comunemente nota come memoria nel contesto di LLMS.

Per raggiungere questo obiettivo, usare la cronologia dei messaggi di chat archiviata nell'istanza di Azure Cosmos DB. La cronologia per ogni sessione di chat viene archiviata tramite un ID sessione per garantire che siano accessibili solo i messaggi della sessione di conversazione corrente. Questa necessità è la ragione dell'esistenza di un metodo Get Session nell'API. Si tratta di un metodo segnaposto per la gestione delle sessioni Web al fine di illustrare l'uso della cronologia dei messaggi di chat.

Selezionare Prova per /session/.

Screenshot dell'uso del metodo Get Session in Python FastAPI, con il pulsante per provarlo.

{
  "session_id": "0505a645526f4d68a3603ef01efaab19"
}

Per l'agente IA, è sufficiente simulare una sessione. Il metodo stubbed-out restituisce semplicemente un ID sessione generato per tenere traccia della cronologia dei messaggi. In un'implementazione pratica, questa sessione verrà archiviata in Azure Cosmos DB e potenzialmente in React localStorage.

Ecco il contenuto di web/session.py:

@router.get("/")
def get_session():
    return {'session_id':str(uuid.uuid4().hex)}

Avviare una conversazione con l'agente di viaggio IA

Usare l'ID sessione ottenuto dal passaggio precedente per avviare una nuova finestra di dialogo con l'agente di intelligenza artificiale, in modo da convalidarne la funzionalità. Efettuare il test presentando la seguente frase: "Voglio fare una vacanza rilassante".

Selezionare Prova per /agent/agent_chat.

Screenshot dell'uso del metodo Agent Chat in Python FastAPI, con il pulsante per provarlo.

Usare questo parametro di esempio:

{
  "input": "I want to take a relaxing vacation.",
  "session_id": "0505a645526f4d68a3603ef01efaab19"
}

Con l'esecuzione iniziale vengono consigliate la Tranquil Breeze Cruise e la Fantasy Seas Adventure Cruise, perché l'agente ritiene che siano le crociere più "rilassanti" disponibili attraverso la ricerca vettoriale. Questi documenti hanno il punteggio più alto per similarity_search_with_score che viene chiamato nel livello dati dell'API, data.mongodb.travel.similarity_search().

I punteggi di ricerca di similarità vengono visualizzati come output dell'API a scopo di debug. Ecco l'output dopo una chiamata a data.mongodb.travel.similarity_search():

0.8394561085977978
0.8086545112328692
2

Suggerimento

Se i documenti non vengono restituiti per la ricerca vettoriale, modificare il limite similarity_search_with_score o il valore del filtro del punteggio in base alle esigenze ([doc for doc, score in docs if score >=.78]) in data.mongodb.travel.similarity_search().

La chiamata a agent_chat per la prima volta crea una nuova raccolta denominata history in Azure Cosmos DB per archiviare la conversazione per sessione. Questa chiamata consente all'agente di accedere alla cronologia dei messaggi di chat archiviata in base alle esigenze. Esecuzioni successive di agent_chat con gli stessi parametri producono risultati diversi, poiché attingono dalla memoria.

Esaminare l'agente di intelligenza artificiale

Quando si integra l'agente IA nell'API, i componenti di ricerca Web sono responsabili dell'avvio di tutte le richieste. I componenti di ricerca Web sono seguiti dal servizio di ricerca e infine dai componenti dati.

In questo caso specifico si usa una ricerca dati MongoDB che si connette ad Azure Cosmos DB. I livelli facilitano lo scambio dei componenti del modello, con il codice dell'agente IA e dello strumento dell'agente IA che risiede nel livello di servizio. Questo approccio consente l'interscambio facile delle origini dati. Estende anche le funzionalità dell'agente di intelligenza artificiale con funzionalità o strumenti aggiuntivi più complessi.

Diagramma dei livelli FastAPI dell'agente di viaggio di intelligenza artificiale.

Livello di servizio

Il livello di servizio costituisce la pietra angolare della logica di business di base. In questo particolare scenario, il livello di servizio svolge un ruolo fondamentale come repository per il codice dell'agente LangChain. Semplifica l'integrazione senza problemi delle richieste degli utenti con le funzioni dei dati, della conversazione e dell'agente di Azure Cosmos DB per l'agente di intelligenza artificiale.

Il livello di servizio usa un modulo modello singleton per la gestione delle inizializzazioni correlate all'agente nel file init.py. Ecco il contenuto del service/init.py:

from dotenv import load_dotenv
from os import environ
from langchain.globals import set_llm_cache
from langchain_openai import ChatOpenAI
from langchain_mongodb.chat_message_histories import MongoDBChatMessageHistory
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain.agents import AgentExecutor, create_openai_tools_agent
from service import TravelAgentTools as agent_tools

load_dotenv(override=False)

chat : ChatOpenAI | None=None
agent_with_chat_history : RunnableWithMessageHistory | None=None

def LLM_init():
    global chat,agent_with_chat_history
    chat = ChatOpenAI(model_name="gpt-3.5-turbo-16k",temperature=0)
    tools = [agent_tools.vacation_lookup, agent_tools.itinerary_lookup, agent_tools.book_cruise ]

    prompt = ChatPromptTemplate.from_messages(
    [
        (
            "system",
            "You are a helpful and friendly travel assistant for a cruise company. Answer travel questions to the best of your ability providing only relevant information. In order to book a cruise you will need to capture the person's name.",
        ),
        MessagesPlaceholder(variable_name="chat_history"),
        ("user", "Answer should be embedded in html tags. {input}"),
         MessagesPlaceholder(variable_name="agent_scratchpad"),
    ]
    )

    #Answer should be embedded in HTML tags. Only answer questions related to cruise travel, If you can not answer respond with \"I am here to assist with your travel questions.\". 


    agent = create_openai_tools_agent(chat, tools, prompt)
    agent_executor  = AgentExecutor(agent=agent, tools=tools, verbose=True)

    agent_with_chat_history = RunnableWithMessageHistory(
        agent_executor,
        lambda session_id: MongoDBChatMessageHistory( database_name="travel",
                                                 collection_name="history",
                                                   connection_string=environ.get("MONGO_CONNECTION_STRING"),
                                                   session_id=session_id),
        input_messages_key="input",
        history_messages_key="chat_history",
)

LLM_init()

Il file init.py avvia il caricamento delle variabili di ambiente da un file con estensione .env usando il metodo load_dotenv(override=False). Viene quindi creata un'istanza di una variabile globale denominata agent_with_chat_history per l'agente. Questo agente è destinato all'uso da parte di TravelAgent.py.

Il metodo LLM_init() viene richiamato durante l'inizializzazione del modulo per configurare l'agente IA per la conversazione tramite il livello Web dell'API. L'oggetto OpenAI chat viene creata un'istanza tramite il modello GPT-3.5 e incorpora parametri specifici, ad esempio il nome del modello e la temperatura. L'oggetto chat, l'elenco degli strumenti e il modello di richiesta vengono combinati per generare AgentExecutor, che opera come agente IA di viaggi.

L'agente con cronologia, agent_with_chat_history, viene stabilito tramite RunnableWithMessageHistory con la cronologia delle chat (MongoDBChatMessageHistory). Questa azione consente di mantenere una cronologia di conversazione completa tramite Azure Cosmos DB.

Richiesta

La richiesta LLM è iniziata con la semplice affermazione "Sei un assistente di viaggio disponibile e cordiale per una compagnia di crociera". Tuttavia, i test hanno dimostrato che è possibile ottenere risultati più coerenti includendo l'istruzione "Rispondere alle domande di viaggio al meglio della propria capacità, fornendo solo informazioni pertinenti. Per prenotare una crociera, acquisire il nome della persona è essenziale". I risultati vengono visualizzati in formato HTML per migliorare l'appeal visivo dell'interfaccia Web.

Strumenti dell'agente

Gli strumenti sono interfacce che un agente può usare per interagire con il mondo, spesso eseguite tramite chiamate di funzione.

Quando si crea un agente, è necessario arredarlo con un set di strumenti che può essere usato. L'elemento Decorator @tool offre l'approccio più semplice per definire uno strumento personalizzato.

Per impostazione predefinita, l'elemento Decorator usa il nome della funzione come nome dello strumento, anche se può essere sostituito fornendo una stringa come primo argomento. L'elemento Decorator usa la docstring della funzione come descrizione dello strumento, quindi richiede il provisioning di una docstring.

Ecco il contenuto di service/TravelAgentTools.py:

from langchain_core.tools import tool
from langchain.docstore.document import Document
from data.mongodb import travel
from model.travel import Ship


@tool
def vacation_lookup(input:str) -> list[Document]:
    """find information on vacations and trips"""
    ships: list[Ship] = travel.similarity_search(input)
    content = ""

    for ship in ships:
        content += f" Cruise ship {ship.name}  description: {ship.description} with amenities {'/n-'.join(ship.amenities)} "

    return content

@tool
def itinerary_lookup(ship_name:str) -> str:
    """find ship itinerary, cruise packages and destinations by ship name"""
    it = travel.itnerary_search(ship_name)
    results = ""

    for i in it:
        results += f" Cruise Package {i.Name} room prices: {'/n-'.join(i.Rooms)} schedule: {'/n-'.join(i.Schedule)}"

    return results


@tool
def book_cruise(package_name:str, passenger_name:str, room: str )-> str:
    """book cruise using package name and passenger name and room """
    print(f"Package: {package_name} passenger: {passenger_name} room: {room}")

    # LLM defaults empty name to John Doe 
    if passenger_name == "John Doe":
        return "In order to book a cruise I need to know your name."
    else:
        if room == '':
            return "which room would you like to book"            
        return "Cruise has been booked, ref number is 343242"

Il file TravelAgentTools.py definisce tre strumenti:

  • vacation_lookup esegue una ricerca vettoriale in Azure Cosmos DB. Usa similarity_search per recuperare materiale correlato al viaggio pertinente.
  • itinerary_lookup recupera i dettagli del pacchetto di crociera e le pianificazioni per una nave da crociera specificata.
  • book_cruise prenota un pacchetto di crociera per un passeggero.

Istruzioni specifiche ("Per prenotare una crociera ho bisogno di conoscere il tuo nome") potrebbe essere necessario per garantire la cattura del nome e del numero di camera del passeggero per prenotare il pacchetto di crociera, anche se sono state incluse tali istruzioni nel prompt LLM.

Agente IA

Il concetto fondamentale degli agenti consiste nell'usare un modello linguistico per selezionare una sequenza di azioni da eseguire.

Ecco il contenuto del service/TravelAgent.py:

from .init import agent_with_chat_history
from model.prompt import PromptResponse
import time
from dotenv import load_dotenv

load_dotenv(override=False)


def agent_chat(input:str, session_id:str)->str:

    start_time = time.time()

    results=agent_with_chat_history.invoke(
    {"input": input},
    config={"configurable": {"session_id": session_id}},
    )

    return  PromptResponse(text=results["output"],ResponseSeconds=(time.time() - start_time))

Il file TravelAgent.py è semplice, come agent_with_chat_history e le relative dipendenze (strumenti, prompt e LLM) vengono inizializzate e configurate nel file init.py. Questo file chiama l'agente usando l'input ricevuto dall'utente, insieme all'ID sessione per la memoria della conversazione. Successivamente, PromptResponse (modello/prompt) viene restituito con l'output e il tempo di risposta dell'agente.

Integrazione dell'agente di intelligenza artificiale con l'interfaccia utente React

Con il corretto caricamento dei dati e l'accessibilità dell'agente IA tramite l'API, è ora possibile completare la soluzione stabilendo un'interfaccia utente Web usando React JS per il sito Web di viaggio. L'uso delle funzionalità di React consente di illustrare la perfetta integrazione dell'agente di intelligenza artificiale in un sito di viaggio. Questa integrazione migliora l'esperienza utente con un assistente di viaggio conversazionale per richieste e prenotazioni.

Configurare l'ambiente per React

Installare Node.js e le dipendenze prima di testare l'interfaccia React.

Eseguire il comando seguente dalla directory Web per eseguire un'installazione pulita delle dipendenze del progetto. L'installazione potrebbe richiedere un po' di tempo.

npm ci

Successivamente, creare un file denominato .env all'interno della directory web per facilitare l'archiviazione delle variabili di ambiente. Includere i dettagli seguenti nel file .env appena creato:

REACT_APP_API_HOST=http://127.0.0.1:8000

Eseguire ora il comando seguente dalla directory Web per avviare l'interfaccia utente Web React:

npm start

L'esecuzione del comando precedente apre l'applicazione Web React.

Esaminare l'interfaccia Web React

Il progetto Web del repository GitHub è un'applicazione semplice per facilitare l'interazione dell'utente con l'agente IA. I componenti principali necessari per conversare con l'agente sono TravelAgent.js e ChatLayout.js. Il file Main.js funge da modulo centrale o pagina di destinazione dell'utente.

Screenshot dell'interfaccia Web JavaScript React.

Principale

Il componente principale funge da gestore centrale dell'applicazione. Funge da punto di ingresso designato per il routing. All'interno della funzione di rendering, produce il codice JSX, per delineare il layout della pagina principale. Questo layout include elementi segnaposto per l'applicazione, ad esempio logo e collegamenti, una sezione che ospita il componente dell'agente di viaggio e un piè di pagina che contiene una dichiarazione di non responsabilità di esempio sulla natura dell'applicazione.

Ecco il contenuto del file main.js:

import React, {  Component } from 'react'
import { Stack, Link, Paper } from '@mui/material'
import TravelAgent from './TripPlanning/TravelAgent'

import './Main.css'

class Main extends Component {
  constructor() {
    super()

  }

  render() {
    return (
      <div className="Main">
        <div className="Main-Header">
          <Stack direction="row" spacing={5}>
            <img src="/mainlogo.png" alt="Logo" height={'120px'} />
            <Link
              href="#"
              sx={{ color: 'white', fontWeight: 'bold', fontSize: 18 }}
              underline="hover"
            >
              Ships
            </Link>
            <Link
              href="#"
              sx={{ color: 'white', fontWeight: 'bold', fontSize: 18 }}
              underline="hover"
            >
              Destinations
            </Link>
          </Stack>
        </div>
        <div className="Main-Body">
          <div className="Main-Content">
            <Paper elevation={3} sx={{p:1}} >
            <Stack
              direction="row"
              justifyContent="space-evenly"
              alignItems="center"
              spacing={2}
            >
              
                <Link href="#">
                  <img
                    src={require('./images/destinations.png')} width={'400px'} />
                </Link>
                <TravelAgent ></TravelAgent>
                <Link href="#">
                  <img
                    src={require('./images/ships.png')} width={'400px'} />
                </Link>
              
              </Stack>
              </Paper>
          </div>
        </div>
        <div className="Main-Footer">
          <b>Disclaimer: Sample Application</b>
          <br />
          Please note that this sample application is provided for demonstration
          purposes only and should not be used in production environments
          without proper validation and testing.
        </div>
      </div>
    )
  }
}

export default Main

Travel agent

Il componente Travel Agent ha uno scopo semplice, acquisire gli input dell'utente e visualizzare le risposte. Svolge un ruolo fondamentale nella gestione dell'integrazione con l'agente IA back-end, principalmente acquisendo sessioni e inoltrando le richieste degli utenti al servizio FastAPI. Le risposte risultanti vengono archiviate in una matrice per la visualizzazione, facilitata dal componente Chat Layout.

Ecco il contenuto di TripPlanning/TravelAgent.js:

import React, { useState, useEffect } from 'react'
import { Button, Box, Link, Stack, TextField } from '@mui/material'
import SendIcon from '@mui/icons-material/Send'
import { Dialog, DialogContent } from '@mui/material'
import ChatLayout from './ChatLayout'
import './TravelAgent.css'

export default function TravelAgent() {
  const [open, setOpen] = React.useState(false)
  const [session, setSession] = useState('')
  const [chatPrompt, setChatPrompt] = useState(
    'I want to take a relaxing vacation.',
  )
  const [message, setMessage] = useState([
    {
      message: 'Hello, how can I assist you today?',
      direction: 'left',
      bg: '#E7FAEC',
    },
  ])

  const handlePrompt = (prompt) => {
    setChatPrompt('')
    setMessage((message) => [
      ...message,
      { message: prompt, direction: 'right', bg: '#E7F4FA' },
    ])
    console.log(session)
    fetch(process.env.REACT_APP_API_HOST + '/agent/agent_chat', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ input: prompt, session_id: session }),
    })
      .then((response) => response.json())
      .then((res) => {
        setMessage((message) => [
          ...message,
          { message: res.text, direction: 'left', bg: '#E7FAEC' },
        ])
      })
  }

  const handleSession = () => {
    fetch(process.env.REACT_APP_API_HOST + '/session/')
      .then((response) => response.json())
      .then((res) => {
        setSession(res.session_id)
      })
  }

  const handleClickOpen = () => {
    setOpen(true)
  }

  const handleClose = (value) => {
    setOpen(false)
  }

  useEffect(() => {
    if (session === '') handleSession()
  }, [])

  return (
    <Box>
      <Dialog onClose={handleClose} open={open} maxWidth="md" fullWidth="true">
        <DialogContent>
          <Stack>
            <Box sx={{ height: '500px' }}>
              <div className="AgentArea">
                <ChatLayout messages={message} />
              </div>
            </Box>
            <Stack direction="row" spacing={0}>
              <TextField
                sx={{ width: '80%' }}
                variant="outlined"
                label="Message"
                helperText="Chat with AI Travel Agent"
                defaultValue="I want to take a relaxing vacation."
                value={chatPrompt}
                onChange={(event) => setChatPrompt(event.target.value)}
              ></TextField>
              <Button
                variant="contained"
                endIcon={<SendIcon />}
                sx={{ mb: 3, ml: 3, mt: 1 }}
                onClick={(event) => handlePrompt(chatPrompt)}
              >
                Submit
              </Button>
            </Stack>
          </Stack>
        </DialogContent>
      </Dialog>
      <Link href="#" onClick={() => handleClickOpen()}>
        <img src={require('.././images/planvoyage.png')} width={'400px'} />
      </Link>
    </Box>
  )
}

Seleziona Pianifica il tuo viaggio senza sforzo per aprire l'assistente di viaggio.

Chat layout

Il componente layout della chat supervisiona la disposizione della chat. Elabora sistematicamente i messaggi di chat e implementa la formattazione specificata nell'oggetto JSON di message.

Ecco il contenuto di TripPlanning/ChatLayout.js:

import React from 'react'
import {  Box, Stack } from '@mui/material'
import parse from 'html-react-parser'
import './ChatLayout.css'

export default function ChatLayout(messages) {
  return (
    <Stack direction="column" spacing="1">
      {messages.messages.map((obj, i = 0) => (
        <div className="bubbleContainer" key={i}>
          <Box
            key={i++}
            className="bubble"
            sx={{ float: obj.direction, fontSize: '10pt', background: obj.bg }}
          >
            <div>{parse(obj.message)}</div>
          </Box>
        </div>
      ))}
    </Stack>
  )
}

Le richieste degli utenti sono sul lato destro e blu colorato. Le risposte dell'agente di viaggio di intelligenza artificiale si trovano sul lato sinistro e sul verde colorato. Come illustrato nell'immagine seguente, le risposte in formato HTML vengono considerate nella conversazione.

Screenshot di una chat con un agente di intelligenza artificiale.

Quando l'agente IA è pronto per passare in produzione, è possibile usare la memorizzazione nella cache semantica per migliorare le prestazioni delle query dell'80% per ridurre i costi di inferenza e chiamata API LLM. Per implementare la memorizzazione nella cache semantica, vedere questo post nel blog di Stochastic Coder.

Diagramma della memorizzazione nella cache semantica per gli agenti di intelligenza artificiale.