
FAISS indexe des vecteurs — et rien d'autre : ni les textes, ni leurs métadonnées, ni la persistance. Chroma comble ce manque. C'est une base vectorielle embarquée qui range au même endroit les vecteurs, les documents et leurs métadonnées, gère la persistance sur disque, et filtre les recherches — « cherche, mais seulement dans les documents de 2026 ». Pas de serveur à déployer : Chroma s'utilise comme une bibliothèque. Ce guide montre comment créer une collection, y indexer des documents, faire une recherche sémantique filtrée et persister le tout. Public visé : développeur qui veut une base vectorielle confortable pour construire un RAG.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Ce que Chroma apporte par rapport à un index vectoriel nu.
- Créer une collection persistante et l'alimenter.
- Indexer des documents avec leurs métadonnées.
- Faire une recherche sémantique et la filtrer par métadonnée.
- Situer Chroma entre prototype et production.
Prérequis
Section intitulée « Prérequis »- Python 3.10+.
- Une instance Ollama avec le modèle d'embedding
nomic-embed-text. - Comprendre les embeddings et avoir vu FAISS.
Ce que Chroma apporte
Section intitulée « Ce que Chroma apporte »Avec FAISS, on gère trois choses séparément : l'index vectoriel, la liste des textes alignée dessus, et la persistance bricolée à la main. Dès que des métadonnées entrent en jeu — la source d'un document, sa date —, l'attelage devient fragile.
Chroma réunit tout. Une collection Chroma stocke pour chaque document : son texte, son vecteur, ses métadonnées, le tout sous un identifiant. La persistance est automatique. Et la recherche peut être filtrée par métadonnée — une capacité que FAISS n'a pas nativement.
C'est ce qui fait de Chroma la base vectorielle de référence pour développer un RAG : tout ce qu'on assemblait à la main est désormais géré. Et comme Chroma s'exécute en bibliothèque embarquée, sans serveur, on garde la simplicité d'un prototype.
Créer une collection persistante
Section intitulée « Créer une collection persistante »Chroma s'utilise via un client. Le PersistentClient écrit les données sur disque : la collection survit à l'arrêt du programme.
import chromadb
client = chromadb.PersistentClient(path="./chroma_db")collection = client.get_or_create_collection("documentation")get_or_create_collection est le bon réflexe : il crée la collection au premier lancement, et la réutilise ensuite. Aucune logique « si elle existe déjà » à écrire — relancer le programme retrouve la collection telle quelle.
Indexer des documents avec leurs métadonnées
Section intitulée « Indexer des documents avec leurs métadonnées »On peuple la collection avec add. Chaque document apporte quatre éléments : un identifiant, un texte, un vecteur et des métadonnées.
collection.add( ids=["doc-0", "doc-1"], documents=[ "Un volume Docker conserve les données du conteneur.", "Terraform décrit une infrastructure en code déclaratif.", ], embeddings=vectoriser([...]), # vecteurs calculés avec Ollama metadatas=[ {"sujet": "docker", "annee": 2026}, {"sujet": "terraform", "annee": 2024}, ],)Les métadonnées sont la grande différence avec un index nu : ce sont des paires clé-valeur attachées à chaque document — sujet, annee, source. Elles ne servent pas à la recherche sémantique, mais à la filtrer, on le verra. Pour ne pas réindexer à chaque lancement, on conditionne l'add au fait que la collection soit vide — collection.count() == 0.
Rechercher dans la collection
Section intitulée « Rechercher dans la collection »La recherche se fait avec query : on fournit le vecteur de la question et le nombre n_results de documents voulus.
def rechercher(collection, question, k=3, filtre=None): """Recherche les k documents les plus proches, avec filtre optionnel.""" resultat = collection.query( query_embeddings=vectoriser([question]), n_results=k, where=filtre, ) return [ {"texte": texte, "sujet": meta["sujet"], "annee": meta["annee"]} for texte, meta in zip(resultat["documents"][0], resultat["metadatas"][0]) ]query renvoie une structure groupée par requête — d'où le [0] qui prend les résultats de la première (et seule) question. Chaque résultat ramène à la fois le texte et ses métadonnées : Chroma a tout gardé ensemble, on n'a aucune liste externe à consulter.
Filtrer par métadonnée
Section intitulée « Filtrer par métadonnée »C'est la capacité qui distingue vraiment Chroma. Le paramètre where restreint la recherche aux documents dont les métadonnées satisfont une condition — la recherche sémantique ne s'applique qu'à ce sous-ensemble.
# Chercher uniquement dans les documents Docker de 2026.filtre = {"$and": [{"sujet": "docker"}, {"annee": 2026}]}resultats = rechercher(collection, "conteneur", k=5, filtre=filtre)Les opérateurs — $and, $or, $eq, $gte — se combinent pour exprimer la condition. L'effet est puissant : on cherche « le passage le plus pertinent parmi les documents récents », ou « dans la section autorisée à cet utilisateur ». Ce filtrage est la base de fonctionnalités plus avancées — le multi-tenant, le contrôle d'accès — vues dans le guide sur le RAG en production.
Chroma entre prototype et production
Section intitulée « Chroma entre prototype et production »Chroma occupe une place précise dans le spectre des bases vectorielles. Plus complète que FAISS — métadonnées, filtrage, persistance —, elle reste embarquée : simple, sans serveur, parfaite pour développer.
Cette simplicité a un revers. Une base embarquée se partage mal entre plusieurs services ou machines, et tient moins bien la charge de très gros volumes interrogés en continu. Quand un RAG passe en production multi-clients, on bascule vers une base vectorielle serveur — Qdrant, utilisée dans les guides pratiques suivants.
| Étape du projet | Base vectorielle |
|---|---|
| Prototype, corpus en mémoire | FAISS |
| Développement, métadonnées, persistance | Chroma |
| Production, service partagé, montée en charge | Qdrant |
Le parcours est naturel : on prototype, on développe avec Chroma, on industrialise avec Qdrant — sans jamais remettre en cause le principe, identique partout : vectoriser, indexer, rechercher.
Dépannage
Section intitulée « Dépannage »| Symptôme | Cause probable | Solution |
|---|---|---|
| La collection est vide au redémarrage | Client non persistant | Utiliser PersistentClient, pas le client en mémoire |
| Documents réindexés à chaque lancement | add non conditionné | N'ajouter que si collection.count() == 0 |
| Erreur de dimension à l'ajout | Modèle d'embedding changé | Recréer la collection, réindexer |
where ne filtre rien | Opérateur ou clé incorrects | Vérifier les noms de métadonnées et la syntaxe $and |
| Résultats hors sujet | Question et docs vectorisés différemment | Utiliser le même modèle des deux côtés |
À retenir
Section intitulée « À retenir »- Chroma réunit vecteurs, textes et métadonnées dans une collection — fini les listes séparées.
- Le
PersistentClientécrit sur disque ;get_or_create_collectiongère création et réutilisation. - Chaque document indexé porte un identifiant, un texte, un vecteur et des métadonnées.
- Le paramètre
wherefiltre la recherche sémantique par métadonnée — la base du multi-tenant. - Chroma est embarquée : idéale pour développer, à remplacer par Qdrant en production.
- Le principe — vectoriser, indexer, rechercher — reste identique d'une base à l'autre.
Prochaines étapes
Section intitulée « Prochaines étapes »Pour aller plus loin
Section intitulée « Pour aller plus loin »- Documentation Chroma — la référence de la base et de son API.