Comment construire un chatbot AI génératif avec la source RAG sur AWS

  • 19 Oct 2023

Aperçu

 

La Retrieval Augmented Generation (RAG) est une technique qui combine les forces des approches traditionnelles basées sur la recherche et celles basées sur l'intelligence artificielle générative pour les systèmes de questions-réponses (QR). Dans un chatbot RAG, la requête de l'utilisateur est d'abord utilisée pour extraire des documents pertinents à partir d'une base de connaissances. Les documents extraits sont ensuite transmis à un grand modèle de langage (LLM), qui génère une réponse basée sur la requête et le contexte extrait.

Les chatbots RAG offrent plusieurs avantages par rapport aux chatbots AI génératifs traditionnels. Tout d'abord, les chatbots RAG peuvent fournir des réponses plus précises et informatives, car ils ont accès à une base de connaissances contenant des informations pertinentes. Deuxièmement, les chatbots RAG sont plus efficaces, car ils n'ont pas besoin de générer des réponses à partir de zéro à chaque fois.

Dans l'un de nos articles précédents, nous avons examiné comment construire un chatbot avec un système RAG en utilisant les données CSSF avec Azure OpenAI et Pinecone. L'objectif était de voir comment nous pouvions efficacement sourcer un modèle de base en utilisant les données publiques CSSF, telles que les documents circulaires, les FAQ, les pages de site Web, et bien d'autres. Egalement dans cet article (lien), comment construire un bot médical GenAI sur AWS.

Dans cet article, nous discuterons de la construction d'un chatbot RAG sur AWS. Nous comparerons différentes solutions et les résultats avec notre article précédent. Nous discuterons également de la manière de stocker des embeddings et des services pouvant être utilisés pour implémenter une source RAG sur AWS.

 

Comment fonctionne un système RAG

 

Un système RAG fonctionne d'abord en extrayant des documents pertinents d'une base de connaissances pour une requête donnée. Les documents extraits sont ensuite transmis à un grand modèle de langage (LLM), qui génère une réponse basée sur la requête et le contexte extrait. Cela permet au LLM de générer des réponses plus précises et de répondre même à des questions pour lesquelles il n'a pas été formé. Voici un aperçu étape par étape de la manière de construire un système RAG et d'inclure des documents :

 

  • Rassembler des documents : Collectez toutes les sources d'information pertinentes pour la tâche, telles que des documents (texte, PDF, DOCX), des pages Web, des e-mails, etc. Dans notre cas, nous avons créé un fichier CSV répertoriant tous les documents publics (principalement des PDF et des pages Web) avec leurs formats et leurs URL sources.

 

  • Déployer un modèle d'embedding : Cette étape consiste à convertir les documents collectés en embeddings pour les stocker et les interroger après une entrée utilisateur. De nombreuses options sont disponibles sur AWS, telles que l'utilisation du modèle Titan d'Amazon via le service Bedrock ou, en alternatif, vous pouvez utiliser SageMaker JumpStart, où vous pouvez créer des points de modèle pour des modèles d'embedding de texte préconstruits tels que BERT, RoBERTa, etc. Voici la liste complète des modèles disponibles : lien

 

  • Générer des embeddings : Utilisez un modèle d'embedding de texte pré-entraîné pour générer des embeddings pour chaque document de la base de connaissances. Les embeddings sont des représentations vectorielles de documents pouvant être utilisées pour mesurer la similarité entre les documents et extraire des documents pertinents pour une requête donnée. Selon la taille du document, vous voudrez peut-être les diviser en morceaux (par page unique ou par nombre de caractères). Dans cette démonstration, nous avons divisé les documents en morceaux de 3000 caractères.

 

  • Indexer les embeddings : Nous devons stocker ces embeddings générés quelque part pour pouvoir les interroger ultérieurement. La plupart des magasins de vecteurs utilisent ce que l'on appelle l'algorithme de recherche des plus proches voisins (KNN) pour rechercher parmi les embeddings. KNN offre un moyen évolutif et efficace de rechercher dans de grands ensembles de données, garantissant que les documents les plus pertinents sont rapidement récupérés.

 

  • Extraire des documents pertinents : Maintenant que nous disposons d'une base de données d'embeddings, nous devrions être en mesure de récupérer des documents pertinents pour l'entrée de l'utilisateur. Cependant, pour interroger un magasin de vecteurs, nous devons également convertir l'entrée de l'utilisateur en embeddings afin de pouvoir interroger notre magasin de vecteurs et récupérer les fichiers les plus proches en fonction des embeddings de la requête. En fonction des embeddings de la requête, nous pouvons récupérer les "k" documents les plus similaires de la source de connaissance indexée.

 

  • Combiner la prompt finale pour LLM : La dernière étape consiste à combiner toutes les informations ensemble. Cela inclut la prompt LLM que nous utilisons pour interagir avec notre modèle de base, la requête de l'utilisateur et les documents pertinents. Par exemple, lorsque l'utilisateur demande : "Pouvez-vous résumer la circulaire CSSF 23/34", nous récupérerons le document circulaire avec le numéro 23/34 et l'ajouterons à la prompt.

 

