Système multi-agents pour le challenge automatisé d'indicateurs de risque opérationnel basé sur la méthode XOI (Exposure, Occurrence, Impact).
Chaque indicateur (probabilité d'occurrence, durée, coût, ratio…) est confronté à des sources externes faisant autorité (régulateurs, instituts académiques, rapports sectoriels) pour produire un verdict argumenté : Corroboration / Refutation / Not Applicable.
État courant : 27 scénarios audités (19 Probability + 8 Distribution), benchmarks Search Perplexity vs Anthropic web_search.
Trois agents séquentiels :
| Agent | Rôle | Sortie |
|---|---|---|
| Search | Trouver des sources externes autoritaires | search_output.json (sources scorées 1-10) |
| Compare | Formaliser le challenge en représentation comparable à l'indicateur | compare_output.json (challenge_candidates ou observed_distribution) |
| Decide | Produire un verdict argumenté avec corrections de scope | decide_output.json (verdict + reasoning) |
Le routage Probability vs Distribution est schema-driven : la présence
d'indicator.distribution_spec dans l'entrée déclenche la branche Distribution
(TVD + masse hors-spec + summary_check), sinon la branche Probability (ratio
adjusted_value / reference_value avec corrections single-coef par dimension).
Chaque agent enchaîne plusieurs passes LLM, chacune confiée au modèle adapté.
Le provider est inféré du nom du modèle (claude-* → Anthropic, gpt-* →
OpenAI, sonar* → Perplexity, mistral-* → Mistral) — une seule var par étape
dans .env.
- QueryBuilder (gpt-4o) — analyse l'indicateur et produit 4-6 stratégies
ciblées (régulateur, académique, industrie, base d'incidents, case studies)
avec
search_domain_filteretsearch_recency_filter. - N appels Perplexity (sonar) en parallèle — un par stratégie, fusion + déduplication par URL, validation HTTP des URLs (browser UA + fallback SSL).
Variante standalone disponible via tools/test_anthropic_websearch.py —
1 seul appel Claude Sonnet 4.6 avec tool web_search_20250305
(max_uses=5) qui décide lui-même ses queries en mode agentic. Voir
docs/SEARCH.md pour le benchmark sonar vs Anthropic
web_search sur les 27 scénarios.
Deux modes d'exécution, sélectionnés par la var COMPARE_SINGLE_PASS du
.env.
Un seul appel LLM qui fusionne Reader + Formalizer.
- Récupération du document : priorité
local_path>url>key_figures(téléchargement direct viafetch_and_extract_documentavec browser UA + fallback SSL). - Filter pipeline :
pymupdf4llm(PDF→Markdown) +trafilatura(HTML→Markdown), nettoyage boilerplate, scoring BM25 + bonus chiffres si >15k chars (cf. docs/EXTRACTION_AND_FILTERING.md). - Single-pass (claude-sonnet-4-6) — Sonnet lit le document filtré et
produit directement les
challenge_candidates(mode Probability) ou l'observed_distributionre-bucketisée sur la spec (mode Distribution), formatés en JSON strict avec scope, missing_data, condition_range éventuel.
Mode utilisé en production sur les 27 scénarios audités.
Trois phases LLM, utile si la qualité du single-pass dégrade ou pour isoler les responsabilités.
- Deep Extract (sonar) — Perplexity lit le document en profondeur et liste tous les chiffres pertinents. Déclenché uniquement si le document n'est pas téléchargeable (page JS, accès protégé) ; sinon l'extraction directe est utilisée et Deep Extract est ignoré.
- Reader pass A (claude-sonnet-4-6) — Sonnet relit l'extraction et
produit des
challenge_candidates. - Formalizer pass B (gpt-4o) — formate le candidat en JSON strict.
À ce jour, 0/27 runs ont effectivement déclenché Deep Extract en mode
multi-pass : les URLs sont quasi toutes fetchables (96% Perplexity, 86%
Anthropic) et les hard cases anti-bot passent par local_path. Le mode
multi-pass reste disponible mais n'est plus la branche par défaut.
- Pass 1 (claude-sonnet-4-6) — identifie les dimensions de scope
(Région, Période, Secteur, Taille, Type d'incident…) avec un coefficient
unique de correction par dimension (
single-coef). Région et Période strictement à 1.0 (déjà capturées parraw_formula). - Python eval — calcule par candidat :
- Probability :
adjusted_value = raw_value × Π(corrections)puisadjusted_ratio = adjusted_value / reference_value. - Distribution :
tvd = ½·Σ|chl_pmf − ref_pmf|,in_range_mass,oor_above/below_mass,summary_check(mean/median observed vs spec implied).
- Probability :
- Pass 2 (gpt-4o) — produit verdict + reasoning par candidat puis un
overall. Une baseline déterministe (table TVD/OOR ou ratio/mean) est conservée dansverdict.deterministic_baseline.
Lookup web optionnel via Perplexity pour vérifier les dénominateurs
(DECIDE_WEB_LOOKUP=true) — désactivé par défaut. Voir
docs/COMPARE.md et docs/DECIDE.md pour
la branche Distribution dans les agents.
TrustAgent/
├── main.py # Point d'entrée CLI
├── config/settings.py # Configuration .env (modèles par étape)
├── data/
│ ├── scenarios/ # 18 scénarios JSON (ABC, ATC, BLD, …)
│ ├── contexts/ # general_context.json (XOI)
│ └── runs/ # 27 dossiers de run (un par indicateur)
│ ├── ABC_probability/ # ABC – Probabilité corruption
│ ├── ATC_probability/ # ATC – Probabilité antitrust
│ ├── ATC_revenue_gain/ # ATC – Surcharge cartel (%)
│ ├── … # (cf. tableau ci-dessous)
│ └── WTF_probability/
├── src/
│ ├── domain/ # Modèles métier (Scenario, Indicator…)
│ ├── agents/ # Search, Compare, Decide, QueryBuilder, Lookup
│ ├── llm/ # Providers (OpenAI, Perplexity, Anthropic, Mistral)
│ ├── prompts/ # Templates de prompts par agent (few-shot)
│ ├── io/ # Schémas, document_extractor (fetch + filter)
│ └── pipeline/ # Orchestrator
├── tools/ # Scripts d'audit/benchmark (pas dans le pipeline)
│ ├── test_anthropic_websearch.py # Search standalone Anthropic
│ ├── test_perplexity_models.py # Comparatif sonar/sonar-pro/reasoning-pro
│ └── audit_compare_filter.py # Audit rétention chiffres-clés
├── docs/ # Documentation détaillée
└── tests/ # 22 tests unitaires
# 1. Cloner le repo
git clone https://github.com/baptisteduperray/TrustAgent.git && cd TrustAgent
# 2. Créer un virtual environment
python -m venv .venv
.venv\Scripts\activate # Windows
# source .venv/bin/activate # Linux/Mac
# 3. Installer les dépendances
pip install -r requirements.txt
# 4. Configurer les clés API et les modèles
cp .env.example .env
# Éditer .env : remplir les clés API et ajuster les modèles par étape si besoinLe .env est la source de vérité unique pour les modèles. Le provider est
inféré du nom du modèle.
# Clés API
OPENAI_API_KEY=sk-...
PERPLEXITY_API_KEY=pplx-...
ANTHROPIC_API_KEY=sk-ant-...
# Modèles par étape (provider inféré)
SEARCH_MODEL=sonar
QUERY_BUILDER_PASS1_MODEL=gpt-4o
COMPARE_DEEP_EXTRACT_MODEL=sonar
COMPARE_READER_MODEL=claude-sonnet-4-6
COMPARE_FORMALIZER_MODEL=gpt-4o
DECIDE_PASS1_MODEL=claude-sonnet-4-6
DECIDE_PASS2_MODEL=gpt-4o
# Search standalone Anthropic (tools/test_anthropic_websearch.py)
SEARCH_ANTHROPIC_MODEL=claude-sonnet-4-6
SEARCH_ANTHROPIC_MAX_USES=5Voir .env.example pour la liste complète.
# Lancer Search sur un scénario
python main.py search data/runs/CSD_probability/search_input.json
# Lancer Compare puis Decide (après Search + sélection humaine du challenge)
python main.py compare data/runs/CSD_probability/compare_input.json
python main.py decide data/runs/CSD_probability/decide_input.json
# Pipeline complet avec pause pour validation humaine
python main.py pipeline data/runs/CSD_probability/search_input.json
# Reprendre après validation humaine (sélection du challenge)
python main.py resume CSD_probability
# Forcer un run_id custom (ex. pour test)
python main.py search data/runs/CSD_probability/search_input.json --run-id _testNote : le flag --provider du CLI est ignoré depuis le refactor —
les providers sont définis par étape via .env (modèle → provider inféré).
| ID | Scénario | Indicateurs |
|---|---|---|
| ABC | Anti-Bribery & Corruption | probability |
| ATC | Anticompetitive Practices | probability, revenue_gain |
| BLD | Building Destruction | probability |
| BSM | Bank Sustainability Misrepresentation | probability_greenwashing, probability_litigation |
| CAF | Corporate Action Failure | probability |
| CDA | Cyber-Attack Data Alteration | probability, duration |
| CDC | Customer Data Compromise | probability, cost (conditional ×3) |
| CSD | Critical Service Disruption | probability, duration |
| CYS | Cyber-Attack Critical Service | probability, duration |
| FID | Fund Improper Disclosure | probability |
| FNC | Financial Crime | probability |
| MCC | Merchant Card Compromise | probability, fraud_ratio (conditional ×4) |
| OVC | Client Overcharging | probability |
| TRE | Trading Error | probability, detection_time |
| URT | Unauthorized Rogue Trading | probability, position_size |
| WCA | Workplace Class Action | probability |
| WTE | Wire Transfer Error | probability |
| WTF | Wire Transfer Fraud | probability |
En gras : indicateurs Distribution (8 au total). Le reste : Probability (19).
Synthèse des verdicts (détails dans docs/RESULTS_PROBABILITY.md et docs/RESULTS_DISTRIBUTION.md) :
| Mode | Corroboration | Refutation | Incomplet | Total |
|---|---|---|---|---|
| Probability | 14 (74%) | 5 (26%) | 0 | 19 |
| Distribution | 2 (25%) | 5 (62.5%) | 1 (12.5%) | 8 |
| Total | 16 | 10 | 1 | 27 |
pytest tests/ -v22 tests : agents (Search/Compare/Decide), domain, providers, parsing.
| Doc | Contenu |
|---|---|
| docs/ONBOARDING.md | Onboarder un nouveau scénario Probability de zéro (pas-à-pas) |
| docs/AVIS_ET_PISTES.md | Avis rétrospectif sur le pipeline + pistes d'évolution |
| docs/VERDICTS.md | Détail des 27 verdicts (top 3 sources, source explorée, candidat, verdict) |
| docs/SEARCH.md | Agent Search en détail + benchmark Perplexity vs Anthropic |
| docs/COMPARE.md | Agent Compare en détail (modes single/multi-pass, formats Probability/Distribution, schema fidelity) |
| docs/DECIDE.md | Agent Decide en détail (Pass 1 / Python eval / Pass 2, baseline déterministe, web lookup) |
| docs/EXTRACTION_AND_FILTERING.md | Pipeline fetch → extract → clean → filter |
| docs/RESULTS_PROBABILITY.md | Audit 19 scénarios Probability (run 2026-04-29) |
| docs/RESULTS_DISTRIBUTION.md | Audit 8 scénarios Distribution (run 2026-04-30) |