Passer au contenu principal
La génération augmentée par récupération, ou RAG (« retrieval-augmented generation »), est l’un des patterns les plus utiles pour créer des applications d’IA qui doivent répondre à partir de vos propres documents. Au lieu de demander à un modèle de s’appuyer uniquement sur sa mémoire, vous récupérez d’abord le matériel source pertinent, vous envoyez ce contexte au modèle, puis vous lui demandez de répondre avec des citations. Dans ce tutoriel, nous allons créer un bot RAG privé en utilisant Python, Venice pour les embeddings et les chat completions, Qdrant pour la recherche vectorielle, et FastEmbed pour le re-ranking local. À la fin, vous disposerez des éléments essentiels d’un assistant de documents local capable d’ingérer vos fichiers, de récupérer les passages pertinents, de les re-classer et de répondre avec des citations. Le bot RAG en action Avant de continuer : si vous voulez exécuter le code de cet article, vous aurez besoin d’une clé API Venice. Exportez-la comme variable d’environnement :
Vous voulez voir l’implémentation complète du code ? Consultez le dépôt GitHub.

Comment fonctionne un bot RAG moderne

Un bon pipeline RAG, c’est bien plus que « mettre des documents dans une base de données vectorielle ». Le flux de base ressemble à ceci : L’étape de re-ranking est l’amélioration qui rend ce système bien plus utile qu’une simple démo RAG. La recherche vectorielle est rapide et efficace pour trouver des passages sémantiquement similaires, mais elle peut encore retourner des passages qui sont adjacents au sujet plutôt que directement utiles. Un cross-encoder lit ensemble la question et chaque passage candidat, puis évalue à quel point ce passage répond réellement à la question.

Installation des dépendances

Nous utiliserons le SDK Python OpenAI car Venice expose une API compatible avec OpenAI. Nous utiliserons également le client Python de Qdrant avec le support de FastEmbed :
Si vous préférez conserver les dépendances dans un fichier, créez un requirements.txt avec les mêmes paquets :

Choix des modèles

Créez un fichier nommé rag_bot.py, puis commencez par ajouter les imports, les structures de données, l’URL de l’API et les noms de modèles :
Le nom du modèle d’embedding est intentionnellement compatible avec OpenAI. Venice mappe les noms de modèles d’embedding compatibles vers les modèles d’embedding hébergés par Venice, de sorte que le code existant utilisant le SDK OpenAI peut généralement être migré en changeant simplement la base_url et la clé API. Vous pouvez lister les modèles Venice disponibles avec :
Pour les modèles de chat :

Création des clients Venice et Qdrant

Créez un seul client Venice compatible OpenAI pour les embeddings et les chat completions :
Pour Qdrant, vous avez trois modes utiles : Pour un bot privé local, commencez avec un chemin Qdrant local sur disque :
Il existe plusieurs façons de gérer le déploiement en production. Cependant, si vous utilisez un déploiement Qdrant distant, n’oubliez pas que les passages de vos documents et leurs métadonnées y seront stockés. Venice peut maintenir la couche d’inférence privée, mais vous devez tout de même choisir le bon déploiement Qdrant pour vos données.

Chargement et découpage des documents

Pour ce tutoriel, nous laisserons le bot ingérer des fichiers ou dossiers locaux. Commencez par les fichiers .md, .rst et .txt :
Une fois les fichiers chargés, nous devons diviser le texte en le « découpant » — en le séparant en morceaux de données. Une stratégie naïve pourrait diviser les passages de manière égale. Cependant, dans la plupart des cas, cela peut faire perdre de l’information aux frontières sémantiques, ce qui peut diminuer l’efficacité de votre système RAG. La stratégie de découpage que nous utiliserons privilégie les frontières de paragraphes ou de phrases afin que le modèle reçoive un contexte cohérent :
Une taille de passage initiale de 1000 caractères avec un chevauchement de 150 caractères constitue un bon point de départ pour des documents mixtes Markdown et texte. Des passages plus petits peuvent améliorer la précision. Des passages plus grands peuvent préserver davantage de contexte. Le bon paramétrage dépendra souvent du type de documents que vous stockez.

Embedding des documents avec Venice

Une fois que nous avons des passages, nous les encodons par lots :
Le traitement par lots est important. Encoder un passage à la fois est simple, mais ajoute une latence évitable. Gardez la taille de lot configurable afin de pouvoir ajuster le débit en fonction de votre charge de travail.

Stockage des vecteurs dans Qdrant

