Partager via


Créer un pipeline de données non structuré pour RAG

Cet article explique comment créer un pipeline de données non structuré pour les applications IA de génération. Les pipelines non structurés sont particulièrement utiles pour les applications de génération Retrieval-Augmented (RAG).

Découvrez comment convertir du contenu non structuré comme des fichiers texte et des fichiers PDF en un index vectoriel que les agents IA ou d’autres récupérateurs peuvent interroger. Vous apprenez également à tester et à paramétrer votre pipeline pour optimiser les données de segmentation, d’indexation et d’analyse, ce qui vous permet de dépanner et d’expérimenter le pipeline pour obtenir de meilleurs résultats.

Carnet de pipeline de données non structurées

Le notebook suivant vous montre comment implémenter les informations de cet article pour créer un pipeline de données non structuré.

Pipeline de données non structurées Databricks

Obtenir un ordinateur portable

Composants clés du pipeline de données

La base de toutes les applications RAG avec des données non structurées est le pipeline de données. Ce pipeline est responsable de l’organisation et de la préparation des données non structurées dans un format que l’application RAG peut utiliser efficacement.

Diagramme des composants de base du pipeline de données RAG.

Bien que ce pipeline de données puisse devenir complexe en fonction du cas d’usage, voici les composants clés à prendre en compte lors de la création de votre application RAG :

  1. Composition et ingestion de Corpus : sélectionnez les sources de données et le contenu appropriés en fonction du cas d’usage spécifique.
  2. Prétraitement des données : transformez les données brutes en un format propre et cohérent adapté à l’incorporation et à la récupération.
    1. Analyse : extrayez les informations pertinentes des données brutes à l’aide de techniques d’analyse appropriées.
    2. Enrichissement : enrichir les données avec des métadonnées supplémentaires et supprimer le bruit.
      1. Extraction de métadonnées : extrayez les métadonnées utiles pour implémenter une récupération de données plus rapide et plus efficace.
      2. Déduplication : analysez les documents pour identifier et éliminer les doublons ou les documents en quasi-double.
      3. Filtrage : éliminez les documents non pertinents ou indésirables de la collection.
  3. Segmentation : décomposez les données analysées en blocs plus petits et gérables pour une récupération efficace.
  4. Incorporation : convertissez les données de texte segmentées en une représentation vectorielle numérique qui capture sa signification sémantique.
  5. Indexation et stockage : créez des index vectoriels efficaces pour optimiser les performances de recherche.

Composition et ingestion du Corpus

Votre application RAG ne peut pas récupérer les informations requises pour répondre à une requête utilisateur sans le corpus de données approprié. Les données correctes dépendent entièrement des exigences et des objectifs spécifiques de votre application, ce qui permet de consacrer du temps à comprendre les nuances des données disponibles. Pour plus d’informations, consultez le flux de travail développeur d’applications IA Générative.

Par exemple, lors de la création d’un bot de support client, vous pouvez envisager d’inclure les éléments suivants :

  • Des documents issus de bases de connaissances
  • Foire Aux Questions (FAQ)
  • Des manuels et des spécifications de produit
  • Guides de résolution des problèmes

Engagez des experts de domaine et des parties prenantes à partir du début de tout projet pour vous aider à identifier et à organiser du contenu pertinent qui pourrait améliorer la qualité et la couverture de votre corpus de données. Ils peuvent fournir des insights sur les types de requêtes que les utilisateurs sont susceptibles d’envoyer et d’aider à hiérarchiser les informations les plus critiques à inclure.

Databricks vous recommande d’ingérer des données de manière évolutive et incrémentielle. Azure Databricks offre différentes méthodes d’ingestion de données, notamment des connecteurs entièrement managés pour les applications SaaS et les intégrations d’API. Comme meilleure pratique, les données sources brutes doivent être ingérées et stockées dans une table cible. Cette approche garantit la conservation, la traçabilité et l’audit des données. Consultez les connecteurs Standard dans Lakeflow Connect.

Prétraitement des données

Une fois les données ingérées, il est essentiel de nettoyer et de mettre en forme les données brutes dans un format cohérent adapté à l’incorporation et à la récupération.

Analyse

