« On voudrait poser des questions à nos documents. » La phrase revient dans presque toutes les réunions où le sujet de l'IA finit par arriver. Derrière, il y a vingt ans de comptes rendus, de procédures et de contrats dans un dossier partagé que plus personne ne fouille, et l'espoir raisonnable qu'une machine sache enfin y retrouver quelque chose.
Ce qu'on installe alors n'est pas un cerveau. C'est un moteur de recherche un peu particulier, doublé d'un rédacteur qui met en forme ce que le moteur a trouvé. Si le moteur cherche mal, le rédacteur écrit joliment des bêtises. Tout le travail est dans la première moitié, et c'est celle dont personne ne parle.
Suivons un document depuis le dossier partagé jusqu'à la réponse affichée à l'écran.
Il entre
Le fichier est un PDF de quarante pages issu d'un scanner. Il ne contient aucun texte, seulement des images de texte. Sans reconnaissance optique en amont, l'indexation produit un document vide et personne ne s'en aperçoit avant les premières questions sans réponse.
Cette étape est le premier tri, et le plus ingrat. Les traitements de texte modernes passent sans difficulté. Les tableurs perdent leur structure, et un tableau aplati en ligne de texte devient illisible pour la suite. Les présentations donnent des bribes. Les vieux formats propriétaires demandent une conversion préalable. Les messages électroniques traînent leurs signatures et leurs citations imbriquées, qui pollueront chaque recherche si on ne les coupe pas.
Une chaîne de gestion documentaire déjà en place, du type de celle décrite dans notre article sur Paperless-ngx, fait une grande partie de ce travail et mérite d'être regardée avant de construire quoi que ce soit.
Il est découpé
Un document entier ne se vectorise pas. Il faut le couper en morceaux, et c'est là que se joue la qualité finale.
Trop court, le morceau perd son contexte : une clause de contrat séparée de l'article qui la conditionne devient fausse. Trop long, il mélange plusieurs sujets et sa représentation mathématique devient floue, ce qui le rend introuvable. Le découpage aveugle tous les mille caractères, celui que proposent tous les tutoriels, produit des coupes au milieu d'une phrase et des morceaux orphelins.
Ce qui marche en pratique : découper sur la structure du document quand elle existe, titres et sous-titres, avec un recouvrement de quelques dizaines de mots entre deux morceaux consécutifs pour que rien ne tombe dans la fente. Et conserver, attaché à chaque morceau, le titre du document et celui de la section dont il provient. Ces métadonnées coûtent trois lignes de code et sauvent la moitié des réponses.
Il devient un vecteur
Un modèle d'embeddings transforme chaque morceau en une liste de nombres qui code son sens. Deux textes proches par le sens donnent deux listes proches dans l'espace, et c'est tout le mécanisme.
Un point mérite d'être compris avant de commencer plutôt qu'après : ce modèle ne se change pas. Les vecteurs produits par deux modèles différents ne sont pas comparables entre eux. Changer de modèle d'embeddings impose de réindexer l'intégralité du fonds documentaire. Sur quelques milliers de pages c'est une soirée, sur un fonds sérieux c'est un chantier. Le choix se fait donc au début, en testant sur des documents réels et en français, langue sur laquelle tous les modèles ne se valent pas.
La dimension du vecteur, généralement entre 384 et 1536, a une conséquence directe sur le stockage et sur l'indexation, comme on va le voir.
Il est rangé dans PostgreSQL
L'extension pgvector ajoute à PostgreSQL le type de données et les opérateurs de distance nécessaires. C'est suffisant, et c'est le choix raisonnable pour la grande majorité des fonds documentaires d'entreprise.
CREATE EXTENSION vector;
CREATE TABLE morceaux (
id bigserial PRIMARY KEY,
document_id bigint NOT NULL,
section text,
contenu text NOT NULL,
plongement vector(1024)
);
CREATE INDEX ON morceaux
USING hnsw (plongement vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
Deux chiffres à connaître. Un vecteur occupe quatre octets par dimension plus huit, ce qui permet d'estimer le volume avant de commencer : cent mille morceaux en 1024 dimensions représentent environ quatre cents mégaoctets, avant index. Et l'index HNSW, le plus rapide à l'interrogation des deux que propose l'extension, plafonne à deux mille dimensions pour le type vecteur standard. Au-delà, il faut passer au type demi-précision, qui monte à quatre mille. Cette limite décide du modèle d'embeddings autant que l'inverse.
Rester sur PostgreSQL évite d'ajouter une base spécialisée à exploiter, à sauvegarder et à mettre à jour. Les documents, leurs droits et leurs vecteurs vivent dans le même moteur, dans la même transaction, dans la même sauvegarde. Sur des volumes qui dépassent la dizaine de millions de morceaux, la question se repose ; en deçà, elle ne se pose pas.
Il est retrouvé, ou pas
La recherche par similarité seule a un défaut connu : elle rate les termes exacts. Une référence de pièce, un numéro de contrat, un nom propre rare sont mal représentés dans l'espace des vecteurs, et le morceau qui les contient ne remonte pas.
La parade consiste à mener deux recherches en parallèle, l'une par similarité, l'autre par mots-clés avec la recherche plein texte native de PostgreSQL, puis à fusionner les deux classements. Le gain est net sur les documents techniques et juridiques, précisément ceux que les entreprises veulent interroger.
SELECT contenu, section, plongement <=> $1 AS distance
FROM morceaux
ORDER BY plongement <=> $1
LIMIT 10;
Vient ensuite le réordonnancement : reprendre les vingt ou trente meilleurs candidats et les faire classer finement par un modèle dédié avant de n'en garder que cinq. C'est l'étape qui fait le plus pour la qualité perçue, et celle qu'on ajoute en second, une fois le reste en place.
Qui a le droit de le lire
C'est le sujet qui fait échouer les projets, et il n'est presque jamais traité dans les démonstrations.
Un fonds documentaire d'entreprise n'est pas uniformément lisible. Les dossiers du personnel, les fiches de paie, les contrats en cours de négociation, les comptes rendus de direction ont des lecteurs autorisés et des lecteurs qui ne le sont pas. Un système de recherche qui ignore cette réalité fait fuiter, non pas par malveillance, mais par construction : il a lu tous les documents et il répond à tout le monde.
Le filtre doit s'appliquer avant la génération de la réponse, jamais après. Chaque morceau porte l'identifiant de son document, chaque document porte ses droits, et la requête de recherche filtre sur les droits de l'utilisateur qui pose la question. Cela suppose que l'identité de cet utilisateur soit connue du système, donc un annuaire et une authentification en bonne et due forme, du type Keycloak ou d'un équivalent déjà en place.
Une variante dangereuse consiste à laisser le modèle décider de ne pas répondre sur les documents sensibles. Un modèle de langage ne fait pas de contrôle d'accès. Il est persuadable, et il n'y a pas de journal.
Il est affiché
L'interface est la partie visible, et souvent le premier réflexe : Open WebUI est le projet dominant, avec plus de cent cinquante mille étoiles et un développement quotidien.
Un point de licence doit être lu avant de bâtir une offre dessus. Le projet n'est pas sous licence BSD standard : une clause supplémentaire interdit de modifier ou de retirer la marque « Open WebUI » de l'interface. Trois exemptions existent, et une seule est gratuite : un déploiement de cinquante utilisateurs au maximum sur trente jours glissants. Au-delà, il faut l'accord écrit des auteurs ou une licence commerciale. Un intégrateur qui déploie une interface aux couleurs de son client pour deux cents utilisateurs est en infraction s'il n'a pas fait cette démarche, et la licence qualifie explicitement ce retrait de manquement substantiel.
Le fait n'est ni scandaleux ni caché, il est simplement ignoré, parce que presque personne ne lit le fichier de licence d'un projet à cent cinquante mille étoiles. La conséquence pratique est qu'il faut choisir : garder la marque visible, payer, ou construire l'interface autrement.
Ce que ça demande une fois en service
Le fonds documentaire n'est pas figé. Des documents arrivent, d'autres sont corrigés, d'autres deviennent obsolètes sans que personne ne les supprime. Un index qui ne suit pas se met à répondre avec la procédure de 2019 en toute confiance, ce qui est pire que ne pas répondre. L'indexation doit donc tourner en continu, détecter les modifications, et surtout supprimer les vecteurs des documents retirés.
La réindexation complète doit être un geste routinier et documenté, parce qu'elle arrivera : changement de modèle d'embeddings, changement de stratégie de découpage, correction d'un bogue d'extraction. Sur un fonds important, elle se compte en heures de GPU et se planifie.
Enfin, la qualité des réponses se mesure, faute de quoi elle dérive sans alerte. Une cinquantaine de questions réelles, avec la réponse attendue et le document qui doit remonter, rejouées après chaque changement : c'est rustique, ça prend une demi-journée à constituer, et c'est la seule chose qui distingue un système qu'on améliore d'un système dont on espère qu'il va bien. La chaîne technique, elle, se supervise comme le reste : latence de la recherche, profondeur de la file d'indexation, part des questions auxquelles aucun document ne répond.
Le modèle qui rédige la réponse finale, lui, peut vivre ailleurs : sur un serveur d'inférence local ou derrière une passerelle qui arbitre entre local et distant. C'est la seule partie du dispositif qui se remplace sans rien réindexer.
Sources
- Dépôt GitHub pgvector/pgvector, extension de recherche vectorielle pour PostgreSQL, licence BSD, 23 115 étoiles au 21 septembre 2026
- Documentation pgvector, types, limites de dimensions, index HNSW et IVFFlat, opérateurs de distance
- Licence Open WebUI, clause 4 sur le branding et seuil de cinquante utilisateurs sur trente jours glissants
- Documentation PostgreSQL, recherche plein texte, pour la moitié lexicale de la recherche hybride


