ChatGPT vous connaissez. Mais saviez-vous qu’il est possible de créer votre propre assistant spécialisé, sur votre ordinateur, qui pourra répondre à des questions sur vos documents personnels ? Dans cet article, nous allons explorer la création d’un système RAG (Retrieval Augmented Generation) qui vous permettra d’interroger vos notes en langage naturel.

Qu’est-ce qu’un modèle d’IA comme ChatGPT ?

Avant de plonger dans le RAG, comprendre le fonctionnement basique des modèles de langage est essentiel. Ces modèles, qu’on appelle souvent LLM (Large Language Models), sont des réseaux de neurones entraînés sur d’immenses quantités de textes. Ils apprennent à prédire la suite probable d’une séquence de mots, ce qui leur permet de générer du texte cohérent et pertinent.

Imaginez un étudiant qui aurait lu des millions de livres et serait capable de reformuler toute cette connaissance pour répondre à vos questions. C’est un peu le principe, sauf qu’ici c’est un modèle mathématique qui a “appris” les patterns du langage.

Les modèles open weights : Démocratisation de l’IA

Si ChatGPT est un service propriétaire, il existe aujourd’hui de nombreux modèles “open weights” (l’équivalent “open sources” des modèles d’IA) comme Llama, Mistral, ou plus récemment DeepSeek. Ces modèles peuvent être téléchargés et utilisés localement sur votre ordinateur. C’est une révolution qui démocratise l’accès à cette technologie.

Dans notre projet, nous utilisons Ollama, un outil qui simplifie grandement l’utilisation de ces modèles en local.

Les concepts clés à comprendre

Tokens

Les modèles de langage ne comprennent pas directement les mots comme nous. Ils découpent le texte en “tokens”, qui peuvent être des mots entiers, des parties de mots ou même des caractères individuels. Par exemple, le mot “intelligence” pourrait être découpé en “intel” et “ligence”. Cette tokenization est cruciale car elle détermine comment le modèle va traiter et comprendre le texte.

Embeddings

Un embedding est une représentation numérique d’un texte sous forme de vecteur (une liste de nombres). Imaginez que chaque mot ou phrase soit représenté par un point dans un espace à plusieurs dimensions. Dans cet espace, des textes sémantiquement proches (parlant de sujets similaires) seront physiquement proches.

Par exemple, les phrases “J’aime les chats” et “Les félins sont mes animaux préférés” auront des embeddings similaires, car elles expriment des idées proches.

Chunks

Le chunking est le processus de découpage de documents en morceaux plus petits et gérables. C’est un équilibre délicat : des chunks trop petits perdent le contexte, des chunks trop grands diluent l’information pertinente.

Base de données vectorielle

C’est le “cerveau” qui stocke et organise tous nos embeddings. Elle permet de retrouver rapidement les passages les plus pertinents en comparant les similarités entre les vecteurs.

Prompt Engineering

L’art de formuler les instructions au modèle pour obtenir les meilleures réponses possibles. Dans un système RAG, cela inclut la façon d’intégrer le contexte récupéré dans la question posée au modèle.

Pourquoi utiliser un RAG ?

Le RAG local résout plusieurs problèmes majeurs des LLM :

  1. Connaissances limitées : Même les meilleurs modèles ont une connaissance figée à leur date d’entraînement
  2. Hallucinations : Les modèles peuvent parfois inventer des informations
  3. Confidentialité : Vos données restent locales, rien n’est envoyé à des serveurs externes
  4. Spécialisation : Le RAG permet au modèle de se concentrer sur vos documents spécifiques

Architecture d’un système RAG

Documents ───────► Chunking ───────► Embeddings ───────► Base vectorielle
                                                              │
                                                              │
                                                              ▼
Question ────────► Embedding ───────► Recherche similaire ────┘
                                            │
                                            ▼
                                         Contexte
                                            │
                                            ▼
                                          LLM
                                            │
                                            ▼
                                         Réponse

Ce graphique montre les composants essentiels et leur interaction :

  • Le pipeline de traitement des documents (haut) : transformation des documents en représentations vectorielles
  • Le pipeline de réponse aux questions (bas) : recherche et génération de réponses
  • La base vectorielle qui fait le lien entre les deux

Mise en place pratique

Le code complet est disponible sur mon repo github.

Téléchargement de Ollama

C’est l’outil central qui permet de faire tourner un modèle de langage. Il existe pour macOS, Linux et Winwdows. Après l’installtion de Ollama il vous faut choisir un modèle de LLM. Ollama en donne accès à plusieurs qui peuvent être téléchargés et donc utilisés en local.

Le code sera écrit en Python

Python s’est imposé comme le langage de référence en IA pour plusieurs raisons :

  • Un écosystème riche de bibliothèques spécialisées
  • Une syntaxe claire et accessible
  • Une grande communauté active
  • D’excellentes performances grâce aux optimisations des bibliothèques

Notre environnement de développement

conda create -n rag-env python=3.10
conda activate rag-env
pip install -r requirements.txt

