Ollama Embedding en pratique : recherche vectorielle locale et RAG

Plus de 200 PDF sur le disque, et vous cherchez le détail d’un plan technique vu il y a six mois. Recherche par mots-clés ? Inutile — vous vous souvenez du sens, pas des formulations exactes. Près d’une heure perdue. À ce moment-là, on rêve d’un outil qui « comprend le sens ».
Pire encore : ces documents touchent à l’architecture interne. Les envoyer dans le cloud pour une recherche vectorielle ? Hors de question. La ligne rouge de la confidentialité est nette.
Les embeddings Ollama règlent ce cas de figure : tout tourne en local, les données ne sortent pas, et la recherche devient sémantique. Après quelques jours d’essais entre mxbai, nomic et Qwen3, et un tour des bases vectorielles, les pièges apparaissent — mauvais modèle, mauvaise base, et la suite devient pénible.
Cet article rassemble ces retours d’expérience. À la fin, vous pourrez monter un RAG local de A à Z, du traitement documentaire à la recherche sémantique, avec le code complet.
La gamme de modèles Embedding Ollama
Ollama propose plusieurs modèles d’embedding ; au début, difficile de trancher. La doc officielle affirme que mxbai dépasse text-embedding-3-large d’OpenAI — ça sonne bien, mais en pratique ? Après les tests, voici une réponse directe.
Un tableau comparatif pour cadrer le choix :
| Modèle | Dimension | Contexte | Taille | Points forts |
|---|---|---|---|---|
| mxbai-embed-large | 1024 | 512 tokens | 670M | Choix généraliste, tête du classement MTEB |
| nomic-embed-text | 768 | 8192 tokens | 274M | Longs textes, extension de contexte |
| Qwen3 Embedding | 1024 | 8192 tokens | ~ 600M | Sortie 2026, adapté au chinois |
mxbai-embed-large est celui que j’utilise le plus. Pourquoi ? Simple, stable. Ses vecteurs 1024 dimensions suffisent dans la majorité des cas ; sur le benchmark MTEB (Massive Text Embedding Benchmark), il se place très haut, un peu au-dessus de text-embedding-3-large d’OpenAI. Recherche documentaire, recherche dans du code : c’est le choix sûr.
nomic-embed-text mise sur 8192 tokens de contexte. Pour un article entier ou un long fil de conversation, c’est utile. Plus léger (274M), donc souvent plus rapide que mxbai. Dimension 768 : en théorie un peu moins expressif — en test, peu de différence sur textes courts ; sur longs textes, nomic gagne.
Qwen3 Embedding est sorti par Alibaba en avril 2026. Le chinois est vraiment bon : sur des articles techniques, « mécanismes de tolérance aux pannes des systèmes distribués » et « conception tolante aux pannes » se rapprochent ; mxbai accroche moins. Contenu surtout en chinois : à essayer.
En résumé : débuter avec mxbai sans hésiter ; longs textes → nomic ; contenu chinois → Qwen3 en priorité. Tester les trois prend une demi-heure — les résultats comptent plus que le tableau.
Choisir une base de données vectorielle
Modèle choisi, où stocker ? Le choix de la base vectorielle piège autant que le modèle. Trop petit : la montée en charge fait mal ; trop gros : gaspillage. Trois options courantes :
| Base | Cas d’usage | Volume | Caractéristiques |
|---|---|---|---|
| ChromaDB | Début, projets perso | moins de 100 000 entrées | Prêt à l’emploi, zéro config |
| FAISS | Performance mono-machine, recherche | 100 000 – 1 million | Open source Meta, très rapide |
| Milvus | Production, entreprise | millions+ | Distribué, extensible, riche |
ChromaDB est mon conseil pour débuter. Une commande : pip install chromadb. API claire : quelques lignes pour indexer et interroger. Index HNSW (Hierarchical Navigable Small World), largement suffisant à petite échelle. Limite : déploiement mono-machine ; au-delà de ~100 000 entrées, les perfs baissent.
FAISS, chez Meta, est un classique. C++ pur, vraiment rapide : sur 500 000 entrées, latence stable au milliseconde. C’est surtout une librairie de recherche, pas une base complète — stockage et fichiers d’index à gérer vous-même. Pour les bidouilleurs ou les besoins extrêmes de perf.
Milvus vise la production : distribué, persistance, plusieurs types d’index, offre cloud (Zilliz Cloud). Configuration et coût plus lourds. Millions d’entrées, haute dispo, équipe : là, ça vaut l’investissement.
Ma règle : perso / prototypage → ChromaDB, vite opérationnel ; recherche perf → FAISS ; production → Milvus ou cloud. Ne comptez pas migrer ChromaDB → Milvus sans douleur : formats et API diffèrent.
RAG complet : mise en œuvre
Moins de théorie, plus de code. Voici un RAG local de bout en bout : PDF → recherche sémantique, avec Ollama + ChromaDB.
Préparation de l’environnement
Dépendances :
pip install ollama chromadb langchain langchain-community pypdf
Ollama doit tourner, modèles téléchargés :
ollama pull mxbai-embed-large
ollama pull qwen2.5:7b # pour générer les réponses
Code
import ollama
from langchain_community.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
import chromadb
# 1. Charger le PDF
loader = PyPDFLoader("./your_document.pdf")
docs = loader.load()
# 2. Découpage — chunk trop grand : recherche imprécise ; trop petit : perte d'info
splitter = RecursiveCharacterTextSplitter(
chunk_size=800, # 800 caractères par bloc
chunk_overlap=100, # 100 caractères de chevauchement
)
chunks = splitter.split_documents(docs)
# 3. Embeddings Ollama + stockage ChromaDB
client = chromadb.Client()
collection = client.create_collection("my_docs")
for i, chunk in enumerate(chunks):
response = ollama.embed(
model="mxbai-embed-large",
input=chunk.page_content,
)
embedding = response["embeddings"][0]
collection.add(
ids=[str(i)],
embeddings=[embedding],
documents=[chunk.page_content],
metadatas=[{"source": chunk.metadata.get("source", "unknown")}],
)
print(f"Indexé : {len(chunks)} fragments")
# 4. Recherche sémantique
query = "Quels sont les mécanismes de tolérance aux pannes des systèmes distribués ?"
query_embedding = ollama.embed(
model="mxbai-embed-large",
input=query,
)["embeddings"][0]
results = collection.query(
query_embeddings=[query_embedding],
n_results=3,
)
# 5. Réponse à partir du contexte récupéré
context = "\n\n".join(results["documents"][0])
response = ollama.chat(
model="qwen2.5:7b",
messages=[
{
"role": "system",
"content": "Répondez à partir du contenu documentaire ci-dessous. Si l'information manque, dites-le clairement.",
},
{"role": "user", "content": f"Contenu : {context}\n\nQuestion : {query}"},
],
)
print(f"Réponse : {response['message']['content']}")
Lancez le script. Le flux reste linéaire : découpage → vecteurs → base → requête → réponse.
Pièges fréquents :
chunk_size : ne pas le fixer au hasard. À 200 caractères, les extraits sont des miettes, impossibles à assembler. 500-1000 caractères est une zone stable.
Traitement par lots : document volumineux, appels un par un = lent. Regroupez :
# Embeddings par lot — gain net
batch_texts = [chunk.page_content for chunk in chunks[:50]]
batch_embeddings = ollama.embed(
model="mxbai-embed-large",
input=batch_texts,
)["embeddings"]
Seuil de similarité : ChromaDB renvoie n_results entrées, pertinentes ou non. Parfois il faut filtrer :
# Filtrer par distance
results = collection.query(
query_embeddings=[query_embedding],
n_results=10,
)
filtered = [
doc for doc, dist in zip(results["documents"][0], results["distances"][0])
if dist < 0.3
]
À ce stade, vous avez un RAG local. Remplacez le PDF et la requête — le reste tient.
Réglages et bonnes pratiques
Système en place, place à l’optimisation. Quelques paramètres changent tout.
chunk_size :
500-1000 caractères en pratique. Trop petit : sens tronqué, mauvais rapprochement avec la question. Trop grand : bruit, plusieurs sujets dans le même bloc.
Selon le type : docs techniques structurés → découpage par paragraphe ; conversations fragmentées → blocs ~500 caractères. Testez sur vos données — pas de valeur universelle.
Lots pour accélérer :
Un appel par fragment = latence réseau à chaque fois. Lots de 50-100 : plusieurs fois plus rapide. Ne dépassez pas la limite d’entrée du modèle d’embedding.
Seuil de similarité :
Entre 0,7 et 0,85 selon l’exigence. Haut (0,85) : peu de faux positifs, moins de rappel ; bas (0,7) : plus de rappel, plus de bruit. Corpus propre et questions nettes → seuil haut ; questions floues → seuil plus bas.
Conseil : commencez avec 50-100 documents, validez la recherche, puis scalez. Tout indexer avant d’ajuster coûte cher en temps.
Synthèse
L’essentiel :
Modèle selon le cas — généraliste mxbai, long texte nomic, chinois Qwen3. Base : ChromaDB pour démarrer, FAISS si la perf prime, Milvus en production. Le code ci-dessus suffit pour un premier run.
Points forts : local, données maîtrisées ; modèles Ollama gratuits ; ChromaDB simple. Limites : plafond mono-machine, au-delà du million il faut une autre architecture.
Lancez le script avec une cinquantaine de documents, observez qualité de recherche et de réponse, puis étendez. Paramètres au vert, puis volume.
Pour aller plus loin avec LangChain et Ollama (chaînes de dialogue, appels d’outils), voir l’article « Intégration LangChain + Ollama en pratique » — celui-ci couvre la recherche vectorielle ; les deux ensemble dessinent une feuille de route LLM locale complète.
Construire un système RAG local
Mettre en place une recherche vectorielle locale avec Ollama + ChromaDB
⏱️ Estimated time: 30 min
- 1
Step 1: Installer les dépendances et préparer les modèles
Installez les dépendances avec les commandes suivantes :
```bash
pip install ollama chromadb langchain langchain-community pypdf
ollama pull mxbai-embed-large
ollama pull qwen2.5:7b
```
Vérifiez que le service Ollama est démarré. - 2
Step 2: Charger et découper les documents
Chargez le PDF avec PyPDFLoader, découpez avec RecursiveCharacterTextSplitter :
```python
loader = PyPDFLoader("./your_document.pdf")
docs = loader.load()
splitter = RecursiveCharacterTextSplitter(
chunk_size=800,
chunk_overlap=100,
)
chunks = splitter.split_documents(docs)
```
chunk_size conseillé : 500-1000 caractères. - 3
Step 3: Générer les vecteurs et les stocker
Appelez l'API Ollama pour les embeddings, stockez dans ChromaDB :
```python
client = chromadb.Client()
collection = client.create_collection("my_docs")
for i, chunk in enumerate(chunks):
response = ollama.embed(
model="mxbai-embed-large",
input=chunk.page_content,
)
embedding = response["embeddings"][0]
collection.add(
ids=[str(i)],
embeddings=[embedding],
documents=[chunk.page_content],
)
```
Pour de gros volumes, privilégiez le traitement par lots. - 4
Step 4: Recherche sémantique et génération de réponse
Vectorisez la requête, récupérez les documents pertinents, puis générez la réponse avec un LLM :
```python
query_embedding = ollama.embed(
model="mxbai-embed-large",
input=query,
)["embeddings"][0]
results = collection.query(
query_embeddings=[query_embedding],
n_results=3,
)
context = "\n\n".join(results["documents"][0])
response = ollama.chat(
model="qwen2.5:7b",
messages=[
{"role": "system", "content": "Répondez aux questions à partir du contenu du document"},
{"role": "user", "content": f"Document : {context}\nQuestion : {query}"},
],
)
```
Ajustez le seuil de similarité pour filtrer les résultats si besoin.
FAQ
Quel modèle Embedding Ollama choisir ?
• mxbai-embed-large : choix généraliste, résultats stables pour la plupart des scénarios
• nomic-embed-text : longs textes, jusqu'à 8192 tokens
• Qwen3 Embedding : adapté au chinois, sorti en 2026
Testez les trois et retenez ce qui marche le mieux en pratique.
ChromaDB, FAISS ou Milvus — lequel prendre ?
• ChromaDB : idéal pour débuter, zéro config, adapté à moins de 100 000 entrées
• FAISS : performance maximale en mono-machine, jusqu'à un million, stockage à gérer soi-même
• Milvus : production, déploiement distribué, millions d'entrées et plus
Projets perso : ChromaDB ; production : Milvus.
Quelle taille pour chunk_size ?
Comment accélérer la génération d'embeddings ?
Quel seuil de similarité utiliser ?
Quels avantages et inconvénients d'un RAG local ?
Inconvénients : performance limitée sur une seule machine, au-delà du million d'entrées il faut monter en gamme, maintenance des services à votre charge.
7 min de lecture · Publié le: 8 avr. 2026 · Mis à jour le: 30 juil. 2026
Guide Ollama LLM local
Si vous arrivez depuis la recherche, le plus rapide est de passer à l’article précédent ou suivant de cette série.
Précédent
Intégration LangChain + Ollama : guide complet pour développer des applications LLM en local
Méthode complète d'intégration LangChain et Ollama avec exemples de code pour Chat, RAG et Agent, stratégies de bascule OpenAI/Ollama, pour construire des applications LLM de niveau entreprise avec des modèles locaux.
Partie 14 sur 18
Suivant
Quantification de modèles Ollama : format GGUF et perte de précision expliqués
Principes de la quantification GGUF dans Ollama, données Red Hat sur 500K+ évaluations pour mesurer la perte de précision, et recommandations par configuration matérielle pour exécuter de grands modèles sur GPU grand public.
Partie 16 sur 18



Commentaires
Connectez-vous avec GitHub pour laisser un commentaire