Aller au contenu principal
Leçon 50 sur 95 · Construire avec l'API Claude

Implémenter le flux RAG

Leçon 50 sur 95 Mis à jour le 5 novembre 2026 Développeur
Sur cette page
  1. Deux temps à ne pas confondre
  2. Un index vectoriel minimal
  3. Étape 1 : découper
  4. Étape 2 : vectoriser tous les morceaux
  5. Étape 3 : stocker vecteurs et textes
  6. Étapes 4 et 5 : vectoriser la question et chercher
  7. Lire les résultats
  8. À vous de jouer
  9. Points clés à retenir

Le flux RAG est compris ; place au code. Cette leçon le met en œuvre sur un vrai document : découper un rapport, vectoriser ses sections, les ranger dans un index vectoriel, puis chercher les sections les plus proches d’une question.

Deux temps à ne pas confondre

Indexer une fois, chercher à chaque question Deux colonnes : l'indexation, faite une fois (découper, vectoriser avec input_type document, stocker vecteurs et textes), puis la recherche, à chaque question (vectoriser la question avec input_type query, chercher les k plus proches, construire le prompt). IMPLÉMENTATION Indexer une fois, chercher à chaque question Indexation, une fois 1. Découper chunk_by_section(text) 2. Vectoriser input_type document 3. Stocker Vecteurs et textes, ensemble. → Recherche, à chaque question 4. Vectoriser La question, input_type query. 5. Chercher Les k morceaux les plus proches. Ensuite Le prompt pour Claude. Recalculer les embeddings du corpus à chaque question multiplie la facture et la latence.
D'après la leçon « Implementing the RAG flow » (Claude Academy, Building with the Claude API).

Les cinq étapes se répartissent en deux temps. Les trois premières (découper, vectoriser, stocker) forment l’indexation : elle a lieu une fois, et de nouveau seulement quand les documents changent. Les deux dernières (vectoriser la question, chercher) forment la recherche : elles s’exécutent à chaque question. Recalculer les embeddings du corpus à chaque question est l’erreur de conception la plus coûteuse d’un système RAG.

Un index vectoriel minimal

Le cours officiel fournit sa classe VectorIndex dans un fichier à part. En voici une version complète et courte, en Python pur :

import math

def cosine_similarity(a, b):
    dot = sum(x * y for x, y in zip(a, b))
    return dot / (math.sqrt(sum(x * x for x in a)) * math.sqrt(sum(y * y for y in b)))

class VectorIndex:
    def __init__(self, embed_fn=None):
        self.embed_fn = embed_fn
        self.vectors = []
        self.documents = []

    def add_vector(self, vector, document):
        self.vectors.append(vector)
        self.documents.append(document)

    def add_document(self, document):
        self.add_vector(self.embed_fn(document["content"], input_type="document"), document)

    def search(self, query, k=1):
        if isinstance(query, str):
            query = self.embed_fn(query, input_type="query")
        results = [(doc, 1 - cosine_similarity(query, vector))
                   for doc, vector in zip(self.documents, self.vectors)]
        results.sort(key=lambda pair: pair[1])   # distance croissante : le plus proche d'abord
        return results[:k]

L’index garde chaque vecteur avec son document. search accepte un vecteur, ou un texte qu’il vectorise lui-même si on lui a donné une fonction d’embedding ; la leçon 52 se servira de cette seconde forme. Pour quelques milliers de morceaux, ce calcul en Python pur suffit. Au-delà, on passe à NumPy, puis à une vraie base vectorielle, qui sait chercher les plus proches voisins sans tout comparer.

Étape 1 : découper

with open("report.md", encoding="utf-8") as f:
    text = f.read()

chunks = chunk_by_section(text)
chunks[2]   # pour vérifier un morceau, ici la table des matières

Étape 2 : vectoriser tous les morceaux

embeddings = generate_embedding(chunks, input_type="document")

Un seul appel pour toute la liste : generate_embedding, écrite à la leçon 48, accepte un texte ou une liste.

Étape 3 : stocker vecteurs et textes

store = VectorIndex(generate_embedding)
for embedding, chunk in zip(embeddings, chunks):
    store.add_vector(embedding, {"content": chunk})

On stocke le texte avec le vecteur, et ce n’est pas un détail : un embedding permet de mesurer une proximité, pas de retrouver le texte dont il vient. Sans le texte, la recherche saurait dire « le morceau n° 7 est le plus proche » sans pouvoir dire ce qu’il contient. Une base réelle stocke au moins une référence vers le texte.

Étapes 4 et 5 : vectoriser la question et chercher

question_vector = generate_embedding(
    "Qu'a fait le département d'ingénierie logicielle l'année dernière ?", input_type="query"
)
results = store.search(question_vector, 2)
for doc, distance in results:
    print(round(distance, 2), doc["content"][:200], "\n")

Lire les résultats

Dans la démonstration du cours officiel, sur son rapport d’exemple, la section 2 (ingénierie logicielle) arrive en tête avec une distance de 0,71, devant la section de méthodologie à 0,72. Deux points à retenir :

  • on lit une distance : plus elle est petite, plus le morceau est proche. Un tri décroissant, réflexe habituel pour des scores, renverrait les morceaux les moins pertinents ;
  • l’écart entre les deux premiers est faible. La recherche sémantique seule n’est pas toujours tranchée, et les leçons suivantes l’améliorent : recherche lexicale, fusion des classements, reclassement.

À vous de jouer

Un premier pipeline. Prenez un document Markdown de votre choix, découpez-le par section, vectorisez les morceaux avec input_type="document", rangez-les dans un VectorIndex, puis posez trois questions. Comparez les résultats avec k égal à 1, 3 et 5, et notez à partir de quand les morceaux renvoyés cessent d’être utiles.

Sources officielles : Implementing the RAG flow (Claude Academy) · Embeddings (documentation Claude : recherche par produit scalaire)

Points clés à retenir

  • Indexation une fois (découper, vectoriser, stocker), recherche à chaque question (vectoriser la question, chercher).
  • On stocke le texte avec son vecteur : un embedding ne permet pas de retrouver le texte.
  • Les morceaux se vectorisent avec input_type="document", la question avec "query".
  • Une distance cosinus se trie par ordre croissant : la plus petite est la meilleure.
  • La recherche sémantique seule laisse parfois des écarts faibles : la suite de la section l’améliore.