Analysons les dépendances en lien avec nos concepts clés :

  • llama-index : L’orchestrateur qui gère tout le pipeline RAG
  • llama-index-llms-ollama : Interface avec notre LLM local (concept : modèles open weights)
  • llama-index-embeddings-huggingface : Création des embeddings (concept : embeddings)
  • sentence-transformers : Le modèle qui transforme le texte en vecteurs (concept : embeddings)
  • chromadb : Notre base de données vectorielle (concept : base vectorielle)
  • rich : Pour une interface console plus agréable

Structure du code et liens avec les concepts

Notre code implémente chaque concept clé discuté précédemment. Voyons comment :

  1. Configuration des modèles :
# Initialisation du modèle d'embedding
embed_model = HuggingFaceEmbedding(model_name="sentence-transformers/all-mpnet-base-v2")
# Ce modèle transforme le texte en vecteurs de 768 dimensions,
# permettant de capturer la sémantique du texte

# Initialisation du LLM local
llm = Ollama(model="llama3.3:70b-instruct-q6_K", request_timeout=120.0)
# C'est notre modèle de langage qui générera les réponses
# C'est un modèle relativement volumineux, d'où le request_timeout
# Vous pouvez choisir des versions moins lourdes disponibles
# ici : https://ollama.com/search
  1. Gestion du chunking :
def split_markdown_by_headers(content: str) -> list[str]:
    """
    Implémente le concept de chunking en découpant le document
    de manière intelligente selon les en-têtes Markdown
    """
    sections = []
    current_section = []

    for line in content.split("\n"):
        if line.startswith("## "):  # Nouveau chunk à chaque titre
            if current_section:
                sections.append("\n".join(current_section))
            current_section = [line]
        else:
            current_section.append(line)

    return sections
  1. Pipeline d’indexation :
# Création des embeddings et stockage
index = VectorStoreIndex.from_documents(documents)
# Cette ligne cache une grande complexité :
# 1. Chaque document est découpé en chunks
# 2. Chaque chunk est transformé en embedding
# 3. Les embeddings sont stockés dans la base vectorielle
  1. Moteur de requête :
query_engine = index.as_query_engine(
    similarity_top_k=8,  # Nombre de chunks similaires à récupérer
    response_mode="tree_summarize",  # Méthode de synthèse
    system_prompt="""Vous êtes un assistant expert..."""  # Prompt engineering
)

Exécution

Pour la démonstration, j’ai placé un fichier comprenant des notes sur les réseaux de neurones (fichier disponible ici). J’ai lancé le petit programme et j’ai posé deux questions : une en rapport avec mes notes sur les réseaux de neurones et l’autre n’ayant aucun rapport. Cette dernière question est une question de contrôle qui montre bien que le programme va puiser uniquement ses connaissances dans les notes personnelles.

(rag-env) ➜  my-rag-project git:(master) python src/main.py

Votre question (ou 'q' pour quitter) : Comment faire pour éviter le surapprentissage ?

Réponse : Pour éviter le surapprentissage, il est possible d'utiliser la régularisation, d'implémenter du dropout, d'augmenter la taille du jeu de données ou d'utiliser la validation croisée.

Votre question (ou 'q' pour quitter) : Comment cuire des oeufs ?

Réponse : Il n'y a aucune information sur la cuisson d'oeufs.

Cela fonctionne plutôt pas mal !

Limites et pièges à éviter

  1. Qualité des chunks

    • Trop petits : perte de contexte
    • Trop grands : réponses imprécises
    • Solution : tester différentes tailles et méthodes de découpage
  2. Choix du modèle d’embedding

    • Tous ne sont pas égaux
    • Certains sont meilleurs pour certaines langues
    • Solution : évaluer plusieurs modèles sur vos données
  3. Ressources matérielles

    • Les grands modèles consomment beaucoup de RAM
    • Les embeddings peuvent occuper beaucoup d’espace
    • Solution : commencer petit et monter en puissance progressivement
  4. Qualité des réponses

    • Le prompt est crucial
    • La qualité des documents sources impacte directement les réponses
    • Solution : itérer sur le prompt et nettoyer les documents

Glossaire

  • Local : Tout ce qui s’exécute sur un ordinateur sans envoyer de données à l’extérieur.
  • LLM : Large Language Model, modèle de langage de grande taille
  • RAG : Retrieval Augmented Generation, génération augmentée par la recherche
  • Embedding : Représentation vectorielle d’un texte
  • Token : Unité de base du texte pour un modèle de langage
  • Chunk : Fragment de document
  • Prompt : Instruction donnée au modèle
  • Base vectorielle : Base de données optimisée pour la recherche de vecteurs similaires

Ressources complémentaires

Documentation officielle

Articles et tutoriels

Communauté

Conclusion

Créer son propre système RAG est un excellent moyen de comprendre les technologies d’IA modernes tout en construisant quelque chose d’utile. Ce projet peut servir de base pour des applications plus spécifiques comme l’analyse de documentation technique, la recherche dans des notes personnelles, ou même l’assistance à la rédaction.

Les possibilités sont infinies, et avec la compréhension des concepts clés et de leur implémentation, vous pouvez adapter ce système à vos besoins spécifiques.

Article suivant : Améliorer Son Assistant IA avec ChromaDB


Cet article fait partie d’une série sur l’IA pratique.