Après avoir identifié les sources de données appropriées pour votre application retriever, l’étape suivante extrait les informations requises des données brutes. Ce processus, appelé analyse, implique de transformer les données non structurées dans un format que l’application RAG peut utiliser efficacement.

Les techniques et outils d’analyse spécifiques que vous utilisez dépendent du type des données avec lesquelles vous travaillez. Par exemple :

  • Documents texte (PDF, documents Word) : bibliothèques prêtes à l’emploi comme unstructured et PyPDF2 peuvent gérer différents formats de fichiers et fournir des options de personnalisation du processus d’analyse.
  • Documents HTML : Les bibliothèques d’analyse HTML telles que BeautifulSoup et lxml peuvent être utilisées pour extraire du contenu pertinent à partir de pages web. Ces bibliothèques peuvent aider à naviguer dans la structure HTML, sélectionner des éléments spécifiques et extraire le texte ou les attributs souhaités.
  • Images et documents numérisés : Les techniques de reconnaissance optique de caractères (OCR) sont généralement requises pour extraire du texte à partir d’images. Les bibliothèques OCR populaires incluent des bibliothèques open source telles que Tesseract ou SaaS, comme Amazon Textract, Azure AI Vision OCR et l’API Google Cloud Vision.

Meilleures pratiques pour l’analyse des données

L’analyse garantit que les données sont propres, structurées et prêtes pour l’incorporation de génération et de recherche vectorielle. Lors de l’analyse de vos données, tenez compte des meilleures pratiques suivantes :

  • Nettoyage des données : Prétraitez le texte extrait pour supprimer des informations inutiles ou bruyantes, telles que des en-têtes, des pieds de page ou des caractères spéciaux. Réduisez la quantité d’informations inutiles ou incorrectes dont votre chaîne RAG a besoin pour traiter.
  • Gestion des erreurs et des exceptions : implémentez des mécanismes de gestion et de journalisation des erreurs pour identifier et résoudre les problèmes rencontrés pendant le processus d’analyse. Cela vous permet d’identifier et de résoudre rapidement les problèmes. Cette démarche met souvent en évidence des problèmes en amont liés à la qualité des données sources.
  • Personnalisation de la logique d’analyse : en fonction de la structure et du format de vos données, il peut être nécessaire de personnaliser la logique d’analyse pour extraire les informations les plus pertinentes. Bien qu’il puisse nécessiter un effort supplémentaire en amont, investissez le temps pour le faire si nécessaire, car il empêche souvent de nombreux problèmes de qualité en aval.
  • Évaluation de la qualité de l’analyse : évaluez régulièrement la qualité des données analysées en examinant manuellement un échantillon du résultat. Ceci peut vous aider à identifier les problèmes ou les points à améliorer dans le processus d’analyse.

Enrichissement

Enrichir les données avec des métadonnées supplémentaires et supprimer le bruit. Bien que l’enrichissement soit facultatif, il peut considérablement améliorer les performances globales de votre application.

Extraction des métadonnées

La génération et l’extraction de métadonnées qui capturent des informations essentielles sur le contenu, le contexte et la structure du document peuvent améliorer considérablement la qualité et les performances de récupération d’une application RAG. Les métadonnées fournissent des signaux supplémentaires qui améliorent la pertinence, activent le filtrage avancé et prennent en charge les exigences de recherche spécifiques au domaine.

Bien que les bibliothèques telles que LangChain et LlamaIndex fournissent des analyseurs intégrés capables d’extraire automatiquement les métadonnées standard associées, il est souvent utile de compléter cela avec des métadonnées personnalisées adaptées à votre cas d’usage spécifique. Cette approche garantit que les informations critiques spécifiques au domaine sont capturées, ce qui améliore la récupération et la génération en aval. Vous pouvez également utiliser des modèles de langage volumineux (LLMs) pour automatiser l’amélioration des métadonnées.

Les types de métadonnées sont les suivants :

  • Métadonnées au niveau du document : Nom de fichier, URL, informations d’auteur, horodatages de création et de modification, coordonnées GPS et contrôle de version de document.
  • Métadonnées basées sur le contenu : Mots clés extraits, résumés, rubriques, entités nommées et balises spécifiques au domaine (noms de produits et catégories comme PII ou HIPAA).
  • Métadonnées structurelles : En-têtes de section, table des matières, numéros de page et limites de contenu sémantique (chapitres ou sous-sections).
  • Métadonnées contextuelles : Système source, date d’ingestion, niveau de sensibilité des données, langue d’origine ou instructions transnationales.