Avant d’insérer des points, créez une collection Qdrant avec la bonne taille de vecteur. Le plus simple pour connaître la taille du vecteur est d’encoder le premier lot, puis d’utiliser len(embeddings[0]).
Chaque point stocke le vecteur ainsi que les métadonnées de payload. Le payload contient le texte original et un chemin source afin que la réponse puisse citer l’origine du contexte :
Utilisez des UUID déterministes dérivés de source, chunk_index et du contenu. Cela rend l’ingestion répétée idempotente pour les passages inchangés.

Récupération des passages candidats

Au moment de la question, le bot encode la question de l’utilisateur et demande à Qdrant les meilleures correspondances vectorielles :
Le limit ici représente le nombre de candidats. Il devrait généralement être plus élevé que le nombre de passages que vous prévoyez d’envoyer au modèle, car l’étape suivante les re-classera. Une bonne valeur par défaut est de récupérer 8 candidats et d’envoyer les 4 meilleurs au modèle de chat.

Re-ranking avec FastEmbed

Nous ajoutons maintenant la partie qui rend la récupération bien plus intelligente.
La différence importante entre la recherche par embedding et le re-ranking par cross-encoder réside dans la manière dont le score est calculé. La recherche par embedding compare un vecteur unique pour la question à un vecteur unique pour chaque passage. C’est rapide et scalable. Un cross-encoder évalue la question et le passage ensemble. C’est plus lent, mais cela permet de juger la pertinence de manière plus directe. C’est pourquoi le pattern habituel est :
  1. Récupérer un ensemble de candidats plus large via la recherche vectorielle.
  2. Re-classer uniquement ces candidats localement.
  3. Envoyer les quelques meilleurs passages au modèle de langage.
Un bon point de départ est candidate_k=8 et top_k=4. Augmentez candidate_k si la bonne source est souvent proche mais n’arrive pas dans le contexte final.

Réponse avec les chat completions Venice

Une fois le contexte sélectionné, formatez-le avec des numéros de source :
Envoyez ensuite le contexte à un modèle de chat Venice :
Remarquez le system prompt : on indique au bot de répondre uniquement à partir du contexte fourni. C’est un garde-fou simple mais important. Un assistant RAG ne devrait pas répondre avec assurance à partir des connaissances générales du modèle lorsque les documents récupérés ne soutiennent pas la réponse.

Exécution du bot

Une fois que vous avez assemblé les pièces dans un script, sauvegardez-le sous le nom rag_bot.py. Une première exécution simple peut utiliser quelques documents d’exemple intégrés afin de vérifier le pipeline avant d’ingérer vos propres fichiers :
Pour ingérer vos propres documents :
Pour conserver une collection Qdrant locale sur disque et démarrer un chat interactif :
Le script affiche la réponse, puis affiche les sources avec leurs scores vectoriel et de re-ranking :
Si vous voulez inspecter le texte réellement passé au modèle, ajoutez :

Options CLI utiles

Exposez les principaux paramètres de récupération comme options CLI afin de pouvoir ajuster le bot sans éditer le code : Pour un développement local répété, un flux courant est :
Puis posez des questions de suivi sans ingérer à nouveau :

Notes sur la confidentialité

Pour une configuration RAG privée, pensez à chaque couche séparément : Le mode le plus privé par défaut pour ce tutoriel est Venice pour l’inférence, Qdrant local sur disque et re-ranking FastEmbed local. Cela vous donne un bot RAG pratique sans envoyer les payloads de votre base de données vectorielle à un magasin de vecteurs tiers.

Erreurs courantes à anticiper

Si vous changez de modèle d’embedding, recréez la collection Qdrant. Différents modèles d’embedding peuvent produire des vecteurs de dimensions différentes, et les collections Qdrant attendent une taille de vecteur fixe.

Pour aller plus loin

Une fois la base en place, les améliorations à plus fort impact sont généralement :
  • Ajouter des chargeurs spécifiques pour PDF, HTML, tickets ou pages de wiki internes.
  • Stocker des métadonnées plus riches comme les titres, les en-têtes, les dates, les propriétaires et les URL.
  • Ajuster candidate_k, top_k, la taille des passages et le chevauchement sur de vraies questions.
  • Ajouter des questions d’évaluation afin de pouvoir mesurer la qualité de la récupération avant et après les changements.
  • Streamer la chat completion finale de Venice pour une meilleure expérience de chat interactif.
Les systèmes RAG sont faciles à démontrer et étonnamment faciles à rendre médiocres. Le pattern recherche vectorielle plus re-ranking est une base solide car il maintient la récupération rapide tout en donnant au bot une meilleure chance d’envoyer au modèle de langage le bon contexte.