Agent IA
Les agents IA sont conçus pour effectuer des tâches spécifiques, répondre aux questions et automatiser des processus pour les utilisateurs. Ces agents varient considérablement en complexité. Ils vont des simples chatbots aux copilotes, en passant par des assistants IA avancés qui se présentent sous la forme de systèmes numériques ou robotiques capables d’exécuter des workflows complexes de manière autonome.
Cet article fournit des présentations conceptuelles des agents IA et des exemples d’implémentation détaillés.
Présentation des agents d’IA
Contrairement aux grands modèles de langage (LLM, Large Language Model) autonomes ou aux systèmes logiciels/matériels basés sur des règles, les agents IA offrent les fonctionnalités courantes suivantes :
- Planification : les agents IA peuvent planifier et séquencer des actions pour atteindre des objectifs spécifiques. L’intégration des LLM a révolutionné leurs capacités de planification.
- Utilisation d’outils : les agents IA avancés peuvent utiliser divers outils, notamment ceux offrant des fonctionnalités d’exécution de code, de recherche et de calcul, pour effectuer efficacement des tâches. Les agents IA utilisent souvent des outils par le biais d’appels de fonction.
- Perception : les agents IA peuvent percevoir et traiter les informations de leur environnement, ce qui les rend plus interactifs et plus sensibles au contexte. Ces informations comprennent des données visuelles, des données auditives et d’autres données sensorielles.
- Mémoire : les agents IA peuvent se souvenir des interactions (utilisation d’outils et perception) et des comportements (utilisation d’outils et planification) passés. Ils stockent ces expériences et effectuent même une auto-réflexion pour éclairer les actions futures. Cette composante de la mémoire permet la continuité et l'amélioration des performances de l'agent au fil du temps.
Remarque
Le terme mémoire employé dans le contexte des agents IA est différent du concept de mémoire d’un ordinateur (volatile, non volatile ou PMEM par exemple).
Copilotes
Les copilotes sont un type d’agent IA. Ils fonctionnent aux côtés des utilisateurs plutôt que de manière indépendante. Contrairement aux agents entièrement automatisés, les copilotes fournissent des suggestions et des recommandations pour aider les utilisateurs à accomplir leurs tâches.
Par exemple, lorsqu’un utilisateur écrit un e-mail, un copilote peut suggérer des expressions, des phrases ou des paragraphes. L’utilisateur peut également demander au copilote de trouver des informations pertinentes dans d’autres e-mails ou fichiers pour prendre en charge la suggestion (voir génération augmentée de récupération). L’utilisateur peut accepter, rejeter ou modifier les passages suggérés.
Agents autonomes
Les agents autonomes peuvent fonctionner de manière plus indépendante. Lorsque vous mettez en place des agents autonomes pour vous assister dans la composition des e-mails, vous pouvez leur permettre d'effectuer les tâches suivantes :
- Consulter des e-mails, des conversations, des fichiers et d’autres informations internes et publiques existants liés au sujet.
- Effectuer une analyse qualitative ou quantitative des informations collectées et tirer des conclusions pertinentes pour l’e-mail.
- Écrire l’e-mail dans son intégralité en fonction des conclusions, avec preuves à l’appui.
- Joindre des fichiers pertinents à l’e-mail.
- Passer en revue l’e-mail pour vérifier que toutes les informations incorporées sont exactes et que les affirmations sont valides.
- Sélectionner les destinataires appropriés pour À, Cc et/ou Cci et rechercher leurs adresses e-mail.
- Planifier une heure appropriée pour envoyer l’e-mail.
- Effectuer des suivis si des réponses sont attendues, mais non reçues.
Vous pouvez configurer les agents pour effectuer chacune des tâches précédentes avec ou sans approbation humaine.
Systèmes multi-agents
L’utilisation de systèmes multi-agents est une stratégie très répandue pour obtenir des agents autonomes performants. Dans les systèmes multi-agents, plusieurs agents autonomes, sous forme numérique ou robotisée, interagissent ou collaborent pour atteindre des objectifs individuels ou collectifs. Les agents du système peuvent fonctionner indépendamment et posséder leurs propres connaissances ou informations. Chaque agent peut également être en mesure de percevoir son environnement, de prendre des décisions et d’exécuter des actions en fonction de ses objectifs.
Les principales caractéristiques des systèmes multi-agents sont les suivantes :
- Autonomes : chaque agent fonctionne indépendamment. Il prend ses propres décisions sans intervention humaine directe ni contrôle par d’autres agents.
- Interactifs : les agents communiquent et collaborent entre eux pour partager des informations, négocier et coordonner leurs actions. Cette interaction peut se produire via différents protocoles et canaux de communication.
- Orientés vers les objectifs : les agents d’un système multi-agent sont conçus pour atteindre des objectifs spécifiques, qui peuvent être alignés sur des objectifs individuels ou sur un objectif partagé entre les agents.
- Distribués : les systèmes multi-agents fonctionnent de manière distribuée, sans point de contrôle unique. Cette répartition améliore la robustesse, la scalabilité et l'efficacité des ressources du système.
Un système multi-agent offre les avantages suivants sur un copilote ou une seule instance d’inférence LLM :
- Raisonnement dynamique : par rapport au prompting par chaîne de pensée ou arbre de pensée, les systèmes multi-agents permettent une navigation dynamique à travers différents chemins de raisonnement.
- Capacités sophistiquées : les systèmes multi-agents peuvent gérer des problèmes complexes ou à grande échelle en effectuant des processus décisionnels approfondis et en répartissant les tâches entre plusieurs agents.
- Mémoire améliorée : les systèmes multi-agents avec mémoire peuvent surmonter les fenêtres contextuelles des LLM pour permettre une meilleure compréhension et une meilleure conservation des informations.
Implémentation d’agents IA
Raisonnement et planification
Le raisonnement et la planification complexes sont les caractéristiques des agents autonomes avancés. Les frameworks populaires pour les agents autonomes incorporent une ou plusieurs des méthodologies suivantes (avec des liens vers les pages d’archive arXiv) pour le raisonnement et la planification :
-
Améliorer la chaîne de pensée en demandant au modèle de se poser explicitement des questions de suivi (et d’y répondre) avant de répondre à la question initiale.
Raisonner et agir (ReAct, Reason and Act)
Utiliser les LLM pour générer des traces de raisonnement et des actions propres aux tâches de manière entrelacée. Les traces de raisonnement aident le modèle à induire, suivre et mettre à jour des plans d’action, ainsi qu’à gérer les exceptions. Les actions permettent au modèle de se connecter à des sources externes, notamment des bases de connaissances ou des environnements, pour collecter des informations supplémentaires.
-
Concevoir un plan pour diviser l’ensemble de la tâche en sous-tâches plus petites, puis effectuer les sous-tâches conformément au plan. Cette approche atténue les erreurs de calcul, les erreurs d’étape manquante et les erreurs de compréhension sémantique qui sont souvent présentes dans le prompting par chaîne de pensée sans exemple (« zero-shot »).
Réfléchir/Faire une autocritique
Utilisez des agents de réflexion qui réfléchissent verbalement aux signaux des commentaires sur les tâches. Ces agents conservent leur propre texte de réflexion dans une mémoire tampon de mémoire épisodique afin d’induire une meilleure prise de décision lors d’essais ultérieurs.
Frameworks
Divers frameworks et outils peuvent faciliter le développement et le déploiement d’agents IA.
Si l’utilisation d’outils et la perception ne nécessitent pas de planification ni de mémoire sophistiquées, vous pouvez recourir à des frameworks d’orchestration LLM populaires comme LangChain, LlamaIndex, Prompt Flow et Semantic Kernel.
Pour les flux de travail avancés et autonomes de planification et d’exécution, AutoGen propulse la vague multi-agent qui a commencé fin 2022. LesAPI Assistants d’OpenAI permettent aux utilisateurs de créer des agents en mode natif dans l’écosystème GPT. Agents LangChain et Agents LlamaIndex ont également émergé en même temps.
Conseil
L’exemple d’implémentation présenté plus loin dans cet article montre comment créer un système multi-agent simple à l’aide de l’un des frameworks couramment utilisés et d’un système de mémoire d’agent unifié.
Système de mémoire de l’agent IA
La pratique courante pour expérimenter des applications améliorées par l’IA de 2022 à 2024 consistait à utiliser des systèmes de gestion de base de données autonomes pour différents workflows ou types de données. Par exemple, vous pouvez utiliser une base de données en mémoire pour la mise en cache, une base de données relationnelle pour les données opérationnelles (y compris les journaux de traçage/d’activité et l’historique des conversations LLM) et une base de données vectorielle pure pour la gestion des incorporations.
Cependant, cette pratique reposant sur l’utilisation d’un réseau complexe de bases de données autonomes peut nuire aux performances d’un agent IA. L’intégration de toutes ces bases de données disparates dans un système de mémoire cohérent, interopérable et résilient pour les agents IA est un défi en soi.
De plus, de nombreux services de bases de données fréquemment utilisés ne sont pas optimaux du fait que la vitesse et la scalabilité qu’ils proposent ne répondent pas aux besoins des systèmes d’agents IA. Les faiblesses individuelles de ces bases de données sont accentuées dans les systèmes multi-agents.
Bases de données en mémoire
Les bases de données en mémoire sont excellentes en termes de vitesse, mais peuvent avoir des difficultés avec la persistance des données à grande échelle dont les agents IA ont besoin.
Bases de données relationnelles
Les bases de données relationnelles ne sont pas idéales pour les modalités variées et les schémas fluides des données que gèrent les agents. Les bases de données relationnelles nécessitent des efforts manuels et même des temps d’arrêt pour gérer l’approvisionnement, le partitionnement et le sharding.
Bases de données vectorielles pures
Les bases de données vectorielles pures ont tendance à être moins efficaces pour les opérations transactionnelles, les mises à jour en temps réel et les charges de travail distribuées. L’offre des bases de données vectorielles pures populaires est généralement la suivante :
- Aucune garantie sur les lectures et les écritures.
- Débit d’ingestion limité.
- Faible disponibilité (inférieure à 99,9 %, ou panne annualisée de 9 heures ou plus).
- Un niveau de cohérence (éventuellement).
- Un index vectoriel en mémoire gourmand en ressources.
- Options limitées pour l’architecture mutualisée.
- Sécurité limitée.
Caractéristiques d’un système de mémoire d’agent IA robuste
Au même titre que des systèmes de gestion de base de données efficaces sont essentiels aux performances des applications logicielles, il est primordial de fournir aux agents avec LLM des informations pertinentes et utiles pour guider leur inférence. Les systèmes de mémoire robustes permettent d’organiser et de stocker différents types d’informations que les agents peuvent récupérer au moment de l’inférence.
Actuellement, les applications basées sur LLM utilisent souvent génération augmentée par récupération qui utilise la recherche sémantique de base ou la recherche vectorielle pour récupérer des passages ou des documents. La recherche vectorielle peut être utile pour trouver des informations générales. Toutefois, la recherche vectorielle peut ne pas capturer le contexte, la structure ou les relations spécifiques qui se rapportent à une tâche ou un domaine particulier.
Par exemple, si la tâche consiste à écrire du code, la recherche vectorielle peut ne pas être en mesure de récupérer l’arborescence de syntaxe, la disposition du système de fichiers, les résumés de code ou les signatures d’API qui sont importants pour générer du code cohérent et correct. De même, si la tâche consiste à utiliser des données tabulaires, la recherche vectorielle peut ne pas être en mesure de récupérer le schéma, les clés étrangères, les procédures stockées ou les rapports qui sont utiles pour interroger ou analyser les données.
L’assemblage d’un réseau de bases de données autonomes en mémoire, relationnelles et vectorielles (comme décrit précédemment) n’est pas non plus une solution optimale pour les différents types de données. Cette approche peut fonctionner pour des systèmes d’agents prototypiques. Toutefois, elle ajoute de la complexité et des goulots d’étranglement qui peuvent entraver les performances des agents autonomes avancés.
Un système de mémoire robuste doit avoir les caractéristiques suivantes.
Multimodal
Les systèmes de mémoire d’agent IA doivent fournir des collections qui stockent des métadonnées, des relations, des entités, des résumés ou d’autres types d’informations qui peuvent être utiles pour des tâches et des domaines divers. Ces collections peuvent être basées sur la structure et le format des données, notamment des documents, des tables ou du code. Elles peuvent également être basées sur le contenu et la signification des données, notamment des concepts, des associations ou des étapes procédurales.
Les systèmes de mémoire ne sont pas seulement essentiels pour les agents IA. Ils sont également importants pour les humains qui développent, entretiennent et utilisent ces agents.
Par exemple, les humains peuvent avoir besoin de superviser les workflows de planification et d’exécution des agents en quasi-temps réel. Pendant la supervision, les humains peuvent intervenir en donnant des conseils ou en apportant des modifications en ligne aux dialogues ou aux monologues des agents. Les humains peuvent également avoir besoin d’auditer le raisonnement et les actions des agents pour vérifier la validité de la sortie finale.
Les interactions humain/agent sont probables dans les langages naturels ou de programmation, tandis que les agents « pensent », « apprennent » et « se souviennent » au moyen d’incorporations. Cette différence pose une autre exigence sur la cohérence des systèmes de mémoire entre les modalités de données.
En fonctionnement
Les systèmes de mémoire doivent fournir des banques de mémoire qui stockent des informations pertinentes pour l’interaction avec l’utilisateur et l’environnement. Ces informations peuvent inclure l’historique des conversations, les préférences utilisateur, les données sensorielles, les décisions prises, les faits appris ou d’autres données opérationnelles mises à jour avec une fréquence élevée et en grand volume.
Ces banques de mémoire peuvent aider les agents à mémoriser des informations à court terme et à long terme, à éviter de répéter ou à se contredire eux-mêmes, et à maintenir la cohérence des tâches. Ces exigences doivent rester valables même si les agents exécutent successivement une multitude de tâches sans rapport les unes avec les autres. Dans les cas avancés, les agents peuvent également tester de nombreux plans de branchement qui divergent ou convergent en différents points.
Partageable mais aussi séparable
Au niveau macro, les systèmes de mémoire doivent permettre à plusieurs agents IA de collaborer sur un problème ou de traiter différents aspects du problème en fournissant une mémoire partagée accessible à tous les agents. La mémoire partagée peut faciliter l’échange d’informations et la coordination des actions entre les agents.
En même temps, le système de mémoire doit permettre aux agents de conserver leur propre personnage et caractéristiques, comme leurs collections uniques d’invites et de souvenirs.
Création d’un système de mémoire d’agent IA robuste
Les caractéristiques précédentes nécessitent que les systèmes de mémoire d’agent IA soient hautement évolutifs et rapides. L’assemblage minutieux de bases de données disparates en mémoire, relationnelles et vectorielles (comme décrit précédemment) peut fonctionner pour les premières applications basées sur l’IA. Toutefois, cette approche ajoute de la complexité et des goulots d’étranglement qui peuvent entraver les performances des agents autonomes avancés.
À la place de toutes les bases de données autonomes, Azure Cosmos DB peut servir de solution unifiée pour les systèmes de mémoire de l’agent IA. Sa robustesse a activé le service ChatGPT d’OpenAI pour effectuer une mise à l’échelle dynamique avec une fiabilité élevée et une faible maintenance. Doté d’un moteur ARS (atom-record-sequence), il s’agit du premier service de bases de données NoSQL, relationnelles et vectorielles distribué à l’échelle mondiale qui offre un mode serverless. Les agents IA basés sur Azure Cosmos DB offrent vitesse, mise à l’échelle et simplicité.
Vitesse
Azure Cosmos DB fournit une latence en millisecondes à un chiffre. Cette capacité convient aux processus qui nécessitent un accès et une gestion rapides des données. Ces processus incluent la mise en cache (à la fois la mise en cache traditionnelle et la mise en cache sémantique), les transactions et les charges de travail opérationnelles.
Une faible latence est cruciale pour les agents IA qui doivent effectuer un raisonnement complexe, prendre des décisions en temps réel et fournir des réponses immédiates. En outre, l’utilisation de l’algorithme DiskANN par le service permet une recherche vectorielle précise et rapide avec une consommation de mémoire minimale.
Mise à l’échelle
Azure Cosmos DB est conçu pour une distribution mondiale et une scalabilité horizontale. Il prend en charge les E/S multirégions et l’architecture mutualisée.
Le service garantit que les systèmes de mémoire peuvent se développer de manière transparente et suivre la croissance rapide des agents et des données associées. La garantie de disponibilité dans son contrat de niveau de service (SLA) se traduit par moins de 5 minutes de temps d’arrêt par an. En revanche, les services de bases de données vectorielles pures sont assortis d’un temps d’arrêt de 9 heures ou plus. Cette disponibilité constitue une base solide pour les charges de travail stratégiques. En même temps, les différents modèles de service dans Azure Cosmos DB, comme la capacité de réserve ou serverless, peuvent contribuer à réduire les coûts financiers.
Simplicité
Azure Cosmos DB peut simplifier la gestion et l’architecture des données en intégrant plusieurs fonctionnalités de base de données dans une plateforme unique et cohérente.
Ses fonctionnalités de base de données vectorielles intégrées peuvent stocker, indexer et interroger des incorporations en même temps que les données correspondantes dans des langages naturels ou de programmation. Cela permet d’améliorer la cohérence des données, la mise à l’échelle et le niveau de performance.
Sa flexibilité prend en charge les modalités variées et les schémas fluides des métadonnées, des relations, des entités, des résumés, de l’historique des conversations, des préférences utilisateur, des données sensorielles, des décisions, des faits appris ou d’autres données opérationnelles impliquées dans les workflows de l’agent. La base de données indexe automatiquement toutes les données sans nécessiter la gestion du schéma ou de l’index, ce qui aide les agents IA à effectuer des requêtes complexes rapidement et efficacement.
Azure Cosmos DB est complètement managé, ce qui élimine la surcharge liée aux tâches d’administration de base de données telles que la mise à l’échelle, la mise à jour corrective et les sauvegardes. Sans cette surcharge, les développeurs peuvent se concentrer sur la création et l’optimisation des agents IA sans se soucier de l’infrastructure de données sous-jacente.
Fonctionnalités avancées
Azure Cosmos DB intègre des fonctionnalités avancées telles que le flux de modification, ce qui permet de suivre les modifications apportées aux données et d’y répondre en temps réel. Cette fonctionnalité est utile pour les agents IA qui doivent réagir rapidement à de nouvelles informations.
En outre, la prise en charge intégrée des écritures multimaîtres permet une disponibilité et une résilience élevées, garantissant le fonctionnement continu des agents IA même à la suite de défaillances régionales.
Les cinq niveaux de cohérence disponibles (de fort à éventuel) peuvent également répondre à différentes charges de travail distribuées en fonction des exigences du scénario.
Conseil
Vous avez le choix entre deux API Azure Cosmos DB pour créer votre système de mémoire d’agent IA :
- Azure Cosmos DB for NoSQL, qui offre une garantie de disponibilité de 99,999 % et fournit trois algorithmes de recherche vectorielle : IVF, HNSW et DiskANN
- Azure Cosmos DB for MongoDB basé sur vCore, qui offre une garantie de disponibilité de 99,995 % et fournit deux algorithmes de recherche vectorielle : IVF et HNSW (DiskANN à venir)
Pour plus d’informations sur les garanties de disponibilité de ces API, consultez les contrats SLA des services.
Exemple d’implémentation
Cette section explore l’implémentation d’un agent autonome pour traiter les demandes et réservations de voyageurs dans une application de voyage pour une compagnie de croisière.
Contrairement aux chatbots qui reposent sur un concept déjà ancien, les agents IA vont au-delà de la conversation humaine de base pour effectuer des tâches basées sur le langage naturel. Par le passé, ces tâches nécessitaient une logique codée. L’agent de voyage IA dans cet exemple d’implémentation utilise le framework LangChain Agent pour la planification de l’agent, l’utilisation d’outils et la perception.
Le système de mémoire unifiée de l’agent de voyage IA utilise la base de données vectorielle et les fonctionnalités du magasin de documents d’Azure Cosmos DB pour répondre aux demandes des voyageurs et faciliter les réservations. L’utilisation d’Azure Cosmos DB à cette fin permet de garantir la vitesse, la mise à l’échelle et la simplicité des opérations, comme décrit précédemment.
L’exemple d’agent fonctionne dans un back-end Python FastAPI. Il prend en charge les interactions utilisateur via une interface utilisateur React JavaScript.
Prérequis
- Un abonnement Azure. Si vous n’en avez pas, vous pouvez essayer gratuitement Azure Cosmos DB pendant 30 jours sans créer de compte Azure. L’essai gratuit ne nécessite pas de carte de crédit, et aucun engagement ne suit la période d’essai.
- Un compte pour l’API OpenAI ou Azure OpenAI Service.
- Un cluster vCore dans Azure Cosmos DB for MongoDB. Vous pouvez en créer un en suivant ce guide de démarrage rapide.
- Un environnement de développement intégré comme Visual Studio Code.
- Python 3.11.4 installé dans l’environnement de développement.
Téléchargez le projet
Le code et les exemples de jeux de données sont disponibles dans ce dépôt GitHub. Le dépôt inclut les dossiers suivants :
- Chargeur: ce dossier contient du code Python pour le chargement d’exemples de documents et d’incorporations vectorielles dans Azure Cosmos DB.
- api : ce dossier contient le projet Python FastAPI pour héberger l’agent de voyage IA.
- web : ce dossier contient du code pour l’interface web de React.
Charger des documents de voyage dans Azure Cosmos DB
Le dépôt GitHub contient un projet Python dans le répertoire loader. Il est destiné au chargement des exemples de documents de voyage dans Azure Cosmos DB.
Configurer l’environnement
Configurez votre environnement virtuel Python dans le répertoire loader en exécutant la commande suivante :
python -m venv venv
Activez votre environnement et installez les dépendances dans le référentiel du chargeur de :
venv\Scripts\activate
python -m pip install -r requirements.txt
Créez un fichier nommé .env dans le répertoire loader pour stocker les variables d’environnement suivantes :
OPENAI_API_KEY="<your OpenAI key>"
MONGO_CONNECTION_STRING="mongodb+srv:<your connection string from Azure Cosmos DB>"
Charger des documents et des vecteurs
Le fichier Python main.py sert de point d’entrée central pour le chargement de données dans Azure Cosmos DB. Ce code traite les exemples de données de voyage à partir du référentiel GitHub, y compris des informations sur les navires et les destinations. Le code génère également des forfaits d’itinéraire de voyage pour chaque navire et destination, ce qui permet aux voyageurs de les réserver à l’aide de l’agent IA. L’outil CosmosDBLoader est responsable de la création des collections, des incorporations vectorielles et des index dans l’instance Azure Cosmos DB.
Voici le contenu de 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')])
Chargez les documents, chargez les vecteurs et créez des index en exécutant la commande suivante à partir du répertoire loader :
python main.py
Voici la sortie de main.py :
--build itinerary--
--load itinerary--
--load destinations--
--load vectors ships--
Générer l’agent de voyage IA à l’aide de Python FastAPI
L’agent de voyage IA est hébergé dans une API back-end via Python FastAPI, ce qui facilite l’intégration avec l’interface utilisateur front-end. Le projet API traite les demandes des agents en basant les invites LLM sur la couche de données, en particulier les vecteurs et les documents dans Azure Cosmos DB.
L’agent utilise différents outils, en particulier les fonctions Python fournies au niveau de la couche de service API. Cet article se concentre sur le code nécessaire pour les agents IA dans le code de l’API.
Le projet d’API dans le référentiel GitHub est structuré comme suit :
- Les composants de modélisation des données utilisent des modèles Pydantic.
- Les composants de la couche web sont responsables de l’acheminement des demandes et de la gestion de la communication.
- Les composants de la couche de service sont responsables de la logique métier principale et de l’interaction avec la couche de données, l’agent LangChain et les outils de l’agent.
- Les composants de la couche de données sont responsables de l’interaction avec le stockage de documents et la recherche vectorielle d’Azure Cosmos DB for MongoDB.
Configurer l’environnement pour l’API
Nous avons utilisé Python version 3.11.4 pour le développement et les tests de l’API.
Configurez votre environnement virtuel Python dans le répertoire api :
python -m venv venv
Activez votre environnement et installez les dépendances à l’aide du fichier requirements situé dans le répertoire api :
venv\Scripts\activate
python -m pip install -r requirements.txt
Créez un fichier nommé .env dans le répertoire api pour stocker vos variables d’environnement :
OPENAI_API_KEY="<your Open AI key>"
MONGO_CONNECTION_STRING="mongodb+srv:<your connection string from Azure Cosmos DB>"
Après avoir configuré l’environnement et configuré des variables, exécutez la commande suivante à partir du répertoire api pour lancer le serveur :
python app.py
Le serveur FastAPI démarre sur le port 8000 de bouclage localhost 127.0.0.1 par défaut. Vous pouvez accéder aux documents Swagger en utilisant l’adresse localhost suivante : http://127.0.0.1:8000/docs
.
Utiliser une session pour la mémoire de l’agent IA
Il est impératif que l’agent de voyage puisse faire référence aux informations fournies précédemment dans la conversation en cours. Cette capacité est communément appelée mémoire dans le contexte des LLM.
Pour atteindre cet objectif, utilisez l’historique des conversations stocké dans l’instance Azure Cosmos DB. L’historique de chaque session de conversation est stocké avec un identifiant de session. De cette façon, seuls les messages de la session de conversation actuelle sont accessibles. C’est cette nécessité qui explique l’existence d’une méthode Get Session
dans l’API. Il s’agit d’une méthode d’espace réservé pour gérer les sessions web afin d’illustrer l’utilisation de l’historique des conversations.
Sélectionnez Essayer pour /session/
.
{
"session_id": "0505a645526f4d68a3603ef01efaab19"
}
Pour l’agent IA, il vous suffit de simuler une session. La méthode stubbed-out retourne simplement un ID de session généré pour le suivi de l’historique des conversations. Dans la pratique, cette session serait stockée dans Azure Cosmos DB et potentiellement dans le localStorage
de React.
Voici le contenu de web/session.py :
@router.get("/")
def get_session():
return {'session_id':str(uuid.uuid4().hex)}
Démarrer une conversation avec l’agent de voyage IA
Utilisez l’ID de session que vous avez obtenu à l’étape précédente pour démarrer un nouveau dialogue avec l’agent AI pour valider sa fonctionnalité. Effectuez le test en soumettant la phrase suivante : « I want to take a relaxing vacation » (Je veux passer des vacances reposantes).
Sélectionnez Essayer pour /agent/agent_chat
.
Utilisez cet exemple de paramètre :
{
"input": "I want to take a relaxing vacation.",
"session_id": "0505a645526f4d68a3603ef01efaab19"
}
L’exécution initiale aboutit à une recommandation pour les croisières Tranquil Breeze Cruise et Fantasy Seas Adventure Cruise, car l’agent estime qu’il s’agit des croisières les plus reposantes disponibles par recherche vectorielle. Ces documents ont le score le plus élevé pour similarity_search_with_score
appelé dans la couche de données de l’API, data.mongodb.travel.similarity_search()
.
Les scores de recherche de similarité apparaissent en sortie de l’API à des fins de débogage. Voici la sortie après un appel à data.mongodb.travel.similarity_search()
:
0.8394561085977978
0.8086545112328692
2
Conseil
Si les documents ne sont pas retournés pour la recherche vectorielle, modifiez la limite de similarity_search_with_score
ou la valeur du filtre de score si nécessaire ([doc for doc, score in docs if score >=.78]
) dans data.mongodb.travel.similarity_search()
.
L’appel de agent_chat
pour la première fois crée une collection nommée history
dans Azure Cosmos DB pour stocker la conversation par session. Cet appel permet à l’agent d’accéder à l’historique des messages de conversation stocké en fonction des besoins. Les exécutions suivantes de agent_chat
avec les mêmes paramètres produisent des résultats variables, car elles puisent dans la mémoire.
Parcourir l’agent IA
Lorsque vous intégrez l’agent AI dans l’API, les composants de recherche web sont chargés de lancer toutes les requêtes. Les composants de la recherche web sont suivis du service de recherche, et enfin des composants de données.
Dans ce cas spécifique, vous utilisez une recherche de données MongoDB qui se connecte à Azure Cosmos DB. Les couches facilitent l’échange de composants du modèle, car le code de l’agent IA et des outils de l’agent IA résident dans la couche de service. Cette approche permet l’échange transparent des sources de données. Elle étend également les fonctionnalités de l’agent IA avec des fonctionnalités ou des outils supplémentaires plus complexes.
Couche de service
La couche de service constitue la pierre angulaire de la logique métier principale. Dans ce scénario particulier, la couche de service joue un rôle crucial en tant que référentiel du code LangChain Agent. Elle facilite l’intégration transparente des prompts utilisateur avec les données Azure Cosmos DB, la mémoire de conversation et les fonctions d’agent pour l’agent IA.
La couche de service utilise un module de modèle singleton pour gérer les initialisations liées à l’agent dans le fichier init.py. Voici le contenu de 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()
Le fichier init.py lance le chargement des variables d’environnement à partir d’un fichier .env à l’aide de la méthode load_dotenv(override=False)
. Ensuite, une variable globale nommée agent_with_chat_history
est instanciée pour l’agent. Cet agent est destiné à être utilisé par TravelAgent.py.
La méthode LLM_init()
est appelée pendant l’initialisation du module afin de configurer l’agent AI pour la conversation via la couche web de l’API. L’objet OpenAI chat
est instancié via le modèle GPT-3.5 et intègre des paramètres spécifiques tels que le nom du modèle et la température. L’objet chat
, la liste d’outils et le modèle de prompt sont combinés pour générer AgentExecutor
, qui joue le rôle d’agent de voyage IA.
L’agent avec historique, agent_with_chat_history
, est établi via RunnableWithMessageHistory
avec l’historique des conversations (MongoDBChatMessageHistory
). Cette action lui permet de conserver un historique des conversations complet via Azure Cosmos DB.
Prompt
L’invite LLM a commencé initialement avec la simple déclaration « Vous êtes un assistant de voyage utile et convivial pour une compagnie de croisière. » Toutefois, les tests ont montré que vous pouviez obtenir des résultats plus cohérents en incluant l’instruction « Répondez aux questions de voyage du mieux que vous pouvez, en fournissant uniquement des informations pertinentes. Pour réserver une croisière, capturer le nom de la personne est essentiel. » Les résultats apparaissent au format HTML pour améliorer l’attrait visuel de l’interface web.
Outils d’agent
Les outils sont des interfaces qu’un agent peut utiliser pour interagir avec le monde, souvent par le biais d’appels de fonction.
Quand vous créez un agent, vous devez lui fournir un ensemble d’outils qu’il peut utiliser. L’élément décoratif @tool
offre l’approche la plus simple pour définir un outil personnalisé.
Par défaut, l’élément décoratif utilise le nom de la fonction comme nom d’outil, bien que vous puissiez le remplacer en fournissant une chaîne comme premier argument. L’élément décoratif utilise la docstring de la fonction comme description de l’outil, ce qui nécessite donc l’approvisionnement d’une docstring.
Voici le contenu de 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"
Le fichier TravelAgentTools.py définit trois outils :
vacation_lookup
effectue une recherche vectorielle sur Azure Cosmos DB. Il utilisesimilarity_search
pour récupérer des informations pertinentes liées au voyage.itinerary_lookup
récupère les détails et le calendrier des forfaits croisière pour un navire de croisière spécifié.book_cruise
réserve un forfait croisière pour un passager.
Il peut être nécessaire de spécifier des instructions spécifiques, comme « In order to book a cruise I need to know your name » (Pour réserver une croisière, je dois connaître votre nom) afin de garantir la capture du nom et du numéro de chambre du passager pour la réservation du forfait croisière, même si vous avez inclus de telles instructions dans le prompt LLM.
Agent IA
Le concept fondamental sur lequel reposent les agents est l’utilisation d’un modèle de langage pour sélectionner une séquence d’actions à exécuter.
Voici le contenu de 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))
Le fichier TravelAgent.py est simple, car agent_with_chat_history
et ses dépendances (outils, prompt et LLM) sont initialisés et configurés dans le fichier init.py. Ce fichier appelle l’agent en utilisant l’entrée reçue de l’utilisateur, ainsi que l’ID de session pour la mémoire de conversation. Par la suite, PromptResponse
(modèle/prompt) est retourné avec la sortie et le temps de réponse de l’agent.
Intégration de l’agent IA à l’interface utilisateur React
Une fois les données chargées et l’agent IA mis à disposition via l’API, vous pouvez désormais terminer la solution en établissant une interface utilisateur web (en utilisant React) pour le site web de voyage. L’utilisation des fonctionnalités de React permet d’illustrer l’intégration transparente de l’agent IA dans un site de voyage. Cette intégration améliore l’expérience utilisateur avec un assistant de voyage conversationnel pour les demandes de renseignements et les réservations.
Configurer l’environnement pour React
Installez Node.js et les dépendances avant de tester l’interface de React.
Exécutez la commande suivante à partir du répertoire web pour effectuer une nouvelle installation des dépendances du projet. L’installation peut prendre du temps.
npm ci
Créez ensuite un fichier nommé .env dans le répertoire web pour faciliter le stockage des variables d’environnement. Incluez les détails suivants dans le fichier .env récemment créé :
REACT_APP_API_HOST=http://127.0.0.1:8000
Exécutez à présent la commande suivante à partir du répertoire web pour lancer l’interface utilisateur web de React :
npm start
L’exécution de la commande précédente ouvre l’application web React.
Parcourir l’interface web de React
Le projet web du dépôt GitHub est une application simple qui facilite l’interaction utilisateur avec l’agent IA. Les principaux composants requis pour converser avec l’agent sont TravelAgent.js et ChatLayout.js. Le fichier Main.js sert de module central ou de page d’accueil utilisateur.
Principal
Le composant principal sert de gestionnaire central de l’application. Il fait office de point d’entrée désigné pour l’acheminement. Dans la fonction de rendu, elle produit du code JSX pour délimiter la mise en page principale. Cette disposition englobe les éléments d’espace réservé pour l’application, tels que les logos et les liens, une section qui héberge le composant de l’agent de voyage et un pied de page contenant un exemple de clause d’exclusion de responsabilité concernant la nature de l’application.
Voici le contenu de 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
Agent de voyage
Le composant agent de voyage a un objectif simple : capturer les entrées utilisateur et d’afficher des réponses. Il joue un rôle clé dans la gestion de l’intégration avec l’agent IA back-end, principalement en capturant les sessions et en transférant les prompts des utilisateurs au service FastAPI. Les réponses obtenues sont stockées dans un tableau pour l’affichage, ce qui est accompli par le composant de disposition de la conversation.
Voici le contenu de 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>
)
}
Sélectionnez Effortlessly plan your voyage (Planifier votre voyage sans effort) pour ouvrir l’assistant de voyage.
Disposition de conversation
Le composant de disposition de la conversation, comme indiqué par son nom, supervise la disposition de la conversation. Il traite systématiquement les messages de conversation et implémente la mise en forme spécifiée dans l’objet JSON message
.
Voici le contenu de TripPlanning/ChatLayout.py :
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>
)
}
Les prompts utilisateur se trouvent sur le côté droit et sont colorés en bleu. Les réponses de l’agent de voyage IA se trouvent sur le côté gauche et sont colorées en vert. Comme le montre l’image suivante, les réponses au format HTML sont prises en compte dans la conversation.
Lorsque votre agent IA est prêt à passer en production, vous pouvez utiliser la mise en cache sémantique pour améliorer les performances des requêtes de 80 % et réduire les coûts d’inférence LLM et d’appel d’API. Pour implémenter la mise en cache sémantique, consultez ce billet sur le blog Stochastic Coder.