Aller au contenu

Le pipeline

flowchart LR
    S[Sources] -->|lecture| D[Document]
    D -->|extraction LLM| F[Faits]
    F -->|consolidation| F2[Faits consolidés]
    F2 -->|sélection| P[Pack]
    F2 -->|indexation| M[Recherche MCP]

1. Lecture

Deux chemins, parce que deux natures de source.

Fichiers — envoyés bruts, convertis côté serveur par pandoc et pdftotext. Personne n'a besoin de préparer sa machine.

Dépôts — six signaux calculés côté CLI :

Signal Contenu
profile Extensions dominantes, volumes par dossier, racine
dependencies go.mod, package.json, pyproject.toml, pom.xml
delivery Dockerfile, Makefile, workflows CI, docker-compose
docs READMEs, ADRs, docs/**/*.md, jusqu'à 25 fichiers
conventions 120 chemins source, 40 chemins de test, configuration de lint
history 120 derniers messages de commit, branches, contributeurs

Les fichiers versionnés sont préférés (git ls-files), ce qui respecte le .gitignore gratuitement.

2. Normalisation

Chaque source devient un Document : identifiant stable, titre, corps markdown, origine lisible, date, empreinte du contenu.

L'identifiant dérive du nom de fichier, jamais d'un chemin absolu : deux personnes déposant le même document depuis deux postes produisent le même identifiant, sans quoi la base se remplirait de doublons.

L'original est archivé dans Blob Storage. Ce n'est pas de la redondance : quand un fait est contesté six mois plus tard, on veut rouvrir le PDF exact, pas sa transcription.

3. Extraction

Un appel LLM par morceau de document, quatre en parallèle.

Découpage aux titres markdown de niveau 1 à 3, jamais au milieu d'une phrase. Morceaux de 22 000 caractères.

Classification demandée dans le même appel : nature du document et date explicite. Le modèle lit déjà le texte, le qualifier ne coûte rien.

Reprise sur troncature. Un passage très dense en règles peut produire plus de JSON que le plafond de sortie du modèle. Plutôt que d'abandonner — et de perdre justement le passage le plus riche — le morceau est recoupé en deux et rejoué, jusqu'à trois fois.

Observé sur le corpus de test

Un document échouait sur troncature. Après re-découpage, il a produit 30 faits — le plus gros contributeur du corpus.

Idempotence. Un marqueur par document stocke l'empreinte de la dernière extraction réussie. Inchangée, le document est sauté.

4. Consolidation

Passe lexicale, automatique. Compare les vocabulaires (Jaccard ≥ 0,62) au sein d'un même type. Le fait le plus riche absorbe les autres : provenances réunies, portées et étiquettes fusionnées, confiance augmentée.

Passe LLM, à la demande. Regroupe les paraphrases, réécrit l'énoncé fusionné, et signale les contradictions au lieu de trancher — les faits concernés passent en conflicting.

5. Sélection

flowchart TD
    F[Faits utilisables] --> R{Runbook détaillé ?}
    R -->|oui| K[Skill]
    R -->|non| T[Tri par priorité]
    T --> B{Dans le budget ?}
    B -->|oui| I[Pack]
    B -->|non| O[MCP seulement]

Les runbooks de plus de 280 caractères de détail deviennent des Skills : volumineux, mais utiles seulement au moment d'exécuter la procédure.

Le reste est trié par priorité — le type pèse plus que la confiance — et empilé jusqu'au budget de lignes du client.

Normalisation des portées à cette étape :

  • le préfixe correspondant au nom d'un dépôt connu est retiré (payment-service/internal/**internal/**) ;
  • une portée universelle (**, *) est supprimée : conservée, elle ferait passer la règle pour spécifique à chaque fichier et noierait les vraies ;
  • les dotfiles sont préservés — une version antérieure transformait .golangci.yml en golangci.yml, produisant un glob qui ne correspondait plus à rien.

6. Émission

Le serveur renvoie le pack en JSON ; le CLI écrit les fichiers, parce que lui seul sait où se trouve le dépôt. C'est aussi ce JSON qui alimente le cache hors ligne.

Voir Les deux canaux de livraison.