Skip to content

Commencer

L’API Python

La version anglaise de cette page a changé depuis sa traduction. La page anglaise est la version à jour. La lire en anglais

Tout ce que fait la CLI, la bibliothèque le fait. Utilisez-la quand l’évaluation a sa place dans un script, un notebook ou une suite de tests plutôt qu’à côté d’un fichier de configuration.

from oloproof import evaluate, system, current_case
from oloproof.evaluators import ExactMatch, Contains, JsonSchema, Regex, RubricJudge, evaluator

Tout ce qui se trouve sous oloproof_core relève des composants internes du moteur et ne fait pas partie de cette surface.

Un système reçoit l’entrée d’un cas, pas le cas

C’est la seule chose qu’il vaut la peine de réussir en premier, parce que s’y tromper échoue sans bruit.

@system(name="support-bot", version="1")
def answer(case):
    return {"label": "refund" if "refund" in case["question"].lower() else "other"}

Une ligne de jeu de données ressemble à ceci :

{"id":"refund_00","input":{"question":"Can I get a refund? #0"},"expected":{"label":"refund"}}

La fonction reçoit l’objet input : case["question"] est donc la question, et il n’y a pas de case["expected"]. Ce qu’elle renvoie est la sortie que lit un évaluateur ; ainsi ExactMatch(field="label") compare le label renvoyé au label attendu du cas.

En exécuter un

result = evaluate(
    system=answer,
    dataset="data/example.jsonl",
    evaluators=[ExactMatch(criterion="exact_label", field="label")],
)

for metric in result.metrics:
    print(metric.metric, metric.estimate, metric.interval, metric.n_observed, metric.n_missing)
exact_label 1.0 lower=0.8842966917779722 upper=1.0 30 0

Trente cas, tous corrects, et l’intervalle descend encore jusqu’à 88,4 %. Trente cas ne peuvent pas établir davantage, quoi que dise l’estimation.

Lire un cas en échec

Si le système lève une exception, ce cas est manquant plutôt que faux, et la métrique le signale :

exact_label None lower=0.0 upper=1.0 0 30

Une estimation None avec un intervalle couvrant toute la plage signifie que rien n’a été observé. Vérifiez n_missing avant de vous fier à une estimation : un système dont chaque cas a levé une exception produit un objet résultat structurellement correct, et c’est l’effectif qui vous dit qu’il est vide.

C’est le contrat du dénominateur qui fait son travail, et non une défaillance de celui-ci — un cas en erreur est borné, pas écarté — mais rien ne lève d’exception à votre place ; la vérification vous revient.

Écrire votre propre évaluateur

@evaluator transforme une fonction en évaluateur. La fonction prend un argument, le cas, et y lit ce dont elle a besoin : case.output est ce que le système a renvoyé et case.expected est l’objet expected de la ligne.

from oloproof.evaluators import evaluator

@evaluator(criterion="known_label", reads=("output",))
def known_label(case):
    return case.output["label"] in {"refund", "other"}

result = evaluate(system=answer, dataset="data/example.jsonl", evaluators=[known_label])
known_label 1.0 lower=0.8842966917779722 upper=1.0 30 0

reads déclare quelles parties du cas il lit, pour la provenance ; la valeur par défaut est ("output", "expected"). Il renvoie True ou False, ou un score s’il déclare value_type="score" et la score_range dans laquelle se situent ses scores. Sa version inclut une empreinte du fichier qui le définit ; le modifier invalide donc ses jugements en cache.

Une fonction écrite sous la forme def f(output, expected) est refusée dès sa déclaration, avec la forme qui fonctionne, plutôt que d’échouer sur chaque cas.

Appliquer une politique

evaluate accepte une politique et décide de l’exécution, avec les mêmes règles que la CLI lit dans release.yaml :

result = evaluate(
    system=answer,
    dataset="data/example.jsonl",
    evaluators=[ExactMatch(criterion="exact_label", field="label")],
    policy="release.yaml",
)
print(result.gate)

Sans politique, result.gate vaut None : il n’y a aucune règle à ne pas atteindre, donc rien à décider.

Pour aller plus loin

des artefacts dans un évaluateur.

intervalles existent.