RAG (Retrieval Augmented Generation) avec LlamaIndex, Elasticsearch et Mistral

Apprenez à mettre en œuvre un système RAG (Retrieval Augmented Generation) en utilisant LlamaIndex, Elasticsearch et Mistral en local.

Elasticsearch dispose d'intégrations natives avec les outils et fournisseurs d'IA générative leaders du secteur. Consultez nos webinars sur le dépassement des bases de RAG ou sur la création d'applications prêtes à l'emploi avec la Base vectorielle Elastic.

Pour élaborer les meilleures solutions de recherche pour votre cas d'utilisation, commencez un essai gratuit d'Elastic Cloud ou essayez Elastic sur votre machine locale dès maintenant.

Dans ce blog, nous verrons comment mettre en œuvre l'expérience Q&A en utilisant une technique RAG (Retrieval Augmented Generation) avec Elasticsearch comme base de données vectorielle. Nous utiliserons LlamaIndex et un LLM Mistral fonctionnant localement.

Avant de commencer, nous allons examiner quelques termes.

Terminologie

LlamaIndex est un cadre de données de premier plan pour la création d'applications LLM (Large Language Model). LlamaIndex fournit des abstractions pour les différentes étapes de la construction d'une application RAG (Retrieval Augmented Generation). Des structures telles que LlamaIndex et LangChain fournissent des abstractions afin que les applications ne soient pas étroitement liées aux API d'un LLM spécifique.

Elasticsearch est proposé par Elastic. Elastic est un leader de l'industrie avec Elasticsearch, un moteur de recherche et d'analyse qui prend en charge la recherche en texte intégral pour la précision, la recherche vectorielle pour la compréhension sémantique, et la recherche hybride pour le meilleur des deux mondes. Elasticsearch est un magasin de données évolutif et une base de données vectorielle. Les fonctionnalités d'Elasticsearch que nous utilisons dans ce blog sont disponibles dans la version gratuite et ouverte d'Elasticsearch.

Retrieval Augment Generation (RAG) est une technique/un modèle d'IA dans lequel les LLM sont dotés de connaissances externes pour générer des réponses aux requêtes des utilisateurs. Cela permet d'adapter les réponses du programme d'éducation et de formation tout au long de la vie à un contexte spécifique et les réponses sont plus spécifiques.

Mistral propose des modèles LLM open-source et optimisés pour les entreprises. Dans ce tutoriel, nous utiliserons leur modèle open source mistral-7b qui fonctionne sur votre ordinateur portable. Si vous ne souhaitez pas exécuter le modèle sur votre ordinateur portable, vous pouvez utiliser la version en nuage, auquel cas vous devrez modifier le code de ce blog afin d'utiliser les clés et les paquets API appropriés.

Ollama permet d'exécuter des LLM localement sur votre ordinateur portable. Nous utiliserons Ollama pour exécuter localement le modèle open source Mistral-7b.

Les encastrements sont des représentations numériques de la signification d'un texte ou d'un média. Il s'agit de représentations de dimensions inférieures d'informations de dimensions supérieures.

Construire une application RAG avec LlamaIndex, Elasticsearch & Mistral : Aperçu du scénario

Scénario :

Nous disposons d'un échantillon de données (sous forme de fichier JSON) de conversations entre des agents et des clients d'une compagnie d'assurance habitation fictive. Nous allons créer une application RAG simple qui peut répondre à des questions telles que

Give me summary of water related issues.

Débit élevé

Mistral LLM fonctionne localement à l'aide d'Ollama.

Ensuite, nous chargeons les conversations du fichier JSON en tant que Documents dans le magasin ElasticsearchStore (qui est un magasin VectorStore soutenu par Elasticsearch). Lors du chargement des documents, nous créons des enchâssements à l'aide du modèle Mistral exécuté localement. Nous stockons ces encastrements ainsi que les conversations dans le magasin vectoriel Elasticsearch de LlamaIndex(ElasticsearchStore).

Nous configurons une ligne d'ingestion LlamaIndex et lui fournissons le LLM local que nous utilisons, dans ce cas Mistral fonctionnant via Ollama.

Lorsque nous posons une question telle que "Donnez-moi un résumé des problèmes liés à l'eau", Elasticsearch effectue une recherche sémantique et renvoie les conversations liées aux problèmes de l'eau. Ces conversations, ainsi que la question initiale, sont envoyées au LLM local pour générer une réponse.

Étapes de la création de l'application RAG

Exécuter Mistral localement

Téléchargez et installez Ollama. Après avoir installé Ollama, lancez la commande suivante pour télécharger et exécuter mistral

Le téléchargement et l'exécution locale du modèle pour la première fois peuvent prendre quelques minutes. Vérifiez si le mistral fonctionne en posant une question telle que la suivante : "Ecrivez un poème sur les nuages" et vérifiez si le poème vous plaît. Gardez ollama en marche car nous aurons besoin d'interagir avec le modèle mistral plus tard par le biais du code.

