Étude § 02 · Mission de conseil

Plateforme d’analytics locale pour un réseau national de distribution

Conseil · local-first · 10 M LIGNES · DUCKDB · MESA · GATE IA

Mission de conseil pour un réseau de distribution national en France, avec plusieurs centaines de magasins organisés en dizaines de regroupements régionaux. Les utilisateurs finaux sont une équipe métier et data, pas des développeurs, donc l’ensemble du produit s’exécute en application locale lancée depuis un seul fichier : un backend FastAPI et un frontend React/TypeScript tournant côte à côte sur la machine de l’utilisateur.

Une contrainte dure a gouverné toute la conception : les données ne quittent jamais cette machine. Pas de cloud, pas d’appel externe. Le client dépose dans l’application un unique fichier de ventes d’environ 10 millions de lignes (2,6 Go), et le logiciel produit seul l’analyse complète du réseau, des simulations multi-agents à 36 mois, et des interprétations des résultats rédigées par l’IA.

Le problème : une IA qui commente des chiffres métier devant des dirigeants est à une hallucination de faire échouer le produit. Pendant les tests, l’assistant intégré a un jour répondu à une question sur un magasin avec un chiffre correct, mais pour tout le réseau : chiffre réel, calcul juste, périmètre faux, sans lever d’erreur.

Une réponse presque juste dite avec une confiance totale est pire qu’une réponse fausse. Le système devait être conçu pour que cette classe d’erreur soit structurellement impossible, pas seulement improbable.

Toute l’architecture est construite autour d’une liste d’interdits : ce que l’IA n’a pas le droit de faire.

Schéma : plateforme d'analytics locale, du fichier au résultat auditéUn fichier local de 2,6 gigaoctets est lu en streaming par DuckDB en environ 5 secondes selon un contrat de 22 colonnes, puis traité en parallèle par des moteurs déterministes et une simulation Mesa de 2 000 agents sur 36 mois en 160 réplications. Les résultats sont gelés avec un intervalle de confiance à 95 %, puis passent une porte d'audit sur quatre critères : fidélité, cohérence, confiance et structure. En cas de succès ou d'avertissement, le résultat s'affiche à l'écran ; en cas d'échec, un résumé déterministe s'affiche à la place. Un modèle de langage, connecté à part en pointillés, reformule les artefacts gelés pour l'écran mais ne calcule jamais lui-même.FAILPASS/WARNFICHIER LOCAL 2,6 GBDUCKDB STREAMING~5 S · CONTRAT 22 COLONNESMOTEURS DÉTERMINISTESSIMULATION MESA2 000 AGENTS · 36 MOIS160 RÉPLICATIONSARTEFACTS GELÉS · IC 95 %GATE D'AUDITFIDÉLITÉCOHÉRENCECONFIANCESTRUCTURERÉSUMÉ DÉTERMINISTEÉCRANLLMREFORMULE· NE CALCULEJAMAISSchéma : plateforme d'analytics locale, du fichier au résultat auditéUn fichier local de 2,6 gigaoctets est lu en streaming par DuckDB en environ 5 secondes selon un contrat de 22 colonnes, puis traité en parallèle par des moteurs déterministes et une simulation Mesa de 2 000 agents sur 36 mois en 160 réplications. Les résultats sont gelés avec un intervalle de confiance à 95 %, puis passent une porte d'audit sur quatre critères : fidélité, cohérence, confiance et structure. En cas de succès ou d'avertissement, le résultat s'affiche à l'écran ; en cas d'échec, un résumé déterministe s'affiche à la place. Un modèle de langage, connecté à part en pointillés, reformule les artefacts gelés pour l'écran mais ne calcule jamais lui-même.FAILPASS/WARNFICHIER LOCAL 2,6 GBDUCKDB STREAMING~5 S · CONTRAT 22 COLONNESMOTEURSDÉTERMINISTESSIMULATION MESA2 000 AGENTS36 MOIS160 RÉPLICATIONSARTEFACTS GELÉS · IC 95 %GATE D'AUDITFIDÉLITÉCOHÉRENCECONFIANCESTRUCTURERÉSUMÉ DÉTERMINISTEÉCRANLLMREFORMULE· NE CALCULE JAMAIS
SCHÉMALe pipeline du fichier local à l’écran, avec le gate d’audit.

Le système est construit autour de ce que l’IA n’a pas le droit de faire. Le LLM ne calcule jamais un chiffre : des moteurs déterministes calculent tout, et les résultats sont figés au moment de la génération avec leurs marges d’incertitude. L’affichage lit toujours les artefacts figés ; rien n’est jamais régénéré au moment du rendu, si bien que la même question ne peut jamais renvoyer discrètement deux réponses différentes. Chaque KPI affiché correspond à un champ backend dédié, et le frontend ne réagrège, ne filtre ni ne dérive jamais de chiffres de son propre chef. Les constantes métier vivent dans une unique source de vérité Python, répliquée vers TypeScript, avec un test de CI qui fait échouer le build si un nombre magique apparaît ailleurs. Chaque interprétation de l’IA passe un audit automatisé avant d’atteindre l’écran, qui vérifie la fidélité des chiffres par rapport aux agrégats figés, la cohérence des recommandations par rapport au modèle de scoring déterministe, un seuil de confiance, et la validation de la structure de sortie. Le gate renvoie PASS, WARN ou FAIL : en cas de FAIL, l’utilisateur voit un résumé déterministe brut à la place du texte de l’IA. Les identifiants de scénario et le schéma de sortie JSON sont traités comme des invariants de compatibilité frontend : la couche IA peut changer, le contrat ne le peut pas.

