Conceitos
Métricas e avaliadores
Escreva a função de pontuação que diz ao motor o que significa "melhor".
A métrica diz ao Skynet quão boa é uma saída. Ela é uma função Python em metric.py. Todos os motores chamam a mesma função. Esta página apresenta o contrato, o valor de retorno e exemplos.
O contrato
def score(input, output, expected=None):
...
return score_value, {"feedback": "..."}| Argumento | O que contém |
|---|---|
input | Um dict com os campos de entrada do caso |
output | O que a sua run(artifact, input) retornou para o caso |
expected | O valor esperado do caso, ou None quando o caso não tem um |
Se a sua função receber apenas dois argumentos, o Skynet chama score(input, output).
Para um programa DSPy, o Skynet adapta a chamada de métrica do DSPy a esta mesma função. Você escreve uma única métrica para todos os tipos de artefato. Leia Como a otimização funciona.
O valor de retorno
score deve retornar um par (uma tupla ou uma lista de dois itens):
- A pontuação. Um número. O otimizador tenta aumentá-lo.
- As informações adicionais. Um dict. Ele deve ter uma chave
"feedback"com um valor do tipo string.
As informações adicionais também podem ter uma chave "scores". Ela mapeia nomes para números, por exemplo {"format": 1.0, "accuracy": 0.5}.
Se o valor de retorno tiver outro formato, a verificação do contrato falha em Valor devolvido pela métrica.
| Valor de retorno | Válido |
|---|---|
(0.8, {"feedback": "Close. Missing the date."}) | Sim |
[1.0, {"feedback": "OK", "scores": {"format": 1.0}}] | Sim |
0.8 | Não. Não há informações adicionais. |
(0.8, "Close.") | Não. As informações adicionais não são um dict. |
(0.8, {}) | Não. Não há string de feedback. |
("0.8", {"feedback": "OK"}) | Não. A pontuação é uma string. |
(0.8, {"feedback": "OK", "scores": {"a": "high"}}) | Não. Uma pontuação nomeada não é um número. |
Escrever um feedback útil
O GEPA, o DSPy GEPA e o Auto leem o texto de feedback para escrever a próxima versão. Diga o que está errado e como é uma saída correta.
| Feedback fraco | Feedback útil |
|---|---|
| "Errado." | "Esperado 'billing', obtido 'other'. A mensagem menciona uma cobrança." |
| "Formato ruim." | "A saída não é um JSON válido. Há uma vírgula sobrando depois do último campo." |
Exemplos
Correspondência exata
def score(input, output, expected=None):
want = expected["label"]
if output == want:
return 1.0, {"feedback": "Correct."}
return 0.0, {"feedback": f"Expected {want!r}, got {output!r}."}expected é um dict indexado pelo nome da sua coluna de Saída. Leia Conjuntos de dados e divisões.
Várias verificações
import json
def score(input, output, expected=None):
try:
data = json.loads(output)
except ValueError as exc:
return 0.0, {"feedback": f"Output is not valid JSON: {exc}", "scores": {"format": 0.0, "fields": 0.0}}
want = expected["fields"]
found = [key for key in want if key in data]
fields = len(found) / len(want) if want else 1.0
missing = [key for key in want if key not in data]
feedback = "All fields present." if not missing else f"Missing fields: {', '.join(missing)}."
return 0.5 + 0.5 * fields, {"feedback": feedback, "scores": {"format": 1.0, "fields": fields}}Modelo como juiz
A métrica pode chamar um modelo. Importe llm do módulo auxiliar skynet. Uma chamada a partir da métrica vai para o modelo da métrica.
from skynet import llm
def score(input, output, expected=None):
verdict = llm(
"Answer PASS or FAIL, then give one sentence of reasons.",
input=f"Question: {input['question']}\nAnswer: {output}",
)
passed = str(verdict).strip().upper().startswith("PASS")
return (1.0 if passed else 0.0), {"feedback": str(verdict)}Se você não selecionar um Modelo da métrica, a métrica usa o mesmo modelo que o modelo de reflexão.
Precisão, velocidade e custo
Uma métrica pode combinar a precisão com o tempo de execução medido e o custo do modelo. Defina REWARD_SPEC no nível do módulo e retorne o valor de reward.
from skynet import reward
REWARD_SPEC = {
"weights": {"accuracy": 0.7, "speed": 0.2, "cost": 0.1},
"accuracy": {},
"speed": {"reference": 2000},
"cost": {"reference": 0.01},
}
def score(input, output, expected=None):
ok = output == expected["label"]
return reward(REWARD_SPEC, 1.0 if ok else 0.0, "Correct." if ok else "Wrong label.")weightsdeve teraccuracy,speedecost. Cada peso é 0 ou mais, e nem todos podem ser 0. O Skynet os reescala para que somem 1.speed.referenceé em milissegundos.cost.referenceé em dólares americanos. Os dois devem ser positivos.- Sem
accuracy.reference, a precisão é uma pontuação de 0 a 1. Com ele, a precisão é um erro, e quanto menor, melhor.
O próprio Skynet mede o tempo e o custo. O código de execução não pode alterá-los. Se o Skynet não conseguir medir o tempo ou o custo, essa parte recebe 0 e o feedback informa isso.
A métrica também pode ler as medições diretamente com observation() e service_cost() de skynet.
Limites
| Item | Valor |
|---|---|
| Tempo limite da métrica | 60 segundos por padrão, no máximo 600 |
| Amostras da verificação do contrato | 3 casos |