Installer Elasticsearch

Faites fonctionner Elasticsearch en créant un déploiement dans le nuage(instructions ici) ou en l'exécutant dans Docker(instructions ici). Vous pouvez également créer un déploiement autonome d'Elasticsearch au niveau de la production en commençant ici.

Si vous utilisez le déploiement dans le nuage, saisissez la clé API et l'ID du nuage pour le déploiement, comme indiqué dans les instructions. Nous les utiliserons plus tard.

Application RAG

Pour référence, le code complet peut être trouvé dans ce dépôt Github. Le clonage de la base de données est facultatif car nous allons parcourir le code ci-dessous.

Dans votre IDE préféré, créez une nouvelle application Python avec les 3 fichiers ci-dessous.

  • index.py où se trouve le code lié à l'indexation des données.
  • query.py où se trouve le code lié à l'interrogation et à l'interaction avec le LLM.
  • .env où se trouvent les propriétés de configuration telles que les clés d'API.

Nous devons installer quelques paquets. Nous commençons par créer un nouvel environnement virtuel python dans le dossier racine de votre application.

Activez l'environnement virtuel et installez les paquets requis ci-dessous.

Indexation des données

Téléchargez le fichier conversations.json qui contient les conversations entre les clients et les agents du centre d'appel de notre compagnie d'assurance habitation fictive. Placez le fichier dans le répertoire racine de l'application avec les 2 fichiers python et le fichier .env. que vous avez créé précédemment. Vous trouverez ci-dessous un exemple du contenu du fichier.

Nous définissons une fonction appelée get_documents_from_file dans index.py qui lit le fichier json et crée une liste de documents. Les objets document sont l'unité de base de l'information avec laquelle LlamaIndex travaille.

Créer un pipeline d'ingestion

Tout d'abord, ajoutez au fichier .env l'Elasticsearch CloudID et les clés API que vous avez obtenues dans la section Install Elasticsearch. Votre fichier .env devrait ressembler à ce qui suit (avec des valeurs réelles).

LlamaIndex IngestionPipeline vous permet de composer un pipeline à l'aide de plusieurs composants. Ajoutez le code ci-dessous au fichier index.py.

Comme nous l'avons déjà mentionné, la LlamaIndex IngestPipeline peut être composée de plusieurs éléments. Nous ajoutons 3 composants au pipeline dans la ligne pipeline = IngestionPipeline(....

  • SentenceSplitter: Comme on peut le voir dans la définition de get_documents_from_file(), chaque document possède un champ texte qui contient la conversation trouvée dans le fichier json. Ce champ de texte est un long texte. Pour que la recherche sémantique fonctionne bien, elle doit être décomposée en morceaux de textes plus petits. La classe SentenceSplitter s'en charge pour nous. Ces morceaux sont appelés nœuds dans la terminologie de LlamaIndex. Les nœuds contiennent des métadonnées qui renvoient au document auquel ils appartiennent. Vous pouvez également utiliser Elasticsearch Ingestpipeline pour le découpage, comme indiqué dans ce blog.
  • OllamaEmbedding: Les modèles d'incorporation convertissent un texte en nombres (également appelés vecteurs). La représentation numérique nous permet d'effectuer une recherche sémantique où les résultats de la recherche correspondent à la signification du mot plutôt que d'effectuer une simple recherche textuelle. Nous fournissons à l'IngestionPipeline le site OllamaEmbedding("mistral"). Les morceaux que nous découpons à l'aide de SentenceSplitter sont envoyés au modèle Mistral qui s'exécute sur votre machine locale via Ollama, mistral crée alors des embeddings pour les morceaux.
  • ElasticsearchStore: Le magasin vectoriel ElasticsearchStore de LlamaIndex sauvegarde les embeddings créés dans un index Elasticsearch. ElasticsearchStore se charge de créer et d'alimenter le contenu de l'index Elasticsearch spécifié. Lors de la création de l'ElasticsearchStore (référencé par es_vector_store), nous fournissons le nom de l'index Elasticsearch que nous voulons créer (calls dans notre cas), le champ de l'index dans lequel nous voulons stocker les embeddings (conversation_vector dans notre cas) et le champ dans lequel nous voulons stocker le texte (conversation dans notre cas). En résumé, selon notre configuration, ElasticsearchStore crée un nouvel index dans Elasticsearch avec conversation_vector et conversation comme champs (parmi d'autres champs créés automatiquement).

Pour relier le tout, nous exécutons le pipeline en appelant pipeline.run(documents=documents).

Lancez le script index.py pour exécuter le pipeline d'ingestion :

Une fois l'exécution du pipeline terminée, nous devrions voir un nouvel index dans Elasticsearch appelé calls. En exécutant une simple requête elasticsearch à l'aide de la Dev Console, vous devriez être en mesure de voir les données chargées avec les embeddings.

