Aller au contenu
Cercle IA Tech · Documents Un site du réseau Cercle IA Tech

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 :

  1. 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.
  2. 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 version qui 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 :

  1. l'exemplaire qui se trouve dans l'emplacement de référence (le dossier validé, pas un dossier personnel) ;
  2. sinon, celui dont les droits d'accès sont les plus restrictifs, pour ne rien ouvrir par erreur ;
  3. 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 :

  1. https://docs.python.org/3/library/hashlib.html
  2. https://ekzhu.com/datasketch/lsh.html
  3. https://developers.google.com/workspace/drive/api/reference/rest/v3/files
  4. https://learn.microsoft.com/en-us/graph/api/resources/hashes?view=graph-rest-1.0

À lire aussi