Saltar al contenido

Guías

Evaluar desde Node

El SDK de Node ejecuta su sistema y sus evaluadores en Node, dentro de su propio ejecutor de pruebas, y entrega las puntuaciones al motor de Python, que decide. Un equipo de TypeScript conserva su código, sus fixtures y su ejecutor de pruebas; cada intervalo, comparación y decisión sigue siendo del motor, y el SDK no calcula ninguno de ellos, ni siquiera una media.

Instalación

npm install --save-dev @oloproof/sdk
pip install oloproof

La primera línea es el SDK; la segunda, el motor al que entrega las puntuaciones (Python 3.11 o posterior). El SDK encuentra oloproof en su PATH; si no está ahí, se detiene e indica cómo instalarlo.

Puntuar un sistema en una prueba

Una suite es el mismo archivo JSON Lines que lee el motor (Escribir una suite), un caso por línea, cada uno con un id. Dé a evaluate la suite, el sistema y un evaluador por criterio:

import { test } from "vitest";
import { type Case, decide, evaluate } from "@oloproof/sdk";
import { answer, rateHelpfulness } from "./support-bot.js";

type SupportCase = Case<{ question: string }, { label: string }>;
type Answer = { label: string; text: string };

test("the support bot is good enough to release", async () => {
  const scored = await evaluate<SupportCase, Answer>({
    suitePath: "data/support.jsonl",
    system: (testCase) => answer(testCase.input.question),
    evaluators: {
      exact_label: (output, testCase) => ({ passed: output.label === testCase.expected?.label }),
      helpfulness: {
        scale: [0, 1],
        judge: "gpt-4o-mini",
        evaluate: async (output, testCase) => ({ score: await rateHelpfulness(output, testCase) }),
      },
    },
    concurrency: 8,
    out: "scores/candidate.jsonl",
  });
  console.log(scored.counts);
}, 600_000);

Un evaluador devuelve { passed } o { score }, con un reason opcional. Una función juzga aprobado o suspenso; un evaluador que puntúa declara su scale, porque un intervalo sobre una media solo es válido dentro de un rango conocido antes de leer las puntuaciones. Nombre el judge cuando haya juzgado un modelo: el motor lo trata entonces como un juez que se debe comprobar frente a personas antes de que pueda actuar como gate de una publicación (Jueces).

concurrency limita cuántos casos se ejecutan a la vez (cuatro por defecto). El archivo de puntuaciones lista los casos en el orden en que los da la suite, sea cual sea el orden en que terminen.

Dejar que decida el motor

const decided = await decide({
  scores: "scores/candidate.jsonl",
  baseline: "scores/baseline.jsonl",
  policy: "release.yaml",
});
console.log(decided.exit, decided.comparison?.gate?.decisions);

decide ejecuta los comandos que usted escribiría, en el directorio indicado como cwd (el actual por defecto):

oloproof scores import scores/baseline.jsonl scores/candidate.jsonl --tool node
oloproof compare RUN_ID BASELINE_RUN_ID --policy release.yaml --json

Con una línea base, el motor compara las dos ejecuciones caso por caso y decided.comparison es el registro que imprimió oloproof compare --json. Sin ella, decide ejecuta oloproof gate sobre la ejecución importada y devuelve en decided.decision.stdout lo que imprimió. En ambos casos, decided.exitCode es el código de salida del motor, sin cambios, y decided.exit su nombre: EXIT_CODES asocia cada nombre con el valor del motor, tal como los enumera Ejecución en CI.

Qué contiene el archivo

El archivo es el que lee oloproof scores import (Una segunda opinión): una fila por caso y criterio, solo ids de casos y puntuaciones. Una respuesta, una entrada o un reason nunca entran en él; se quedan en scored.results, en Node.

  • Un caso cuyo sistema lanza una excepción se escribe con un valor vacío en cada criterio, y un caso cuyo evaluador lanza una excepción, con un valor vacío en ese criterio. El motor cuenta cada uno como faltante y lo acota en su peor valor, de modo que un fallo reduce lo que la evidencia puede mostrar en lugar de desaparecer de ella. scored.errors enumera cada uno con su mensaje.
  • Un veredicto que el archivo no puede contener detiene la ejecución con un error y no escribe nada: una puntuación sin escala o fuera de ella, una puntuación y un aprobado a la vez, o un criterio que el motor no pudo nombrar como métrica.
  • Cada archivo es una versión del sistema identificada por su contenido, así que importar de nuevo el mismo archivo reutiliza lo que el motor almacenó.

Sin instalar el motor

secondOpinion envía dos archivos de puntuaciones a la página alojada que responde «¿es real?» sin nada instalado, y devuelve la respuesta del motor tal como la escribió:

import { secondOpinion } from "@oloproof/sdk";

const result = await secondOpinion({
  baseUrl: "https://oloproof.com",
  baseline: "scores/baseline.jsonl",
  candidate: "scores/candidate.jsonl",
});
if (result.ok) console.log(result.opinion.answers);
else console.log(result.error, result.description);

La página no guarda nada y no requiere ninguna cuenta. Lee hasta 2 MB por archivo y está limitada por cliente; un rechazo devuelve la frase del motor que nombra la fila que hay que cambiar.

Qué no está construido

  • Publicar @oloproof/sdk en npm. Hasta entonces, compílelo desde packages/sdk en el repositorio.
  • Una estadística de cualquier tipo en Node, por diseño: el SDK escribe puntuaciones y lee la respuesta del motor.
  • Un group_id o time_order en su suite no se traslada a la importación, que solo lee ids de casos y puntuaciones, así que el motor lee los casos como independientes.

Siguientes pasos