· 5 min de lecture

L'arabe a cassé
mon RAG. Voici
ce qui l'a sauvé.

J'ai mis en production un chatbot en arabe égyptien. Le premier jour, il ne retrouvait à peu près rien. Six correctifs plus tard, il tenait debout.

RAG TAL arabe IA en production
Un agriculteur en galabeya sombre marchant sur un étroit chemin de terre à travers des champs verts, sous des palmiers dattiers
Ceux à qui ce système répond : des champs, des palmiers dattiers, des questions tapées en dialecte

En anglais, dans une démo, le RAG a tout du tour de magie : on verse des PDF, on interroge, le modèle répond. J'en ai mis un en production en arabe égyptien, pour du conseil agricole. Le premier jour, il ne remontait presque rien. Les utilisateurs tapaient en dialecte depuis leur téléphone, ma base était rédigée en arabe standard : la recette anglaise n'a pas tenu deux jours.

Voici les six correctifs qui ont fait passer ce presque-rien à quelque chose que j'accepte de mettre entre les mains d'agriculteurs.

CORRECTIF 1 CORRECTIF 2 CORRECTIF 3 CORRECTIFS 4 · 5 REQUÊTE DIALECTE ازاى اروى الكوسة؟ NORMALISER alif · diacritiques RÉÉCRIRE → ASM noms figés RECHERCHE HYBRIDE vecteurs + BM25 CONFIANCE deux signaux RÉPONSE conf ≥ 0,7 AVERTISSEMENT 0,5 – 0,7 EXPERT HUMAIN < 0,5 CORRECTIF 6 · LES RÉPONSES D'EXPERTS RÉINJECTÉES DANS LA BASE
Le trajet d'une question en dialecte : six correctifs entre l'agriculteur et sa réponse

L'arabe n'est pas une seule langue

Deux arabophones n'écrivent pas le même mot de la même manière. L'alif change de forme (ٱ, آ, إ, أ), les diacritiques apparaissent ou disparaissent, et le clavier du téléphone glisse au passage ses marques RTL invisibles. Le dialecte, lui, vient se superposer à tout ça : entre la forme de dictionnaire que contiennent vos documents et ce qu'un agriculteur écrit sur WhatsApp, il y a un monde. La plupart des modèles d'embedding, même multilingues, ne voient pas que « comment j'arrose ma courgette en été » et ازاى اروى الكوسة فى الصيف؟ disent exactement la même chose.

Correctif n° 1 : normaliser la requête, pas les documents

Le gain le plus facile, et le premier venu. Sur chaque requête entrante : diacritiques, tatweel et marques RTL dégagent, et toutes les variantes d'alif se replient sur un seul ا. Le ya devient maqsura. Une seule chose à laquelle je ne touche pas : le ta marbouta. En arabe technique il porte du sens, et le supprimer effaçait des distinctions bien réelles.

La leçon qui m'a coûté plus cher : n'appliquez surtout pas la même normalisation à votre base. Vous y abîmeriez en silence les mots mêmes que les agriculteurs cherchent. On normalise ce qui entre ; on ne touche pas à ce qui est déjà indexé.

text = strip_diacritics(text)
text = re.sub(r"[ٱآإأ]", "ا", text)
text = re.sub(r"ي", "ى", text)
text = re.sub(r"\s+", " ", text).strip()

Correctif n° 2 : réécrire le dialecte en arabe standard, mais figer les noms

La normalisation règle l'orthographe, pas le dialecte. Avant la recherche, la requête passe donc par un petit appel GPT-4o, prompt few-shot, qui repasse l'égyptien parlé en arabe standard.

L'astuce, que presque tout le monde rate, tient dans le prompt : il faut dire au modèle ce à quoi il n'a pas le droit de toucher. Noms de cultures, de pesticides, d'engrais, variétés, chiffres, dates, unités : tout cela reste mot pour mot. Si GPT se met à « traduire » un nom de courgette, votre base ne le retrouvera jamais.

