Skip to content

Embeddings et recherche sémantique

Un embedding de phrase transforme un texte en un vecteur de nombres, construit pour qu’un texte proche en sens — même sans mot commun — ait un vecteur proche.

from sentence_transformers import SentenceTransformer
embedder = SentenceTransformer("paraphrase-multilingual-MiniLM-L12-v2")
chunk_embeddings = embedder.encode(chunks, normalize_embeddings=True)
print(chunk_embeddings.shape)
(5, 384)

Chaque document devient un vecteur de 384 nombres. normalize_embeddings=True ramène chaque vecteur à une longueur de 1 — une préparation qui simplifie radicalement le calcul de similarité.

La similarité cosinus, un simple produit scalaire

Section titled “La similarité cosinus, un simple produit scalaire”

Une fois les vecteurs normalisés, la similarité cosinus entre une question et tous les chunks se calcule en une seule opération matricielle :

question_embedding = embedder.encode(question, normalize_embeddings=True)
similarites = chunk_embeddings @ question_embedding
indices_top = np.argsort(-similarites)[:2]
for idx in indices_top:
print(f"[{similarites[idx]:.3f}] {sources[idx]}")
[0.755] rollback.pdf
[0.653] sauvegardes.pdf

Pour la question sur le délai de rollback, le chunk rollback.pdf ressort nettement en tête (0,755) — sans qu’aucun mot de la question ne soit un copier-coller du document : la recherche fonctionne par proximité de sens, pas par correspondance exacte de mots-clés.

chunk_embeddings n’est ici qu’une simple matrice NumPy : à 5 documents, aucune infrastructure dédiée n’est nécessaire. Pour un corpus de plusieurs milliers de documents, cette approche resterait correcte mais deviendrait lente (la recherche exhaustive compare la question à tous les vecteurs) ; des bases vectorielles dédiées (FAISS, Chroma, Pinecone) résolvent ce problème avec des index de recherche approximative, bien plus rapides à grande échelle.

👉 Le RAG complet : assembler recherche et génération


Junior TSAFACK – 12/09/2026