Retour à l'accueil

RAG juridique ARLC 2026 : 17 itérations pour atteindre 0.791

L'article décompose le pipeline RAG pour le défi juridique ARLC 2026 : de la première soumission avec grounding 0.05 à 0.791. Décrit l'architecture avec indexation au niveau page, recherche hybride RRF, reclassement cross-encoder et fast-paths pour réponses typées. Analyse de la chute de performance en passant de 30 à 300 documents.

RAG sur PDFs juridiques : de l'échec au meilleur score ARLC
Advertisement 728x90

RAG juridique à l'ARLC 2026 : de 0,034 à 0,791 en 17 itérations avec analyse d'échelle

Dans le cadre du défi juridique ARLC 2026, le pipeline RAG partait d'un score de fondation de 0,05 et d'un score global de 0,034. Les réponses déterministes (S_det) avaient déjà atteint 0,857, mais le facteur G annulait les résultats. Le problème provenait du format du doc_id : submission.json attendait le nom de fichier sans l'extension '.pdf', tandis que le code transmettait le nom complet. Corriger une seule ligne a fait passer G à 0,55 et le score global à 0,438 — une amélioration de 13 fois.

Leçon pour les développeurs RAG : valider le format de soumission doit précéder toute optimisation de récupération. Même un reranking parfait est inutile sans une correspondance correcte entre (doc_id, numéro_de_page).

Architecture du pipeline : ingestion au niveau page et recherche hybride

Le pipeline indexe des pages entières, sans découpage. Cela simplifie la fondation au niveau page, mais nécessite une distillation de contexte avant traitement par LLM.

Google AdInline article slot

Analyse PDF avec sauvegarde OCR

def extract_pages(pdf_path, min_chars=50, ocr_dpi=300):
    pages = []
    doc = pdfplumber.open(pdf_path)
    for i, page in enumerate(doc.pages):
        text = page.extract_text() or ""
        if len(text.strip()) < min_chars:
            text = ocr_page(pdf_path, i + 1, dpi=ocr_dpi)
        pages.append({
            "doc_id": pdf_path.stem,      # sans .pdf !
            "page_number": i + 1,
            "text": text
        })
    return pages

Le code gère les PDF numérisés via OCR lorsque le texte extrait est trop court. Le doc_id utilise le nom de base sans extension ; le numéro de page est basé sur 1.

Recherche hybride avec fusion de rang inverse (RRF)

Combinaison de BM25 pour les correspondances exactes et des embeddings pour la sémantique, via la fusion de rang inverse (k=60) :

def hybrid_search(query, bm25_index, embedding_index, pages, top_k=20, rrf_k=60):
    bm25_scores = bm25_index.get_scores(tokenize(query))
    bm25_ranked = sorted(range(len(pages)), key=lambda i: -bm25_scores[i])

    q_emb = embed_model.encode([query[:512]], normalize_embeddings=True)
    sim_scores = (embedding_index @ q_emb.T).flatten()
    emb_ranked = sorted(range(len(pages)), key=lambda i: -sim_scores[i])

    combined = {}
    for rank, idx in enumerate(bm25_ranked[:top_k * 3]):
        combined[idx] = combined.get(idx, 0) + 1.0 / (rrf_k + rank)
    for rank, idx in enumerate(emb_ranked[:top_k * 3]):
        combined[idx] = combined.get(idx, 0) + 1.0 / (rrf_k + rank)

    return sorted(combined, key=lambda i: -combined[i])[:top_k]

Modèle d'embeddings : all-MiniLM-L6-v2 (22M paramètres). La RRF ne nécessite pas de normalisation d'échelle — elle fonctionne directement sur les rangs.

Google AdInline article slot

Reranking et étiquetage de priorité

Un cross-encodeur (ms-marco-MiniLM-L-6-v2) reclasse les 30 meilleures pages. Une limite stricte de 30 empêche l'explosion du temps de première réponse (TTFT) en O(N²).

def rerank(pages, query, top_k=5):
    HARD_CAP = 30
    priority = [p for p in pages if p.get("_priority")]
    non_priority = pages[:HARD_CAP - len(priority)]

    all_pages = priority + non_priority
    pairs = [(query, p["text"][:512]) for p in all_pages]
    scores = cross_encoder.predict(pairs)

    for i, p in enumerate(all_pages):
        if p.get("_priority"):
            scores[i] = 1000.0

    ranked = sorted(zip(scores, all_pages), key=lambda x: -x[0])
    return [p for _, p in ranked[:top_k]]

Les pages prioritaires (pages de titre, articles) obtiennent un score de 1000 — garantissant leur inclusion dans le contexte.

Routage documentaire pour les requêtes comparatives

Pour les questions comme « qui a été nommé en premier dans CFI 001/2020 vs CFI 002/2021 », un index de pages de titre est construit :

Google AdInline article slot
  • Modèles : CFI 010/2024 → doc_id
  • Requête double avec entrelacement round-robin des contextes

Chemins rapides déterministes pour les réponses typées

Types : nombre (±1 %), booléen, nom (exact), date (YYYY-MM-DD), noms (Jaccard), texte libre (jugement par LLM).

Exemples d'extraction par regex :

  • Numéro de loi : re.search(r"(?:DIFC\s+)?Law\s+No\.\s*(\d+)")
  • Date d'émission : analyser les premières pages avec Date of Issue[:\s]+(\w+ \d+,?\s+\d{4})
  • Montants : extraire les prétentions monétaires via case_ref

Les chemins rapides économisent 700 ms sur les appels Haiku, en retournant la réponse + la fondation.

Formule de notation et optimisation du TTFT

Total = (0,7 × S_det + 0,3 × S_asst) × G × T × F
  • G (F-beta, β=2,5) : fondation au niveau page — le multiplicateur clé
  • F : <1000 ms → +5 %, >3000 ms → -15 %

| TTFT (ms) | Multiplicateur |

|-----------|----------------|

| <1000 | 1,05 |

| <2000 | 1,02 |

| <3000 | 1,00 |

| >3000 | 0,85–0,99 |

Mur d'échelle : phase de préchauffage vs finale

Sur 30 documents (préchauffage), le score était de 0,791. Sur 300 (phase finale), il a chuté de 42 %. Causes :

  • Plus grand corpus dilue la qualité de récupération
  • Le TTFT croît linéairement avec la taille
  • Le reranking sur 300+ pages nuit à F

Optimisations finales : mise en cache des embeddings, batchage du cross-encodeur, arrêt anticipé dans la recherche hybride.

Ce qui compte vraiment

  • Indexation au niveau page : simplifie la fondation mais exige une distillation de contexte.
  • RRF (k=60) : fusion optimale de BM25 + embeddings sans normalisation.
  • Étiquetage de priorité : assure que les pages critiques sont toujours présentes.
  • Chemins rapides : regex pour 80 % des requêtes typées réduit fortement le TTFT.
  • Approche TTFT-first : la vitesse donne un bonus de +5 % gratuitement à qualité égale.

— Editorial Team

Advertisement 728x90

Lire ensuite