Trois détails ont gagné leur place. Je donne à réécrire la requête d'origine, non normalisée : c'est dans l'orthographe que se logent les indices de registre. Je mets les réécritures en cache sur la forme normalisée, pour que les variantes dialectales tombent dans la même case — les échecs aussi. Et je joue le fail-open : si la réécriture tombe, la recherche repart de la requête brute. Ensuite je lance les deux versions et je fusionne au meilleur score.

Correctif n° 3 : recherche hybride avec le tokenizer arabe

Seule, la recherche vectorielle rate les noms de cultures. Seul, BM25 rate les paraphrases dialectales. À deux, ils se couvrent l'un l'autre. pgvector pour le sémantique, le plein texte Postgres pour les mots-clés, fusion par identifiant de nœud, le meilleur score l'emporte.

Le piège est minuscule et coûteux : par défaut, le plein texte de Postgres tokenise de l'anglais. Sur de l'arabe, il produit de la bouillie. Il faut lui désigner explicitement la configuration arabe. Cette ligne-là a plus fait pour le rappel que toutes mes retouches de prompt réunies.

Correctif n° 4 : recalibrer vos scores de similarité

Les embeddings multilingues ne notent pas l'arabe comme l'anglais. Le seuil de 0,7 que je traînais depuis mes projets anglophones rejetait presque toutes les bonnes réponses arabes : en vrai, les passages pertinents sortaient entre 0,20 et 0,45.

D'où un petit banc d'essai : 20 requêtes, moitié dans le périmètre agricole, moitié hors sujet, en arabe, en français et en anglais. J'en ai tiré un plancher (0,15) et un plafond (0,50) empiriques, puis j'ai remappé le cosinus brut sur une confiance de 0 à 1. Le seuil tombe à 0,30 brut.

Correctif n° 5 : la confiance, ce sont deux questions, pas une

Je demande au LLM de renvoyer sa propre confiance dans sa réponse JSON : {"answer": "...", "confidence": 0.XX}. C'est le signal principal. Je garde max_similarity, côté recherche, comme filet : pour les fois où le JSON part de travers, ou où le modèle hallucine jusqu'à sa propre certitude.

Trois cas de figure :

En agriculture, une dose de travers peut tuer une récolte. Le chemin « je ne sais pas, je vais chercher quelqu'un » n'est pas un pis-aller : c'est une fonctionnalité.

Correctif n° 6 : chaque réponse d'expert nourrit le cerveau

Quand un expert traite une question remontée, la paire question + réponse repart dans la base : un nœud unique, non découpé, étiqueté expert_answer, dans la langue même de l'utilisateur. La prochaine fois qu'un agriculteur pose la même chose en dialecte, ce qu'il touche en premier n'est plus un document générique, mais une réponse d'expert à une vraie question, écrite dans le même registre.

L'essentiel de ce que mon retriever sait aujourd'hui du dialecte n'y était pas au départ. Le système l'a appris tout seul, une escalade après l'autre.

Ce qui a vraiment compté

L'arabe, ce n'est pas de l'anglais écrit avec d'autres lettres. Ce que tapent les gens ne ressemble presque jamais à ce que disent vos documents, et c'est exactement dans cet écart que le RAG se casse sans prévenir. Pris un par un, les correctifs ci-dessus sont dérisoires. Mis bout à bout, ils ont fait passer la recherche de « presque rien » à « utilisable ».

Ce que personne ne dit

Aucun embedding spécialement arabe ne m'a sauvé. Ce qui a marché, c'est une suite d'étapes simples et honnêtes : normaliser les requêtes, réécrire le dialecte sans toucher aux noms, chercher en hybride avec le bon tokenizer, recalibrer les seuils, croiser deux sources de confiance, et boucler avec les experts. Pas de modèle miracle.

/ Un avis ?

Commentaires

Pas de connexion, pas de pistage. Écrivez juste votre nom et votre avis. Restez courtois.

Chargement…
← Précédent J'ai utilisé pip pendant des années. Poetry en équipe. Puis uv est arrivé. Suivant → Ce qu'un boîtier à 250 $ sait vraiment faire : Jetson Orin Nano