Pour résumer ce que nous avons fait jusqu'à présent, nous avons créé des documents à partir d'un fichier JSON, nous les avons divisés en morceaux, nous avons créé des embeddings pour ces morceaux et nous avons stocké les embeddings (et la conversation textuelle) dans un magasin vectoriel (ElasticsearchStore).

Interrogation

Le VectorStoreIndex llamaIndex vous permet de retrouver des documents pertinents et d'interroger des données. Par défaut, VectorStoreIndex stocke les intégrations en mémoire dans un SimpleVectorStore. Cependant, des entrepôts de vecteurs externes (comme ElasticsearchStore) peuvent être utilisés à la place pour rendre les enregistrements persistants.

Ouvrez le site query.py et collez le code ci-dessous

Nous définissons un LLM local (local_llm) pour indiquer le modèle Mistral fonctionnant sur Ollama. Ensuite, nous créons un VectorStoreIndex (index) à partir du magasin de vecteurs ElasticssearchStore que nous avons créé précédemment, puis nous obtenons un moteur de requête à partir de l'index. Lors de la création du moteur de requête, nous référençons le LLM local qui doit être utilisé pour répondre, nous fournissons également (similarity_top_k=10) pour configurer le nombre de documents qui doivent être récupérés dans le magasin vectoriel et envoyés au LLM pour obtenir une réponse.

Lancez le script query.py pour exécuter le flux RAG :

Nous envoyons la demande à Give me summary of water related issues (n'hésitez pas à personnaliser query) et la réponse du LLM, qui est accompagnée des documents correspondants, devrait ressembler à ce qui suit.

Dans le contexte fourni, nous voyons plusieurs cas où les clients se sont renseignés sur la couverture des dommages liés à l'eau. Dans deux cas, les inondations ont causé des dommages aux sous-sols et les fuites de toiture ont été à l'origine d'un autre cas. Les agents ont confirmé que les deux types de dégâts des eaux sont couverts par leurs polices respectives. Par conséquent, les problèmes liés à l'eau, tels que les inondations et les fuites de toit, sont généralement couverts par les polices d'assurance habitation.

Quelques mises en garde :

Cet article de blog est une introduction pour débutants à la technique RAG avec Elasticsearch et omet donc la configuration des fonctionnalités qui vous permettront de passer de ce point de départ à la production. Lorsque vous construisez pour des cas d'utilisation en production, vous voudrez prendre en compte des aspects plus sophistiqués comme la possibilité de protéger vos données avec Document Level Security, le découpage de vos données dans le cadre d'un pipeline d'ingestion Elasticsearch ou même l'exécution d'autres tâches de ML sur les mêmes données que celles utilisées pour les cas d'utilisation GenAI/Chat/Q&A.

Vous pouvez également envisager d'obtenir des données et de créer des embeddings à partir de diverses sources externes (par exemple Azure Blob Storage, Dropbox, Gmail, etc.) à l'aide d'Elastic Connectors.

Elastic rend possible tout ce qui précède et plus encore, et fournit une solution d'entreprise complète pour les cas d'utilisation de la GenAI et au-delà.

Quelle est la suite ?

  • Vous avez peut-être remarqué que nous envoyons 10 conversations connexes avec la question de l'utilisateur au LLM pour formuler une réponse. Ces conversations peuvent contenir des IPI (informations personnelles identifiables) telles que le nom, la date de naissance, l'adresse, etc. Dans notre cas, le LLM est local, la fuite de données n'est donc pas un problème. Cependant, lorsque vous souhaitez utiliser un LLM fonctionnant dans le nuage (par exemple OpenAI), il n'est pas souhaitable d'envoyer des textes contenant des informations PII. Dans un blog ultérieur, nous verrons comment masquer les informations PII avant de les envoyer aux LLM externes dans le flux RAG.
  • Dans ce billet, nous avons utilisé un LLM local. Dans le prochain billet sur le masquage des données PII dans RAG, nous verrons comment passer facilement d'un LLM local à un LLM public.

Questions fréquentes

Qu'est-ce que le LlamaIndex ?

LlamaIndex est un cadre de données de premier plan pour la création d'applications LLM (Large Language Model).

Qu'est-ce que le mistral ?

Mistral est une société qui propose des modèles LLM à code source ouvert et optimisés pour les entreprises.

Pour aller plus loin

Prêt à créer des expériences de recherche d'exception ?

Une recherche suffisamment avancée ne se fait pas avec les efforts d'une seule personne. Elasticsearch est alimenté par des data scientists, des ML ops, des ingénieurs et bien d'autres qui sont tout aussi passionnés par la recherche que vous. Mettons-nous en relation et travaillons ensemble pour construire l'expérience de recherche magique qui vous permettra d'obtenir les résultats que vous souhaitez.

Jugez-en par vous-même