Le stockage des métadonnées en même temps que les documents segmentés ou leurs incorporations correspondantes est essentiel pour des performances optimales. Il permet également de limiter les informations récupérées et d’améliorer la précision et l’évolutivité de votre application. En outre, l’intégration de métadonnées dans des pipelines de recherche hybrides, ce qui signifie combiner la recherche de similarité vectorielle avec un filtrage basé sur des mots clés, peut améliorer la pertinence, en particulier dans les jeux de données volumineux ou dans des scénarios de critères de recherche spécifiques.

Déduplication

Selon vos sources, vous pouvez vous retrouver avec des documents en double ou des doublons proches. Par exemple, si vous extrayez un ou plusieurs lecteurs partagés, plusieurs copies du même document peuvent exister à plusieurs emplacements. Certaines de ces copies peuvent avoir des modifications subtiles. De même, votre base de connaissances peut avoir des copies de votre documentation produit ou des copies brouillons de billets de blog. Si ces doublons restent dans votre corpus, vous pouvez finir par des blocs hautement redondants dans votre index final qui peuvent réduire les performances de votre application.

Vous pouvez éliminer certains doublons à l’aide de métadonnées uniquement. Par exemple, si un élément a le même titre et la même date de création, mais que plusieurs entrées provenant de différentes sources ou emplacements, vous pouvez filtrer celles en fonction des métadonnées.

Toutefois, cela peut ne pas suffire. Pour identifier et éliminer les doublons en fonction du contenu des documents, vous pouvez utiliser une technique appelée hachage sensible à la localité. Plus précisément, une technique appelée MinHash fonctionne bien ici, et une implémentation Spark est déjà disponible dans Spark ML. Il fonctionne en créant un hachage pour le document en fonction des mots qu’il contient et peut ensuite identifier efficacement les doublons ou les doublons proches en joignant ces hachages. À un niveau très élevé, il s’agit d’un processus en quatre étapes :

  1. Créez un vecteur de fonctionnalité pour chaque document. Si nécessaire, envisagez d’appliquer des techniques telles que la suppression des mots vides, la racinisation et la lemmatisation pour améliorer les résultats, puis la tokenisation en n-grammes.
  2. Ajuster un modèle MinHash et hacher les vecteurs à l’aide de MinHash pour la distance Jaccard.
  3. Exécutez une jointure par similarité à l'aide de ces hachages pour produire un jeu de résultats pour chaque doublon ou document quasi-doublon.
  4. Filtrez les doublons que vous ne souhaitez pas conserver.

Une étape de déduplication de référence peut sélectionner les documents à conserver arbitrairement (par exemple, le premier dans les résultats de chaque doublon ou un choix aléatoire parmi les doublons). Une amélioration potentielle consisterait à sélectionner la « meilleure » version du doublon à l’aide d’une autre logique (par exemple, mise à jour la plus récente, état de la publication ou source la plus faisant autorité). Notez également que vous devrez peut-être expérimenter l’étape de caractérisation et le nombre de tables de hachage utilisées dans le modèle MinHash pour améliorer les résultats correspondants.

Pour plus d’informations, consultez la documentation Spark pour le hachage sensible à la localité.

Filtrage

Certains des documents que vous ingérerez dans votre corpus peuvent ne pas être utiles pour votre agent, soit parce qu’ils ne sont pas pertinents à son objectif, trop vieux ou peu fiable, ou parce qu’ils contiennent du contenu problématique tel que la langue dangereuse. Toutefois, d’autres documents peuvent contenir des informations sensibles que vous ne souhaitez pas exposer via votre agent.

Par conséquent, envisagez d’inclure une étape dans votre pipeline pour filtrer ces documents à l’aide de toutes les métadonnées, telles que l’application d’un classifieur de toxicité au document pour produire une prédiction que vous pouvez utiliser comme filtre. Un autre exemple consisterait à appliquer un algorithme de détection d’informations d’identification personnelle (PII) aux documents pour filtrer les documents.