Les systèmes RAG offrent plusieurs avantages par rapport aux chatbots AI génératifs traditionnels :

  • Précision : Les systèmes RAG peuvent générer des réponses plus précises, car ils ont accès à une base de connaissances contenant des informations pertinentes.
  • Efficacité : Les systèmes RAG sont plus efficaces, car ils n'ont pas besoin de générer des réponses à partir de zéro à chaque fois.
  • Flexibilité : Les systèmes RAG peuvent être utilisés pour répondre à un plus large éventail de questions, y compris des questions pour lesquelles le LLM n'a pas été formé.

 

Voici un diagramme d'ensemble de la façon dont fonctionne un système RAG :

 

Rag diagram

 

Magasins de vecteurs sur AWS

 

À mesure que l'espace de l'IA générative se développe, le nombre de bases de données prenant en charge les embeddings augmente également. De nombreuses options sont disponibles, y compris des bases de données de vecteurs purs et des bases de données multi-modèles prenant en charge le stockage des embeddings. Certaines options bien connues et populaires incluent PostgreSQL, MongoDB et Redis. Pour une liste des moteurs de base de données de vecteurs et de leurs tendances, consultez ce lien. Si vous n'êtes pas familier avec les embeddings, consultez notre article précédent d'Alain pour une explication.

 

Sur AWS, il existe de multiples options pour construire un système RAG, notamment :

Dans cet article, nous approfondirons les trois premières solutions. Allons-y !

 

 

Amazon Kendra

 

AWS Kendra est un moteur de recherche d'entreprise intelligent qui vous permet de rechercher dans différentes sources de contenu avec des connecteurs intégrés. Il utilise l'apprentissage automatique pour comprendre le sens sémantique de votre contenu et renvoyer des résultats pertinents. Kendra est l'un des services de source RAG les plus faciles à configurer et à utiliser. Il gère la plupart des obstacles, car vous n'avez pas besoin de convertir la requête ou les documents en embeddings. De plus, vous pouvez indexer directement la source de documents, voire des pages Web en quelques clics.

Dans notre cas, nous avons créé un compartiment S3 contenant tous les documents PDF et texte. Nous avons également utilisé les connecteurs Kendra pour parcourir la page Web du CSSF à la recherche de sources d'informations supplémentaires. Pour parcourir une page Web, il vous suffit de fournir une URL de départ. Vous pouvez même configurer une planification récurrente pour recréer automatiquement les pages Web.
Kendra peut être utilisé pour rechercher différents types de contenu, notamment :

 

  • Compartiments d'objets S3
  • Bases de données
  • Documents (PDF, TXT, CSV)
  • Pages Web
  • E-mails
  • Code
  • Billets de support client
  • Systèmes de messagerie (comme Slack)

