Beaucoup de développeurs cherchant à bâtir un assistant documentaire ou une base de connaissances avec DeepSeek se demandent comment obtenir les embeddings de leurs textes via l’API. La requête “DeepSeek embeddings” est fréquente, mais mène souvent à de la confusion. En effet, contrairement à OpenAI qui propose un endpoint dédié (/embeddings avec text-embedding-ada-002 par ex.), DeepSeek n’affiche aucun endpoint public pour générer des embeddings vectoriels dans sa documentation officielle. Cela ne signifie pas qu’on ne peut pas utiliser DeepSeek pour du Retrieval-Augmented Generation – bien au contraire –, mais il faut comprendre quel rôle joue (ou ne joue pas) l’API DeepSeek dans un pipeline de ce type.
DeepSeek est une plateforme de modèles de langage axée sur le reasoning (raisonnement pas à pas) et les grandes fenêtres de contexte. Son API imite celle d’OpenAI, notamment pour les chat-completions. Les deux modèles mis en avant sont deepseek-chat (mode non-thinking) et deepseek-reasoner (mode thinking avec chaîne de pensées), correspondant tous deux à la version DeepSeek-V3.2 en API cloud. Ces modèles acceptent un contexte allant jusqu’à 128 000 tokens, ce qui est précieux pour inclure de larges extraits de documents dans vos requêtes. En revanche, la documentation ne mentionne nulle part un modèle d’embedding ni une route REST type /v1/embeddings – de quoi dérouter ceux qui cherchent à indexer leurs documents avec DeepSeek.
Mais ne vous fiez pas aux tutoriels trop génériques ou aux rumeurs ! Certains articles peu spécialisés laissent entendre que “DeepSeek fait tout en natif” ou suggèrent d’utiliser le LLM DeepSeek lui-même pour vectoriser des documents. C’est inexact. DeepSeek n’est pas conçu (pour l’instant) pour produire des embeddings de haute qualité semantique. D’ailleurs, même le modèle open-source DeepSeek-R1 (orchestré via vLLM) s’est avéré peu performant pour la recherche sémantique comparé à un modèle d’embeddings dédié. La bonne approche consiste donc à dissocier la vectorisation et la génération : on utilise un modèle spécialisé pour créer les vecteurs (étape retrieval) et on réserve DeepSeek à son point fort, la génération de réponse contextuelle (étape generation).
Avant de plonger dans l’implémentation, clarifions ce que l’API DeepSeek offre officiellement et ce qu’elle ne propose pas, afin de construire notre solution en toute transparence (et éviter les “bulles” marketing).
Ce que propose officiellement l’API DeepSeek
La documentation officielle de DeepSeek présente avant tout une API conversationnelle compatible avec le format OpenAI. Concrètement, on envoie une requête HTTP à l’endpoint /chat/completions avec une liste de messages (system, user, assistant) et le modèle choisi, puis on reçoit une réponse générée par le modèle. Une requête minimale ressemble à ceci :
POST https://api.deepseek.com/chat/completions
Authorization: Bearer DEEPSEEK_API_KEY
Content-Type: application/json{
"model": "deepseek-chat",
"messages": [
{"role": "system", "content": "Vous êtes un assistant utile."},
{"role": "user", "content": "Bonjour !"}
]
}
Cette compatibilité est suffisamment proche de l’API OpenAI pour permettre la réutilisation du SDK officiel OpenAI en changeant simplement l’URL de base. En Python, on peut par exemple écrire :
import os
from openai import OpenAIclient = OpenAI(
api_key=os.environ["DEEPSEEK_API_KEY"],
base_url="https://api.deepseek.com",
)response = client.chat.completions.create(
model="deepseek-chat",
messages=[
{"role": "system", "content": "Vous êtes un assistant utile."},
{"role": "user", "content": "Bonjour !"},
],
stream=False,
)print(response.choices[0].message.content)
les identifiants publics principaux sont deepseek-chat et deepseek-reasoner. D’après le change log officiel, ces deux identifiants ont été mis à jour vers DeepSeek-V3.2 : deepseek-chat correspond au mode non-thinking, tandis que deepseek-reasoner correspond au mode thinking. Les deux variantes partagent une fenêtre de contexte de 128K tokens, ce qui les rend adaptées à des usages exigeants comme l’analyse de documents longs, la synthèse multi-sources ou les pipelines RAG.
En plus du chat, l’écosystème API DeepSeek documente plusieurs fonctionnalités complémentaires. La documentation mentionne notamment le Thinking Mode, le JSON Output, les Tool Calls, le Chat Prefix Completion (Beta), ainsi qu’un endpoint /completions dédié au FIM (Fill-In-the-Middle) Completion en bêta. Il est donc plus précis de parler d’un endpoint FIM spécialisé que d’un simple endpoint de “complétion classique” généraliste.
La documentation publique indique aussi qu’il n’existe pas de rate limit fixe universellement affiché par utilisateur, mais cela ne signifie pas pour autant un débit illimité : des erreurs 429 (requêtes trop rapides) ou 503 (surcharge temporaire) restent possibles selon la charge et les conditions d’usage. Il faut donc présenter l’API comme souple, mais pas comme dépourvue de toute contrainte.
Autre point important : le context caching. DeepSeek documente un mécanisme de cache destiné à réduire les coûts et la latence lorsque plusieurs requêtes partagent un préfixe commun. L’idée n’est pas simplement que “tout texte répété” serait automatiquement réutilisé, mais plutôt que les parties communes en début de prompt peuvent bénéficier du cache. Cela est particulièrement utile dans les scénarios multi-tours, les assistants documentaires, ou les workflows où l’on renvoie souvent le même préambule système ou le même bloc de contexte. Le change log officiel mentionne d’ailleurs explicitement le lancement d’un système de context caching sur disque, présenté comme un moyen de réduire fortement les coûts sur les portions réutilisées.
Récapitulons ce que l’API DeepSeek propose officiellement aujourd’hui :
- un endpoint
/chat/completionscompatible avec le format OpenAI ; - les modèles publics
deepseek-chatetdeepseek-reasoner, actuellement alignés sur DeepSeek-V3.2 ; - une fenêtre de contexte de 128K tokens ;
- des fonctionnalités avancées comme le Thinking Mode, le JSON Output, les Tool Calls, le Chat Prefix Completion (Beta) et le FIM Completion (Beta) ;
- un système de context caching permettant de réduire les coûts sur certaines portions réutilisées du prompt.
En résumé, l’API DeepSeek fournit aujourd’hui la couche de génération, de raisonnement et d’orchestration conversationnelle. En revanche, elle ne documente pas publiquement de brique native de vectorisation sémantique ni de base de connaissances clé en main. Pour construire un pipeline RAG complet, il faut donc associer DeepSeek à une couche externe d’embeddings et de recherche vectorielle.
Ce qui n’est pas (encore) documenté par DeepSeek
Ce que l’on ne trouve pas dans la doc DeepSeek actuelle, c’est tout ce qui concerne la création d’une base de connaissances personnalisée prête à être interrogée. En particulier :
- Pas d’endpoint d’embeddings public : L’API DeepSeek ne mentionne aucun modèle du type
deepseek-embeddingaccessible via une route officielle. Contrairement à l’API OpenAI où l’on peut fairePOST /v1/embeddingsavec un modèle comme Ada-002, rien de tel n’est documenté côté DeepSeek (ni sur la page des modèles disponibles ni dans le changelog). À ce jour, la documentation publique de DeepSeek ne liste aucun modèle d’embedding ni endpoint/embeddings. Sauf annonce officielle ultérieure, il faut donc considérer que la vectorisation sémantique doit être assurée par un modèle d’embedding externe. Il est possible que DeepSeek travaille sur un tel endpoint ou le propose à titre privé, on doit considérer qu’il n’y a pas d’API d’embedding DeepSeek publique. - Pas de recherche vectorielle intégrée côté serveur : DeepSeek ne fournit pas de solution clé en main pour ingérer votre corpus et y effectuer des recherches sémantiques côté cloud. Pas de base de connaissances prête à indexer (contrairement par exemple à certaines solutions style Azure Cognitive Search ou à des “ChatGPT Retrieval Plugin”). C’est à vous de mettre en place votre base vectorielle ou votre index de similarité, sur vos infrastructures ou via un service tiers.
- À ce jour, la documentation publique de l’API DeepSeek ne documente pas d’endpoint de fine-tuning pour les clients: À ce jour, DeepSeek n’annonce pas de mécanisme de fine-tuning (ré-entraînement) personnalisé de ses modèles sur les données d’un client. Le focus est mis sur le zero-shot et les capacités du modèle pré-entraîné (avec RLHF et cie) à suivre les instructions et à raisonner. Donc, inutile de chercher un “DeepSeek fine-tune” dans la doc, ce n’est pas accessible publiquement. En pratique, ce n’est pas un problème pour construire une base de connaissances : l’approche RAG justement évite d’avoir à fine-tuner le LLM, en lui fournissant les connaissances sous forme de contexte au moment de la requête.
En résumé, DeepSeek n’apporte pas nativement la brique de vectorisation sémantique. Il faut la combiner avec un ou plusieurs outils externes pour obtenir la solution complète. Mais la bonne nouvelle, c’est que DeepSeek est hautement compatible avec ces outils : son API accepte des prompts très longs, ce qui la rend idéale pour injecter du contenu de documents en entrée (bien plus qu’avec des modèles à contexte limité). On va donc pouvoir bâtir un pipeline sans couture où chaque composant fait ce qu’il sait faire le mieux : la recherche vectorielle trouve les passages pertinents, et DeepSeek formule la réponse finale de façon fluide et argumentée.
Ce que beaucoup d’articles racontent à tort…
Ce que beaucoup d’articles racontent à tort : On trouve sur le web des tutoriels simplistes suggérant que “DeepSeek offre aussi des embeddings, il suffit de les demander” ou qu’il existerait un endpoint caché pour vectoriser du texte avec DeepSeek. C’est faux – du moins publiquement. D’autres contenus affirment qu’on peut utiliser directement le grand modèle DeepSeek pour faire de la recherche sémantique (e.g. en faisant une question du genre « quel document correspond le mieux à … » sans pipeline dédié). C’est méconnaître le fonctionnement des LLM : un modèle comme DeepSeek-R1 ou V3 n’a pas été entraîné pour émettre des embeddings cohérents sur la similitude de documents. Au contraire, des tests ont montré que les vecteurs produits par R1 sur des textes juridiques, par exemple, donnaient des résultats de recherche très faibles par rapport à un modèle d’embedding calibré (ici Qwen-7B). Bref, il ne faut pas demander à DeepSeek ce pour quoi il n’est pas fait : utilisons-le pour la génération et le raisonnement, et déléguons la sémantique à un modèle spécialisé. De même, attention aux articles qui survolent l’implémentation : construire un assistant RAG robuste nécessite plus que quelques lignes de code copiées-collées. Dans la suite, nous adopterons un angle honnête et pratique, sans minimiser le travail d’ingestion/structuration des données ni promettre des “QA bots magiques en 5 minutes” qui, en réalité, ne tiendraient pas la route en production.
Architecture recommandée aujourd’hui avec DeepSeek
Pour construire une base de connaissances pilotée par DeepSeek, nous allons articuler plusieurs composantes distinctes. C’est l’architecture RAG classique, adaptée au cas particulier de DeepSeek (grande fenêtre contextuelle, pas d’embedding natif). Voici un aperçu de la solution complète :
- Ingestion & préparation des documents : Récupérez les sources (PDF, pages web, Markdown, etc.), extrayez le texte brut et nettoyez les contenus (enlever le HTML, caractères spéciaux, etc.).
- Découpage en chunks de texte : Segmentez chaque document en fragments de taille raisonnable (quelques centaines de mots) avec éventuel chevauchement pour ne pas perdre de contexte entre segments.
- Vectorisation (embeddings) : Utilisez un modèle d’embedding externe (open-source ou API tierce) pour convertir chaque chunk de texte en un vecteur numérique (typiquement 384 à 1536 dimensions).
- Base vectorielle : Stockez ces vecteurs dans une base conçue pour la similarité (FAISS, Chroma, Weaviate, Qdrant, pgvector, etc.), en les liant à des métadonnées (texte original du chunk, source, titre, etc.).
- Recherche sémantique (retrieval) : Lorsqu’une question utilisateur arrive, vectorisez la question avec le même modèle d’embedding, puis utilisez la base vectorielle pour trouver les k vecteurs de documents les plus similaires (ce sont les passages les plus susceptibles de contenir la réponse).
- Construction du prompt et appel DeepSeek : Formez un prompt de requête pour DeepSeek en incluant les extraits de documents récupérés (par ex. dans le message système ou utilisateur) + la question de l’utilisateur. Appelez l’API DeepSeek (modèle chat ou reasoner) en passant ce prompt.
- Réponse et post-traitement : DeepSeek génère la réponse en langage naturel en s’appuyant sur le contexte fourni. Vous pouvez ensuite post-traiter cette réponse (formatage, ajout de références, etc.) avant de la renvoyer à l’utilisateur final.
- Évaluation continue : Surveillez la qualité des réponses, identifiez les cas d’échec, ajustez les paramètres (taille des chunks, modèles d’embedding alternatifs, réglages du prompt) et enrichissez/mettre à jour la base de connaissances au fil du temps.
Cette architecture peut sembler complexe, mais elle est modulaire. Chaque couche peut être améliorée indépendamment, et de nombreux outils open-source existent pour chacune. Passons en revue chaque étape plus en détail pour bien comprendre les choix à faire.
Ingestion et préparation des documents
La première étape consiste à ingérer vos données. Cela peut être : des manuels PDF, une base de tickets de support, la FAQ de votre produit, des pages web de documentation, etc. On parle ici de collecter le contenu brut et de le préparer.
- Extraction du texte brut : Utilisez des outils adaptés à vos formats (par ex.
pdfplumberouPyMuPDFpour PDF, un parser HTML pour les pages web, etc.). Veillez à récupérer le contenu textuel dans le bon ordre (par exemple, éviter de mélanger des colonnes ou des notes de bas de page dans un PDF multi-colonnes). - Nettoyage : Supprimez les éléments non pertinents : code HTML, balises Markdown, scripts, styles, texte caché, etc. Normalisez les espaces, corrigez éventuellement les caractères encodés bizarrement. Une bonne pratique est de convertir tout en texte UTF-8 sans mise en forme, et de garder une version “propre” du contenu.
- Segmentation initiale : Si vos documents sont très volumineux, il peut être judicieux de les segmenter en sections logiques avant même le chunking algorithmique. Par exemple, séparer un livre blanc par chapitres, ou un guide par sections H2/H3, etc. Cela permettra souvent de préserver des séparations logiques utiles (et d’attacher des métadonnées de section).
- Métadonnées de document : Profitez de l’ingestion pour stocker quelques infos de contexte : le titre du document, l’auteur, la date, la source (URL ou chemin de fichier), etc. Ces métadonnées pourront être utilisées plus tard pour filtrer ou pour être incluses en référence dans la réponse (ex. “d’après le Guide utilisateur.pdf de 2021…”).
Exemple : Supposons qu’on veuille intégrer la FAQ d’un produit SaaS, une base de connaissances interne Confluence, et la politique RH de l’entreprise. On va extraire le texte de la page FAQ HTML, exporter les articles Confluence en Markdown, récupérer le PDF de la politique RH, et passer tout cela dans des extracteurs pour obtenir du texte brut. On supprimera les gabarits communs (menu de navigation, pied de page répété) pour ne garder que le contenu utile. Chaque document (FAQ, doc interne, politique) sera traité séparément à ce stade.
Découpage en fragments (chunking)
Une fois qu’on a le texte de nos documents, il faut les découper en fragments de taille adaptée à la fois à la recherche vectorielle et à la génération finale. Si un chunk est trop gros, il diluera la pertinence (et risque de dépasser la fenêtre utile même si DeepSeek peut avaler 128k tokens). S’il est trop petit, on perdra du contexte et il faudra en assembler trop à la génération. Il s’agit donc de trouver le juste milieu.
- Taille de chunk recommandée : Bien que DeepSeek supporte de très longs prompts, on obtient souvent de meilleurs résultats en chunkant aux alentours de 300 à 800 mots (disons 1000 à 2000 caractères) par fragment. Cela correspond à quelques paragraphes ou une sous-section. Dans nos tests, des chunks ~500 mots offrent un bon équilibre : assez d’information pour contenir une idée complète, mais pas au point d’injecter plein de matière hors sujet.
- Chevauchement (overlap) : Introduire un léger chevauchement (par ex. répéter 1-2 phrases ou 20% de contenu entre la fin d’un chunk et le début du suivant) peut aider à ne pas “casser” une idée en deux chunks sans lien. Cependant, évitez un overlap trop grand qui ferait quasi dupliquer tout le texte (coût mémoire inutile et possible confusion lors de la recherche). Un overlap de ~50 mots ou la phrase de transition est un bon compromis.
- Basé sur la structure : Idéalement, coupez aux frontières logiques : fin de phrase, changement de section, etc. Par exemple, évitez de couper en plein milieu d’une phrase ou d’une liste à puces. Si vos documents ont une structure (titres, sections), essayez de l’exploiter. On peut par exemple décider qu’un chunk correspond à une section H2 complète si elle n’est pas trop longue, sinon on la coupera en plusieurs morceaux.
- Indexation des chunks : Conservez l’information permettant de remonter du chunk au document source et à sa position. Par exemple, stockez pour chaque chunk un identifiant de document et éventuellement un identifiant de section/page. Ainsi, si plus tard vous voulez afficher la réponse avec un lien “voir dans le document original”, vous saurez reconstruire cette trace.
Exemple : Notre FAQ produit fait 5000 mots, on peut la chunker en ~10 fragments de ~500 mots (en suivant les questions : idéalement un Q/R par chunk si chaque réponse fait quelques paragraphes). La doc interne Confluence est très longue (20k mots), on la découpera par grandes sections (chaque article ou page séparé), puis chaque page en 2-3 chunks si nécessaire. La politique RH PDF (30 pages) pourrait être découpée par page ou par section thématique (congé, rémunération, etc.). On veillera à inclure les titres de section dans le début du chunk pour le contexte.
Vectorisation : calcul des embeddings
C’est une étape cruciale : il s’agit de transformer chaque chunk de texte en un vecteur numérique représentant son contenu sémantique. Comme l’API publique de DeepSeek ne documente pas de service d’embeddings, il faut combiner DeepSeek pour la génération avec un modèle d’embedding externe pour la phase de retrieval.
Le choix du modèle d’embedding dépend avant tout de votre langue, de votre budget d’inférence, de votre infrastructure et de la taille de votre corpus. Si votre base contient du français, de l’anglais ou plusieurs langues, il est préférable d’opter pour un modèle explicitement multilingue. Par exemple, BAAI/bge-m3 a été conçu comme un modèle multi-fonction, multilingue et multi-granularité, avec prise en charge de plus de 100 langues. De son côté, Qwen3-Embedding-4B est un modèle dédié aux tâches d’embedding et de ranking, supporte lui aussi plus de 100 langues et propose une longueur de contexte de 32K ainsi qu’une dimension de sortie configurable jusqu’à 2560.
La dimension de l’embedding influence directement le stockage, la RAM, la latence et le coût de recherche. En règle générale, des vecteurs plus grands peuvent améliorer la qualité de retrieval, mais ils coûtent plus cher à indexer et à comparer. Il faut donc éviter de choisir un modèle “plus gros” par réflexe. sentence-transformers/paraphrase-multilingual-mpnet-base-v2 reste une base simple et fiable pour prototyper : sa model card indique un espace vectoriel dense de 768 dimensions et un usage adapté à la recherche sémantique. À l’autre extrémité, Snowflake/snowflake-arctic-embed-l-v2.0 vise un retrieval multilingue de haute qualité, fournit des embeddings de 1024 dimensions, prend en charge jusqu’à 8192 tokens de contexte et met fortement l’accent sur la compression vectorielle pour réduire la taille mémoire des index.
Il faut aussi distinguer les modèles réellement entraînés pour la similarité sémantique des LLM génériques utilisés hors contexte. Pour un pipeline RAG, privilégiez des modèles explicitement publiés pour le text embedding, le semantic search ou le ranking. Les modèles de la famille Sentence Transformers, BGE, Arctic Embed ou Qwen3 Embedding entrent dans cette catégorie. En revanche, il vaut mieux éviter de déduire des embeddings à partir des couches internes d’un grand modèle de génération non conçu pour cela : même si cela peut fonctionner en prototype, ce n’est pas l’approche la plus robuste pour un retrieval de production.
Sur le plan du déploiement, deux approches sont possibles. La première consiste à exécuter un modèle open-source localement via Sentence Transformers, Transformers ou un serveur spécialisé comme Text Embeddings Inference (TEI). La seconde consiste à utiliser une API tierce pour les embeddings et à réserver DeepSeek à la génération. Le choix dépendra surtout de votre priorité : confidentialité, simplicité, coûts récurrents ou facilité de montée en charge. Pour un prototype ou un corpus de taille modérée, un modèle open-source local est souvent suffisant. Pour un système à plus grande échelle, il peut être utile de tester plusieurs modèles sur un petit jeu de requêtes réelles afin de mesurer le recall, la pertinence des résultats et la latence avant de figer votre choix.
Exemple concret : pour une première version, on peut choisir sentence-transformers/paraphrase-multilingual-mpnet-base-v2. Ce modèle est facile à charger avec la bibliothèque Sentence Transformers, fonctionne bien en recherche sémantique multilingue, et produit des embeddings de 768 dimensions. Si vous avez 1 000 chunks, vous obtiendrez donc 1 000 vecteurs qu’il faudra ensuite stocker dans un index vectoriel. Pour une qualité plus élevée sur des workloads multilingues exigeants, vous pourrez ensuite comparer ce baseline à des modèles plus récents comme bge-m3, Snowflake Arctic Embed 2.0 ou Qwen3-Embedding.
Enfin, retenez un point simple : la qualité finale de votre assistant dépend énormément de la qualité des embeddings. Il ne faut donc pas choisir un modèle uniquement sur sa popularité ou sa taille. Le bon réflexe consiste à préparer 10 à 20 questions réelles en français, à comparer les passages récupérés par plusieurs modèles, puis à garder celui qui retrouve le plus souvent les bons extraits avec la meilleure latence pour votre cas d’usage.
Stockage dans une base vectorielle
Les vecteurs seuls ne sont pas utiles sans un moyen efficace de rechercher parmi eux. C’est le rôle de la base vectorielle (vector store). Plusieurs options s’offrent à vous :
- FAISS – bibliothèque C++/Python par Meta AI, incontournable pour la similarité de vecteurs en mémoire ou sur disque. Faiss offre des index rapides, y compris approximatifs (HNSW, IVF) pour passer à l’échelle des millions de vecteurs. C’est un excellent choix pour une application auto-hébergée : léger, performant, et open-source. Il faut cependant la gérer dans votre code (FAISS n’est pas un service : c’est une librairie que vous intégrez).
- pgvector – extension PostgreSQL open-source pour le stockage de vecteurs et la recherche k-NN directement dans Postgres. Pratique si vous voulez stocker vecteurs et métadonnées ensemble dans une base relationnelle classique. pgvector supporte la recherche exacte et approximative, avec l’avantage de s’appuyer sur l’écosystème Postgres (transactions ACID, sauvegardes, etc.). En contrepartie, la performance brute peut être un peu en deçà de solutions spécialisées pour de très grands volumes, et il faut maintenir un Postgres.
- Vector DB “full service” – ex: Chroma, Qdrant, Weaviate, Milvus, Pinecone, etc. Ce sont des bases vectorielles dédiées, souvent open-source (sauf Pinecone), avec parfois des fonctionnalités avancées (filtrage par métadonnées, recherche hybride texte+vecteur, etc.). Elles peuvent être déployées en self-hosted ou utilisées via un cloud. Par exemple, ChromaDB est très simple à démarrer en local (juste une lib Python) et stocke les vecteurs sur disque; Qdrant offre un service clé en main avec API REST et scaling distribué. Le choix dépendra de vos besoins d’échelle et de vos affinités. Pour un petit projet, une simple instance Chroma ou FAISS suffit. Pour un produit à grande échelle, on pourra se tourner vers Milvus ou Pinecone gérés.
Dans tous les cas, la base vectorielle devra stocker : le vecteur de chaque chunk, un identifiant ou clé, et idéalement les métadonnées associées (source, titre, etc.). On configurera l’index pour la métrique choisie (cosine ou dot-product typiquement – c’est équivalent si les vecteurs sont normalisés). Pour la recherche approximative, il faudra éventuellement paramétrer le nombre de clusters, la profondeur de recherche, etc., mais on peut souvent commencer en recherche brute exacte si le volume n’est pas énorme, puis affiner.
Exemple : On décide d’utiliser FAISS pour notre prototype. On crée un index FAISS IndexFlatIP (produit scalaire simple) et on y ajoute nos 1000 vecteurs. On garde en parallèle un tableau ou un dict {id_chunk: contenu_chunk}. Si on avait utilisé pgvector, on aurait créé une table Postgres avec une colonne de type VECTOR(768) et inséré chaque vecteur avec un identifiant et des métadonnées JSON en plus. L’important est qu’à la fin de cette étape, on peut répondre à la question : « Quels sont les X vecteurs les plus proches du vecteur de la requête ? » et retrouver les chunks correspondants rapidement.
Recherche sémantique des passages pertinents
Lorsque l’utilisateur pose une question, on entre dans la phase retrieval. Cette étape consiste à trouver, parmi tous nos chunks vectorisés, ceux qui sont les plus pertinents par rapport à la question – c’est-à-dire dont l’embedding est le plus proche de l’embedding de la question.
Le processus est le suivant :
- Vectoriser la requête utilisateur avec le même modèle d’embedding que celui utilisé pour les documents. C’est crucial : on reste dans le même espace vectoriel, pour que la similarité ait un sens. On obtient ainsi un vecteur
q_vecreprésentant la question. - Recherche k plus proches voisins (k-NN) dans l’index vectoriel. On interroge notre base vectorielle avec
q_vecpour obtenir, par exemple, les 5 meilleurs chunks (on appelle souvent ce paramètre Top k). La base retourne typiquement les identifiants des chunks classés par distance croissante (ou score de similarité décroissant). Parfois, elle peut aussi retourner le score de similarité, que l’on peut utiliser pour information (par ex, si le meilleur score est très faible, c’est que rien n’est vraiment pertinent). - Récupération des textes bruts correspondants. À partir des identifiants de chunks retournés, on va chercher le texte du chunk original (celui qu’on avait stocké ou dont on a la référence). On obtient ainsi une petite collection de passages de documents qui devraient contenir la réponse ou des indices sur la réponse.
- (Optionnel) Filtrage ou re-ranking : parfois, on peut vouloir affiner ce set de résultats. Par exemple, éliminer un chunk trop générique (en se basant sur des métadonnées type
document_type != "glossary"), ou au contraire booster la diversité des sources (pour éviter d’avoir 5 chunks venant du même document alors qu’un autre document pourrait être pertinent). Des méthodes de re-ranking existent, y compris basées sur un second modèle (ex : utiliser un modèle plus lourd style cross-encoder pour reranker les top 20 résultats). Dans un premier temps, on peut s’en passer et faire confiance à notre recherche vectorielle brute.
Le paramètre k (nombre de passages) à inclure est important à ajuster. Une valeur courante est k = 3 à 5. Moins de 3 risque de louper des éléments de réponse complémentaires (sauf si vos chunks sont gros et couvrent déjà beaucoup de contenu). Plus de 5 commence à injecter beaucoup de texte dans le prompt, possiblement hors sujet, qui peut diluer l’attention du modèle voire l’induire en erreur. Rappelons qu’avec DeepSeek on a de la marge (128k tokens), donc on n’est pas contraint séverement par la taille totale, mais tout de même : mieux vaut fournir juste assez de contexte pertinent. Un bon principe est d’expérimenter : si vous voyez que la réponse manque de certains détails, peut-être augmenter k; si au contraire le modèle se perd ou hallucine, peut-être c’était surchargé inutilement -> diminuer k ou améliorer le tri.
Exemple : L’utilisateur demande : “Quelle est la durée de la période d’essai pour un nouvel employé ?”. Notre pipeline va vectoriser cette question en q_vec (768-dims). La base vectorielle renvoie les 3 chunks les plus proches. Imaginons qu’il s’agisse de : (a) un passage de la politique RH mentionnant la période d’essai de 3 mois, (b) un paragraphe de la FAQ RH qui explique la période d’essai, (c) un segment moins pertinent sur la période de préavis (faux positif). On récupère le texte de (a), (b) et (c). On note que (c) semble hors sujet (“préavis” vs “période d’essai”) – cela peut arriver. On peut choisir de quand même fournir les trois à DeepSeek en espérant qu’il filtrera, ou décider d’écarter (c) manuellement si le score était en fait très faible par rapport aux deux premiers. Pour l’exemple, gardons les 3 en nous disant que DeepSeek, grâce à son raisonnement, fera peut-être le tri.
Génération de la réponse avec DeepSeek
C’est ici que DeepSeek entre réellement en scène dans notre pipeline : la génération de la réponse finale en langage naturel, en s’appuyant sur les documents retrouvés.
Pour cela, on va construire un prompt contenant : la consigne d’utilisation des documents, les documents eux-mêmes (ou un résumé de leur contenu), et la question de l’utilisateur. Ensuite, on appelle l’API DeepSeek chat/completions avec ce prompt, et on obtient la réponse du modèle.
Plusieurs façons de structurer le prompt sont possibles. Voici une approche courante, avec un message système et un message utilisateur :
- Message système : on y indique à l’IA son rôle et comment utiliser le contexte documentaire. Par exemple : “Tu es un assistant d’aide basé sur la documentation suivante. Utilise exclusivement les informations fournies dans les extraits pour formuler ta réponse. S’il manque des données, réponds que tu ne sais pas. Fournis une réponse concise et cite la source de chaque information.” On peut aussi définir le ton (“assistant professionnel et factuel”) et la langue de réponse.
- Insertion du contexte : on peut insérer les passages sous forme d’une liste ou les inclure dans le message système. Exemple dans le système : “Informations disponibles : [Document 1: …] [Document 2: …] …” ou bien les fournir dans le message utilisateur avant la question en disant “Voici des extraits : …”. L’essentiel est que le modèle les voit avant de répondre. Étant donné la longueur potentielle (plusieurs milliers de tokens), on profite de la capacité 128k de DeepSeek, mais il faut tout de même rester organisé et éventuellement numéroter les documents ou indiquer leur source à côté du texte pour que l’IA puisse les référencer.
- Question de l’utilisateur : enfin, on place la question précise de l’utilisateur, soit à la fin du message utilisateur (après le contexte), soit dans un message user séparé qui suit le système+documents.
Concrètement, le prompt final peut ressembler à :
System:
"Vous êtes un assistant qui aide l’utilisateur en se basant sur des documents fournis.
Utilisez uniquement ces documents pour répondre, en citant la source entre parenthèses.
Si l’information n’est pas dans les documents, dites que vous ne savez pas.DOCUMENT 1 (FAQ Produit):
Blabla... (contenu du chunk 1) ... blabla...DOCUMENT 2 (Guide Interne):
... contenu chunk 2 ...DOCUMENT 3 (Politique RH):
... contenu chunk 3 ..."User:
"Question: Quelle est la durée de la période d’essai pour un nouvel employé ?"
Puis on envoie ce dialogue à l’API DeepSeek en spécifiant model: deepseek-chat (ou deepseek-reasoner si on voulait qu’il “pense à voix haute” – pas forcément utile ici).
DeepSeek va alors traiter ce prompt potentiellement très long, et générer une réponse formulée en français, par exemple : “La période d’essai d’un nouvel employé est de 3 mois renouvelable une fois (source : Politique RH, section Contrat d’embauche).”.
Quelques conseils pour cette étape :
- Vérifier la cohérence langue/ton : Si vos documents sont majoritairement en français et la question en français, la réponse sera en français. Mais si vous injectez des extraits en anglais et posez la question en français, l’IA pourra répondre en français en se basant sur le contenu anglais. DeepSeek est multilingue de par son entraînement, mais indiquer explicitement la langue souhaitée dans le système peut aider.
- Rôles spéciaux (developer/tool) : DeepSeek V3.2 a introduit un rôle
developer(réservé aux scénarios agent/tools), mais l’API ne supporte pas de le passer. Donc restez sursystem/user/assistantclassiques. Pas besoin de complexifier avec des rôles outils ici, on fait déjà la recherche nous-mêmes hors LLM. - Tronquer ou synthétiser le contexte : Si les passages sont très longs, on pourrait être tenté de demander au LLM de les résumer avant de répondre. Cependant, dans nos tests, il est souvent plus fiable de donner les passages bruts (ou légèrement abrégés si nécessaire) que de compter sur un résumé automatique avant la réponse – car cela double les risques d’erreur. Étant donné la capacité 128k de DeepSeek, on peut se permettre d’insérer des passages assez conséquents. Néanmoins, inutile d’envoyer 15 pages de texte si la question porte sur un point précis abordé dans 2 paragraphes… D’où l’importance de bien cibler les chunks en amont.
Une fois la réponse générée par DeepSeek, on la retourne à l’utilisateur final dans votre application. Vous pouvez éventuellement y ajouter les références en clair (puisque nous on a la correspondance chunk->source). Par exemple, si l’IA a répondu “(source : Politique RH)”, on pourrait la transformer en un lien cliquable vers le PDF de la politique RH. On peut aussi logguer quels chunks ont été utilisés, pour améliorer le système plus tard si on se rend compte que souvent tel document est choisi alors qu’un autre aurait été plus pertinent, etc.
Évaluation et amélioration continue
Aucun système n’est parfait du premier coup. Il faudra prévoir une phase de tests et probablement plusieurs itérations pour peaufiner votre assistant DeepSeek.
- Jeux de questions de test : Constituez un petit ensemble représentatif de questions auxquelles votre assistant est censé répondre. Idéalement, prenez des questions réelles (FAQ client, demandes support fréquentes) et quelques-unes pointues pour le pousser dans ses retranchements. Utilisez ces questions pour valider que les bons documents sont retrouvés et que les réponses sont correctes.
- Vérifier les sources dans les réponses : Un bon assistant documentaire doit citer ses sources ou au moins ne pas inventer. Vérifiez que DeepSeek ne sort pas d’informations non présentes dans les extraits fournis. Si vous constatez des hallucinations, essayez de durcir le prompt (e.g. “si ce n’est pas dans les documents, ne pas inventer”). Vous pouvez aussi réduire le temperature du modèle (mettre
temperature: 0pour qu’il soit plus déterministe et collé aux faits). DeepSeek est déjà plutôt orienté “raisonnement factuel”, mais avec temperature trop haut (>1.0) il peut parfois broder. - Instrumentation : Enregistrez les requêtes et les réponses, ainsi que les passages choisis. Cela vous permettra d’analyser où ça ne va pas. Par exemple, si un utilisateur pose une question légitime et que l’assistant répond “Je ne sais pas”, inspectez : est-ce parce que le chunk pertinent n’a pas été sélectionné ? Ou bien le chunk était là mais l’IA ne l’a pas utilisé correctement ? Selon le cas, la solution diffère (améliorer les embeddings vs améliorer le prompt).
- Feedback utilisateurs : Si possible, intégrez un moyen pour l’utilisateur final de signaler une réponse incorrecte ou insatisfaisante. C’est précieux pour repérer des lacunes du système. Par exemple, peut-être qu’un document important manque dans la base, ou qu’une définition n’est pas trouvée car formulée différemment dans le texte (synonymes). Vous pourrez alors étoffer la base de connaissances ou ajouter des alias.
- Mises à jour du corpus : N’oubliez pas que la connaissance évolue. Mettez à jour régulièrement vos documents (et re-calculez leurs embeddings). Vous pouvez soit tout reconstruire périodiquement, soit mettre en place une ingestion continue (ex : dès qu’un nouvel article est publié, calculer son embedding et l’insérer dans la base vectorielle). Veillez aussi à retirer/archiver les données obsolètes pour ne pas qu’elles faussent les réponses.
- Scalabilité : Si votre base passe de 1000 à 1 million de documents, il faudra adapter certaines composantes. Par exemple, passer à un index vectoriel approximatif (FAISS IVF/HNSW) pour accélérer les requêtes, ou opter pour une base distribuée (Milvus) et dimensionner les ressources. De même, surveillez la consommation de l’API DeepSeek (coût des tokens) et utilisez le caching contextuel autant que possible pour économiser.
L’objectif est qu’au fil du temps, votre assistant devienne de plus en plus fiable, couvrant un maximum de questions avec des réponses précises et justifiées. DeepSeek, grâce à son mode raisonneur et sa capacité de synthèse, peut même fournir des réponses assez élaborées en combinant plusieurs sources, ce qui apporte une vraie valeur ajoutée par rapport à une simple recherche documentaire traditionnelle.
Quels embeddings pour un corpus francophone ?
Arrêtons-nous un instant sur le choix du modèle d’embedding dans le cas spécifique d’un corpus en français (ou multilingue contenant du français). C’est un point crucial, et souvent source de questions.
En 2026, la plupart des meilleurs modèles d’embeddings sont multilingues, c’est-à-dire qu’ils ont été entraînés sur de nombreuses langues (typiquement anglais, français, espagnol, allemand, chinois, etc.) et parviennent à projeter des phrases de différentes langues dans un espace vectoriel commun. Cela signifie, par exemple, qu’une question en français peut être trouvée similaire à un paragraphe en anglais traitant du même sujet. Cette propriété est très utile pour des bases de connaissances bilingues ou pour utiliser un modèle d’embedding entraîné majoritairement sur de l’anglais (car il comprendra suffisamment le français).
Voici quelques modèles/populations de modèles à considérer :
- Sentence Transformers (SBERT) : Ce sont des modèles dérivés de BERT/RoBERTa/MPNet fine-tunés pour la tâche de similarité de phrases. Par exemple, distiluse-base-multilingual-cased-v2 était un classique pour le français. Aujourd’hui, des variantes plus récentes comme all-MiniLM-L12-multilingual ou paraphrase-multilingual-mpnet offrent de bonnes performances en étant compactes. SBERT a l’avantage de la simplicité (chargement via
sentence_transformersen deux lignes) et d’un large choix sur HuggingFace. - BGE (Beijing Generative Encoder) : La famille BGE-M mentionnée plus haut est intéressante car elle unifie dense & sparse embeddings et supporte plus de 100 langues. Le modèle bge-m3-base par exemple est un bon candidat pour un corpus multi-thématique car il combine des signaux lexicaux et sémantiques.
- GTE / Qwen : Alibaba a sorti plusieurs modèles GTE (Generic Text Embedding) dont le Qwen-7B-Embedding qui a dominé les benchmarks en 2025. C’est un modèle plus lourd (7 milliards de paramètres) qui fonctionne comme un mini-LLM optimisé pour les embeddings. Il offre d’excellents résultats, mais nécessite des ressources GPU plus costaudes pour l’inférence. Si la qualité prime et que vous pouvez déployer un tel modèle (ou utiliser une API la proposant), ça peut valoir le coup.
- Modèles spécialisés domaine : Si votre base de connaissances est très ciblée (domaine médical, juridique, code source, etc.), il existe des embeddings spécialisés. Par ex, LegalBERT-Sentence ou d’autres modèles entraînés sur des textes juridiques pourraient mieux capter le jargon légal. Idem en technique (il y a des modèles d’embedding pour du code ou des doc API). Cependant, attention : souvent un bon modèle généraliste reste performant, et en multilingue certains domaines non-anglais sont moins bien couverts. Vous pourriez envisager de fine-tuner un modèle sur vos données (ça se fait pour les embeddings aussi, en le spécialisant via du contrastive learning sur votre corpus), mais ce n’est pas trivial et rarement nécessaire si le modèle de base est bon.
- Taille vs performance : Les progrès récents montrent que même des modèles compacts (~100M de paramètres) peuvent approcher la performance de gros modèles pour les embeddings, grâce à des techniques de distillation. Par exemple, GTE-base (~300M) ou Jina Embeddings V3 (basé sur XLM-R) offrent un très bon compromis. Donc inutilement prendre un modèle énorme si un plus petit fait quasiment aussi bien – vos inférences n’en seront que plus rapides et faciles à scaler.
En pratique, pour un corpus francophone généraliste, un modèle multilingue grand public fera très bien l’affaire. Comparez sur 5-10 questions test : est-ce que les bons passages ressortent dans le top 3 ? Si oui, la différence de performance de l’un à l’autre sera sans doute minime pour votre usage.
Enfin, n’oublions pas la possibilité d’utiliser une API d’embedding tierce. Si vous avez déjà un compte OpenAI, leur modèle Ada-002 fonctionne très bien en français (il a appris suffisamment de multilingue). Cohere également propose des embeddings multilingues. Cela peut être un raccourci pour démarrer, quitte à remplacer plus tard par un modèle open-source si vous voulez vous affranchir des appels externes. Pensez juste à la latence : appeler deux API (embedding puis DeepSeek) ajoutera quelques centaines de ms chacune, vs tout faire en local potentiellement plus rapidement. Selon votre application (synchronisme de la réponse), ça peut compter.
Exemple d’implémentation RAG simple (Python)
Pour donner vie à tout cela, rien de tel qu’un petit exemple concret en Python. Imaginons que nous ayons un répertoire documents/ avec quelques fichiers texte (ou HTML, peu importe, déjà extraits pour simplifier). Nous allons :
- Indexation initiale : lire les fichiers, les chunker, calculer les embeddings avec un modèle HuggingFace, puis construire un index vectoriel FAISS.
- Traitement de requête : écrire une fonction qui prend une question utilisateur, effectue la recherche vectorielle dans FAISS, puis envoie le prompt à DeepSeek et renvoie la réponse.
Cet exemple est simplifié (pas de nettoyage poussé ni de multi-doc complexes), mais servira de base de départ.
Vectorisation des documents et indexation
from sentence_transformers import SentenceTransformer
import faiss
import numpy as np
import os
# 1) Charger le modèle d'embedding (modèle multilingue SBERT)
model = SentenceTransformer("sentence-transformers/paraphrase-multilingual-mpnet-base-v2")
# 2) Lire et chunker les documents
chunks = [] # liste de dicts: {id, text, source}
chunk_size_words = 500 # ~500 mots
overlap_words = 50 # ~50 mots de chevauchement
documents_dir = "documents"
for filename in os.listdir(documents_dir):
filepath = os.path.join(documents_dir, filename)
# Ignorer les dossiers
if not os.path.isfile(filepath):
continue
with open(filepath, "r", encoding="utf-8") as f:
text = f.read().strip()
if not text:
continue
# Découpage naïf par mots
words = text.split()
start = 0
while start < len(words):
end = min(len(words), start + chunk_size_words)
chunk_text = " ".join(words[start:end]).strip()
if chunk_text:
chunks.append({
"id": len(chunks),
"text": chunk_text,
"source": filename
})
if end == len(words):
break
start += chunk_size_words - overlap_words
# 3) Calculer les embeddings de tous les chunks
texts = [c["text"] for c in chunks]
embeddings = model.encode(
texts,
batch_size=16,
show_progress_bar=True,
normalize_embeddings=True, # important pour similarité type cosine
convert_to_numpy=True
)
# Conversion en float32 (recommandé pour FAISS)
embeddings = embeddings.astype("float32")
dim = embeddings.shape[1]
# 4) Construire l'index vectoriel FAISS
index = faiss.IndexFlatIP(dim) # produit scalaire (équivalent cosine si normalisé)
index.add(embeddings)
print(f"{index.ntotal} embeddings indexed in FAISS.")
Explications
On utilise SentenceTransformer.encode pour vectoriser en batch la liste des textes de chunks. Le modèle paraphrase-multilingual-mpnet-base-v2 produit des embeddings de dimension 768, adaptés à des tâches de similarité sémantique multilingue.
Les embeddings sont normalisés (normalize_embeddings=True) afin que le produit scalaire utilisé par FAISS (IndexFlatIP) corresponde à une similarité de type cosine. Cette étape est essentielle pour obtenir des résultats pertinents lors de la recherche.
On convertit explicitement les embeddings en float32, car FAISS est optimisé pour ce type de données et peut produire des résultats incorrects ou inefficaces avec d’autres formats.
On crée ensuite un index FAISS de type IndexFlatIP, qui effectue une recherche exacte basée sur le produit scalaire. Ce type d’index est parfaitement adapté pour des volumes modestes (quelques milliers à dizaines de milliers de chunks). Pour des volumes plus importants, on pourra envisager des index approximatifs comme HNSW ou IVF.
Enfin, on ajoute tous les vecteurs d’un coup avec index.add. Chaque vecteur correspond à un chunk de texte stocké dans la liste chunks, ce qui permet ensuite de retrouver facilement le contenu original lors de la phase de recherche.
Après cette étape, il est recommandé de sauvegarder l’index FAISS sur disque (faiss.write_index) ainsi que la liste des chunks (par exemple en JSON). Cela permet d’éviter de recalculer les embeddings à chaque redémarrage de l’application et d’accélérer considérablement le chargement du système.
Requête de l’utilisateur et construction du prompt
Maintenant, implémentons la fonction de requête :
from openai import OpenAI
# Client DeepSeek officiel via SDK OpenAI-compatible
client = OpenAI(
api_key="votre_cle_api_deepseek",
base_url="https://api.deepseek.com",
)
def answer_question(query, top_k=3):
# 1. Encoder la question en embedding
# Remarque : cette étape reste externe à DeepSeek si vous utilisez
# un modèle d'embedding séparé + un index vectoriel (FAISS, etc.)
q_vec = model.encode([query]) # shape: (1, dim)
# 2. Recherche des k plus proches voisins
D, I = index.search(q_vec, top_k)
retrieved_chunks = [chunks[idx] for idx in I[0] if idx != -1]
# 3. Construire le contexte documentaire
docs_content = ""
for i, chunk in enumerate(retrieved_chunks, start=1):
source = chunk.get("source", f"source_{i}")
text = chunk.get("text", "")
docs_content += f"\n[Document {i} - {source}]\n{text}\n"
system_prompt = (
"Tu es un assistant de question-réponse basé sur des documents.\n"
"Réponds uniquement à partir des documents fournis ci-dessous.\n"
"Si l'information n'est pas présente, dis clairement que la réponse "
"n'est pas disponible dans les documents.\n"
"Cite les documents utilisés sous la forme [Document X].\n\n"
f"Documents fournis :{docs_content}"
)
messages = [
{"role": "system", "content": system_prompt},
{"role": "user", "content": query},
]
# 4. Appel API DeepSeek
response = client.chat.completions.create(
model="deepseek-chat",
messages=messages,
temperature=0.0,
)
answer = response.choices[0].message.content
return answer, retrieved_chunks
# Exemple
question = "Quelle est la durée de la période d'essai pour un nouvel employé chez nous ?"
answer, docs_used = answer_question(question)
print("Réponse de l'IA:\n", answer)
Dans ce code :
- On utilise le même modèle d’embedding pour encoder la question.
- On interroge l’index FAISS avec
index.search. Cela nous donne les indices destop_kchunks les plus similaires (et les scores D qu’on n’utilise pas ici, mais on pourrait). - On récupère le texte de ces chunks et on forme une variable
docs_contentqui liste les documents trouvés, chacun précédé d’un label[Document i - NomDuFichier]. Ce format est arbitraire mais aide le modèle à contextualiser et à citer. - On construit le
system_prompten donnant les consignes (utiliser ces documents, citer les sources) et on insère les documents. On place ensuite la question utilisateur telle quelle. - On appelle
openai.ChatCompletion.createqui en réalité va faire un appel à l’API DeepSeek (puisqu’on a redéfiniapi_base). On fixetemperature=0pour favoriser une réponse déterministe et factuelle. On obtient la réponse et on la retourne.
Cet exemple simplifié illustre le pipeline complet. En pratique, vous voudrez sans doute améliorer le format des sources (par ex, ne pas mettre tout le texte du chunk s’il est très long mais plutôt un résumé ou juste les phrases pertinentes contenant le mot-clé – cela peut se faire en prétraitant le chunk ou en highlightant). Vous pourriez aussi vouloir post-traiter la réponse pour ajouter manuellement les références sous forme de liens. Mais l’essentiel est là : la mécanique RAG fonctionne.
Exemple de prompt DeepSeek avec contexte documentaire
Pour bien montrer comment le prompt DeepSeek peut être construit, prenons un exemple concret avec du contenu fictif.
Supposons les documents suivants dans notre base :
- Document 1 (FAQ produit) : contient la question “Quelle est la durée de la garantie de ce produit ?” avec la réponse “La garantie est de 2 ans pièces et main d’œuvre.”
- Document 2 (Guide interne technique) : paragraphe sur les versions supportées d’un logiciel.
- Document 3 (Politique RH) : mentionne “La période d’essai standard est de 3 mois renouvelable une fois.”
Et la question utilisateur est : “Combien de temps dure la période d’essai pour un nouvel employé ?”.
Imaginons que la recherche vectorielle ait bien renvoyé : le chunk contenant « période d’essai standard 3 mois…« , un autre chunk peut-être d’un FAQ RH, et éventuellement un chunk hors sujet. On va construire le prompt. Cela pourrait donner (en français dans le texte) :
Système :
Vous êtes un assistant expert des ressources humaines qui aide l’utilisateur en se basant sur des documents fournis.
Utilisez uniquement les informations pertinentes des documents pour formuler votre réponse. Si une information n’est pas présente dans ces documents, dites "Je ne sais pas".
Citez entre parenthèses la source de chaque information que vous donnez (Document 1, Document 2, ...).Documents :
[Document 1 - FAQ RH]
Q: Quelle est la durée de la période d'essai pour un nouvel employé ?
R: La période d'essai pour un nouvel employé est de 3 mois, renouvelable une fois.[Document 2 - Politique RH 2023]
... La période d'essai standard est de trois (3) mois renouvelable une fois pour les nouvelles embauches. ...
(fin des documents)Utilisateur :
Combien de temps dure la période d’essai pour un nouvel employé ?
Quelques points à noter dans cet exemple :
- On a inclus deux documents (Document 1 et Document 2) qui contiennent l’information. Le Document 1 est formulé en QA (FAQ), le Document 2 en phrase continue.
- On a instructé le modèle de ne répondre qu’avec les informations dans ces docs et de citer les sources.
- On a explicitement mis la mention « fin des documents » après pour bien délimiter. Ce n’est pas toujours nécessaire mais ça peut aider à éviter que le modèle ne continue à lire ailleurs.
- La question utilisateur est clairement posée à la fin.
La réponse que DeepSeek pourrait générer ici serait par exemple :
“La période d’essai dure 3 mois, avec possibilité de renouveler une fois (Document 1, Document 2).”
On voit qu’il a extrait la durée et mentionné les deux sources. C’est exactement le comportement souhaité : l’IA fait la synthèse des documents fournis, ne sort pas de ce cadre, et cite ses références.
Ce format de prompt est évolutif. Vous pouvez décider de présenter différemment : par exemple, fournir les documents sous forme de liste à puces, ou les introduire comme « Extrait du Manuel RH : …* ». L’essentiel est que l’IA comprenne bien que tout ce dont elle a besoin est dans ces textes.
Avec DeepSeek, grâce à son entrainement orienté raisonnement et exactitude, on trouve qu’il est assez obéissant aux consignes de ne pas halluciner. Toutefois, il est toujours prudent de vérifier en testant. Si jamais l’IA commence à inventer des choses hors documents, renforcez le message système du style « Ne complète pas tes réponses par des connaissances extérieures.« .
Cas d’usage : 3 mini-tests sur un mini-corpus
Pour illustrer concrètement la démarche, prenons trois scénarios de mini-corpus et voyons comment l’assistant DeepSeek s’en sort. Ces tests sont reproductibles avec l’architecture décrite (vous pouvez simuler avec quelques fichiers textes correspondant aux exemples).
Test 1 : FAQ produit (questions fréquentes)
Contexte : Une liste FAQ publique d’un produit (par exemple un logiciel). Elle contient une question « Comment changer mon mot de passe ? » avec la réponse détaillée. L’utilisateur pose la question exactement (ou quasiment) présente dans la FAQ.
- Corpus : Un fichier
faq_produit.txtavec ~10 Q/R courtes. - Question utilisateur : « Bonjour, comment puis-je changer mon mot de passe ? »
- Attendu : L’assistant doit retrouver la Q/R correspondante et la restituer clairement, idéalement en reformulant légèrement et en citant que cela provient de la FAQ produit.
- Résultat exemple : “Pour changer votre mot de passe, allez dans les paramètres de votre compte, section ‘Sécurité’, puis cliquez sur ‘Modifier le mot de passe’. Suivez les instructions en entrant votre ancien mot de passe puis le nouveau deux fois (source : FAQ produit).”
- Analyse : Ici, la réponse est quasiment copiée de la FAQ, ce qui est normal et même souhaitable (on veut la réponse officielle). DeepSeek a reformulé légèrement l’intro (« allez dans… puis cliquez… »), ce qui montre qu’il intègre bien le contenu. Il a cité la source. Si on avait demandé explicitement de ne pas citer, il aurait pu répondre juste la procédure. L’important est qu’il n’a pas halluciné d’étapes non présentes.
Test 2 : Document technique interne
Contexte : Un document interne (non public) de documentation technique, par exemple un guide d’installation d’un logiciel, ou un manuel d’architecture. L’utilisateur pose une question pointue couverte par ce doc.
- Corpus :
guide_interne.mdcontenant par exemple la procédure pour configurer une base de données dans une application. - Question : « Quelle variable de configuration permet de définir l’URL de la base de données ? »
- Attendu : L’assistant doit sortir le nom exact de la variable (ex :
DB_CONNECTION_STRING) et éventuellement le chemin du fichier de config, en citant le guide interne. - Résultat exemple : “La variable de configuration à définir est
DB_CONNECTION_STRING, qui correspond à l’URL de connexion à la base de données (source : Guide interne, section Configuration BDD).” - Analyse : DeepSeek a bien pioché l’information du document. Notons qu’il a cité « Guide interne, section Configuration BDD » – cela suppose qu’on avait inclu le titre de la section dans le chunk ou en métadonnée. C’est là l’intérêt des métadonnées : le chunk peut contenir
'section': 'Configuration BDD'et on peut l’ajouter dans le prompt à côté du texte. Si c’est fait, l’IA peut naturellement utiliser cette info dans la source citée, ce qui rend la réponse plus précise.
Test 3 : Politique RH (base de connaissances support)
Contexte : Un document PDF “Politique RH” contenant toutes les règles d’entreprise (congés, avantages, etc.). C’est un doc assez verbeux. Un employé pose une question spécifique qui est couverte, mais noyée dans le texte.
- Corpus :
politique_RH.pdf(text extrait). - Question : « Est-ce qu’on a le droit à des congés payés supplémentaires pour ancienneté ? »
- Attendu : Si la politique dit par exemple « Au-delà de 5 ans d’ancienneté, 1 jour de congé supplémentaire par an est accordé », l’assistant doit répondre cela précisément, en citant la politique RH.
- Résultat exemple : “Oui. D’après notre politique RH, au-delà de 5 ans d’ancienneté, vous bénéficiez d’un jour de congé payé supplémentaire par an (source : Politique RH 2023).”
- Analyse : L’assistant a fait du cherrypicking de l’info pertinente. On voit la valeur du LLM ici : il a condensé une section de la politique RH peut-être rédigée en langage administratif en une phrase claire. On constate qu’il a bien contextualisé « d’après notre politique RH… » ce qui est bien. S’il ne l’avait pas fait spontanément, on pourrait l’encourager dans le prompt système (« réponds en disant ‘d’après la politique RH…’ « ). La mention de l’année 2023 dans la source pourrait venir du titre du PDF ou d’une meta qu’on aurait fournie.
Ces tests montrent un aspect important : la qualité du résultat dépend fortement du contenu fourni dans les chunks. Si le chunk est trop large, le modèle pourrait négliger l’info clé ou se tromper de phrase. Si le chunk est bien ciblé, DeepSeek saura en extraire le fait utile. Par ailleurs, la citation des sources fonctionne bien dès lors qu’on a formaté les documents avec un label. DeepSeek, comme ChatGPT, comprend très bien une instruction du type « cite la source (Document X)« .
En cas de réponse incomplète ou ambiguë, c’est souvent qu’un document manquant ou un chunk mal découpé est en cause. Par exemple, si pour la question de l’ancienneté, le chunk récupéré ne contenait pas la phrase des 5 ans (coupée juste avant), l’IA pourrait ne pas répondre exactement ou dire « Je ne sais pas ». D’où l’importance du chunk overlap et de vérifier nos chunks.
Astuces pour améliorer la qualité des réponses
Même une fois le pipeline en place et fonctionnel, on peut affiner un certain nombre de paramètres pour améliorer la qualité des réponses fournies par DeepSeek. Voici quelques conseils et leviers d’optimisation :
- Taille des chunks : Ajustez le chunk size en fonction de la nature de vos documents et des questions types. Si vous constatez que l’assistant a besoin de consulter deux chunks consécutifs pour répondre (ex. un chunk contient la question, l’autre la réponse, dans un FAQ mal découpé), c’est signe qu’il faut des chunks plus grands. À l’inverse, si les réponses contiennent souvent des digressions ou du contenu hors sujet, c’est peut-être que les chunks englobent trop de choses : réduire leur taille pourrait aider à cibler l’information.
- Chevauchement (overlap) : Si une information importante se trouve à cheval sur deux chunks, vous risquez de la manquer. Augmenter légèrement l’overlap peut résoudre ce problème (e.g. passer de 50 à 100 tokens, ou chevaucher systématiquement d’une phrase entière). Mais n’abusez pas, car trop d’overlap signifie beaucoup de duplication de texte qui peut faire ressortir deux fois la même info dans la recherche. C’est un équilibre à trouver.
- Utilisation des métadonnées : Exploitez les métadonnées à la fois dans la recherche et dans le prompt. Par exemple, si chaque chunk a une catégorie ou un tag, certaines requêtes pourraient directement filtrer : “dans la catégorie FAQ produit”. Des vectore databases comme Chroma permettent d’appliquer un filtre par métadonnée lors du k-NN. De plus, inclure des titres ou contextes (ex. nom du doc, date) dans le prompt aide l’IA à formuler sa réponse avec plus de contexte (“d’après le manuel 2022…”).
- Nombre de passages (Top k) : Tweakez le k. On l’a évoqué, 3 à 5 est une bonne base. Si vous avez un corpus hétérogène, il peut être pertinent d’adapter dynamiquement k en fonction de la confiance. Par exemple, si le score du 1er résultat est très élevé par rapport au 2e, peut-être que ce seul document suffit. Au contraire, si les scores sont serrés ou modérés, prendre 5 documents donnera plus de chances d’avoir la bonne info dedans. Vous pourriez aussi faire un système itératif : demander à DeepSeek de formuler une première réponse, puis si elle dit « ne sait pas », essayer avec plus de contexte ou un prompt modifié. Mais cela coûte plus de tokens, donc mieux vaut bien régler la première passe.
- Consignes de réponse et style : N’hésitez pas à personnaliser le message système pour obtenir le style souhaité. Par exemple, précisez « réponds en une seule phrase » ou « donne la réponse sous forme de liste si applicable ». DeepSeek suivra ces instructions du mieux possible. Pour la citation des sources, comme on l’a fait, il suffit de le demander et de fournir un format. On pourrait aussi dire « cite les sources sous forme de [1], [2] » si on préfère un format de référence numérique. L’important est d’être clair dans l’instruction système.
- Vérification et cross-validation : Pour des applications critiques, une technique consiste à poser la question de plusieurs manières ou à vérifier la cohérence de la réponse. Par exemple, si l’IA répond « 3 mois d’essai », on pourrait en back-end s’assurer que le texte « 3 mois » apparaissait bien dans les documents sources. C’est du post-traitement basique mais qui peut attraper des hallucinations flagrantes. Une autre idée : reposer la réponse en question à l’IA pour voir si elle confirme – mais ça, c’est plus du bricolage. Mieux vaut améliorer prompt et retrieval pour éviter les erreurs en amont.
- Température et paramètres : DeepSeek permet de régler
temperature,max_tokensetc. Pour un assistant factuel, gardeztemperaturerelativement basse (0 à 0.5) pour éviter qu’il ne « divague ». Utilisezmax_tokenspour limiter la longueur de réponse au besoin (mais DeepSeek par défaut a des limites élevées : deepseek-chat peut sortir 4k tokens par défaut, deepseek-reasoner jusqu’à 32k). Vous pouvez aussi tester le mode reasoner – celui-ci va produire un raisonnement interne que vous pouvez récupérer (via un paramètre spécial). Ce raisonnement peut aider à comprendre comment l’IA analyse le contexte, mais il n’est pas destiné à l’utilisateur final. En général, pour de la QA documentaire simple, le mode reasoner n’est pas nécessaire, mais si vos questions impliquent des calculs ou des déductions complexes à partir des documents, il pourrait apporter un plus (au prix d’une réponse souvent plus longue). - Ré-embedding vs cache : Si votre application reçoit souvent les mêmes questions, sachez utiliser le cache de DeepSeek pour les réponses multi-tour, mais aussi pensez au cache côté vecteurs. Vous pouvez conserver en mémoire les vecteurs de requêtes déjà posées (embedding de la question) pour éviter de recomputer un embedding si une question identique revient. Idem, FAISS permet de préchauffer certaines requêtes fréquentes en calculant leur voisins. Ce sont des micro-optimisations mais sur de gros volumes ça compte.
- Enrichir la base progressivement : Parfois, vous verrez que l’IA répond « Je ne sais pas » parce que l’info n’est tout simplement pas dans votre base de connaissances. Ce retour est précieux : cela signifie peut-être qu’un document manque. Utilisez ce feedback pour incorporer de nouvelles sources. Exemple, si plusieurs utilisateurs posent des questions sur une fonctionnalité X qui n’est pas documentée, envisagez d’ajouter au corpus un document (ou même une note manuelle) sur X, pour que la prochaine fois l’IA puisse répondre. Le duo IA + base de connaissances doit évoluer avec les besoins des utilisateurs.
En appliquant ces astuces, vous devriez obtenir un assistant documentaire de haute qualité, qui fait ce qu’on attend de lui : fournir rapidement la bonne information provenant de la bonne source, sans en inventer, et en s’adaptant aux formulations de l’utilisateur.
Coûts et performance du pipeline
Abordons l’aspect coûts et performance, car en production ces questions sont cruciales pour dimensionner la solution.
Coûts liés à DeepSeek : L’utilisation de l’API DeepSeek est tarifée en fonction des tokens d’entrée (prompt) et de sortie (réponse). Selon la documentation tarifaire, on est sur l’ordre de $0.28 par million de tokens input (cache miss) et $0.42 par million de tokens output, avec un rabais x10 sur les tokens en cache (0.028$ par million si cache hit). En clair, chaque 1000 tokens envoyés coûte ~0.00028$, soit 0.028 ¢ – c’est très faible. Même en comptant large, un prompt de 5000 tokens = 0.0014$, peanuts. La sortie, mettons 200 tokens = 0.000084$. Donc par requête on parle de millièmes de centime. Ce qui peut chiffrer, c’est le volume si vous avez des milliers de requêtes par jour, mais même 1000 requêtes avec 5000 tokens chacune reviennent à ~1.4$. DeepSeek est donc compétitif avec les prix OpenAI (0.3$/1M tokens pour GPT-4 8k contexte).
Le cache de contexte devient intéressant si vos prompts ont une grosse partie fixe répétée (ce qui est le cas ici : les documents injectés pour une question dans la même session). Par exemple, si un utilisateur pose 5 questions successives liées au même document, les passages de ce document seront en cache dès la 2ème question, donc ces tokens-là coûteront 10x moins cher. Sur l’ensemble, DeepSeek estime que ça réduit la facture de ~50% en moyenne sur du multi-turn. Profitez-en : ne craignez pas de renvoyer un gros contexte si c’est le même sur plusieurs requêtes, le cache amortira.
Coûts du côté embeddings : Si vous utilisez un modèle open-source local sur CPU/GPU, le coût est en “capex” (vous investissez dans une machine GPU ou du temps de calcul). Si vous utilisez une API payante pour les embeddings, il faudra la prendre en compte. Par exemple, OpenAI Ada-002 coûte 0.1$ par 1k embeddings de 1536 dims. Donc vectoriser 1000 chunks = 0.1$. Ce n’est pas énorme non plus, mais comparé au coût des prompts DeepSeek quasi nul, ça peut devenir le poste principal si vous avez des millions de documents. En open-source, calculer 1k embeddings sur un GPU prend quelques secondes, donc là le coût est surtout l’infrastructure (une bonne machine GPU on-demand peut coûter quelques dollars de l’heure).
Heureusement, la vectorisation documents est fait une fois en amont. Ce qui compte ensuite c’est la vectorisation des requêtes utilisateur à la volée. Un embedding de question c’est rapide (quelques dizaines de ms sur CPU) et négligeable en coût. Donc pas d’inquiétude, l’inférence LLM (DeepSeek) dominera largement le temps de réponse perçu (typiquement 0.5s à 2s selon longueur).
Latence globale : parlons-en. DeepSeek annonce <13s pour un prompt de 128k tokens (premier token) réduit à 0.5s avec cache – en gros ça veut dire que même un énorme prompt a une latence gérable. Pour nos cas plus modestes (quelques k tokens max), on obtient souvent une réponse en ~1 seconde ou moins. Le bottleneck initial peut être la vectorisation (si votre modèle d’embedding est lourd). Il faut idéalement pré-charger le modèle d’embedding en mémoire au lancement de l’app, pour que chaque requête ne subisse pas ce surcoût.
La recherche vectorielle est ultra rapide (FAISS sur 100k vecteurs, c’est de l’ordre de 5 ms pour top10). Donc ce n’est pas un problème. Si vous scalez à des millions, un index approximatif pourra maintenir la latence sous les 50 ms aisément.
Scalabilité : DeepSeek ne semble pas imposer de limite de QPS (requêtes par seconde) proprement dit. Vous pouvez paralléliser autant que voulu. Le vrai scaling sera sur votre système : la base vectorielle doit encaisser les requêtes (un Postgres + pgvector peut gérer plein de requêtes en // mais sature si beaucoup de calcul cosinus ; une base comme Qdrant scale horizontalement). De même, si vous servez 100 utilisateurs simultanés, et que votre modèle d’embedding est local sur 1 GPU, il devra faire 100 encodages en // – certains frameworks permettent de batcher ou de faire du multi-thread sur CPU. Pensez à ces aspects si votre user base est large.
Une architecture possible est de containeriser le service d’embedding à part, et le requêter via HTTP interne, de façon à pouvoir le scaler séparément de la logique RAG. Ou utiliser un service managé d’embedding pour plus de facilité, mais attention au coût par appel.
Économie de contexte : Ayez le réflexe de ne pas envoyer plus de contexte que nécessaire. 128k tokens c’est fantastique mais inutilement tout remplir va juste coûter (un peu) et potentiellement ralentir la génération. Donc restez parcimonieux : si seule une petite partie d’un chunk est pertinente, vous pourriez envisager de ne mettre que cet extrait dans le prompt. Certaines pipelines avancées font du “source collapse” : elles réduisent le texte des documents (via un modèle de résumé ou en ne gardant que les phrases contenant les mots-clés liés à la question). Ça peut être utile si vos documents sont très verbeux. Mais c’est un équilibrage : trop réduire risque de louper de l’info. À tester selon les cas.
Gestion des erreurs : Côté DeepSeek, surveillez les codes d’erreur (ils en ont dans la doc). Par ex, trop de tokens renverra une erreur qu’il faut attraper (on a peu de chances de l’atteindre à 128k mais on ne sait jamais). Aussi, si vous dépassez vos quotas ou que l’API key expire. En bref, encapsulez l’appel d’API dans un try/except pour réagir proprement (ex. retenter, ou alerter l’utilisateur que le service est indisponible temporairement).
En matière de coûts, un dernier point : évaluez le ROI. Si votre assistant permet d’automatiser des réponses support qui prenaient 5 minutes humaines, même en payant quelques centimes par requête LLM, le calcul est vite fait. DeepSeek étant moins cher (pour usage équivalent) que GPT-4, et offrant possiblement de meilleures réponses sur du raisonnement, c’est un bon choix économique. Et la combinaison RAG permet d’éviter de payer pour entraîner un modèle custom. Vous paierez à l’usage réel plutôt qu’en upfront, ce qui est souvent plus flexible.
Erreurs fréquentes à éviter
Malgré tout le soin apporté, il existe des pièges classiques lors de la construction d’un pipeline RAG. Voici un florilège des erreurs fréquentes et comment les éviter :
- Chunks trop longs ou mal découpés : C’est probablement l’erreur #1. Si vous découpez mal vos documents, toute la chaîne s’en ressent. Par exemple, un chunk de 2000 mots qui couvre 5 sujets différents va ressortir pour des questions sur l’un ou l’autre sujet, mais l’IA devra faire le tri dans un gros bloc – risque de confusion ou de réponse partielle. Au contraire, des chunks de 50 mots isolés font perdre le contexte et multiplient les hits irrélèves. Solution : itérez sur le chunking. Regardez pour quelques questions de test quels chunks sont remontés et s’ils contiennent clairement la réponse. Ajustez la taille jusqu’à ce que ce soit le cas.
- Top k mal réglé : On en a parlé, c’est une cause courante de contre-performance. Si k est trop petit, l’info pertinente peut ne pas être présente dans le prompt (et l’IA ne peut deviner). Si k est trop grand, vous diluez le contexte et potentiellement embrouillez l’IA avec des infos contradictoires. Solution : commencez avec k=3 par exemple. Si vous voyez des “Je ne sais pas” alors que vous aviez un doc sur le sujet, passez à 5. Si vous voyez l’IA mélanger deux sources ou citer la mauvaise, peut-être k=5 était trop, redescendez à 3. Chaque projet a un sweet spot selon la densité d’information par document.
- Documents mal nettoyés : Des artefacts de conversion (genre des
\npartout, ou des numéros de page en plein milieu du texte) peuvent perturber l’embedding. Par exemple, si chaque ligne de votre PDF se termine par un numéro de page ou un mot tronqué, l’embedding peut être de moindre qualité. Solution : passez du temps à nettoyer. Supprimez les entêtes/pieds de page répétitifs, corrigez les mots collés par des coupures de ligne, etc. Vous pouvez aussi filtrer les tokens les plus rares ou les blocs non textuels (ex. blocs de code : parfois on ne veut pas les inclure sauf si nécessaire). Un bon nettoyage = des embeddings plus homogènes et plus pertinents. - Confusion entre recherche sémantique et génération : C’est conceptuel, mais beaucoup pensent que “l’IA va retrouver la réponse dans la base”. Non, ce n’est pas magique : c’est la recherche vectorielle qui fait remonter les passages pertinents. L’IA ne fait que les exploiter pour formuler une réponse. Donc si vous posez une question en dehors du périmètre du corpus, l’IA ne pourra pas rechercher ailleurs. Par exemple, demander “Qui est le PDG de Google ?” alors que votre base parle de tout autre chose – la bonne approche serait d’avoir un fallback sur un moteur externe ou d’entraîner l’IA sur des connaissances générales. Mais dans un assistant de connaissances spécifique, il vaut mieux qu’elle réponde “Je ne sais pas”. Solution : assurez-vous que l’utilisateur comprenne ce que l’assistant couvre ou non (via la UI ou la formulation). Et de votre côté, ne mélangez pas dans le prompt des attentes impossibles : on a vu des devs faire l’erreur de dire « si tu ne trouves pas dans les documents, cherche dans ta connaissance générale« . Cela va à l’encontre du principe RAG (et peut rouvrir la porte aux hallucinations). Mieux vaut cloisonner : pas trouvé = pas de réponse, point.
- Pas de mesure de performance : Parfois on déploie un POC et on oublie de mesurer si ça répond correctement aux questions. On se base sur quelques tests manuels. C’est risqué, car on peut avoir un biais (on teste les questions qui marchent). Solution : mettez en place un petit set de validation (même 20 questions) avec les réponses attendues, et voyez si l’assistant répond correctement. Si possible, mesurez la pertinence des documents renvoyés (par ex, calculer un score de recall@k sur un ensemble question->doc pertinent). C’est ainsi qu’on détecte que l’embedding X a 90% de réussite là où l’embedding Y en avait 80%, etc. Professionnalisez un peu l’évaluation, surtout si c’est un outil support critique.
En évitant ces écueils, vous gagnerez du temps et vous livrerez un assistant robuste. N’hésitez pas à consulter des retours d’expérience de la communauté (il y a pas mal de blogs et de projets open source RAG, souvent en anglais, partageant leurs erreurs et solutions).
Conclusion
Construire un assistant documentaire avec DeepSeek en 2026 est tout à fait réalisable et même relativement accessible grâce à la compatibilité OpenAI de son API et aux avancées en recherche sémantique. La clé du succès réside dans une architecture RAG propre, où chaque composant joue son rôle : un bon modèle d’embedding pour comprendre vos documents, une base vectorielle efficace pour la recherche, et DeepSeek pour formuler des réponses précises à partir du matériau trouvé.
Contrairement à certains discours marketing qui font miroiter une IA “qui sait tout faire toute seule”, nous avons vu qu’il faut être pragmatique et ne pas prêter à DeepSeek des fonctionnalités qu’il n’a pas. Pas d’endpoint magique d’embeddings ? Qu’à cela ne tienne, le monde open-source nous fournit d’excellents modèles pour ça. L’important est que DeepSeek, lui, apporte une génération de très haute qualité, capable de synthétiser de l’information et de raisonner sur du contenu complexe. Son contexte de 128k tokens élimine pratiquement les soucis de longueur : vous pourrez lui fournir plusieurs pages de référence sans problème, là où d’autres modèles plus limités obligent à trier agressivement le contexte.
En termes de décision pour votre projet, vous pouvez retenir ceci :
- Si vous avez déjà un entrepôt documentaire (intranet, FAQ, base de tickets), ajouter une brique DeepSeek RAG peut immensément améliorer l’accessibilité à l’information (fini les recherches manuelles fastidieuses, l’IA apporte la réponse directe avec la référence).
- Le coût de mise en œuvre est modeste comparé à du développement spécifique ou à de l’entraînement de modèles – on assemble des composants existants. Ce guide a d’ailleurs utilisé presque exclusivement des solutions libres ou standard du marché.
- En production, le coût financier à l’usage reste faible au vu du service rendu, surtout si on profite du caching et qu’on optimise les appels. DeepSeek se positionne comme une option viable à évaluer selon vos propres benchmarks pour ce cas d’usage, en étant potentiellement plus économique et possédant des atouts techniques (raisonnement approfondi, très longue context, sortie JSON/tool use si besoin).
- Il faut prévoir un peu de maintenance (mettre à jour la base de connaissances, monitorer la qualité des réponses, ajuster si besoin les modèles d’embeddings lorsque de meilleurs sortent). Ce n’est pas un système qu’on “code et oublie” totalement, mais l’effort reste bien moindre que de maintenir une FAQ manuelle ou de former le staff support sur toutes les nouveautés : l’assistant se mettra à jour dès que vous lui fournissez la nouvelle documentation.
En conclusion, construire une base de connaissances personnalisée avec DeepSeek est un projet tout à fait réalisable pour une équipe technique aujourd’hui. En suivant une approche rigoureuse (sans brûler les étapes ingestion -> vecteurs -> retrieval -> génération), on obtient un chatbot documenté qui donne confiance aux utilisateurs (car il sourcera ses réponses) et fait gagner un temps précieux. Ce guide francophone aura, je l’espère, démystifié le sujet et corrigé les informations trompeuses que l’on peut lire ailleurs. À vous maintenant de passer à l’implémentation : sélectionnez vos outils, entraînez vos embeddings, branchez l’API DeepSeek… et vous aurez bientôt un assistant intelligent, honnête et efficace pour exploiter votre base de connaissances !
FAQ
DeepSeek propose-t-il un service d’embeddings vectoriels via son API ?
Non, pas officiellement à ce jour. La documentation DeepSeek (mars 2026) ne mentionne aucun endpoint type /embeddings ni de modèle “deepseek-embedding” utilisable directement. Il est possible que cela apparaisse à l’avenir (certaines sources officieuses en parlent), mais actuellement il faut utiliser un modèle séparé pour générer vos embeddings. En clair, DeepSeek fournit la partie Chat/Complétion, mais la partie Vectorisation sémantique est à votre charge via un outil externe.
Quel modèle d’embedding recommandez-vous pour un corpus en français ?
Un modèle multilingue de haute qualité. En 2026, des modèles open-source comme BGE-m3 ou Qwen-7B-Embedding excellent sur les tâches de similarité sémantique en français. Pour un bon compromis taille/perf, paraphrase-multilingual-mpnet-base-v2 reste une valeur sûre facile à déployer. Si vous avez les ressources, le modèle Qwen2 (Alibaba) offre une précision redoutable y compris en français, surpassant même les modèles propriétaires sur certains benchmarks. L’essentiel est qu’il soit entraîné pour la recherche de similarité (évitez d’utiliser directement un GPT non entraîné pour ça). Vous pouvez aussi tester les APIs d’OpenAI ou Cohere qui gèrent bien le français, mais attention au coût si votre corpus est grand.
Quelle base vectorielle choisir pour stocker les embeddings ?
Pour démarrer simplement, FAISS est idéal – c’est une librairie ultra-optimisée pour la recherche de vecteurs, facile à intégrer en Python. Si vous préférez tout stocker dans Postgres, l’extension pgvector est une bonne option pour ajouter la recherche vectorielle à votre BDD. Pour des besoins plus avancés (scaling horizontal, API REST native), regardez du côté de Qdrant, Weaviate ou Milvus qui sont des solutions dédiées performantes. En résumé : FAISS si vous aimez le local/simple, pgvector si vous voulez SQL, une Vector DB full-stack si vous voulez un service clé en main ou du SaaS.
Peut-on utiliser DeepSeek pour un chatbot de documentation sans mettre en place de base vectorielle ?
Techniquement, on pourrait tenter de tout mettre dans le prompt manuellement (par ex, coller tout un document de référence dans chaque question). Mais ce n’est pas du tout scalable ni efficace. Même avec 128k tokens, envoyer systématiquement l’encyclopédie entière n’a pas de sens et va embrouiller l’IA plus qu’autre chose. La base vectorielle sert à sélectionner uniquement les passages utiles. Sans elle, votre chatbot ne fera que brasser du texte inutilement. À moins d’avoir un corpus minuscule (quelques pages tout au plus), il est fortement conseillé de mettre en place la couche vectorielle. C’est ce qui différencie un assistant RAG intelligent d’un simple prompt fourre-tout.
Comment réduire les coûts d’utilisation si le corpus devient très volumineux ?
Plusieurs pistes : 1) Réduire la dimension et le nombre d’embeddings – utilisez un modèle qui sort des vecteurs plus petits (ex : 384 dims au lieu de 768) pour stocker deux fois moins de données, et assurez-vous de ne pas indexer des documents inutiles (faites du tri en amont, éventuellement indexez uniquement en français si votre corpus contient plusieurs langues mais que vos questions seront en français). 2) Recherche approximative – pour accélérer, utilisez un index de type HNSW ou IVF qui évitera de comparer tous les vecteurs, ce qui réduit la latence et permet d’économiser du calcul CPU. 3) Context caching – côté DeepSeek, profitez du cache contextuel : si vos utilisateurs explorent un même document sur plusieurs questions, encouragez-les à le faire en une seule session conversationnelle, ainsi le prompt restera en cache en grande partie et sera facturé beaucoup moins. 4) Batcher les requêtes – si vous avez des pics de questions, traitez-les par petits paquets quand c’est possible (côté vector search, interroger pour 5 questions en même temps peut mutualiser des calculs). Enfin, surveillez le Top k : ne montez pas à 10 si 3 suffisent, sinon vous envoyez trop de texte à l’API pour rien.
Mon assistant hallucine parfois des réponses qui n’étaient pas dans les documents. Comment l’éviter ?
C’est rare avec un bon prompt, mais possible si les documents ne contiennent qu’une réponse partielle. Par exemple, s’il manque un morceau d’information, l’IA pourrait le “deviner” pour combler le vide. Pour éviter cela : assurez-vous de bien dire dans le message système de ne pas inventer et de dire “Je ne sais pas” en cas de manque. Ensuite, vérifiez vos résultats de recherche : peut-être que le bon chunk n’a pas été récupéré (embedding fail). Parfois augmenter le k ou améliorer l’embedding modèle résout le souci en donnant assez de contexte réel à l’IA. Vous pouvez aussi mettre temperature=0 pour la rendre maximument déterministe (elle collera aux faits, mais répondra peut-être de façon plus sèche). Enfin, envisagez un post-traitement de la réponse : si elle affirme quelque chose sans source et que vous vous apercevez que ça ne figure pas dans les docs, vous pourriez filtrer ou redemander une clarification à l’IA (“quelle est ta source ?” – si elle ne peut en citer, c’est que c’était inventé). Ce genre de double vérification peut être automatisé en interne.
Peut-on fine-tuner le modèle DeepSeek sur nos documents au lieu d’utiliser RAG ?
Pas via l’API publique en tout cas. DeepSeek n’offre pas de programme de fine-tuning sur données client (et de toute façon fine-tuner un modèle de cette taille sur un corpus spécifique est très coûteux et complexe). L’approche RAG est plus pragmatique : on laisse le modèle général tel quel, et on lui fournit le savoir contextuellement. C’est moins “intégré” qu’un modèle carrément entraîné sur vos textes, mais c’est beaucoup plus flexible (mise à jour instantanée quand un doc change) et sécurisé (pas de risque d’altérer les autres capacités du modèle). Donc la réponse courte : non, on ne peut/veut pas fine-tuner DeepSeek directement pour ça – RAG est la bonne méthode, sauf cas ultra-spécifique où un fine-tuning léger de dernière couche pourrait améliorer les embeddings mais c’est un autre sujet, pas faisable via DeepSeek directement.