Enfin, toutes les sources de document que vous alimentez dans votre agent sont des vecteurs d’attaque potentiels pour les acteurs malveillants afin de lancer des attaques d’empoisonnement de données. Vous pouvez également envisager d’ajouter des mécanismes de détection et de filtrage pour aider à identifier et à éliminer ceux-ci.

Chunking

Diagramme de données de documents segmentées pour l’index vectoriel.

Après avoir analysé les données brutes dans un format plus structuré, en supprimant les doublons et en filtrant les informations indésirables, l’étape suivante consiste à la décomposer en unités plus petites et gérables appelées blocs. Le segmentation de documents volumineux en segments plus petits et concentrés sémantiquement garantit que les données récupérées s’intègrent dans le contexte du LLM tout en réduisant l’inclusion d’informations distraites ou non pertinentes. Les choix effectués sur la segmentation affectent directement les données récupérées fournies par le LLM, ce qui en fait l’une des premières couches d’optimisation dans une application RAG.

Lors de la segmentation de vos données, tenez compte des facteurs suivants :

  • Stratégie de segmentation : la méthode que vous utilisez pour diviser le texte d’origine en segments. Cela peut impliquer des techniques de base telles que le fractionnement par phrases, paragraphes, nombres de caractères/jetons spécifiques et des stratégies de fractionnement plus avancées spécifiques au document.
  • Taille de bloc : Les blocs plus petits peuvent se concentrer sur des détails spécifiques, mais perdre des informations contextuelles environnantes. Les blocs plus volumineux peuvent capturer plus de contexte, mais peuvent inclure des informations non pertinentes ou être coûteux en calcul.
  • Chevauchement entre blocs : pour faire en sorte que des informations importantes ne sont pas perdues lors du fractionnement des données en segments, envisagez d’inclure du chevauchement entre des blocs adjacents. Le chevauchement peut garantir la continuité et la conservation du contexte entre les segments et améliorer les résultats de récupération.
  • Cohérence sémantique : Dans la mesure du possible, visez à créer des blocs sémantiquement cohérents qui contiennent des informations connexes, mais peuvent se présenter indépendamment en tant qu’unité de texte significative. Pour cela, il faut tenir compte de la structure des données d’origine, comme les paragraphes, les sections ou les limites des sujets.
  • Métadonnées :les métadonnées pertinentes, telles que le nom du document source, l’en-tête de section ou les noms de produits, peuvent améliorer la récupération. Ces informations supplémentaires peuvent aider à faire correspondre les requêtes de récupération aux blocs.

Stratégies de segmentation des données

La recherche de la méthode de segmentation appropriée dépend à la fois de l'aspect itératif et du contexte. Il n’y a pas d’approche unique. La taille et la méthode de segment optimales dépendent du cas d’usage spécifique et de la nature des données en cours de traitement. En général, les stratégies de segmentation peuvent être considérées comme les suivantes :

  • Segmentation de taille fixe : fractionner le texte en blocs d’une taille prédéterminée, comme un nombre fixe de caractères ou de jetons (par exemple CharacterTextSplitter de LangChain). Bien que le fractionnement selon un nombre arbitraire de caractères/jetons soit rapide et facile à configurer, il ne va généralement pas aboutir à des blocs sémantiquement cohérents. Cette approche fonctionne rarement pour les applications de niveau production.
  • Segmentation basée sur les paragraphes : utilisez les limites naturelles des paragraphes dans le texte pour définir des blocs. Cette méthode peut aider à préserver la cohérence sémantique des blocs, car les paragraphes contiennent souvent des informations connexes (par exemple , LangChain RecursiveCharacterTextSplitter).
  • Segmentation spécifique au format : Les formats tels que Markdown ou HTML ont une structure inhérente qui peut définir des limites de bloc (par exemple, des en-têtes Markdown). Les outils tels que MarkdownHeaderTextSplitter de LangChain ou les séparateurs basés sur dessections/ HTML peuvent être utilisés à cet effet.
  • Segmentation sémantique : Des techniques telles que la modélisation de rubriques peuvent être appliquées pour identifier des sections sémantiquement cohérentes dans le texte. Ces approches analysent le contenu ou la structure de chaque document pour déterminer les limites de segment les plus appropriées en fonction des changements de rubrique. Bien que plus impliqué que les approches de base, la segmentation sémantique peut aider à créer des blocs plus alignés avec les divisions sémantiques naturelles dans le texte (voir LangChain SemanticChunker, par exemple).

