rss logo

Configurer le RAG avec Ollama et Open WebUI sous Linux

RAG avec Ollama et Open WebUI illustré par une parodie de Rags to Rags sur le thème de l’intelligence artificielle

Dans de précédents articles, j’ai expliqué comment installer Ollama pour exécuter des modèles LLM en local et comment installer Open WebUI, une interface conviviale permettant d’interagir avec des LLM. Dans ce tutoriel, je vais vous montrer comment mettre en œuvre la génération augmentée par récupération (RAG, Retrieval-Augmented Generation) avec Ollama et Open WebUI. Un LLM local pourra ainsi exploiter des informations internes, privées ou propres à un domaine qui ne figuraient pas dans ses données d’entraînement initiales, tout en conservant l’intégralité du processus RAG sur site.

Par défaut, un LLM exécuté avec Ollama ne peut s’appuyer que sur les connaissances acquises lors de son préentraînement et sur les informations présentes dans son contexte actuel. Le RAG permet d’ajouter des documents, des procédures, des notes techniques ou des informations d’entreprise à une base de connaissances interrogeable. Lorsqu’un utilisateur pose une question, Open WebUI convertit la requête en une représentation vectorielle (embedding), recherche les fragments de documents les plus pertinents dans la base de données vectorielle, puis ajoute le contenu récupéré au prompt envoyé au LLM. Le modèle peut ainsi produire des réponses fondées sur vos propres données.

Pour ce tutoriel, j’utilise une carte graphique NVIDIA Quadro P2000 dotée de 5 Go de VRAM avec le LLM mistral:instruct. Je vous recommande toutefois une carte graphique plus puissante et disposant de davantage de VRAM si vous souhaitez exécuter des modèles plus volumineux ou augmenter la taille du contexte avec le paramètre num_ctx. Une fenêtre de contexte plus grande peut accueillir davantage de fragments récupérés et d’historique de conversation, mais elle augmente également l’utilisation de la mémoire.

Pour le modèle d’embedding, j’utiliserai nomic-embed-text, un modèle léger de représentation vectorielle de texte disponible avec Ollama. Son rôle consiste à convertir les fragments de texte en vecteurs numériques appelés embeddings. Open WebUI stocke ces vecteurs, ainsi que les fragments et métadonnées qui leur sont associés, dans une base de données vectorielle. Lorsqu’une question est soumise, le même modèle d’embedding convertit la requête en vecteur afin qu’Open WebUI puisse identifier les fragments sémantiquement similaires. Ce modèle accepte uniquement du texte en entrée.

Vous vous demandez peut-être pourquoi le RAG est utile alors qu’il est déjà possible de joindre directement des documents à une conversation. Chaque LLM possède une fenêtre de contexte limitée, ce qui restreint la quantité de texte qu’il peut traiter au cours d’une même requête. Le chargement intégral d’un document volumineux peut consommer trop de tokens, entraîner la troncature d’informations utiles et laisser moins de place à la conversation ainsi qu’à la réponse générée. Le RAG divise au contraire les documents en fragments plus petits et récupère uniquement les sections jugées les plus pertinentes pour la question posée. Cette méthode réduit la consommation inutile de tokens et permet d’interroger une base de connaissances bien plus volumineuse que la fenêtre de contexte du modèle.

Vous vous demandez peut-être également pourquoi ne pas simplement affiner le modèle (fine-tuning) avec nos propres données. L’affinage est une approche différente qui modifie les paramètres du modèle et nécessite généralement des données d’entraînement soigneusement préparées, des outils adaptés, une expertise technique et d’importantes ressources de calcul. Pour un fonctionnement entièrement local, il exige aussi un modèle compatible avec la méthode d’affinage choisie. De plus, le modèle peut devoir être de nouveau affiné lorsque les informations évoluent. Le RAG est donc généralement plus pratique pour les documents, les procédures, les inventaires et les autres informations nécessitant des mises à jour régulières.

Comprendre le fonctionnement du RAG

La première étape d’un processus RAG consiste à ajouter les informations privées, internes ou propres à un domaine que nous souhaitons faire utiliser au modèle pour répondre aux questions. Dans Open WebUI, le contenu importé est extrait et divisé en fragments de texte plus petits. Chaque fragment est ensuite traité par le modèle d’embedding nomic-embed-text via Ollama, qui le convertit en vecteur numérique.

Ces embeddings, accompagnés des fragments de texte et des métadonnées qui leur sont associés, sont stockés dans une base de données vectorielle. Lorsqu’un utilisateur pose une question, Open WebUI convertit la requête en embedding et recherche dans la base les fragments les plus pertinents sur le plan sémantique. Le contenu récupéré est ensuite ajouté au prompt envoyé au LLM, ce qui lui permet de produire une réponse fondée sur la base de connaissances indexée.

