الانتقال إلى المحتوى

الأدلة الإرشادية

التقييم من Node

تشغّل حزمة SDK الخاصة بـ Node نظامك ومُقيِّماته داخل Node، ضمن مشغّل الاختبارات الخاص بك، وتسلّم الدرجات إلى محرك Python، وهو الذي يحسم. يحتفظ فريق TypeScript بشيفرته وبيانات اختباره الثابتة (fixtures) ومشغّل اختباراته؛ وتبقى كل فترة وكل مقارنة وكل قرار من شأن المحرك، ولا تحسب حزمة SDK أيًّا منها، ولا حتى متوسطًا.

التثبيت

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

السطر الأول هو حزمة SDK، والثاني هو المحرك الذي تسلّمه الدرجات (Python 3.11 أو أحدث). تجد حزمة SDK الأمر oloproof في PATH لديك؛ وإن لم يكن هناك، تتوقف وتوضح كيفية تثبيته.

منح نظامٍ درجاتٍ داخل اختبار

مجموعة الاختبار هي ملف JSON Lines نفسه الذي يقرؤه المحرك (كتابة مجموعة اختبار)، حالة واحدة في كل سطر، لكلٍّ منها id. أعطِ evaluate مجموعة الاختبار والنظام ومُقيِّمًا واحدًا لكل معيار:

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);

يعيد المُقيِّم { passed } أو { score }، مع reason اختياري. الدالة تحكم بالنجاح أو الإخفاق؛ أما المُقيِّم الذي يمنح درجات فيصرّح بـ scale الخاص به، لأن الفترة حول المتوسط لا تصح إلا داخل مدى معروف قبل قراءة الدرجات. سمِّ judge حين يكون الحاكم نموذجًا: فيعامله المحرك عندئذ بوصفه حَكَمًا يجب فحصه مقابل الأشخاص قبل أن يُسمح له بأن يكون بوابة لإصدار (الحُكّام).

يحدّ concurrency عدد الحالات التي تُشغَّل في آن واحد (أربع افتراضيًا). ويسرد ملف الدرجات الحالات بالترتيب الذي تعطيه مجموعة الاختبار، أيًّا كان ترتيب انتهائها.

دع المحرك يحسم

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

يشغّل decide الأوامر التي كنت ستكتبها، في الدليل المعطى بوصفه cwd (الدليل الحالي افتراضيًا):

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

مع خط أساس، يقارن المحرك التشغيلين حالةً بحالة، ويكون decided.comparison السجل الذي طبعه oloproof compare --json. ومن دونه، يشغّل decide الأمر oloproof gate على التشغيل المستورَد ويعيد ما طبعه في decided.decision.stdout. وفي الحالتين يكون decided.exitCode رمز خروج المحرك، دون تغيير، وdecided.exit اسمه: يربط EXIT_CODES كل اسم بقيمة المحرك، كما يسردها التشغيل في CI.

ما يحمله الملف

الملف هو الذي يقرؤه oloproof scores import (رأي ثانٍ): صف واحد لكل حالة ومعيار، معرِّفات الحالات والدرجات فقط. لا تدخله أبدًا إجابة أو مُدخَل أو reason؛ بل تبقى في scored.results، داخل Node.

  • الحالة التي يرمي نظامها استثناءً تُكتب بقيمة فارغة في كل معيار، والحالة التي يرمي مُقيِّمها استثناءً تُكتب بقيمة فارغة في ذلك المعيار. يحتسب المحرك كلًّا منها مفقودة ويحدّها عند أسوأ قيمها، فيُنقص الإخفاق ما تستطيع الأدلة إظهاره بدلًا من أن يختفي منها. ويسرد scored.errors كلًّا منها مع رسالته.
  • الحكم الذي لا يستطيع الملف حمله يوقف التشغيل بخطأ ولا يكتب شيئًا: درجة بلا مدى أو خارج مداها، أو درجة ونجاح معًا، أو معيار لم يستطع المحرك تسميته مقياسًا.
  • كل ملف نسخة من النظام تُعرَّف بمحتواها، لذا فإن استيراد الملف نفسه مرة أخرى يعيد استخدام ما خزّنه المحرك.

دون تثبيت المحرك

يرسل secondOpinion ملفَّي درجات إلى الصفحة المستضافة التي تجيب عن «هل هو حقيقي؟» دون تثبيت أي شيء، ويعيد إجابة المحرك كما كتبها:

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);

لا تحتفظ الصفحة بشيء ولا تتطلب حسابًا. تقرأ حتى 2 MB لكل ملف، ولها حدّ لكل عميل؛ ويعيد الرفض جملة المحرك التي تسمّي الصف الواجب تغييره.

ما لم يُبنَ

  • نشر @oloproof/sdk على npm. وإلى أن يُنشر، ابنِه من packages/sdk في المستودع.
  • أي إحصاء من أي نوع داخل Node، عن قصد: تكتب حزمة SDK الدرجات وتقرأ إجابة المحرك.
  • لا يُنقل group_id أو time_order في مجموعة الاختبار لديك إلى الاستيراد، الذي يقرأ معرِّفات الحالات والدرجات فقط، لذا يقرأ المحرك الحالات بوصفها مستقلة.

إلى أين بعد ذلك