Skip to content

Começar

A API Python

A versão em inglês desta página mudou desde que foi traduzida. A página em inglês é a atual. Ler em inglês

Tudo o que a CLI faz, a biblioteca faz. Use-a quando a avaliação pertencer a um script, um notebook ou uma suíte de testes, e não a um arquivo de configuração ao lado.

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

Tudo o que está sob oloproof_core é parte interna do engine e não faz parte desta superfície.

Um sistema recebe a entrada de um caso, não o caso

Esta é a única coisa que vale a pena acertar primeiro, porque errá-la falha em silêncio.

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

Uma linha do dataset tem esta forma:

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

A função recebe o objeto input, então case["question"] é a pergunta e não existe case["expected"]. O que ela retorna é a saída que um avaliador lê, então ExactMatch(field="label") compara o label retornado com o label esperado do caso.

Executando uma avaliação

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

Trinta casos, todos corretos, e o intervalo ainda desce até 88,4%. Trinta casos não conseguem estabelecer mais do que isso, diga a estimativa o que disser.

Lendo um caso que falhou

Se o sistema levanta uma exceção, aquele caso fica ausente em vez de errado, e a métrica informa isso:

exact_label None lower=0.0 upper=1.0 0 30

Uma estimativa None com um intervalo que cobre toda a faixa significa que nada foi observado. Confira n_missing antes de confiar em uma estimativa: um sistema em que todos os casos levantaram exceção produz um objeto de resultado estruturalmente correto, e é a contagem que diz que ele está vazio.

Isso é o contrato de denominador fazendo o seu trabalho, e não uma falha dele — um caso que deu erro é limitado, não descartado —, mas nada levanta exceção por você, então a verificação é sua.

Escrevendo o seu próprio avaliador

@evaluator transforma uma função em um avaliador. A função recebe um argumento, o caso, e lê dele o que precisa: case.output é o que o sistema retornou e case.expected é o objeto expected da linha.

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 declara quais partes do caso ele lê, para fins de proveniência; o padrão é ("output", "expected"). Ele retorna True ou False, ou uma pontuação se declarar value_type="score" e o score_range em que suas pontuações ficam. A versão dele inclui um digest do arquivo que o define, então editá-lo invalida os julgamentos dele em cache.

Uma função escrita como def f(output, expected) é recusada no momento em que é declarada, com a forma que funciona, em vez de falhar em cada caso.

Aplicando uma política

evaluate recebe uma política e decide a execução, com as mesmas regras que a CLI lê de release.yaml:

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

Sem uma política, result.gate é None: não há regra a deixar de cumprir, então não há nada a decidir.

Próximos passos

em um avaliador.

os intervalos existem.