Guides
Un second avis sur les scores d’un autre outil
Votre score d’évaluation a augmenté. Est-ce réel ? Et pouvez-vous faire confiance au juge qui l’a mesuré ? Si vous évaluez déjà avec un autre outil, exportez ses résultats par cas avant et après un changement, et Oloproof répond aux deux questions sur ces résultats sans rien exécuter à nouveau.
Ce qu’il lit
Un fichier par version du système, en CSV ou en JSON Lines, avec une ligne par cas et par critère :
| Colonne | Ce qu’elle contient |
|---|---|
| case_id | L’identifiant du cas. Deux fichiers ne s’apparient que sur un identifiant qu’ils contiennent tous les deux |
| criterion | Le nom de la métrique, qui devient la métrique que nomme une règle |
| score | Un nombre sur l’échelle de la métrique, ou vide si l’outil n’a pas noté ce cas |
| passed | true ou false à la place d’un score, ou vide |
| score_min, score_max | L’échelle sur laquelle se situe un score (0 et 1 pour la plupart des outils), obligatoire pour un score |
| judge, judge_version | Le modèle qui a jugé, si c’est un modèle qui a jugé. Facultatif |
Rien d’autre n’est lu, et un fichier qui a une autre colonne est refusé : un fichier contient des identifiants de cas et des scores, jamais une question, une réponse ni aucun autre contenu. Les recettes ci-dessous transforment les résultats de chaque outil en ce fichier.
L’exécuter
oloproof init --example second-opinion second-opinion
cd second-opinionL’exemple contient deux exports de la fidélité d’un assistant de support sur 150 questions, avant et après un changement de prompt, tels que le juge d’un autre outil les a notés : un score de 0 à 1, et sa réussite ou son échec à 0.7. make_exports.py est la simulation qui les a écrits. Le score moyen a augmenté d’environ 0.02.
oloproof scores import before.csv after.csv --policy release.yamlfaithfulness: +0.023 [-0.024, +0.068] · 150 paired · 0 missing · 0 excluded
faithfulness_passed: +5.3 points [-6.9, +18.0] · 150 paired · 0 missing · 0 excluded
Decisions
score-went-up faithfulness superiority INSUFFICIENT_EVIDENCE evaluator_not_validated
more-answers-pass faithfulness_passed superiority INSUFFICIENT_EVIDENCE evaluator_not_validated
Gate: BLOCK (exit 3)
score-went-up, more-answers-pass: the judge (or model or custom evaluator) behind these rules has not been measured against people yet, so it may not decide.Chaque fichier est devenu une exécution, et les deux exécutions ont été comparées cas par cas. La réponse a deux moitiés.
- Est-ce réel ? Pas encore. Le score a augmenté de 0.023, mais l’intervalle va de 0.024 de moins à 0.068 de plus : avec 150 questions, un changement aussi petit ne peut pas être distingué du bruit. La part des réponses que le juge fait réussir a augmenté de 5.3 points, avec un intervalle allant de 6.9 points de moins à 18.0 de plus.
- Pouvez-vous faire confiance au juge ? Personne ne l’a vérifié. release.yaml ne laisse un juge décider d’une publication qu’une fois que des étiquettes posées par des personnes l’ont mesuré (require_validated_evaluators: true), donc les deux règles s’arrêtent à evaluator_not_validated avant d’atteindre l’intervalle.
Pour voir la première moitié seule, comme si le juge avait été vérifié :
oloproof scores import before.csv after.csv --policy statistics-only.yaml score-went-up faithfulness superiority INSUFFICIENT_EVIDENCE interval_overlaps_zero
more-answers-pass faithfulness_passed superiority INSUFFICIENT_EVIDENCE interval_overlaps_zeroEn CI, ajoutez --summary markdown >> "$GITHUB_STEP_SUMMARY" : la pull request s’ouvre alors sur « Is it real? » et une ligne par règle, qui dit « not established » et pourquoi, et le code de sortie est le même. Les lignes propres à l’import vont sur la sortie d’erreur standard, si bien que le résumé ne reçoit que la réponse (CI).
Sans --policy, la commande rapporte la comparaison et ne décide rien. Avec un seul fichier, elle rapporte cette exécution, et --policy la soumet à une porte selon les règles d’exécution de la politique.
Vérifier le juge
Des personnes étiquettent un échantillon aléatoire des cas d’une exécution importée, en aveugle par rapport au juge, et Oloproof mesure le juge par rapport à elles :
oloproof labels export RUN_ID --criterion faithfulness_passed --sample 60 --out sample.csv
oloproof labels import sample.csv
oloproof evaluators validate EVALUATOR_ID --by NAMEL’échantillon montre l’identifiant de chaque cas et rien du verdict du juge. L’étiqueteur lit le cas dans l’outil qui le contient, par son identifiant, et écrit pass ou fail dans passed. oloproof evaluators list donne l’identifiant de l’évaluateur. Une fois validé, les règles qui lisent ce juge décident sur les seules preuves.
Les étiquettes sont une réussite ou un échec, donc elles vérifient le verdict de réussite ou d’échec d’un juge, pas son score. Importez le verdict à côté du score, comme le fait l’exemple avec faithfulness_passed : c’est le critère que des personnes peuvent valider.
Depuis votre outil
Le dossier recipes/ de l’exemple contient un court script par outil. Chacun lit les résultats de cet outil et écrit le fichier, en ne gardant que les identifiants et les scores. Exécutez-en un par version, puis importez les deux fichiers.
| Outil | Recette | Ce qui identifie un cas d’une exécution à l’autre | Remarques |
|---|---|---|---|
| DeepEval | deepeval_results.py RESULTS_JSON OUT | Le name du cas de test | Enregistrez les résultats avec DisplayConfig(results_folder=...) et nommez chaque LLMTestCase. Chaque métrique donne son score et sa réussite ou son échec sous la forme <metric>_passed, avec le modèle juge |
| Braintrust | braintrust_experiment.py PROJECT EXPERIMENT OUT | L’enregistrement du jeu de données que l’expérience a exécuté (origin.id) | Scores de 0 à 1 ; --judge nomme le modèle si un seul les a tous jugés |
| LangSmith | langsmith_experiment.py EXPERIMENT OUT --scale LOW HIGH | L’exemple du jeu de données (reference_example_id) | Un score vrai ou faux devient une réussite ou un échec ; un nombre a besoin de son échelle |
| Langfuse | langfuse_experiment.py EXPERIMENT SINCE OUT | L’élément du jeu de données (experiment_item_id) | Les expériences de Langfuse 5 ; scores numériques sur la plage de leur configuration de score, ou --scale |
Les recettes suivent le SDK de chaque outil tel que publié le 16 octobre 2026 (DeepEval 4.3.1, braintrust 0.46.1, langsmith 0.14.11, langfuse 5.0.2) et sont testées sur des résultats de cette forme, pas sur un compte réel. Un outil qui renomme un champ casse sa recette, pas l’import : le fichier qu’elle écrit est le contrat.
Ce qu’un fichier doit respecter
- Un cas présent dans un seul fichier est manquant de l’autre côté, compté et borné au pire ; il n’est jamais apparié avec un autre cas.
- Une deuxième ligne pour un même cas et un même critère, un score en dehors de score_min et score_max, une ligne qui a à la fois un score et une réussite ou un échec, et un critère qui est un score dans un fichier et une réussite ou un échec dans l’autre sont refusés, avec le nom de la ligne.
- Les fichiers comparés doivent s’accorder sur l’échelle et le juge de chaque critère : les scores de deux juges sont deux instruments, et leur écart serait en partie celui des instruments.
- Chaque fichier est une version du système identifiée par son contenu. Importer de nouveau le même fichier réutilise ce qui a été stocké ; rien n’est jamais exécuté, donc aucune réexécution ne peut reproduire ni modifier un score importé.
- --tool enregistre d’où viennent les scores, et --name nomme le système de chaque fichier ; les deux sont conservés avec l’exécution.
Ce qui n’est pas construit
- Lire directement le format d’export propre à un outil : une recette le transforme en le fichier ci-dessus.
- Téléverser les fichiers sur le site hébergé sans rien installer.
- Valider les scores d’un juge, par opposition à ses verdicts de réussite ou d’échec.
Pour aller plus loin
- Comparer un candidat à une référence : ce que lit une comparaison appariée.
- Règles de comparaison : supériorité, non-infériorité et équivalence.
- Juges : comment un juge est mesuré par rapport à des personnes avant de pouvoir servir de porte.