Exemple : segmentation de taille fixe

Image montrant un exemple de segmentation de taille de fixe d’un document.

Exemple de segmentation de taille fixe à l’aide de RecursiveCharacterTextSplitter de LangChain avec chunk_size=100 et chunk_overlap=20. ChunkViz offre un moyen interactif de visualiser comment différentes tailles de morceaux et valeurs de chevauchement de morceaux avec les séparateurs de caractères de Langchain influencent les morceaux résultants.

Encastrement

Diagramme de la façon dont les blocs de données sont vectorisés en fonction de leur signification sémantique.

Une fois que vous avez segmenté vos données, l’étape suivante consiste à convertir les blocs de texte en une représentation vectorielle en utilisant un modèle d’incorporation. Un modèle d’incorporation convertit chaque bloc de texte en une représentation vectorielle qui capture sa signification sémantique. En représentant des segments sous forme de vecteurs denses, les incorporations permettent une récupération rapide et précise des blocs les plus pertinents en fonction de leur similarité sémantique à une requête de récupération. La requête de récupération sera transformée au moment de la requête à l’aide du même modèle d’incorporation utilisé pour incorporer des blocs dans le pipeline de données.

Quand vous sélectionnez un modèle d’incorporation, tenez compte des facteurs suivants :

  • Choix du modèle : Chaque modèle d’incorporation a des nuances et les benchmarks disponibles peuvent ne pas capturer les caractéristiques spécifiques de vos données. Il est essentiel de sélectionner un modèle formé sur des données similaires. Il peut également être utile d’explorer tous les modèles d’incorporation disponibles conçus pour des tâches spécifiques. Expérimentez différents modèles d’incorporation prêts à l’emploi, même ceux qui peuvent figurer plus bas dans des classements standard, comme MTEB. Voici quelques exemples à prendre en compte :
  • Nombre maximal de jetons : Connaissez la limite maximale de jetons pour votre modèle d’incorporation choisi. Si vous passez des blocs qui excèdent cette limite, ils seront tronqués, ce qui risque de vous faire perdre des informations importantes. Par exemple, bge-large-en-v1.5 a une limite maximale de 512 jetons.
  • Taille du modèle : Les modèles d’incorporation plus volumineux fonctionnent généralement mieux, mais nécessitent davantage de ressources de calcul. En fonction de votre cas d’usage spécifique et des ressources disponibles, vous devez équilibrer les performances et l’efficacité.
  • Réglage précis : Si votre application RAG traite d’un langage spécifique à un domaine (par exemple, des acronymes d’entreprise internes ou de la terminologie), envisagez d’ajuster le modèle d’incorporation sur des données spécifiques au domaine. Cela peut aider le modèle à mieux capturer les nuances et la terminologie de votre domaine particulier et peut souvent entraîner une amélioration des performances de récupération.

Indexation et stockage

L’étape suivante du pipeline consiste à créer des index sur les incorporations et les métadonnées générées aux étapes précédentes. Cette étape implique l’organisation d’incorporations de vecteurs haute dimension dans des structures de données efficaces qui permettent des recherches de similarité rapides et précises.

Mosaïque AI Vector Search utilise les techniques d’indexation les plus récentes lorsque vous déployez un point de terminaison de recherche vectorielle et un index pour garantir des recherches rapides et efficaces pour vos requêtes de recherche vectorielle. Vous n’avez pas besoin de vous soucier des tests et du choix des meilleures techniques d’indexation.

Une fois votre index généré et déployé, il est prêt à stocker dans un système qui prend en charge des requêtes évolutives et à faible latence. Pour les pipelines RAG de production avec des jeux de données volumineux, utilisez une base de données vectorielle ou un service de recherche évolutif pour garantir une faible latence et un débit élevé. Stockez des métadonnées supplémentaires en même temps que des incorporations pour permettre un filtrage efficace lors de la récupération.