Comment construire un système RAG en 10 lignes de Python sans frameworks
Déverrouillez la puissance de RAG (Retrieval Augmented Generation) avec ce tutoriel de code Python en 10 lignes. Plongez dans la recherche d'informations, construisez votre propre système de documents et tirez parti des LLM pour des réponses robustes - le tout sans dépendre de cadres complexes. Optimisez votre contenu pour le référencement et l'engagement.
16 février 2025

Découvrez comment construire un puissant système de génération augmenté par la recherche (RAG) à partir de zéro en seulement 10 lignes de code Python, sans dépendre de frameworks externes. Cette approche concise mais complète vous donne une compréhension approfondie des composants de base, vous permettant de créer des solutions robustes et personnalisables alimentées par l'IA pour vos applications basées sur des documents.
Comprendre le concept de Retrieval Augmented Generation (RAG)
Apprendre à découper les documents en paragraphes
Incorporer des documents et des requêtes d'utilisateur à l'aide de Sentence Transformers
Récupérer les fragments pertinents en fonction de la similarité cosinus
Augmenter la requête de l'utilisateur avec les fragments récupérés et générer une réponse à l'aide d'OpenAI GPT-4
Conclusion
Comprendre le concept de Retrieval Augmented Generation (RAG)
Comprendre le concept de Retrieval Augmented Generation (RAG)
La génération augmentée par la recherche (RAG) est une technique utilisée pour la recherche d'informations dans vos propres documents. Elle implique un processus en deux étapes :
-
Création de la base de connaissances : Les documents sont découpés en sous-documents plus petits, et des embeddings sont calculés pour chaque fragment. Ces embeddings et les fragments d'origine sont stockés, généralement dans un magasin de vecteurs.
-
Récupération et génération : Lorsqu'une nouvelle requête d'utilisateur arrive, un embedding est calculé pour la requête. Les fragments les plus pertinents sont récupérés en comparant l'embedding de la requête avec les embeddings des fragments stockés. Les fragments récupérés sont ensuite ajoutés à la requête d'origine et transmis à un modèle de langage (LLM) pour générer la réponse finale.
Cette configuration est appelée un pipeline de "génération augmentée par la recherche", car la génération du LLM est augmentée par les informations pertinentes récupérées dans la base de connaissances.
Apprendre à découper les documents en paragraphes
Apprendre à découper les documents en paragraphes
Lors de la construction d'un système de génération augmentée par la recherche (RAG), l'une des étapes clés consiste à découper les documents d'entrée en morceaux plus petits et plus gérables. Dans cet exemple, nous découpons le document d'entrée (un article Wikipédia) en paragraphes.
La justification de cette approche est que les paragraphes représentent souvent des unités logiques d'information qui peuvent être efficacement récupérées et utilisées pour augmenter la requête de l'utilisateur. En décomposant le document de cette manière, nous pouvons mieux identifier les sections les plus pertinentes à inclure dans la réponse finale.
Le code pour cette étape est le suivant :
# Découper le document en paragraphes
chunks = [paragraph.strip() for paragraph in text.split('\n') if paragraph.strip()]
Ici, nous utilisons une approche simple qui consiste à diviser le texte d'entrée sur les caractères de saut de ligne pour extraire les paragraphes individuels. Nous supprimons ensuite les espaces blancs en début et en fin de chaque paragraphe pour garantir une représentation propre.
La liste chunks
résultante contient les paragraphes individuels, qui peuvent ensuite être encodés et stockés dans le magasin de vecteurs. Cela nous permet de récupérer efficacement les paragraphes les plus pertinents en fonction de la requête de l'utilisateur et de les inclure dans la réponse finale générée par le modèle de langage.
Incorporer des documents et des requêtes d'utilisateur à l'aide de Sentence Transformers
Incorporer des documents et des requêtes d'utilisateur à l'aide de Sentence Transformers
Pour encoder les fragments de document et la requête de l'utilisateur, nous utiliserons la bibliothèque Sentence Transformers. Cette bibliothèque fournit des modèles pré-entraînés qui peuvent générer des embeddings de haute qualité pour le texte.
Tout d'abord, nous chargeons le modèle d'encodage :
from sentence_transformers import SentenceTransformer
embedding_model = SentenceTransformer('all-mpnet-base-v2')
Ensuite, nous calculons les embeddings pour les fragments de document :
chunk_embeddings = embedding_model.encode(chunks, normalize_embeddings=True)
Ici, chunks
est une liste des fragments de texte du document. L'option normalize_embeddings=True
garantit que les embeddings sont normalisés, ce qui est important pour le calcul de similarité ultérieur.
Pour obtenir l'embedding de la requête de l'utilisateur, il suffit d'exécuter :
query_embedding = embedding_model.encode([user_query], normalize_embeddings=True)[0]
Maintenant, nous avons les embeddings pour les fragments de document et la requête de l'utilisateur, que nous pouvons utiliser pour l'étape de récupération.
Récupérer les fragments pertinents en fonction de la similarité cosinus
Récupérer les fragments pertinents en fonction de la similarité cosinus
Pour récupérer les fragments les plus pertinents en fonction de la requête de l'utilisateur, nous devons d'abord calculer la similarité cosinus entre l'embedding de la requête et les embeddings des fragments de document. Voici comment nous pouvons procéder :
- Calculer l'embedding de la requête de l'utilisateur à l'aide du même modèle d'encodage que pour les fragments de document.
- Calculer le produit scalaire entre l'embedding de la requête et chacun des embeddings des fragments de document. Cela nous donne les scores de similarité cosinus.
- Trier les fragments de document en fonction des scores de similarité cosinus et sélectionner les K fragments les plus pertinents.
- Récupérer le contenu textuel des fragments sélectionnés pour l'utiliser comme contexte pour le modèle de langage.
Les étapes clés sont :
- Calculer l'embedding de la requête
- Calculer les scores de similarité cosinus
- Trier et sélectionner les K meilleurs fragments
- Récupérer le contenu textuel des fragments
Cette approche simple nous permet de récupérer efficacement les informations les plus pertinentes dans la collection de documents pour augmenter la requête de l'utilisateur avant de la transmettre au modèle de langage pour la génération.
Augmenter la requête de l'utilisateur avec les fragments récupérés et générer une réponse à l'aide d'OpenAI GPT-4
Augmenter la requête de l'utilisateur avec les fragments récupérés et générer une réponse à l'aide d'OpenAI GPT-4
Pour générer une réponse à l'aide des fragments récupérés et de la requête de l'utilisateur, nous créons d'abord une invite qui inclut les fragments pertinents et la requête de l'utilisateur. Nous utilisons ensuite le modèle OpenAI GPT-4 pour générer une réponse en fonction de cette invite.
Voici le code :
# Obtenir la requête de l'utilisateur
user_query = "Quelle est la capitale de la France ?"
# Récupérer les fragments les plus pertinents en fonction de la requête de l'utilisateur
top_chunk_ids = [6, 8, 5]
top_chunks = [chunks[i] for i in top_chunk_ids]
# Créer l'invite
prompt = "Utilisez le contexte suivant pour répondre à la question à la fin. Si vous ne connaissez pas la réponse, dites que vous ne savez pas et n'essayez pas d'inventer une réponse.\n\nContexte:\n"
for chunk in top_chunks:
prompt += chunk + "\n\n"
prompt += f"\nQuestion : {user_query}"
# Générer la réponse à l'aide d'OpenAI GPT-4
response = openai_client.chat.create(
model="gpt-4",
messages=[
{"role": "user", "content": prompt}
],
max_tokens=1024,
n=1,
stop=None,
temperature=0.7,
).choices[0].message.content
print(response)
Dans ce code, nous récupérons d'abord les fragments les plus pertinents en fonction de la requête de l'utilisateur en trouvant les 3 meilleurs fragments avec les scores de similarité les plus élevés. Nous créons ensuite une invite qui inclut ces fragments et la requête de l'utilisateur. Enfin, nous utilisons le modèle OpenAI GPT-4 pour générer une réponse en fonction de cette invite.
La réponse générée sera une réponse concise et pertinente à la requête de l'utilisateur, en tirant parti des informations des fragments récupérés.
Conclusion
Conclusion
Dans ce tutoriel, nous avons appris à construire un système de chat complet avec un système de récupération de documents en utilisant seulement 10 lignes de code Python. Nous avons couvert les composants clés d'un pipeline de Génération Augmentée par la Recherche (RAG), notamment la création de la base de connaissances, le découpage des documents, l'encodage, la récupération et la génération à l'aide d'un modèle de langage de grande taille.
Les points clés à retenir sont :
- Vous pouvez mettre en œuvre un pipeline RAG de base sans avoir besoin de frameworks complexes comme Langchain ou LlamaIndex. Le Python pur et quelques bibliothèques suffisent.
- Le découpage de vos documents en fonction de leur structure (par exemple, les paragraphes) est une stratégie simple mais efficace pour la plupart des cas d'utilisation.
- L'encodage des fragments de document et de la requête de l'utilisateur, puis le calcul des scores de similarité, vous permet de récupérer les informations les plus pertinentes pour augmenter la requête de l'utilisateur.
- L'intégration des fragments récupérés avec la requête de l'utilisateur et leur transmission à un modèle de langage de grande taille permet de générer une réponse pertinente et informative.
Bien que cet exemple fournisse une base solide, il existe de nombreuses possibilités pour construire des systèmes RAG plus robustes et avancés. Des frameworks comme Langchain et LlamaIndex peuvent être utiles lors de l'intégration avec divers magasins de vecteurs et modèles de langage. Cependant, commencer avec une implémentation en Python pur peut vous aider à mieux comprendre les concepts et les composants de base d'un pipeline RAG.
Si vous êtes intéressé par l'exploration de techniques RAG plus avancées, je vous recommande de consulter mon cours "RAG Beyond Basics", qui approfondit la construction de systèmes RAG complexes et prêts pour la production.
FAQ
FAQ