Processus d’ingestion RAG montrant des documents importés dans Open WebUI, divisés en fragments, convertis en embeddings avec nomic-embed-text via Ollama, puis stockés dans une base de données vectorielle
Processus d’ingestion des documents RAG illustrant l’extraction du texte, son découpage, la génération des embeddings et l’indexation vectorielle avec Open WebUI et Ollama.

Une fois les fragments de documents et leurs embeddings indexés dans la base de données vectorielle, ils peuvent être récupérés lorsqu’un utilisateur pose une question. Au lieu de s’appuyer uniquement sur les connaissances acquises lors de son préentraînement, le LLM reçoit les fragments les plus pertinents en tant que contexte supplémentaire et les utilise pour produire une réponse plus pertinente et mieux étayée.

Traitement d’une requête RAG montrant une question envoyée par l’intermédiaire d’Open WebUI, les fragments pertinents récupérés dans une base de données vectorielle, ajoutés au contexte du modèle, puis utilisés par le LLM pour produire la réponse finale
Traitement d’une requête RAG illustrant la manière dont Open WebUI récupère les fragments pertinents dans la base de données vectorielle et les ajoute au contexte du modèle avant la génération de la réponse.

Installer le modèle d’embedding pour le RAG

  • Sur le serveur qui exécute Ollama, téléchargez le modèle d’embedding nomic-embed-text :
john@host:~$ ollama pull nomic-embed-text:latest
  • Dans Open WebUI, ouvrez le menu utilisateur, sélectionnez Admin Panel, puis cliquez sur Settings :
Interface d’Open WebUI affichant l’option Admin Panel dans le menu utilisateur et l’onglet Settings dans le panneau d’administration
Ouverture du panneau d’administration d’Open WebUI et accès à ses paramètres.
  • Dans les paramètres Documents, sélectionnez Ollama pour Embedding Model Engine, saisissez nomic-embed-text dans le champ Embedding Model, puis cliquez sur Save :
Paramètres Documents d’Open WebUI affichant Ollama comme moteur de modèle d’embedding et nomic-embed-text comme modèle d’embedding
Configuration d’Ollama comme moteur d’embedding et de nomic-embed-text comme modèle dans Open WebUI.

Créer une base de connaissances dans Open WebUI

Le modèle d’embedding est maintenant configuré. L’étape suivante consiste à créer une base de connaissances (Knowledge Base) dans Open WebUI, puis à y ajouter les documents ou le contenu textuel qui seront indexés et utilisés par le processus RAG.

  • Cliquez sur Workspace, puis ouvrez l’onglet Knowledge :
Interface d’Open WebUI affichant le menu Workspace et l’onglet Knowledge
Ouverture de la section Knowledge depuis le menu Workspace d’Open WebUI.
  • Cliquez sur le bouton Create, saisissez un nom et une courte description pour la nouvelle base de connaissances, choisissez ses autorisations d’accès, puis cliquez sur Create Knowledge :
Fenêtre d’Open WebUI permettant de créer une base de connaissances nommée STD.ROCKS website, avec une description de son objectif, des autorisations d’accès privées et le bouton Create Knowledge
Création d’une base de connaissances privée dans Open WebUI en définissant son nom, son objectif et ses autorisations d’accès.
  • Cliquez sur le bouton +, puis sélectionnez Add text content :
Base de connaissances Open WebUI affichant le menu du bouton plus avec l’option Add text content mise en évidence
Ouverture du menu de contenu de la base de connaissances et sélection de l’option Add text content.
  • Saisissez le contenu textuel que vous souhaitez ajouter à la base de connaissances, puis cliquez sur Save :
Éditeur de texte d’Open WebUI contenant des informations sur le site STD.ROCKS avec le bouton Save mis en évidence
Ajout de contenu textuel à la base de connaissances Open WebUI et enregistrement en vue de son indexation.
  • Lancer un nouveau Chat, cliquez sur le bouton +, sélectionnez Attach Knowledge, puis choisissez la base de connaissances que vous avez créée. Vous pouvez également saisir # dans le champ du prompt et sélectionner la base de connaissances dans la liste :
Interface New Chat d’Open WebUI affichant le menu du bouton plus, l’option Attach Knowledge et la base de connaissances STD.ROCKS website sélectionnée
Association de la base de connaissances STD.ROCKS à une nouvelle conversation Open WebUI.
  • Posez une question en rapport avec la base de connaissances jointe. Open WebUI récupère le contenu pertinent et le fournit au LLM comme contexte pour sa réponse :