Le fichier de ventes de 2,6 Go rendait tout chemin naïf physiquement impossible : les outils tableur plafonnent autour d’un million de lignes, et un chargement complet en mémoire ne tient pas. L’ingestion passe par un streaming DuckDB directement depuis le chemin du fichier sur disque, sans aucun transfert des données elles-mêmes, et se termine en environ 5 secondes, validation comprise, contre un contrat de schéma strict à 22 colonnes. Le problème le plus brut venait d’en amont : une colonne critique de classification de gamme produit arrivait à 84 % nulle. Plutôt que d’imputer ou de dégrader silencieusement, le pipeline a verrouillé le KPI phare concerné, affiché comme indisponible avec la raison, et a quantifié l’écart avec assez de précision pour que l’équipe data du client puisse reconstruire la classification à la source et réexporter un fichier complet. Mesurer rigoureusement un trou de données s’est révélé le moyen le plus rapide de le corriger.

La projection de scénarios s’appuie sur une simulation multi-agents Mesa : un échantillon stratifié d’agents clients (2 000 dans la configuration de référence, testé en charge jusqu’à 30 000) simulé sur 36 mois, répliqué façon Monte-Carlo avec un critère de convergence explicite ; le scénario phare a convergé à 160 réplications. Chaque chiffre clé est livré sous forme de fourchette avec son intervalle de confiance à 95 %, jamais comme un point isolé. Le pipeline initial chargeait les 10 millions de lignes avant d’échantillonner les agents ; en inversant l’ordre, en échantillonnant d’abord la population d’agents puis en ne chargeant que leur historique, une simulation complète est passée de 27 minutes à environ 2 minutes, et cette optimisation n’a été acceptée qu’après qu’une reproduction octet par octet d’une exécution de référence figée a prouvé qu’elle ne changeait rien aux résultats. Le calibrage a fixé la limite de l’honnêteté : les projections au niveau agrégé étaient statistiquement solides, mais à la granularité infra-réseau, la variance imposait un plafond strict au nombre de regroupements pouvant être certifiés, et ajouter des agents ne le relevait pas. Plutôt que de publier des écarts par regroupement que les statistiques ne pouvaient pas garantir, le produit n’expose les résultats qu’au niveau de granularité qu’il peut défendre, et l’indique à l’écran.

L’assistant suit la même doctrine que le reste du système. Une question passe par une analyse d’intention et une résolution de périmètre, le backend exécute une requête déterministe et calcule le chiffre exact, et le LLM se contente de formuler la réponse. Les questions hors périmètre reçoivent un refus explicite, jamais une supposition. La logique de périmètre a été testée dans les deux sens : non seulement si elle peut donner une réponse fausse, mais aussi si elle peut refuser une question légitime. Le passage final sur 33 questions est ressorti net sur les deux plans : zéro réponse fausse, zéro refus injustifié. L’un sans l’autre aurait donné soit un système qui ment, soit un assistant inutile.

Stack: Python, FastAPI, React, TypeScript, Vite, DuckDB, Mesa, scikit-learn, [LLM RUNTIME : À COMPLÉTER PAR BAPTISTE]

Qualité de la donnée

Une colonne de classification de gamme produit arrivant à 84 % nulle a été verrouillée, pas imputée : le KPI phare concerné s’affiche comme indisponible, avec la raison, plutôt que d’être calculé sur des données incomplètes.

Quantifier l’écart avec assez de précision a permis à l’équipe data du client de reconstruire la classification à la source et de réexporter un fichier complet : mesurer le trou a été le moyen le plus rapide de le corriger.

Vitesse vs preuve

En inversant le pipeline de simulation, en échantillonnant la population d’agents avant de charger leur historique, une exécution complète est passée de 27 minutes à environ 2 minutes.

L’optimisation n’a été acceptée qu’après qu’une reproduction octet par octet d’une exécution de référence figée a prouvé qu’elle ne changeait rien aux résultats : la vitesse n’a jamais été une justification en soi.

Plafond de granularité

La granularité infra-réseau est plafonnée à l’écran au niveau que les statistiques peuvent réellement certifier.

La variance sur les regroupements plus fins imposait un plafond strict qu’ajouter des agents ne relevait pas, donc le produit ne publie pas d’écarts par regroupement qu’il ne peut pas garantir.

Discipline de livraison

Un scénario de stress dont le mécanisme de compensation produisait un artefact connu a été masqué de la livraison plutôt qu’affiché avec une réserve.

Un chiffre indéfendable n’était pas affiché, réserve ou pas.

Livrée en application locale installée chez le client. Validation finale sur 33 questions : zéro réponse fausse, zéro refus injustifié.

Concevoir un système IA structurellement incapable d’inventer un chiffre, de l’ingestion des données à la simulation, jusqu’à la réponse affichée à l’écran.