Saltar al contenido
Páginas

Conceptos

Métricas y evaluadores

Escribe la función de puntuación que le dice al motor qué significa «mejor».

La métrica le dice a Skynet lo buena que es una salida. Es una función de Python en metric.py. Todos los motores llaman a la misma función. Esta página explica el contrato, el valor devuelto y algunos ejemplos.

El contrato

def score(input, output, expected=None):
    ...
    return score_value, {"feedback": "..."}
ArgumentoQué contiene
inputUn dict con los campos de entrada del caso
outputLo que devolvió tu run(artifact, input) para el caso
expectedEl valor esperado del caso, o None cuando el caso no tiene ninguno

Si tu función solo recibe dos argumentos, Skynet llama a score(input, output).

Para un programa DSPy, Skynet adapta la llamada a la métrica de DSPy a esta misma función. Escribes una sola métrica para todos los tipos de artefacto. Lee Cómo funciona la optimización.

El valor devuelto

score debe devolver un par (una tupla o una lista de dos elementos):

  1. La puntuación. Un número. El optimizador intenta que sea más alto.
  2. La información adicional. Un dict. Debe tener una clave "feedback" con un valor de tipo cadena.

La información adicional también puede tener una clave "scores". Asocia nombres a números, por ejemplo {"format": 1.0, "accuracy": 0.5}.

Si el valor devuelto tiene otra forma, la comprobación del contrato falla en Valor que devuelve la métrica.

Valor devueltoVálido
(0.8, {"feedback": "Close. Missing the date."})Sí
[1.0, {"feedback": "OK", "scores": {"format": 1.0}}]Sí
0.8No. No hay información adicional.
(0.8, "Close.")No. La información adicional no es un dict.
(0.8, {})No. No hay cadena de comentarios.
("0.8", {"feedback": "OK"})No. La puntuación es una cadena.
(0.8, {"feedback": "OK", "scores": {"a": "high"}})No. Una puntuación con nombre no es un número.

Escribe comentarios útiles

GEPA, DSPy GEPA y Auto leen el texto de los comentarios para escribir la siguiente versión. Di qué está mal y cómo es una salida correcta.

Comentario pobreComentario útil
«Incorrecto.»«Se esperaba 'billing' y se obtuvo 'other'. El mensaje menciona un cargo.»
«Formato erróneo.»«La salida no es un JSON válido. Tiene una coma sobrante después del último campo.»

Ejemplos

Coincidencia exacta

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 es un dict cuya clave es el nombre de tu columna de salida. Lee Conjuntos de datos y divisiones.

Varias comprobaciones

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 juez

La métrica puede llamar a un modelo. Importa llm desde el módulo auxiliar skynet. Una llamada desde la métrica va al modelo de la 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)}

Si no seleccionas un Modelo de la métrica, la métrica usa el mismo modelo que el modelo de reflexión.

Precisión, velocidad y coste

Una métrica puede combinar la precisión con el tiempo de ejecución medido y el coste del modelo. Define REWARD_SPEC a nivel de módulo y devuelve el 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.")
  • weights debe tener accuracy, speed y cost. Cada peso es 0 o más, y no pueden ser todos 0. Skynet los escala para que sumen 1.
  • speed.reference está en milisegundos. cost.reference está en dólares estadounidenses. Ambos deben ser positivos.
  • Sin accuracy.reference, la precisión es una puntuación de 0 a 1. Con él, la precisión es un error, y cuanto más bajo, mejor.

Skynet mide el tiempo y el coste por sí mismo. El código de ejecución no puede cambiarlos. Si Skynet no puede medir el tiempo o el coste, esa parte puntúa 0 y los comentarios lo indican.

La métrica también puede leer las mediciones directamente con observation() y service_cost() de skynet.

Límites

ElementoValor
Tiempo límite de la métrica60 segundos por defecto, como máximo 600
Muestras de la comprobación del contrato3 casos

Páginas relacionadas