Conversation Open WebUI affichant une question sur le meilleur groupe de rock, une réponse générée par mistral:instruct et une source récupérée dans la base de connaissances STD.ROCKS jointe
Open WebUI récupère une source pertinente dans la base de connaissances jointe et la fournit au LLM comme contexte pour générer sa réponse.

Configuration et dépannage du RAG

Réindexer la base de connaissances

🚨 Attention : après avoir changé de modèle d’embedding, réindexez tous les documents existants de la base de connaissances. Les embeddings générés par des modèles différents ne sont pas compatibles entre eux.

Si vous changez de modèle d’embedding ou modifiez les paramètres d’indexation des documents, vous devez réindexer le contenu existant de votre base de connaissances afin que les documents précédemment ajoutés soient de nouveau traités avec la configuration mise à jour.

  • Dans Open WebUI, ouvrez le menu utilisateur, sélectionnez Admin Panel, puis cliquez sur Settings :
Interface d’Open WebUI affichant l’option Admin Panel dans le menu utilisateur et l’onglet Settings dans le panneau d’administration
Ouverture du panneau d’administration d’Open WebUI et accès à ses paramètres.
  • Dans les paramètres Documents, faites défiler la page jusqu’à la section Reindex Knowledge Base Vectors, puis cliquez sur Reindex afin de recréer les embeddings du contenu déjà indexé :
Paramètres Documents d’Open WebUI affichant la section Reindex Knowledge Base Vectors avec le bouton Reindex mis en évidence
Réindexation des vecteurs existants de la base de connaissances depuis les paramètres Documents d’Open WebUI.

Augmenter la taille du contexte

Si le contenu récupéré par le RAG est volumineux ou si votre conversation contient déjà beaucoup de texte, le LLM risque de ne pas pouvoir intégrer l’intégralité du contexte utile dans sa fenêtre de contexte. Certains fragments récupérés, certaines instructions ou certaines parties de la conversation peuvent alors être tronqués, ce qui risque de réduire la qualité des réponses. Pour y remédier, vous pouvez augmenter le paramètre num_ctx, qui définit la taille du contexte du modèle.

💡 Remarque : avant d’augmenter num_ctx, vérifiez la longueur maximale de contexte prise en charge par votre modèle et assurez-vous que votre système dispose de suffisamment de mémoire. Une taille de contexte plus importante nécessite généralement davantage de VRAM ou de RAM. Sur un système équipé d’un GPU NVIDIA, vous pouvez surveiller l’utilisation de la mémoire avec la commande nvidia-smi. L’augmentation de num_ctx offre davantage d’espace pour les fragments récupérés, l’historique de la conversation et la réponse générée, mais elle n’augmente pas automatiquement le nombre de fragments récupérés. La récupération dépend également de paramètres tels que Top K et Chunk Size, décrits ci-dessous.

  • Dans Open WebUI, ouvrez Admin Panel, puis cliquez sur Settings. Dans les paramètres Models, modifiez le modèle utilisé pour le RAG et définissez une valeur personnalisée pour le paramètre Ollama num_ctx :
Paramètres du modèle dans Open WebUI affichant le paramètre Ollama num_ctx configuré avec la valeur personnalisée 8192
Augmentation de la valeur num_ctx dans les paramètres du modèle Open WebUI afin d’envoyer davantage de contexte au LLM.

Optimiser la récupération RAG

Vous pouvez ajuster plusieurs paramètres afin d’améliorer la qualité de votre processus RAG. Les plus importants sont Chunk Size, Chunk Overlap et Top K. Leurs valeurs optimales dépendent de la structure de vos documents, du modèle d’embedding et de la fenêtre de contexte disponible pour le LLM.

  • Lors de l’ajustement de votre configuration RAG, prenez en compte les paramètres suivants :
    • Chunk Size : définit la taille maximale de chaque fragment de texte avant sa conversion en embedding et son indexation dans la base de données vectorielle. Selon le Text Splitter sélectionné, cette valeur est exprimée en caractères ou en tokens. Des fragments plus grands préservent davantage le contexte environnant, mais peuvent réduire la précision de la récupération et occuper une part plus importante de la fenêtre de contexte du LLM. Des fragments plus petits peuvent améliorer la précision de la récupération, mais risquent de faire perdre des informations contextuelles importantes.
    • Chunk Overlap : définit la quantité de contenu répétée entre deux fragments consécutifs. Ce chevauchement permet de préserver le sens lorsqu’une phrase, un paragraphe ou une procédure s’étend au-delà de la limite d’un fragment. Un point de départ courant consiste à utiliser environ 10 % de la valeur de Chunk Size, par exemple un Chunk Size de 1000 avec un chevauchement de 100.
    • Top K : définit le nombre maximal de fragments pertinents récupérés dans la base de données vectorielle et ajoutés au contexte du modèle. Une valeur comprise entre 3 et 5 constitue généralement un point de départ raisonnable pour les modèles dont la fenêtre de contexte est limitée. L’augmentation de cette valeur fournit davantage de contenu récupéré, mais consomme aussi plus de tokens et peut introduire des informations moins pertinentes.

