Retrieval-Augmented Generation (RAG)

Maîtriser la recherche sémantique : la colonne vertébrale des systèmes RAG modernes

Les moteurs de recherche traditionnels basés sur les mots-clés échouent à comprendre le contexte. Si un utilisateur recherche « comment réparer un tuyau cassé », une recherche par mots-clés pourrait manquer des documents contenant « réparation de plomberie » ou « résolution de fuite ». C'est là que la recherche sémantique brille. En convertissant le texte en représentations vectorielles de haute dimension (embeddings), nous pouvons capturer le sens sous-jacent du contenu plutôt que de simplement correspondre à des chaînes exactes. Pour les développeurs construisant des systèmes de génération augmentée par récupération (RAG), la recherche sémantique n'est pas seulement une optimisation — c'est l'étape critique initiale pour récupérer le contexte pertinent pour les grands modèles de langage (LLM).

Fonctionnement de la recherche sémantique

La recherche sémantique fonctionne sur le principe de la similarité cosinus ou de la distance de produit scalaire entre les vecteurs. Le processus implique deux étapes principales :

  1. Génération d'embeddings : À l'aide d'un modèle transformeur pré-entraîné (comme Sentence-BERT ou l'API d'embeddings d'OpenAI), les extraits de texte sont convertis en vecteurs numériques. Des significations similaires produisent des vecteurs proches les uns des autres dans l'espace multidimensionnel.
  2. Récupération de vecteurs : Lorsqu'une requête est effectuée, elle est également convertie en embedding. Le système recherche ensuite dans un index vectoriel pour trouver les $K$ plus proches voisins (KNN) du vecteur de requête.

Mise en œuvre de la recherche sémantique avec FAISS

Facebook AI Similarity Search (FAISS) est une bibliothèque populaire pour la recherche de similarité efficace sur des vecteurs denses. Ci-dessous, un exemple pratique de configuration d'un pipeline de recherche sémantique utilisant Python, FAISS et les transformers de Hugging Face.

import faiss
import numpy as np
from transformers import AutoTokenizer, AutoModel

def get_sentence_embeddings(sentences, model_name='sentence-transformers/all-MiniLM-L6-v2'):
    """Génère des embeddings normalisés pour une liste de phrases."""
    tokenizer = AutoTokenizer.from_pretrained(model_name)
    model = AutoModel.from_pretrained(model_name)
    
    inputs = tokenizer(sentences, padding=True, truncation=True, return_tensors='pt')
    with torch.no_grad():
        output = model(**inputs)
        embeddings = output.last_hidden_state[:, 0, :]  # jeton [CLS]
        embeddings = torch.nn.functional.normalize(embeddings, p=2, dim=1)
    return embeddings.cpu().numpy()

# 1. Préparer les données
documents = [
    "Le ciel est bleu pendant la journée.",
    "Python est un langage de programmation populaire.",
    "Les modèles d'apprentissage automatique nécessitent de grands jeux de données.",
    "L'océan est vaste et profond."
]

# 2. Générer les embeddings des documents
doc_embeddings = get_sentence_embeddings(documents)
doc_embeddings = np.float32(doc_embeddings)

# 3. Construire l'index FAISS (Produit scalaire)
dimension = doc_embeddings.shape[1]
index = faiss.IndexFlatIP(dimension)
index.add(doc_embeddings)

# 4. Effectuer la recherche
query = "Quel temps fait-il dehors ?"
query_embedding = get_sentence_embeddings([query])
query_embedding = np.float32(query_embedding)

# Rechercher les 2 documents les plus pertinents
k = 2
distances, indices = index.search(query_embedding, k)

for i, doc_idx in enumerate(indices[0]):
    print(f"Score: {distances[0][i]:.4f} | Doc: {documents[doc_idx]}")

Bonnes pratiques pour les systèmes de production

  • Stratégie de découpage (Chunking) : Divisez les grands documents en plus petits extraits contextuellement complets (par exemple, 100 à 500 jetons) pour améliorer la précision des embeddings.
  • Recherche hybride : Combinez la recherche sémantique avec BM25 (recherche par mots-clés) pour obtenir les meilleurs résultats des deux mondes. Cela garantit que les noms propres rares ou les codes spécifiques restent récupérables.
  • Re-classement (Re-ranking) : Utilisez un modèle cross-encoder pour re-classement les $N$ meilleurs candidats retournés par la recherche vectorielle afin d'améliorer la précision finale.

Conclusion

La recherche sémantique est le pont entre les données non structurées et les applications IA intelligentes. En exploitant les bases de données vectorielles et les modèles d'embeddings robustes, vous pouvez considérablement améliorer les performances des pipelines RAG, garantissant que vos LLM ont accès au contexte le plus pertinent possible. Commencez petit avec FAISS, mais envisagez de passer à des bases de données vectorielles dédiées comme Pinecone, Weaviate ou Milvus à mesure que votre volume de données augmente.

Share: