Aller au contenu principal
Leçon 38 sur 67 · Claude sur Amazon Bedrock

Implémenter le flux RAG

Leçon 38 sur 67 Mis à jour le 5 novembre 2026 Développeur
Sur cette page
  1. Une base vectorielle minimale
  2. Les étapes, dans le code
  3. À vous de jouer
  4. Points clés à retenir

Passons à la pratique : une base vectorielle minimale, écrite à la main, puis les étapes du flux RAG sur un vrai document, un rapport report.md découpé en sections.

Une base vectorielle minimale

Le cours officiel fournit une classe VectorIndex dans son notebook. En voici une version courte, qui suffit pour apprendre :

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"]), document)

    def search(self, query, k=1):
        if isinstance(query, str):
            query = self.embed_fn(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]

search renvoie des couples (document, distance cosinus), du plus proche au plus lointain. add_document et la recherche par texte serviront aux leçons suivantes ; embed_fn est la fonction generate_embedding de la leçon 36. Une vraie base vectorielle fait la même chose en beaucoup plus rapide, avec des index qui évitent de comparer la question à chaque vecteur.

Les étapes, dans le code

Le flux RAG dans le code Deux colonnes : le prétraitement (chunk_by_section, un appel Titan par morceau, VectorIndex qui stocke vecteurs et textes) et chaque question (la question vectorisée, search qui renvoie les plus proches, chat qui répond à partir des extraits). IMPLÉMENTATION Le flux RAG dans le code Prétraitement, une fois chunk_by_section Le rapport en sections. generate_embedding Un appel Titan par morceau. VectorIndex Vecteurs et textes stockés. À chaque question generate_embedding La question vectorisée. search Les morceaux les plus proches. chat La réponse à partir des extraits. Le texte voyage avec son vecteur : c'est lui qui va dans le prompt.
D'après la leçon « Implementing the RAG flow » (Claude Academy, Claude with Amazon Bedrock).

1. Découper par sections.

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

chunks = chunk_by_section(text)

2. Vectoriser chaque morceau. Titan traite un texte par appel : cette étape fait autant d’appels que de morceaux, et prend un peu de temps.

embeddings = [generate_embedding(chunk) for chunk in chunks]

3. Stocker vecteurs et textes.

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

C’est le point essentiel de l’étape : on stocke l’embedding et le texte. Une liste de nombres seule ne servirait à rien ; c’est le texte qui ira dans le prompt.

4 et 5. Vectoriser la question et chercher.

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

Dans la démonstration du cours officiel, la section d’ingénierie logicielle arrive en tête avec une distance de 0,71, suivie de la section de méthodologie à 0,72. L’écart est mince : la recherche vectorielle seule n’est pas toujours tranchée, ce que les leçons suivantes amélioreront.

6. Construire le prompt.

context = "\n\n".join(doc["content"] for doc, _ in results)

messages = []
add_user_message(messages, f"""Réponds à la question à partir des extraits du rapport.

<extraits>
{context}
</extraits>

<question>
{question}
</question>""")
print(chat(messages)["text"])

chat est la version de la section Tool Use, qui renvoie un dictionnaire. Les extraits passent avant la question, comme le conseille la leçon 20.

À vous de jouer

Votre premier RAG. Prenez un document Markdown de votre choix, avec des titres de niveau 2. Indexez-le, puis posez trois questions : une dont la réponse tient dans une section, une qui demande deux sections, une qui n’est pas dans le document. Regardez les distances et les réponses : que fait Claude quand les extraits ne contiennent pas la réponse ?

Sources officielles : Implementing the RAG flow (Claude Academy) · Amazon Titan Embeddings Text (documentation AWS)

Points clés à retenir

  • Une base vectorielle stocke des vecteurs et le texte qui va avec, puis renvoie les plus proches d’une question.
  • Les étapes : découper, vectoriser, stocker, puis vectoriser la question, chercher, construire le prompt.
  • Avec Titan, un appel par morceau : l’indexation prend du temps.
  • Gardez toujours le texte avec son vecteur : c’est lui qui va dans le prompt.
  • Une distance proche entre deux sections signale une recherche peu tranchée.