💡 Remarque : il n’existe pas de configuration universelle adaptée à toutes les bases de connaissances. Testez plusieurs valeurs à l’aide de questions représentatives et réindexez les documents existants après toute modification de la taille des fragments, de leur chevauchement, du séparateur de texte ou du modèle d’embedding.

  • Dans les paramètres Documents, configurez Chunk Size, Chunk Overlap et Top K, puis cliquez sur Save :
Paramètres Documents d’Open WebUI affichant Chunk Size défini sur 1000, Chunk Overlap sur 100 et Top K sur 3
Configuration des paramètres de récupération Chunk Size, Chunk Overlap et Top K dans Open WebUI.

Contourner le RAG et joindre un fichier

💡 Remarque : cette méthode peut nécessiter une fenêtre de contexte bien plus grande qu’un processus RAG classique. Avant de l’utiliser, assurez-vous que votre modèle prend en charge une valeur num_ctx suffisamment élevée et que votre système dispose d’assez de mémoire.

Dans certains cas, le processus RAG peut ne pas fournir la réponse attendue. Plusieurs raisons peuvent l’expliquer : un découpage sous-optimal, une valeur top_k inadaptée, les limites du modèle d’embedding ou une taille de contexte insuffisante. Si votre document est suffisamment petit pour tenir dans la fenêtre de contexte du modèle, vous pouvez contourner la récupération et joindre directement le fichier d’origine à la conversation.

Cette approche peut être utile lorsque vous souhaitez que le LLM lise l’intégralité du document plutôt que quelques fragments récupérés seulement. Elle consomme toutefois davantage de tokens en entrée et reste limitée par la taille maximale de contexte prise en charge par le modèle.

  • Revenez à New Chat, cliquez sur le bouton +, sélectionnez Attach Files, puis choisissez le fichier que vous souhaitez envoyer au modèle :
Interface New Chat d’Open WebUI affichant le menu du bouton plus, l’option Attach Files et le fichier STD.ROCKS.txt sélectionné
Ajout direct d’un fichier à une nouvelle conversation Open WebUI au lieu d’utiliser une base de connaissances.
  • Cliquez sur le fichier joint, puis activez Using Entire Document afin qu’Open WebUI envoie l’intégralité du contenu du fichier au modèle au lieu de s’appuyer sur la récupération de fragments :
Aperçu d’un fichier dans Open WebUI affichant le document STD.ROCKS.txt joint avec l’option Using Entire Document activée
Activation de l’option Using Entire Document afin d’envoyer l’intégralité du contenu du fichier dans le contexte du modèle.

Conclusion

Comme nous l’avons vu, la génération augmentée par récupération (RAG, Retrieval-Augmented Generation) constitue une méthode efficace pour fournir à un LLM local du contexte extrait de documents privés, internes ou propres à un domaine, sans modifier le modèle lui-même. En combinant Ollama, Open WebUI, un modèle d’embedding tel que nomic-embed-text et une base de données vectorielle, il est possible de créer une base de connaissances entièrement locale capable de produire des réponses plus pertinentes et mieux étayées.

Le RAG n’est toutefois pas une solution parfaite et peut nécessiter quelques ajustements. La qualité de la récupération dépend de plusieurs facteurs, notamment la structure des documents, l’extraction du texte, les paramètres Chunk Size, Chunk Overlap et Top K, le modèle d’embedding ainsi que la taille de contexte disponible pour le LLM. Dans certains cas, il peut être nécessaire de tester différentes valeurs et de réindexer la base de connaissances avant d’obtenir des résultats cohérents.

Malgré ces limites, le RAG reste une approche pratique et flexible pour fournir, au moment de la requête, des informations régulièrement mises à jour à un LLM local. Un matériel plus performant, notamment une carte graphique disposant de davantage de VRAM, facilite également l’exécution de modèles plus volumineux et l’utilisation d’une fenêtre de contexte plus étendue.