Pour une liste complète des connecteurs que vous pouvez utiliser avec Kendra, consultez la liste des connecteurs.

Pour récupérer des documents pertinents dans Kendra, vous pouvez utiliser l'API Retrieve. Cela renverra les extraits pertinents des documents avec un score de confiance. Vous pouvez également filtrer en fonction des champs et des attributs du document.

Une autre chose intéressante à propos de Kendra, c'est qu'il dispose d'une configuration de permission d'accès utilisateur intégrée. Vous pouvez contrôler l'accès aux documents en fonction du contexte de l'utilisateur en utilisant un jeton utilisateur, un ID utilisateur ou un attribut utilisateur (plus d'informations ici).

Kendra présente de très bonnes fonctionnalités et facilite le développement pour récupérer des documents à partir d'un index RAG. Si nous examinons les avantages :

 

  • Facilité d'importation des documents : Il vous suffit de créer des connecteurs, Kendra s'occupe du reste pour les ingérer et les indexer.
  • Pas besoin de convertir les documents ou l'entrée utilisateur en embedding : Cela peut vous faire gagner beaucoup de temps et d'efforts.
  • Possibilité de planifier des connecteurs pour analyser une source de documents : Cela peut vous aider à maintenir votre index RAG à jour et à éviter les tâches manuelles récurrentes.

Mais tout cela a un coût, le prix du service. Bien que vous puissiez tester Kendra gratuitement pendant un mois, il devient rapidement cher si vous souhaitez l'utiliser en environnement de production. Kendra se décline en deux niveaux : édition développeur et édition entreprise, au prix de 810 $ et 1008 $ respectivement. De plus, vous devez prendre en compte le taux horaire de synchronisation des connecteurs.

 

Amazon OpenSearch

 

La deuxième solution pour stocker des embeddings sur AWS est OpenSearch. Le service OpenSearch est un service géré qui facilite le déploiement, le fonctionnement et l'évolutivité des clusters OpenSearch dans AWS. Ce service est une version d'Amazon du moteur Elasticsearch entièrement open-source et analytique, principalement utilisé pour l'analyse des journaux, les applications et la recherche en entreprise.

La version 2.9 d'OpenSearch prend également en charge le stockage d'embeddings vectoriels, ce qui est parfait pour notre cas.

Pour stocker et indexer des vecteurs dans OpenSearch, nous utilisons un plugin appelé k-NN (pour les plus proches voisins k). Le plugin k-NN permet de rechercher les k-plus proches voisins d'un point de requête dans un index de vecteurs. Ce plugin prend en charge trois méthodes différentes de recherche de vecteurs :

 

  • Approximation des k-plus proches voisins : comme son nom l'indique, elle adopte une approche approximative des plus proches voisins en utilisant plusieurs algorithmes tels que nmslib et faiss. Ces algorithmes échangent généralement la précision de la recherche en retour de performances, de latence et de mémoire plus petites.
  • Recherche de k-NN par score de script : cette méthode effectue une recherche brute et exacte des k-plus proches voisins dans les champs "knn_vector".
  • Extensions Painless : en plus du score de script, cette méthode prend également en charge la pré-filtration en utilisant d'autres champs.

 

Pour créer des index et des mappages, vous pouvez utiliser l'API OpenSearch, le tableau de bord (fourni par le service) et les outils de développement du tableau de bord.

1. Créez un index qui prend en charge le plugin KNN.

PUT /cssf-rag-poc
{
  "settings": {
 "index": {
   "knn": true,
   "knn.space_type": "cosinesimil"
 }
  }
}

 

2. Création de la structure de mappage pour l'index 

{
 "properties": {
     "embedding": {
         "type": "knn_vector",
         "dimension": 1536 //length of created embeddings
     },
     "document_id": {"type": "text"},
     "url": {"type": "text"},
     "title": {"type": "text"},
     "page": {"type": "integer"},
     "document_type": {"type": "text"},
     "language_code": {"type": "text"},
     "cssf_circular_num": {"type": "text"},
     "page_content": {"type": "text"}
 }
}

 

3. Importation des embeddings

payload = {
     "embedding": embeddings,
     "document_id": title,
     "url": file_path,
     "title": title,
     "page": index,
     "document_type": doc_type,
     "cssf_circular_num": circular_num,
     "language_code": lang,
     "page_content": item.page_content
}
opensearch_client.index(
     index=index_name,
     body=payload
 )

 

4. Interrogation

vector_query = {
    "size": 5,
    "query": {
        "knn": {
            "embedding": {
                "vector": query_embeddings,
                "k": 2
            }
        }
    },
    "_source": [
        "page_content",
        "document_id",
        "document_type",
        "cssf_circular_num",
        "lang",
        "url"
    ]
}
resp = aos_client.search(body=vector_query, index=AWS_AOS_INDEX_NAME)

 

 

Amazon Aurora Serverless

 

Amazon Relational Database Service (RDS) est le service de base de données géré par AWS qui prend en charge un large éventail de moteurs de base de données, notamment MySQL, PostgreSQL, Oracle, SQL Server, MariaDB et Amazon Aurora. Dans cette démonstration, nous avons utilisé Aurora Serverless v2 avec la compatibilité PostgreSQL. Aurora PostgreSQL est jusqu'à 5 fois plus rapide que les bases de données PostgreSQL exécutées sur du matériel traditionnel et peut évoluer horizontalement.

Aurora Serverless ne propose pas de solution prête à l'emploi pour stocker des embeddings vectoriels, mais il existe un plugin open source appelé pgvector qui peut être utilisé à cette fin. pgvector offre une recherche des plus proches voisins (NN) exacte par défaut, mais il prend également en charge une recherche des plus proches voisins approximative pour de meilleures performances, avec un compromis entre vitesse et rappel. Les index pris en charge sont IVFFlat et HNSW. Nous n'allons pas les détailler dans cet article, mais si cela vous intéresse, vous pouvez trouver la documentation ici.

1. Déploiement d'Aurora : Vous avez en réalité trois options pour déployer une base de données PostgreSQL : RDS, Aurora et Aurora Serverless. Pour ce cas d'utilisation, nous avons choisi Aurora Serverless PostgreSQL. Pour pgvector, vous aurez besoin d'une version de PostgreSQL 11 et ultérieure.

2. Plugin pgvector : Vous pouvez facilement activer le plugin pgvector sur PostgreSQL en utilisant l'un des clients PostgreSQL (nous avons utilisé DBeaver depuis un certain temps). Création d'une table : Créez une table pour stocker les embeddings vectoriels. La définition de table suivante montre un exemple. 3.3. 

CREATE EXTENSION vector;

3.  Création de la table : Créez une table pour stocker les embeddings vectoriels. La définition de table suivante montre un exemple.4

CREATE TABLE embeddings (
 id SERIAL PRIMARY KEY,
 embedding vector(1536),
 cssf_circular_num varchar,
 document_type varchar,
 document_id varchar,
 language_code varchar,
 page integer,
 page_content varchar,
 title varchar,
 url varchar
);

4. Indexation des embeddings :

INSERT INTO embeddings (embedding, cssf_circular_num, document_type, document_id,language_code, page, page_content, title, url) 
VALUES ([1,2,3],”08/350”,”PDF”, , “EN”, 3, “Some Content”, “Circular 08/350”, “https://cssf.lu/08350en.pdf”)

 

5. Interrogation des embeddings: Pour interroger les embeddings, vous pouvez utiliser l'instruction SQL suivante.

    SELECT *
    FROM embeddings 
    ORDER BY embedding <-> '{embedding}' LIMIT 5;
    

     

    Amélioration de la conversation

     

    Rechercher des documents pertinents dans les sources RAG pour chaque requête est inutile et gourmand en ressources, en particulier pour les conversations informelles ou les questions sans rapport. Dans notre cas, nous souhaitions rechercher des sources RAG si nécessaire, tout en étant en mesure de filtrer les documents contenant des informations extraites. Comme dans l'exemple suivant :

    User Input: => "Can you summarize the CSSF Circular 08/350?"
    User intent => “Circular” Get this specific document
    Information to extract => circular 08/350
    

    Ci-dessus, l'intention de l'utilisateur est de trouver un document spécifique, et nous devons extraire le numéro du document circulaire pour pouvoir effectuer une recherche dans RAG et filtrer un document spécifique.

    Nous catégorisons quatre types d'intentions :

     

    • GenericCSSF : Toute question générique sur le CSSF.
    • GenericCircular : Toute question générique sur les circulaires du CSSF.
    • Circular : une question sur une circulaire spécifique (tout comme l'exemple ci-dessus).
    • SmallTalk ou OT : petites conversations, hors sujet.

     

    Ici, les questions de petites conversations et hors sujet n'ont pas besoin d'une recherche de source RAG, tandis que les autres en ont besoin. De plus, nous pouvons aller encore plus loin avec les circulaires et filtrer les documents pertinents en fonction du numéro de circulaire extrait de l'entrée de l'utilisateur.

    Pour résoudre ce problème, nous avons d'abord essayé de chaîner des requêtes LLM en utilisant la célèbre bibliothèque LangChain (pour plus d'informations, lisez notre article ici). En chaînant les requêtes LLM, nous avons pu affiner les questions et extraire l'intention de l'utilisateur et les informations afin de décider de faire ou non une recherche RAG.

    Nous voulions également essayer quelque chose de nouveau et tester le service Amazon Lex (lisez nos réflexions à ce sujet plus tard ici) pour voir si nous pouvions l'utiliser pour guider la conversation entre l'utilisateur et notre LLM. Lex est un service entièrement géré qui facilite la création, les tests et le déploiement d'interfaces conversationnelles dans n'importe quelle application, en utilisant la voix et le texte. Il est basé sur la même technologie d'apprentissage profond qui alimente les appareils Amazon Alexa.

    Dans cette démonstration, nous avons utilisé Lex pour comprendre l'intention de l'utilisateur et extraire des informations importantes pour récupérer des documents pertinents. Nous avons créé des intentions (voir la capture d'écran a), telles que des requêtes circulaires, des questions génériques sur le CSSF, des petites conversations, ainsi qu'une intention de secours en cas d'absence d'intention correspondante. Si l'intention de l'utilisateur est l'une des trois premières, nous essayons de trouver des documents pertinents ; sinon, le LLM génère directement une réponse sans documents supplémentaires.

    Amazon Lex Intents

    Nous avons configuré ces intentions en fournissant à Lex quelques exemples d'expressions, qui sont des requêtes types que les utilisateurs pourraient saisir. À l'aide de l'IA, Lex tente de faire correspondre l'intention à partir de l'entrée de l'utilisateur et des exemples d'expressions. Vous pouvez voir ci-dessous (capture d'écran b), les exemples d'expressions que nous avons créés pour l'intention "Circular".

    Sample utterance

    Vous pouvez également voir dans la capture d'écran b, un modèle appelé "circular_num". Ce sont en fait des "Slots" dans Amazon Lex. Les Slots sont utilisés pour extraire des informations spécifiques de l'entrée de l'utilisateur (dans notre cas, le numéro de circulaire). Tout comme pour les Intentions, vous pouvez créer des Slots et saisir des valeurs d'exemple sous forme de chaînes ou d'expressions régulières et leurs variations, et Lex tentera de faire correspondre pour vous.

    types values

    Lorsque vous appelez l'API recognizeText de Lex, elle renvoie les correspondances possibles d'intentions avec leur classement de score, ainsi que les types de Slots capturés dans le processus. Vous pouvez voir ci-dessous une capture d'écran de l'interface de test de Lex, où vous pouvez voir les intentions et les types de Slots pour une entrée utilisateur. En résumé, sans interagir avec notre modèle de base, nous pouvons obtenir l'intention de l'utilisateur et comprendre essentiellement si nous devons interroger notre source RAG ou non.

    test ui

    Avantages de l'utilisation de Lex en tant que gestionnaire de conversation :

     

    • Temps de réponse beaucoup plus rapide que la génération de réponses LLM : Si vous voulez simplement obtenir l'intention derrière l'entrée de l'utilisateur, c'est génial.
    • Rentabilité : Soyons honnêtes, chaque génération de réponse LLM nous coûte de l'argent, par jeton ! Il est donc beaucoup moins cher d'utiliser Lex à cette fin.
    • Facilité de configuration : Pour notre cas d'utilisation, il était vraiment facile de configurer et de commencer à utiliser Lex. Nous avons créé quelques Intentions et Slots, et c'est tout. Cela peut ne pas être le cas si vous essayez de construire un chatbot complet avec des conditions, etc.

     

    Inconvénients de l'utilisation de Lex :

     

    • Exige un code de langue dans la demande : Lors de l'interaction avec l'API Lex, vous envoyez également un localID, essentiellement un code de langue dans la demande. Et vous pourriez avoir besoin de passer entre les localID si vous souhaitez prendre en charge plusieurs langues dans votre application. Le problème est que Lex ne reconnaît pas automatiquement la langue du texte. Vous pourriez avoir besoin d'utiliser le service Amazon Translate ou quelque chose de similaire pour capturer la langue. Heureusement, j'ai pu trouver une petite bibliothèque en Python qui a fait le travail sans aucun appel API.
    • Nécessite une nouvelle formation : Chaque fois que vous devez ajouter des Intentions et des Slots ou prendre en charge différentes langues, vous devrez re-former votre bot avec des questions d'exemple.
    • Limite de caractères : Une autre limitation de Lex est que l'API recognizeText est limitée à seulement 1024 caractères, et cela s'applique à certains cas d'utilisation des chatbots LLM.

     

    Dans l'ensemble, Lex est un outil puissant pour guider la conversation entre un utilisateur et un LLM. Il offre plusieurs avantages par rapport à la génération de réponses LLM, tels qu'un temps de réponse plus rapide et une rentabilité accrue. Cependant, Lex nécessite une configuration et une maintenance supplémentaires, telles que la fourniture du code de langue dans la demande et la réinitialisation à chaque modification de la structure (Intentions et Slots) ou l'ajout de nouvelles langues.

     

    Architecture

     

    rag architecture

    Jetons maintenant un coup d'œil à l'architecture de la solution. La solution est similaire à celle utilisée dans notre article précédent (ici). Nous avons simplement ajouté des sources RAG et également la partie de conversion des documents en embeddings. Les principales parties de la solution sont les suivantes :

     

    • Interface utilisateur Web : Une application monopage écrite en ReactJS, stockée dans un compartiment S3 et distribuée avec le CDN CloudFront.
    • Backend : Fonction Lambda exposée via la passerelle API.
    • Authentification et autorisation : Fournies par le service Cognito. Une page de connexion avec une IU hébergée sur Cognito a été créée, et les appels API sont autorisés à l'aide de Cognito via une fonction Lambda d'autorisation intermédiaire.
    • Compartiment S3 : Utilisé pour stocker les documents de nos sources RAG. Les documents nouvellement téléchargés sont convertis en embeddings et indexés dans les différentes sources RAG.
    • Fonction Lambda : Composant central de la solution, responsable des tâches suivantes :
      • Obtenir l'intention de l'utilisateur depuis Amazon Lex.
      • Convertir la question en embeddings.
      • Rechercher les documents pertinents dans la source RAG.
      • Créer une invite en utilisant les informations des étapes précédentes.
      • Appeler le modèle Claude sur Amazon Bedrock pour générer une réponse.

     

    Lors du développement de cette solution, nous avons rencontré une limitation de la passerelle API. Apparemment, la passerelle API a une durée limite de temporisation de la demande de 29 secondes, et cette limite n'est pas configurable. Pour contourner cette limitation, nous avons trouvé deux choix : Exposer la fonction Lambda directement en utilisant une URL de fonction (documentation). Créer une API WebSocket en utilisant la passerelle API, mais cela a créé un besoin de stocker une carte externe des connexions utilisateur-client. La deuxième option étant trop complexe pour une démonstration, nous avons opté pour l'URL de fonction.

     

    Comparaison des solutions :

     

    En ce qui concerne le choix de la solution, Amazon OpenSearch et Aurora PostgreSQL offrent le même niveau de fonctionnalité. OpenSearch est un moteur de recherche et d'analyse distribué, tandis qu'Aurora est une base de données relationnelle. Par conséquent, le meilleur choix pour votre équipe dépendra de son expérience et de son expertise. Si votre équipe a l'habitude d'utiliser des bases de données relationnelles, choisissez Aurora. Si elle a déjà de l'expérience avec OpenSearch ou Elasticsearch, ou si vous avez besoin d'une solution capable de gérer un grand volume de données, choisissez OpenSearch.

    Tant Aurora que OpenSearch nécessitent une certaine connaissance du développement et de la gestion de documents (découpage en morceaux, conversion en embeddings). Cependant, Amazon Kendra excelle dans sa capacité à développer rapidement et à construire un système RAG sans avoir à traiter les documents. Kendra élimine la nécessité de traiter les documents car il dispose d'un processeur de documents intégré qui peut gérer toutes les tâches nécessaires. Cela fait de Kendra un bon choix pour les équipes qui souhaitent construire rapidement et facilement un système RAG, sans avoir à investir dans de nombreuses ressources de développement.

    Examinons maintenant les prix des solutions :

    Solutions RAG Kendra OpenSearch Aurora PostgreSQL OpenAI + Pinecone
    (Article Précedent)
    Développement / Configuration Facile Moyen Moyen Moyen
    Prix de la source RAG 810 $ / mois 27 $ / mois 44 $ / mois 70 $ / mois
    Prix d'Amazon Lex 0,00075 $ / req
    Lambda 0,0000166667 $ pour chaque Go-seconde 0,20 $ par million de reqs
    Coût de création des embeddings * 0,502 $
    Coût total 811,252 $ 28,252 $ 45,252 $ 70,502 $
    Coût par requête 0,811 $ 0,028 $ 0,045 $ 0,07 $

    _Avec notre utilisation de démonstration, nous avons pu rester dans la tranche gratuite de Lambda.
    *_Nous avons utilisé OpenAI Embedding pour convertir les documents en embeddings en utilisant le modèle text-embeddings-ada. Le prix sur OpenAI est de 0,0001 $ par 1000 jetons.

    Remarques sur la démonstration :

    • Nous avons indexé environ 500 documents dans les sources RAG (400 fichiers PDF et 100 pages web).
    • Le coût total est calculé pour 1000 requêtes.
    • Nous avons découpé les documents en morceaux de 3000 caractères avec un chevauchement de 200 caractères. Au total, 5020 documents sont stockés dans les sources RAG. En moyenne, un document contient 1000 jetons.

    Nous comparerons également les résultats et la précision avec notre démonstration précédente (article précédent). Jetons un coup d'œil aux résultats sur trois sources différentes.

     

    Questions

     

    Récapitulation

     

    Choix de la source RAG

     

    La création d'un chatbot RAG sur AWS peut être une tâche complexe, mais elle peut être réalisée à l'aide de différents outils et services. Amazon Kendra est une bonne option pour ceux qui souhaitent une solution facile à utiliser, mais elle peut être coûteuse. D'autres options, telles que le service OpenSearch et la base de données Aurora, sont plus complexes à configurer, mais peuvent être plus rentables.

    En ce qui concerne les réponses, lorsque Claude dispose de la documentation pertinente, il est capable de répondre de manière concise, d'expliquer et de résumer des informations sur le CSSF. Malgré la capacité de Claude à communiquer des concepts techniques complexes de manière claire et concise, Lex provoque de la confusion en ne fournissant pas d'informations complètes.

    En ce qui concerne les sources RAG, Aurora et OpenSearch fonctionnent plutôt bien avec des vitesses de récupération similaires. Nous avons remarqué que les trois sources récupèrent des documents similaires si les questions contiennent toutes les informations nécessaires. Ce n'est pas surprenant pour Aurora et OpenSearch car ils utilisent les mêmes fragments et embeddings.

     

    Gestion de la conversation avec Amazon Lex

     

    Amazon Lex est un bon choix pour la création de chatbots dans un cadre limité, en ce qui concerne la capture de l'intention et le support linguistique. Par exemple, si vous avez un cas d'utilisation restreint avec un nombre limité de questions possibles, vous pouvez utiliser Lex pour gérer la conversation. Cependant, il devient plus difficile d'utiliser Lex lorsque vous devez extraire des informations de questions liées. Par exemple, si vous posez à Lex les questions suivantes :

    • Quand le circular CPDI 23/34 a-t-il été publié ?
    • Pouvez-vous me résumer le circular ?

    Lex perdra l'historique des informations extraites de la première question et ne pourra pas récupérer le document pertinent (le circular 23/34) pour la deuxième question.

    Une façon de contourner cette limitation est de créer une structure arborescente dans Lex pour continuer la conversation. Cependant, cette approche peut être complexe et chronophage, en particulier si vous avez un grand nombre de questions possibles. De plus, à quoi sert l'IA générative si nous construisons une arborescence de conversation pour chaque action possible d'un chatbot.

    Une autre option consiste à utiliser une requête LLM chaînée pour répondre à des questions liées (comme nous l'avons fait dans notre article précédent). Nous pouvons utiliser les LLM pour affiner la question et extraire l'intention et les informations. Cette approche est plus précise que l'utilisation de Lex, mais elle est aussi plus coûteuse, car chaque requête LLM coûte de l'argent.

     

    Limitations de Claude

     

    Une autre limitation concernait la structure de la requête et les réponses de Claude. Après de nombreuses itérations, nous avons pu mettre au point quelque chose de gérable, mais il a encore ses limites, notamment le fait que Claude ne tient pas compte de ses instructions. Par exemple :

    L'utilisation de balises XML, comme suggéré par le guide de prompts d'Anthropic (lien), mais Claude continuait d'utiliser les mêmes balises XML dans ses réponses. De nos itérations, nous avons conclu qu'il est préférable de marquer des sections spécifiques comme dans l'exemple suivant. Cela réduit considérablement l'utilisation des séparateurs de section par Claude. Mais nous pouvons voir parfois que Claude utilise encore des séparateurs dans ses réponses. Consultez la question-réponse concernant "Quand le circular CPDI 23/34 a-t-il été publié ?"

     

    Exemple de séparateur de section XML :

    Human: 
    <history>
    ${HISTORY}
    </history>
    

    Deuxième type de séparateurs :

    The CSSF description :   
    -------------------
    ${CSSF_DESCRIPTION}
    -------------------
    Relevant Documents:
    -------------------
    ${DOCUMENTS}
    -------------------

    De plus, la même chose vaut pour Claude posant et répondant de manière proactive à des questions par lui-même. Consultez cette question ci-dessus :

    "je cherche aussi les circulaires détaillant les risques ICT pour les sociétés réglementées par le cadre PSF. Peux-tu me les indiquer?"
    

    Jetez un œil au passage mis en évidence. Vous remarquerez à la fin que Claude pose et répond à des questions de manière proactive, même si les instructions spécifiques de Claude incluent :

    "Do NOT proactively ask and answer questions on your own. Only respond directly to the user's questions."
    

    Le revers de la médaille est que Claude le fait plusieurs fois au sein d'une même réponse.

     

    Captures d'écran de la démonstration

     

    rag demo 1

    rag demo 2