FAISS detailed..
Semantic Textual Similarity, Sentence Transformers, embeddings, FAISS et clustering : comment construire un moteur de recherche sémantique qui transforme des textes en vecteurs, les stocke et retrouve les meilleures correspondances.
Vector Stores : comment conserver et rechercher les embeddings avec FAISS
1. Pourquoi utiliser un vector store ?
Nous avons vu qu’un modèle Sentence Transformers transforme les textes en vecteurs numériques.
Par exemple :
Texte : « Développer les compétences en conduite du changement ».
Embedding : [0.12, -0.34, 0.08, ...]
Mais lorsque nous avons des centaines ou des milliers de formations, une question apparaît :
Où conserver tous ces vecteurs pour éviter de les recalculer à chaque nouvelle recherche ?
C’est le rôle d’un index vectoriel, généralement intégré à une architecture de vector store.
Le fonctionnement est le suivant :
- Extraire et nettoyer les textes.
- Générer leurs embeddings avec Sentence Transformers.
- Ajouter les embeddings à un index FAISS.
- Conserver les identifiants et métadonnées des textes dans un stockage associé.
- Sauvegarder l’index et les métadonnées.
- Pour une nouvelle requête, calculer uniquement son embedding.
- Rechercher les vecteurs les plus proches dans FAISS.
- Retrouver les formations correspondantes grâce à leurs identifiants.
L’avantage : les embeddings du catalogue sont calculés une seule fois, tant que les textes et le modèle ne changent pas.
2. FAISS : qu’est-ce que c’est exactement ?
FAISS signifie Facebook AI Similarity Search.
C’est une bibliothèque développée initialement par Meta AI pour rechercher efficacement les vecteurs les plus proches dans des ensembles de données.
Elle permet notamment :
- La recherche exacte des plus proches voisins.
- La recherche approximative sur de grands ensembles
- La comparaison par distance euclidienne ou produit scalaire.
- L’utilisation d’index optimisés selon le volume de données et les ressources disponibles.
- La sauvegarde et le rechargement d’index.
FAISS n’est pas, à lui seul, une base de données documentaire complète.
Il faut généralement lui associer un fichier ou une table contenant les informations métier.
Dans notre cas, les embeddings sont indexés par FAISS tandis que les intitulés, organismes, objectifs pédagogiques et références de formation restent dans un DataFrame ou un fichier structuré.
3. Architecture complète : Sentence Transformers + FAISS
CATALOGUES DE FORMATIONS
Institut XX
|
v
Extraction des données
|
v
Nettoyage / Normalisation
|
v
Sentence Transformers
|
v
EMBEDDINGS
|
v
FAISS
Index vectoriel
|
Sauvegarde locale
|
+------------+------------+
| |
v v
formations.index formations.csv
(vecteurs) (métadonnées)
| |
+------------+------------+
|
v
NOUVEAU BESOIN
|
v
Embedding de la requête
|
v
Recherche Top K FAISS
|
v
Formations candidates
|
v
Validation métierLe point essentiel : FAISS ne remplace pas Sentence Transformers. Les deux composants remplissent des fonctions complémentaires.
Sentence Transformers calcule les représentations.
FAISS organise les vecteurs pour permettre des recherches efficaces.
4. Quel type d’index FAISS choisir ?
FAISS propose plusieurs familles d’index.
IndexFonctionnementUtilisationIndexFlatIPRecherche exacte par produit scalairePetit POC, vecteurs normalisésIndexFlatL2Recherche exacte par distance euclidienneComparaison L2IndexHNSWFlatRecherche approximative par grapheCorpus plus importantsIndexIVFFlatRecherche approximative par partitionsVolumes importants, avec entraînement de l'index
Pour un POC contenant quelques centaines ou milliers de formations, je recommande IndexFlatIP avec des embeddings normalisés.
Pourquoi ?
Parce qu’il est simple, déterministe pour un même index et ne nécessite pas d’entraînement préalable.
Sur des vecteurs normalisés, le produit scalaire correspond à la similarité cosinus.
L’utilisation d’un index HNSW ou IVF n’est pas nécessaire tant que les performances d’une recherche exacte sont suffisantes.
5. Implémentation Python complète et exécutable
Nous allons construire un moteur simple à partir de quatre formations fictives.
Installation
pip install sentence-transformers faiss-cpu pandas numpyAucun GPU n’est nécessaire pour cette démonstration.
Étape 1 — Préparer le catalogue
import pandas as pdformations = pd.DataFrame([
{
"formation_id": "F001",
"organisme": "Institut XX",
"intitule": "Conduire une transformation organisationnelle",
"objectifs": "Accompagner les équipes dans le changement"
},
{
"formation_id": "F002",
"organisme": "XX",
"intitule": "Développer son leadership",
"objectifs": "Encadrer et mobiliser une équipe"
},
{
"formation_id": "F003",
"organisme": "Institut XX",
"intitule": "Maîtriser Excel",
"objectifs": "Analyser et présenter des données"
},
{
"formation_id": "F004",
"organisme": "XX",
"intitule": "Communiquer en situation de changement",
"objectifs": "Adapter sa communication aux transformations"
}
])formations["texte_recherche"] = (
formations["intitule"]
+ ". "
+ formations["objectifs"]
)
Les organismes et intitulés sont fictifs dans cet exemple. Ils ne représentent pas des formations réelles des catalogues.
Étape 2 — Charger le modèle et calculer les embeddings
import numpy as np
from sentence_transformers import SentenceTransformermodel = SentenceTransformer(
"sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2"
)embeddings = model.encode(
formations["texte_recherche"].tolist(),
convert_to_numpy=True,
normalize_embeddings=True
)embeddings = np.ascontiguousarray(
embeddings,
dtype="float32"
)print(embeddings.shape)
Pour ce modèle, nous attendons quatre vecteurs de 384 dimensions :
(4, 384)La normalisation permet d’utiliser le produit scalaire pour calculer une mesure équivalente à la similarité cosinus.
Étape 3 — Créer l’index FAISS
import faissdimension = embeddings.shape[1]index = faiss.IndexFlatIP(dimension)index.add(embeddings)print("Vecteurs indexés :", index.ntotal)
Résultat attendu :
Vecteurs indexés : 4Chaque ligne de notre matrice correspond à un vecteur indexé.
Avec IndexFlatIP, les positions des résultats correspondent aux positions des lignes ajoutées à l'index.
Étape 4 — Sauvegarder l’index et les métadonnées
from pathlib import Pathdossier = Path("vector_store")
dossier.mkdir(exist_ok=True)faiss.write_index(
index,
str(dossier / "formations.index")
)formations.to_csv(
dossier / "formations.csv",
index=False,
encoding="utf-8-sig"
)
Nous obtenons :
vector_store/
formations.index
formations.csvformations.index contient l'index FAISS et ses vecteurs.
formations.csv contient les informations métier et le texte ayant servi à produire les embeddings.
Il faut sauvegarder les deux de manière cohérente, car le CSV permet de retrouver la formation correspondant à une position de l’index.
Étape 5 — Recharger le vector store
index = faiss.read_index(
"vector_store/formations.index"
)formations = pd.read_csv(
"vector_store/formations.csv"
)assert index.ntotal == len(formations)
Cette vérification permet de détecter un décalage simple entre le nombre de vecteurs et le nombre de formations.
Get Sara Hamouda’s stories in your inbox
Join Medium for free to get updates from this writer.
En production, il faudrait aussi conserver la version du modèle, la version du catalogue et un identifiant de construction de l’index.
Étape 6 — Rechercher les formations les plus proches
besoin = (
"Accompagner les managers "
"dans la conduite du changement"
)query_embedding = model.encode(
[besoin],
convert_to_numpy=True,
normalize_embeddings=True
)query_embedding = np.ascontiguousarray(
query_embedding,
dtype="float32"
)scores, indices = index.search(
query_embedding,
k=min(3, index.ntotal)
)for score, position in zip(
scores[0],
indices[0]
):
formation = formations.iloc[int(position)] print(
formation["formation_id"],
formation["intitule"],
round(float(score), 4)
)
FAISS renvoie deux éléments :
scores: les scores de proximité.indices: les positions des vecteurs retrouvés.
Nous utilisons ensuite les positions pour retrouver les formations correspondantes dans le DataFrame.
Important : le classement exact dépend des embeddings calculés. Il doit être vérifié à l’exécution, et non supposé.
6. Pourquoi la sauvegarde est importante
Sans index sauvegardé, chaque exécution peut nécessiter de recalculer les embeddings du catalogue.
Avec un index sauvegardé, on peut recharger les vecteurs et effectuer directement les recherches.
Mais il existe une condition fondamentale : le modèle utilisé pour encoder les requêtes doit être compatible avec celui utilisé pour encoder le catalogue.
Si nous changeons de modèle, il faut normalement recalculer les embeddings et reconstruire l’index.
Deux modèles peuvent produire des vecteurs de même dimension sans partager le même espace sémantique.
La compatibilité ne se limite donc pas à la dimension.
7. Comment gérer les modifications du catalogue ?
Supposons que le catalogue XX soit mis à jour.
Certaines formations sont ajoutées, d’autres supprimées ou modifiées.
Trois stratégies sont possibles.
Reconstruction complète : recalculer les embeddings et recréer l’index. C’est généralement le choix le plus simple et le plus sûr pour un petit POC.
Mise à jour incrémentale : encoder uniquement les nouveaux documents et les ajouter. Cela exige une gestion rigoureuse des identifiants, des suppressions et des versions.
Index avec identifiants explicites : utiliser un mécanisme tel que IndexIDMap2 pour associer des identifiants numériques stables aux vecteurs, tout en conservant les métadonnées dans un stockage séparé.
Pour notre périmètre, je privilégierais la reconstruction complète à chaque nouvelle version validée des catalogues.
Elle réduit le risque de conserver des formations obsolètes ou des associations incorrectes entre vecteurs et métadonnées.
8. FAISS et clustering : peut-on réutiliser les mêmes embeddings ?
Oui.
Les embeddings calculés pour la recherche sémantique peuvent également être utilisés pour regrouper les besoins similaires.
Mais FAISS et le clustering ne sont pas exactement la même chose.
FAISS sert principalement à rechercher des voisins proches.
K-Means et le clustering agglomératif servent à former des groupes.
Une architecture simple peut donc réutiliser les mêmes vecteurs :
Embeddings
|
+-------+-------+
| |
v v
FAISS Clustering
| |
v v
Top 3 formations Groupes de besoinsCela évite de recalculer inutilement les représentations pour chaque analyse.
9. La limite fondamentale : FAISS ne sait pas si une formation est réellement adaptée
Une recherche FAISS peut retourner une formation très proche sémantiquement du besoin.
Mais elle ne sait pas automatiquement si :
- Le public est éligible.
- Le niveau correspond.
- Les prérequis sont satisfaits.
- La formation est toujours disponible.
- Le financement est applicable.
Il faut donc prévoir une seconde couche.
FAISS → candidats sémantiques → contrôles métier → recommandations validables.
C’est cette séparation qui rend le moteur défendable dans un contexte professionnel.
10. Sécurité et qualité du vector store
Un index vectoriel peut contenir des représentations dérivées de données internes.
Ces représentations ne doivent pas être considérées comme anonymes par défaut.
Pour un POC interne, il faut notamment :
- Stocker l’index et les métadonnées dans un espace autorisé.
- Éviter d’y inclure inutilement des données personnelles.
- Restreindre les droits d’accès.
- Conserver la provenance et la version des documents.
- Ne charger que des fichiers d’index provenant d’une source fiable.
- Tester que les résultats ne renvoient pas de documents supprimés ou non autorisés.
FAISS n’applique pas automatiquement les règles de confidentialité propres à chaque formation ou document.
Si des droits d’accès différents existent, ils doivent être vérifiés par l’application avant de présenter les résultats.
Architecture finale
Phase 1 — Préparation
Plan de compétences + catalogues → extraction → nettoyage → normalisation.
Phase 2 — Vectorisation
Sentence Transformers → embeddings des besoins et formations.
Phase 3 — Stockage
FAISS → index vectoriel sauvegardé + métadonnées dans un fichier structuré.
Phase 4 — Recherche
Embedding du besoin → recherche FAISS → Top K des formations candidates.
Phase 5 — Analyse
Contrôles métier → éventuel reranking → sélection des recommandations.
Phase 6 — Financement
Application des règles déterministes à partir du référentiel de prise en charge.
Phase 7 — Restitution
PDF explicable → validation par l’équipe Formation.
Phase 8 — Évaluation
Gold Dataset → Precision@3, Recall@3, NDCG@3 → analyse des erreurs.
Ce que les autres ne voient pas : FAISS n’est pas forcément indispensable
C’est le point stratégique.
Pour quelques centaines de formations, nous pouvons tout à fait conserver les embeddings dans un tableau NumPy et calculer directement les similarités.
FAISS devient intéressant lorsque nous voulons un index réutilisable, une interface de recherche efficace et la possibilité de faire évoluer le volume.
Il ne faut donc pas confondre l’ajout d’un vector store avec une amélioration automatique de la qualité du matching.
À modèle, vecteurs et métrique identiques, une recherche exacte FAISS et une recherche exacte par produit matriciel doivent retrouver les mêmes voisins, sous réserve des effets numériques et des égalités de scores.
FAISS améliore principalement l’organisation et l’efficacité de la recherche. Il ne corrige pas un mauvais modèle d’embeddings.
Mini-exercice pratique — Votre premier vector store
Construisez un fichier CSV de 20 formations fictives ou autorisées.
Calculez leurs embeddings avec un modèle multilingue.
Créez un index IndexFlatIP.
Sauvegardez-le, puis rechargez-le.
Testez cinq besoins et affichez les trois formations les plus proches.
Enfin, comparez les résultats avec les jugements d’un expert métier.
Critère de réussite : le système doit retrouver les formations attendues, conserver les bonnes associations entre identifiants et vecteurs et produire les mêmes résultats après rechargement de l’index.
TL;DR
Sentence Transformers transforme les textes en embeddings. FAISS stocke et indexe ces vecteurs pour retrouver rapidement les formations les plus proches. Les métadonnées restent dans un stockage associé. Le clustering exploite éventuellement les mêmes représentations pour regrouper les besoins. Les règles métier et l’évaluation déterminent si les recommandations sont réellement utiles.
Sources techniques
- FAISS — Dépôt officiel
- FAISS — Getting Started
- FAISS — Guide des index
- Sentence Transformers — Semantic Search
- Sentence Transformers — Calcul des embeddings
- Sentence Transformers — Clustering
By Sara HAMOUDA







