Guide
Dédoublonner des documents avant l'indexation par une IA
Doublons exacts par empreinte, quasi-doublons par MinHash, versions périmées par métadonnées : la méthode et le code Python pour nettoyer une base.
Mis à jour le
Une base documentaire d'entreprise contient presque toujours des doublons : le même PDF déposé dans trois dossiers, un Word et son export PDF, la version 2 et la version 3 d'une procédure. Pour une IA, c'est une double peine : les copies prennent la place d'autres passages dans les résultats de recherche, et deux versions donnent deux réponses. Le nettoyage se fait en trois passes : doublons exacts, quasi-doublons, versions périmées.
Passe 1 : les doublons exacts, par empreinte
Deux fichiers identiques octet par octet ont la même empreinte (un hachage du contenu). En Python, hashlib.file_digest, ajouté à la version 3.11, calcule cette empreinte directement depuis un fichier ouvert en mode binaire :
import hashlib
from collections import defaultdict
from pathlib import Path
groupes = defaultdict(list)
for f in Path("export").rglob("*"):
if f.is_file():
with open(f, "rb") as fh:
groupes[hashlib.file_digest(fh, "sha256").hexdigest()].append(f)
doublons = {h: fs for h, fs in groupes.items() if len(fs) > 1}
Inutile de tout télécharger pour cela : les plateformes fournissent souvent l'empreinte.
| Source | Empreinte disponible | Limite |
|---|---|---|
| Google Drive | md5Checksum, sha256Checksum |
seulement pour les fichiers binaires stockés dans Drive, pas pour les documents Google |
| SharePoint, OneDrive (Microsoft Graph) | quickXorHash |
seule valeur garantie sur OneDrive professionnel et personnel ; sha256Hash n'est pas pris en charge |
Passe 2 : les quasi-doublons, sur le texte converti
Un Word et son export PDF n'ont pas la même empreinte de fichier, mais leur texte est presque le même. Il faut donc comparer après conversion en Markdown ou en texte. Deux niveaux :
- Empreinte du texte normalisé : passez le texte en minuscules, retirez espaces multiples et en-têtes répétés, puis hachez. Cela attrape les copies converties depuis des formats différents.
- Similarité approchée : pour les textes très proches mais pas identiques (une date changée, un paragraphe ajouté), la méthode MinHash LSH retrouve les textes dont la similarité de Jaccard (part de mots communs) dépasse un seuil, sans comparer chaque paire. La documentation de datasketch précise que la requête est plus rapide qu'une comparaison exhaustive, au prix de quelques faux positifs et de quelques oublis.
from datasketch import MinHash, MinHashLSH
def signature(texte):
m = MinHash(num_perm=128)
for mot in set(texte.lower().split()):
m.update(mot.encode("utf8"))
return m
lsh = MinHashLSH(threshold=0.8, num_perm=128)
for doc_id, texte in textes.items():
lsh.insert(doc_id, signature(texte))
proches = lsh.query(signature(textes["procedure-achats-v3"]))
Le seuil et num_perm se fixent à la création de l'index. Un seuil élevé (0,8 ou plus) vise les vraies copies ; plus bas, vous ramenez des documents simplement voisins (deux contrats sur le même modèle), qu'il ne faut surtout pas fusionner.
Passe 3 : les versions périmées
Les versions ne sont pas des doublons : elles ont un contenu différent, et une seule est valide. La machine ne peut pas deviner laquelle ; il faut une règle.
- Une métadonnée de statut (
en_vigueur,remplace,brouillon) posée par le propriétaire du document. C'est la seule méthode fiable. Voir Métadonnées. - Le numéro de version de la source : Google Drive fournit un champ
versionqui augmente à chaque modification. Il distingue des états d'un même fichier, pas deux fichiers distincts « v2 » et « v3 ». - Le nom de fichier, en dernier recours : « v3 », « définitif », une date. Fragile, mais utile pour proposer des candidats à un humain. Une convention de nommage aide beaucoup : voir les règles de nommage des fichiers.
Les versions remplacées sortent de l'index, mais ne se suppriment pas de la source : archivez-les. La méthode côté organisation est décrite sur la page consacrée à la gestion des versions.
Quel exemplaire garder
Quand un groupe de doublons est trouvé, gardez :
- l'exemplaire qui se trouve dans l'emplacement de référence (le dossier validé, pas un dossier personnel) ;
- sinon, celui dont les droits d'accès sont les plus restrictifs, pour ne rien ouvrir par erreur ;
- sinon, le plus récent.
Notez les identifiants des copies écartées : si l'exemplaire gardé disparaît, une copie peut reprendre sa place.
Refaire le contrôle à chaque synchronisation
Le dédoublonnage n'est pas un nettoyage ponctuel : chaque nouvel ajout peut en recréer. Calculez l'empreinte à l'arrivée de chaque document, avant le découpage et le calcul des vecteurs, et refusez ce qui existe déjà. Les chaînes de synchronisation sont décrites pour SharePoint et Google Drive.
Questions fréquentes
Pourquoi les doublons gênent-ils un RAG ?
Plusieurs copies d'un même passage occupent les premières places des résultats de recherche à la place d'autres passages utiles, et deux versions différentes d'un même document peuvent donner deux réponses contradictoires.
Comment repérer deux documents presque identiques ?
Par une mesure de similarité sur le texte. MinHash LSH, disponible par exemple dans la bibliothèque datasketch, retrouve les textes dont la similarité de Jaccard dépasse un seuil, sans comparer chaque document à tous les autres.
Sources
Pages consultées pour écrire cet article :