LLM & RAG
Architecture, Fonctionnement et Applications
Un cours complet pour développeurs et data scientists
Du token à la réponse — Comprendre, construire et déboguer
2025 — Niveau intermédiaire / avancé
Cours LLM & RAG — Architecture, Fonctionnement et Applications
Table des matières
1. Introduction
1.1 Pourquoi les LLM ont une connaissance figée
1.2 Objectifs du cours
2. Fonctionnement interne d'un LLM
2.1 Tokenisation
2.2 Embedding
2.3 Positional Encoding
2.4 Mécanisme d'Attention
2.5 Empilement des couches Transformer
2.6 Génération de texte
3. RAG — Retrieval-Augmented Generation
3.1 Pourquoi le RAG ?
3.2 Phase d'indexation
3.3 Phase d'utilisation
3.4 Exemple concret avec code
4. Interaction entre LLM et RAG
4.1 Le RAG ne modifie pas le LLM
4.2 Pipeline complet de bout en bout
5. Limites des LLM et solutions avancées
5.1 Vocabulaire fixe
5.2 Dimension d'embedding
6. Outils et ressources
7. Diagnostic des erreurs courantes
8. Conclusion et perspectives
© 2025 — Cours pédagogique — Usage personnel et professionnel Page 2
Cours LLM & RAG — Architecture, Fonctionnement et Applications
1 Introduction
Contexte et motivation
Les Grands Modèles de Langage (LLM) ont révolutionné le traitement automatique du langage
naturel. GPT-4, LLaMA, Mistral ou encore Falcon sont capables de résumer des textes, traduire,
coder, raisonner et converser avec une fluidité remarquable. Pourtant, ces modèles souffrent d'une
limitation fondamentale : leur connaissance est figée à la date de leur entraînement.
Un LLM entraîné en décembre 2023 ignore tout ce qui s'est passé après cette date. Il ne connaît pas
i les mises à jour d'une API, les nouveaux produits de votre entreprise, ni les modifications d'un
règlement interne.
De plus, ces modèles peuvent halluciner : générer des réponses plausibles mais fausses, inventer
des sources ou des chiffres. Ils n'ont pas accès aux données privées de votre organisation. C'est là
qu'intervient le RAG (Retrieval-Augmented Generation) : plutôt que de tout mémoriser dans les
poids du modèle, on lui apporte dynamiquement les informations pertinentes au moment de la
requête.
1.1 Pourquoi les LLM ont une connaissance figée
Lors de l'entraînement, un LLM ajuste des milliards de paramètres pour minimiser l'erreur de
prédiction sur un corpus massif. Une fois l'entraînement terminé, ces paramètres sont gelés. Le
modèle ne peut plus apprendre de nouvelles informations sans un ré-entraînement (coûteux) ou un
fine-tuning. La connaissance est donc implicite et distribuée dans les poids — elle ne peut pas être
mise à jour facilement, comme on mettrait à jour une entrée de base de données.
1.2 Objectifs du cours
• Comprendre l'architecture interne d'un LLM : de la tokenisation à la génération.
• Maîtriser le pipeline RAG : indexation, recherche vectorielle, augmentation du prompt.
• Choisir les bons outils : modèles d'embedding, bases vectorielles, orchestrateurs.
• Diagnostiquer les erreurs : hallucinations, réponses hors sujet, troncatures.
• Lire du code réel (Python, LangGraph, Qdrant) et comprendre chaque composant.
© 2025 — Cours pédagogique — Usage personnel et professionnel Page 3
Cours LLM & RAG — Architecture, Fonctionnement et Applications
2 Fonctionnement interne d'un LLM
Avant de comprendre le RAG, il faut comprendre comment un LLM digère le texte. Le pipeline interne
d'un LLM se compose de six grandes étapes : tokenisation, embedding, encodage positionnel,
attention, empilement des couches, et génération.
2.1 Tokenisation
La première étape consiste à transformer le texte brut en unités discrètes appelées tokens. Un token
n'est pas nécessairement un mot entier : il peut s'agir d'un sous-mot, d'un caractère, d'un signe de
ponctuation ou même d'un espace.
Pourquoi des sous-mots ?
Un vocabulaire de mots entiers aurait des millions d'entrées et serait incapable de gérer les mots
rares ou les néologismes. Un vocabulaire de caractères serait trop granulaire et allongerait
inutilement les séquences. Les algorithmes de sous-mots constituent un compromis optimal :
vocabulaire de taille fixe (30k–100k tokens) couvrant presque tous les mots par combinaison.
Algorithmes principaux
Algorithme Description Utilisé par
BPE
Fusion itérative des paires de bytes/chars GPT-2, GPT-3, GPT-4,
(Byte-Pair
les plus fréquentes RoBERTa
Encoding)
Similaire à BPE mais maximise
WordPiece BERT, DistilBERT
la vraisemblance du corpus
Modèle probabiliste, supprime
Unigram LM XLNet, T5 (partiel)
les tokens les moins utiles
Opère sur le flux de bytes bruts, LLaMA, Mistral,
SentencePiece
langue-agnostique T5, ALBERT
Exemple concret : découpage de 'anticonstitutionnellement'
Avec un tokenizer BPE de type GPT (50k tokens), le mot anticonstitutionnellement pourrait être
découpé en :
© 2025 — Cours pédagogique — Usage personnel et professionnel Page 4
Cours LLM & RAG — Architecture, Fonctionnement et Applications
Python — Tokenisation BPE
# Découpage BPE approximatif
tokens = ["anti", "const", "itution", "nel", "lement"]
# => 5 tokens pour un seul mot
# Avec tiktoken (GPT-4) :
import tiktoken
enc = tiktoken.get_encoding("cl100k_base")
tokens = [Link]("anticonstitutionnellement")
print(tokens) # [428, 15968, 58624, 616, 23633]
print(len(tokens)) # 5
Règle pratique : en anglais, 1 token ≈ 0,75 mot. En français, 1 token ≈ 0,6 mot car les mots français
i
sont souvent plus longs. Un texte de 1 000 mots en français ≈ 1 500–1 700 tokens.
2.2 Embedding — La matrice de sens
Une fois tokenisé, chaque token est converti en un vecteur dense de nombres flottants. Cette
conversion est réalisée par une matrice d'embedding de taille (vocab_size × d_model).
Modèle vocab_size d_model Paramètres embedding
BERT-base 30 522 768 ~23,4 M
GPT-2 (small) 50 257 768 ~38,6 M
GPT-3 (175B) 50 257 12 288 ~617 M
LLaMA-2 7B 32 000 4 096 ~131 M
Mistral 7B 32 000 4 096 ~131 M
Python — Matrice d'embedding BERT
# Illustration : accès à la matrice d'embedding
import torch
from transformers import AutoModel, AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
model = AutoModel.from_pretrained("bert-base-uncased")
# Matrice d'embedding : (30522, 768)
emb_matrix = [Link].word_embeddings.weight
print(emb_matrix.shape) # [Link]([30522, 768])
# Token ID pour le mot 'chat'
token_id = tokenizer.convert_tokens_to_ids("chat")
vecteur = emb_matrix[token_id] # vecteur de 768 floats
print(vecteur[:5]) # tensor([-0.021, 0.032, -0.011, ...])
© 2025 — Cours pédagogique — Usage personnel et professionnel Page 5
Cours LLM & RAG — Architecture, Fonctionnement et Applications
Propriétés des vecteurs denses
Les vecteurs d'embedding ont des propriétés remarquables : des mots sémantiquement proches ont
des vecteurs proches dans l'espace vectoriel (mesurés par la similarité cosinus). La célèbre
analogie : roi - homme + femme ≈ reine.
Attention — Confusion fréquente : la couche d'embedding INTERNE au LLM (qui convertit les
! token_ids en vecteurs) est différente du modèle d'embedding utilisé dans le RAG (qui encode des
phrases entières pour la recherche sémantique). Ce sont deux choses distinctes !
2.3 Positional Encoding
Le mécanisme d'attention (voir section suivante) traite tous les tokens en parallèle, sans notion
d'ordre. Pourtant, 'le chat mange la souris' et 'la souris mange le chat' ont des sens opposés. Il faut
donc injecter l'information de position.
Encodage sinusoïdal (Transformer original — Vaswani et al., 2017)
Pour la position pos et la dimension i :
PE(pos, 2i) = sin(pos / 10000^(2i/d_model))
PE(pos, 2i+1) = cos(pos / 10000^(2i/d_model))
Python — Encodage positionnel sinusoïdal
import numpy as np
def positional_encoding(seq_len, d_model):
PE = [Link]((seq_len, d_model))
for pos in range(seq_len):
for i in range(0, d_model, 2):
PE[pos, i] = [Link](pos / 10000 ** (2*i / d_model))
PE[pos, i+1] = [Link](pos / 10000 ** (2*i / d_model))
return PE
# Exemple : 5 tokens, d_model=4
pe = positional_encoding(5, 4)
# pos=0: [ 0.000, 1.000, 0.000, 1.000]
# pos=1: [ 0.841, 0.540, 0.010, 1.000]
# pos=2: [ 0.909, -0.416, 0.020, 1.000]
Les modèles modernes (LLaMA, Mistral) utilisent RoPE (Rotary Position Embedding) qui encode la
✓ position de façon relative dans l'espace complexe. Cela permet une meilleure généralisation aux
longues séquences.
© 2025 — Cours pédagogique — Usage personnel et professionnel Page 6
Cours LLM & RAG — Architecture, Fonctionnement et Applications
2.4 Mécanisme d'Attention (Self-Attention)
L'attention est le cœur du Transformer. Elle permet à chaque token de 'regarder' tous les autres
tokens de la séquence pour construire une représentation contextuelle. Le token 'banque' dans 'Je
dépose de l'argent à la banque' doit savoir qu'il s'agit d'une institution financière, pas d'un bord de
rivière.
Étapes détaillées du calcul
1. Projection QKV : à partir du vecteur de chaque token x (dim d_model), on calcule 3 vecteurs
via des matrices apprises : Q = x·W_Q, K = x·W_K, V = x·W_V (chacun de dim d_k).
2. Scores bruts : score(Q_i, K_j) = Q_i · K_j^T / sqrt(d_k). La division par sqrt(d_k)
stabilise les gradients.
3. Softmax : normalisation des scores pour obtenir des poids d'attention (somme = 1) : a_ij =
softmax(score_i)
4. Combinaison pondérée : la sortie pour le token i est output_i = sum_j(a_ij * V_j) —
moyenne pondérée des valeurs V.
Python — Scaled Dot-Product Attention
import torch, [Link] as F
def scaled_dot_product_attention(Q, K, V):
d_k = [Link](-1)
scores = [Link](Q, [Link](-2, -1)) / (d_k ** 0.5)
weights = [Link](scores, dim=-1) # poids d'attention
output = [Link](weights, V) # combinaison pondérée
return output, weights
# Exemple : 1 séquence, 4 tokens, d_k=8
Q = [Link](1, 4, 8)
K = [Link](1, 4, 8)
V = [Link](1, 4, 8)
out, attn_weights = scaled_dot_product_attention(Q, K, V)
# attn_weights[0,2,:] montre combien le token 2 'regarde' chaque token
Multi-Head Attention : plusieurs 'points de vue' en parallèle
Plutôt qu'une seule attention, on en calcule h têtes en parallèle (ex. h=12 pour BERT-base, h=32
pour LLaMA-7B). Chaque tête apprend à capturer un type de relation différent : une tête peut se
spécialiser dans les relations sujet-verbe, une autre dans les coréférences, etc.
MultiHead(Q,K,V) = Concat(head_1, ..., head_h) · W_O
où head_i = Attention(Q·W_Q_i, K·W_K_i, V·W_V_i)
2.5 Empilement des couches Transformer
© 2025 — Cours pédagogique — Usage personnel et professionnel Page 7
Cours LLM & RAG — Architecture, Fonctionnement et Applications
Un bloc Transformer (ou 'couche') enchaîne : Multi-Head Attention → Add & Norm → Feed-Forward
Network → Add & Norm. Les connexions résiduelles (x + sublayer(x)) permettent au gradient de
remonter efficacement lors de l'entraînement.
Modèle Nb de blocs d_model Nb têtes Paramètres totaux
BERT-base 12 768 12 110 M
BERT-large 24 1024 16 340 M
GPT-2 (small) 12 768 12 117 M
GPT-3 96 12288 96 175 B
LLaMA-2 7B 32 4096 32 7B
LLaMA-2 70B 80 8192 64 70 B
L'empilement permet un raffinement progressif des représentations. Les premières couches
capturent des patterns lexicaux et syntaxiques (ex. accord sujet-verbe). Les couches intermédiaires
encodent la sémantique. Les couches profondes représentent des concepts abstraits et des relations
de haut niveau.
2.6 Génération de texte
La couche de sortie projette le vecteur de la dernière couche (d_model) vers le vocabulaire complet
(vocab_size) via une transformation linéaire, puis un softmax produit une distribution de probabilité
sur tous les tokens possibles.
Python — Stratégies de décodage
# Logits -> probabilités -> token suivant
logits = model_output.logits[:, -1, :] # (batch, vocab_size)
probs = [Link](logits, dim=-1)
# Greedy decoding (choisit le token le plus probable)
next_token_id = [Link](probs, dim=-1)
# Top-p (nucleus) sampling
sorted_probs, sorted_ids = [Link](probs, descending=True)
cumsum = [Link](sorted_probs, dim=-1)
# Garde uniquement les tokens dont la proba cumulée <= p=0.9
mask = cumsum - sorted_probs > 0.9
sorted_probs[mask] = 0
next_token_id = sorted_ids[[Link](sorted_probs, 1)]
Génération auto-régressive
La génération est auto-régressive : le modèle produit un token à la fois, puis réintègre ce token dans
la séquence pour prédire le suivant. Pour une réponse de 200 tokens, le modèle effectue 200 passes
en avant (forward passes). C'est pourquoi la génération est lente pour les longues réponses.
© 2025 — Cours pédagogique — Usage personnel et professionnel Page 8
Cours LLM & RAG — Architecture, Fonctionnement et Applications
3 RAG — Retrieval-Augmented Generation
Le RAG est une architecture hybride qui combine la puissance de génération d'un LLM avec la
précision de la récupération d'informations depuis une base de données. L'idée : avant d'appeler le
LLM, on récupère les documents pertinents et on les insère dans le prompt.
3.1 Pourquoi le RAG ?
• Hallucinations : le LLM invente des faits plausibles mais incorrects.
– Solution RAG : on lui fournit les vrais documents comme contexte.
• Connaissances figées : le LLM ignore les événements post-entraînement.
– Solution RAG : on indexe les nouveaux documents en temps réel.
• Données privées : le LLM ne connaît pas les données internes de votre entreprise.
– Solution RAG : on indexe ces données dans une base vectorielle privée.
• Traçabilité : impossible de savoir d'où vient une information.
– Solution RAG : chaque réponse peut citer ses sources (chunks récupérés).
3.2 Phase d'indexation (opération unique)
L'indexation est effectuée une seule fois (ou lors de mises à jour). Elle transforme les documents
bruts en vecteurs stockés dans une base vectorielle.
Étape 1 : Chunking (découpage)
Les documents sont découpés en morceaux (chunks) de taille fixe. Le overlap (chevauchement)
permet de préserver le contexte aux coupures.
© 2025 — Cours pédagogique — Usage personnel et professionnel Page 9
Cours LLM & RAG — Architecture, Fonctionnement et Applications
Python — RecursiveCharacterTextSplitter (LangChain)
# Chunking avec LangChain
from langchain.text_splitter import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
chunk_size=500, # ~500 tokens par chunk
chunk_overlap=50, # 50 tokens de chevauchement
separators=[chr(10)+chr(10), chr(10), '. ', ' ', '']
)
# Document de 1500 tokens -> 3 chunks de 500
# Chunk 1 : tokens 0-499
# Chunk 2 : tokens 450-949 (overlap: 450-499)
# Chunk 3 : tokens 900-1499 (overlap: 900-949)
chunks = splitter.split_text(document_text)
print(f'{len(chunks)} chunks crees')
Pourquoi l'overlap ? Une phrase importante peut se trouver à la frontière de deux chunks. Avec 50
i tokens d'overlap, les deux chunks contiennent cette phrase, donc la recherche aura plus de chances
de la retrouver.
Étape 2 : Embedding des chunks
Chaque chunk est converti en un vecteur de haute dimension par un modèle d'embedding de
phrases (ex. BAAI/bge-small-en-v1.5, all-MiniLM-L6-v2). Ce vecteur capture le sens sémantique
du chunk.
Python — fastembed (BAAI/bge-small-en-v1.5)
# Embedding avec fastembed (utilisé dans Agent Extract)
from fastembed import TextEmbedding
embed_model = TextEmbedding("BAAI/bge-small-en-v1.5")
# Dimension des vecteurs : 384
chunks = [
"Le modèle Transformer utilise l'attention pour...",
"Le RAG combine récupération et génération...",
"Qdrant est une base vectorielle open-source...",
]
vectors = list(embed_model.embed(chunks))
print(vectors[0].shape) # (384,)
print(vectors[0][:4]) # [-0.021 0.045 -0.012 0.089]
Étape 3 : Stockage dans Qdrant
© 2025 — Cours pédagogique — Usage personnel et professionnel Page 10
Cours LLM & RAG — Architecture, Fonctionnement et Applications
Python — Indexation dans Qdrant
from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams, PointStruct
client = QdrantClient(host="localhost", port=6333)
# Créer la collection (une seule fois)
client.create_collection(
collection_name="cours_llm",
vectors_config=VectorParams(size=384, distance=[Link]),
)
# Indexer les chunks
points = [
PointStruct(
id=i,
vector=vectors[i].tolist(),
payload={'text': chunks[i], 'source': '[Link]', 'page': 3}
)
for i in range(len(chunks))
]
[Link](collection_name='cours_llm', points=points)
3.3 Phase d'utilisation (à chaque requête)
© 2025 — Cours pédagogique — Usage personnel et professionnel Page 11
Cours LLM & RAG — Architecture, Fonctionnement et Applications
Python — Pipeline RAG complet
def rag_query(user_question: str, top_k: int = 3) -> str:
# 1. Embedder la question avec le MÊME modèle
q_vector = list(embed_model.embed([user_question]))[0]
# 2. Rechercher les k chunks les plus proches
results = [Link](
collection_name="cours_llm",
query_vector=q_vector.tolist(),
limit=top_k,
with_payload=True
)
# 3. Construire le contexte
context = chr(10).join([[Link]['text'] for r in results])
# 4. Construire le prompt augmenté
prompt = f'''Contexte :
{context}
Question : {user_question}
Réponse basée uniquement sur le contexte :'''
# 5. Appel au LLM
response = [Link](prompt)
return response
3.4 Exemple concret — Agent Extract (Evalia/Talentium)
Voici comment les fonctions clés du projet Evalia implémentent le pipeline RAG :
_get_embedding(text)
Convertit un texte en vecteur 384D via fastembed + BAAI/bge-small-en-v1.5. Appel :
list(self.embed_model.embed([text]))[0]
_ensure_collection()
Vérifie si la collection Qdrant existe, la crée sinon (COSINE distance, size=384). Idempotent —
safe à appeler plusieurs fois.
index_interview_result(data)
Prend un résultat d'entretien, génère le vecteur de son contenu textuel, et l'insère dans Qdrant
avec les métadonnées (candidate_id, job_id, score...). Pas de PostgreSQL ici — la base
vectorielle est indépendante.
search_similar_interviews(query, top_k)
Embedde la requête et lance une recherche cosinus dans Qdrant. Retourne les top-k points avec
leurs payloads (texte + métadonnées).
© 2025 — Cours pédagogique — Usage personnel et professionnel Page 12
Cours LLM & RAG — Architecture, Fonctionnement et Applications
get_rag_context_for_questions(questions)
Pour chaque question du formulaire RH, récupère les chunks d'entretiens similaires et les formate
en contexte injectable dans le prompt du LLM.
Point clé : les données dans Qdrant et dans PostgreSQL sont indépendantes. PostgreSQL stocke
les données structurées (candidats, jobs, scores). Qdrant stocke les vecteurs pour la recherche
!
sémantique. L'insertion dans Qdrant se fait directement depuis le code Python, sans passer par
PostgreSQL.
© 2025 — Cours pédagogique — Usage personnel et professionnel Page 13
Cours LLM & RAG — Architecture, Fonctionnement et Applications
4 Interaction entre LLM et RAG
4.1 Le RAG ne modifie pas le LLM
Idée fondamentale à retenir : le RAG est une technique de pré-traitement du prompt. Il ne touche
pas aux poids du LLM, ne fait pas de fine-tuning, n'altère pas le modèle. Le LLM est une boîte noire
dont on enrichit simplement l'entrée.
Analogie : imaginez un expert qui doit répondre à une question d'histoire. Sans RAG, il répond de
mémoire. Avec RAG, on lui pose la question en lui tendant également les 3 pages de l'encyclopédie
✓
les plus pertinentes. Sa façon de raisonner ne change pas — mais sa réponse sera bien plus précise
et sourcée.
4.2 Pipeline complet de bout en bout
# Étape Outil/Composant Entrée → Sortie
1 Réception de la requête API / Interface Texte utilisateur → Question brute
2 Embedding de la question Texte → Vecteur 384D
fastembed / sentence-transformers
3 Recherche vectorielle Qdrant / FAISS Vecteur → Top-k chunks (texte + score)
4 Construction du prompt Template Python / LangChain Question + Chunks → Prompt enrichi
5 Génération LLM HuggingFace / OpenAI / OllamaPrompt enrichi → Réponse finale
6 Post-traitement Parser / Validator Réponse brute → JSON structuré
Exemple de bout en bout — 'Quelle est la hauteur de la tour Eiffel ?'
© 2025 — Cours pédagogique — Usage personnel et professionnel Page 14
Cours LLM & RAG — Architecture, Fonctionnement et Applications
Python — Pipeline RAG bout en bout
# === QUESTION ===
question = "Quelle est la hauteur de la tour Eiffel ?"
# === ÉTAPE 2 : Embedding de la question ===
q_vec = embed_model.embed([question])[0]
# q_vec = [0.021, -0.034, 0.089, ...] (384 dimensions)
# === ÉTAPE 3 : Recherche dans Qdrant ===
hits = [Link]('monuments', q_vec, limit=3)
# hit[0].payload['text'] = 'La tour Eiffel mesure 330m...'
# hit[0].score = 0.94 (similarité cosinus)
# === ÉTAPE 4 : Prompt augmenté ===
prompt = f'''
Tu es un assistant factuel. Réponds uniquement avec les infos ci-dessous.
CONTEXTE : {hits[0].payload['text']}
QUESTION : {question}
RÉPONSE :'''
# === ÉTAPE 5 : LLM ===
response = llm(prompt)
# => 'La tour Eiffel mesure 330 mètres avec son antenne.'
© 2025 — Cours pédagogique — Usage personnel et professionnel Page 15
Cours LLM & RAG — Architecture, Fonctionnement et Applications
5 Limites des LLM et solutions avancées
5.1 Vocabulaire fixe : pourquoi et comment contourner
Un LLM possède un vocabulaire fixe et figé après l'entraînement. La matrice d'embedding a
vocab_size lignes. Si un nouveau mot apparaît après l'entraînement (ex. un néologisme, un nouveau
nom de produit), le tokenizer va le découper en sous-mots existants.
Pourquoi un vocabulaire dynamique est impossible
• Coût mémoire : la matrice de sortie (d_model × vocab_size) occupe plusieurs Go. Doubler le
vocabulaire doublerait cette mémoire.
• Softmax : calculer un softmax sur un vocabulaire croissant est de plus en plus coûteux
(O(vocab_size) par token généré).
• Apprentissage : chaque nouveau token nécessiterait un ré-entraînement pour que le modèle
apprenne comment l'utiliser dans les bonnes contextes.
Solutions et contournements
Sous-mots (BPE, SentencePiece)
Avec 50k tokens de sous-mots, on peut représenter presque n'importe quel mot par composition.
Analogie : avec 26 lettres, on peut écrire une infinité de livres.
RAG
Pour les données privées et récentes, on n'injecte pas les mots dans le vocabulaire — on fournit le
contexte complet dans le prompt.
Softmax adaptatif
Divise le vocabulaire en clusters (mots fréquents vs rares). Réduit le coût de calcul.
Mixture of Experts (MoE)
Différents 'experts' se spécialisent sur différents domaines. Mistral, Mixtral et GPT-4 utilisent cette
approche.
5.2 Dimension d'embedding : une coordonnée abstraite
© 2025 — Cours pédagogique — Usage personnel et professionnel Page 16
Cours LLM & RAG — Architecture, Fonctionnement et Applications
La dimension d'embedding d_model (768, 1024, 4096...) n'est pas un nombre de catégories. C'est la
taille de l'espace vectoriel dans lequel le modèle représente les concepts. Chaque dimension est
une coordonnée abstraite dont le sens est appris lors de l'entraînement.
Analogie : en géographie, un lieu est représenté par 2 coordonnées (lat, lon). Dans l'espace
i d'embedding, un concept est représenté par 768 coordonnées abstraites. Plus de dimensions = plus
de nuances que le modèle peut encoder = meilleure capacité de représentation.
© 2025 — Cours pédagogique — Usage personnel et professionnel Page 17
Cours LLM & RAG — Architecture, Fonctionnement et Applications
6 Outils et ressources
Orchestration RAG
Outil Source / URL Description
LangChain [Link] Framework complet : loaders, splitters, chains, agents. Idéal pour
LlamaIndex [Link] Spécialisé RAG. Excellent pour l'indexation avancée et les query
LangGraph [Link]
Graphes d'agents basés sur LangChain. Utilisé dans Evalia/Talen
Modèles d'embedding
Outil Source / URL Description
BAAI/bge-small-en-v1.5 HuggingFace Hub 384D. Rapide, léger. Utilisé dans Agent Extract.
BAAI/bge-large-en-v1.5 HuggingFace Hub 1024D. Plus précis, plus lourd.
all-MiniLM-L6-v2 sentence-transformers 384D. Populaire, bon rapport perf/taille.
text-embedding-3-small OpenAI API 1536D. Très performant, mais propriétaire.
Bases vectorielles
Outil Source / URL Description
Qdrant [Link] Open-source, cloud/on-prem, filtres sur payload. Utilisé dans Eva
FAISS Meta AI En mémoire, très rapide. Idéal pour le prototypage.
Chroma [Link] Embarqué (SQLite + FAISS). Simple à démarrer.
Pinecone [Link] SaaS managé. Scalabilité sans infrastructure.
Weaviate [Link] GraphQL API, modules intégrés (OpenAI, Cohere).
LLM et inférence
Outil Source / URL Description
HuggingFace Transformers
[Link] à des milliers de modèles open-source.
Ollama [Link] Exécution locale de LLM (LLaMA, Mistral, Gemma).
vLLM [Link] Inférence haute performance (PagedAttention).
OpenAI API [Link] GPT-4o, GPT-4, embeddings.
© 2025 — Cours pédagogique — Usage personnel et professionnel Page 18
Cours LLM & RAG — Architecture, Fonctionnement et Applications
Anthropic API [Link] Claude 3.5 Sonnet, Haiku, Opus.
Ressources d'apprentissage
• Hugging Face Course ([Link] — Gratuit, interactif, couvre NLP +
Diffusion.
• [Link] — LangChain for LLM Apps ([Link] — Cours pratiques
par Andrew Ng.
• Full Stack LLM Bootcamp ([Link] — Berkeley, couvre MLOps +
RAG.
• Pinecone Engineering Blog — Articles approfondis sur les embeddings et la recherche
vectorielle.
• Weaviate Blog — Tutoriels RAG, benchmarks de bases vectorielles.
• awesome-rag (GitHub) — Compilation de ressources RAG.
© 2025 — Cours pédagogique — Usage personnel et professionnel Page 19
Cours LLM & RAG — Architecture, Fonctionnement et Applications
7 Diagnostic des erreurs courantes
Les systèmes RAG peuvent échouer de plusieurs façons. Voici un guide de diagnostic structuré pour
identifier et corriger les problèmes.
Problème : Réponse hors sujet
• Les chunks récupérés ne sont pas pertinents à la question.
• Diagnostic 1 : vérifier le score de similarité des chunks retournés (doit être > 0.7 pour
COSINE normalisé).
• Diagnostic 2 : tester différents modèles d'embedding (bge-large vs MiniLM).
• Diagnostic 3 : ajuster la taille des chunks (trop grands = bruit, trop petits = perte de contexte).
• Solution : ajouter des métadonnées filtrantes (filtre par job_id, date, catégorie).
Checklist rapide : (1) score de similarité > 0.7 ? (2) top_k suffisant ? (3) taille du prompt <
!
max_tokens ? (4) cache non pollué ?
Problème : Hallucinations
• Le LLM génère des informations absentes du contexte.
• Diagnostic 1 : le contexte ne contient pas l'information → augmenter top_k (de 3 à 5-8).
• Diagnostic 2 : le prompt ne contraint pas assez le LLM → ajouter "Réponds uniquement avec
les informations fournies."
• Diagnostic 3 : vérifier que le cache Redis n'est pas pollué (données obsolètes). Exécuter
FLUSHALL si nécessaire.
• Solution avancée : ajouter un step de citation vérification (vérifier que la réponse contient
des éléments du contexte).
Checklist rapide : (1) score de similarité > 0.7 ? (2) top_k suffisant ? (3) taille du prompt <
!
max_tokens ? (4) cache non pollué ?
Problème : Troncature du contexte
• Le prompt dépasse la fenêtre de contexte du LLM (ex. 4096 tokens pour certains modèles).
• Diagnostic : calculer len([Link](prompt)) avant l'envoi.
• Solution 1 : réduire la taille des chunks (de 500 à 300 tokens).
• Solution 2 : réduire top_k (de 5 à 3 chunks).
• Solution 3 : utiliser un LLM avec fenêtre plus grande (128k tokens pour GPT-4o, Claude 3).
© 2025 — Cours pédagogique — Usage personnel et professionnel Page 20
Cours LLM & RAG — Architecture, Fonctionnement et Applications
Checklist rapide : (1) score de similarité > 0.7 ? (2) top_k suffisant ? (3) taille du prompt <
i
max_tokens ? (4) cache non pollué ?
Problème : Lenteur de la recherche
• La recherche dans la base vectorielle prend > 500ms.
• Diagnostic 1 : vérifier que l'index HNSW est créé dans Qdrant (activé par défaut, mais peut
être désactivé par erreur).
• Diagnostic 2 : la dimension d'embedding est-elle trop grande ? Passer de 1536D (OpenAI) à
384D (bge-small).
• Diagnostic 3 : activer le cache Redis pour les requêtes fréquentes.
Checklist rapide : (1) score de similarité > 0.7 ? (2) top_k suffisant ? (3) taille du prompt <
i
max_tokens ? (4) cache non pollué ?
Python — Outil de débogage RAG
# Outil de diagnostic : inspecter les chunks récupérés
def debug_rag(question, top_k=5):
q_vec = embed_model.embed([question])[0]
hits = [Link]('collection', q_vec, limit=top_k, with_payload=True)
print(f'Question: {question}')
print(f'Top {top_k} chunks:')
for i, hit in enumerate(hits):
print(f' [{i+1}] Score: {[Link]:.3f}')
print(f' Texte: {[Link][chr(116)+chr(101)+chr(120)+chr(116)][:100]}...')
prompt_tokens = len([Link](
'Contexte: ' + ' '.join([[Link]['text'] for h in hits])))
print(f'Tokens prompt: {prompt_tokens}')
© 2025 — Cours pédagogique — Usage personnel et professionnel Page 21
Cours LLM & RAG — Architecture, Fonctionnement et Applications
8 Conclusion et perspectives
Ce cours a couvert l'ensemble du pipeline, de la tokenisation interne du LLM jusqu'à la génération
augmentée par récupération. Voici les points essentiels à retenir.
Récapitulatif des concepts clés
• Tokenisation : le texte est découpé en tokens (sous-mots) via BPE/SentencePiece.
Vocabulaire fixe de 30k–100k tokens.
• Embedding interne : chaque token est un vecteur dense appris (vocab_size × d_model). À ne
pas confondre avec les embeddings RAG.
• Attention : mécanisme central du Transformer. Chaque token construit une représentation
contextuelle en 'regardant' tous les autres (Q·K·V).
• Génération auto-régressive : token par token, chaque nouveau token dépend de tous les
précédents.
• RAG = Retrieval + Generation : enrichir le prompt avec des chunks pertinents avant d'appeler
le LLM. Le modèle n'est pas modifié.
• Base vectorielle : stocke les embeddings des chunks pour une recherche par similarité
cosinus en quelques millisecondes.
Le RAG dans une architecture d'agent
Dans une architecture multi-agents comme Evalia/Talentium, le RAG est l'un des outils qu'un agent
peut invoquer. L'agent décide quand appeler le RAG (versus une base SQL, une API externe, ou sa
propre mémoire). LangGraph orchestre ces décisions via un graphe d'état.
Perspectives : VLM et RAG multimodal
• VLM (Vision Language Models) : GPT-4o, LLaVA, Idefics. Le LLM traite simultanément texte
et images.
• ColPali / ColBERT : modèles de retrieval multi-vecteurs. Chaque token génère un vecteur,
permettant un matching plus précis.
• RAG multimodal : indexation d'images, graphiques, tableaux. La question peut référencer une
image et retrouver les documents visuellement similaires.
• GraphRAG : enrichir le RAG avec un knowledge graph pour capturer les relations entre entités
(Microsoft GraphRAG).
• Agentic RAG : l'agent reformule sa question si les résultats sont insuffisants, lance plusieurs
recherches, synthétise les résultats.
© 2025 — Cours pédagogique — Usage personnel et professionnel Page 22
Cours LLM & RAG — Architecture, Fonctionnement et Applications
Ce cours est un document vivant. Les outils évoluent rapidement : consultez régulièrement les blogs Hugging Face,
LangChain et Qdrant pour rester à jour. Bonne construction de systèmes RAG !
© 2025 — Cours pédagogique — Usage personnel et professionnel Page 23