İçeriğe geç

Kılavuzlar

Eğitim: bir sınıflandırıcı ya da yapılandırılmış çıktı

Destek sorularını etiketleyen bir Python fonksiyonunu değerlendirin, sürümün neden engellendiğini okuyun, kaçırılanları düzeltin ve düzeltmeyi özgün sürümle karşılaştırın; hepsini kendi makinenizde, hesap, ağ ve model olmadan yapın.

Ne oluşturacaksınız

Bir answer ve bir label (refund, account ya da other) içeren bir JSON nesnesi döndüren bir destek botu. Onu üç gereksinime tabi tutacaksınız: etiket yeterince sık doğrudur, çıktı her zaman doğru biçimdedir ve hiçbir yanıt ABD sosyal güvenlik numarasına benzeyen bir şey sızdırmaz. Bunlardan ikisi referans yanıt gerektirmeyen biçim denetimleridir; biri görev başarısını bir referans etikete göre ölçer. Bu fark önemlidir ve bu sayfa onları ayrı tutar.

Aşağıda kullanılan terimler (vaka, çalıştırma, metrik, aralık, kural, kapı) Kavramlar sayfasında tanımlanmıştır.

Ön koşullar

  • Python 3.11 veya üstü.
  • Bir sanal ortama kurulmuş Oloproof:
python3 -m venv .venv
. .venv/bin/activate
pip install oloproof
  • Paketle birlikte gelen örnek proje ve aday değişiklik. İkisini de yeni dizinlere kopyalayın ve ilkinde çalışın; her dosya aşağıda da listelenmiştir, yani onları elle de yazabilirsiniz:
oloproof init --example support_bot support-classifier
oloproof init --example classification support-change
cd support-classifier

Bu sayfanın hiçbir yerinde API anahtarı, sağlayıcı hesabı ya da ağ erişimi kullanılmaz.

Dosyalar

support-classifier/
  app.py              the application under test (a Python callable)
  oloproof.yaml       the suite: dataset, system, evaluators
  release.yaml        the release policy: rules the run is decided against
  data/support.jsonl  18 cases, one JSON object per line
  rubrics/helpful.md  a judge rubric, unused here

Her komutu support-classifier/ dizininden çalıştırın. Oloproof deposunu orada .oloproof/ içinde tutar; sıfırdan yeniden başlamak için o dizini silin.

Uygulama ve bağdaştırıcısı

Uygulamanıza bir bağdaştırıcı aracılığıyla ulaşılır. Bir Python uygulaması için bağdaştırıcı fonksiyonun kendisidir: Oloproof onu içe aktarır, her vaka için vakanın input değeriyle bir kez çağırır ve döndürdüğü sözlüğü o vakanın çıktısı olarak kaydeder.

# app.py
from typing import Any

from oloproof import system


@system(name="support-bot", version="slice-a-example")
def answer(case: dict[str, Any]) -> dict[str, str]:
    question = str(case["question"]).lower()
    if "refund" in question:
        return {"answer": "Refunds are available within 30 days when the order is eligible.",
                "label": "refund"}
    if "password" in question or "login" in question:
        return {"answer": "Use password reset, then contact support if the login still fails.",
                "label": "account"}
    return {"answer": "A support specialist will follow up with the next step.", "label": "other"}

Kendi sınıflandırıcınızı değerlendirmek için kodunu olduğu yerde bırakın ve onu çağırıp bir sözlük döndüren bunun gibi ince bir fonksiyon yazın. Fonksiyon async olabilir. Oloproof onu çağırır; uygulamanızı barındırmaz, yalıtmaz ya da sıfırlamaz, bu yüzden uygulamanızın çağrılar arasında tuttuğu her durumu yönetmek size kalır.

oloproof.yaml bu fonksiyonu ve değerlendiricileri adlandırır:

version: 1
project: support-bot-example
dataset: data/support.jsonl
system:
  name: support-bot
  version: slice-a-example
  callable: app:answer
  timeout_s: 30
evaluators:
  - type: exact_match
    criterion: exact_label
    field: label
  - type: json_schema
    criterion: format_valid
    field: null
    schema:
      type: object
      required: [answer, label]
      properties:
        answer: {type: string}
        label: {type: string}
      additionalProperties: false
  - type: regex
    criterion: pii_free
    field: answer
    pattern: '\b\d{3}-\d{2}-\d{4}\b'
    pass_if: no_match

Çıktılar fonksiyonun kaynak koduna, bildirilen version ve config değerlerine göre önbelleğe alınır. Fonksiyon başka dosyaları okuyorsa (bir istem, bir kural tablosu), onları system.code_paths altında listeleyin; böylece onları düzenlemek sistemi yeniden çalıştırır.

Veri kümesi

Her satırda bir vaka. input, fonksiyonunuzun case olarak aldığı şeyin tam kendisidir; expected, exact_match değerlendiricisinin karşılaştırdığı referanstır:

{"id":"refund_00","input":{"question":"Can I get a refund for yesterday's order?"},"expected":{"label":"refund"}}
{"id":"account_04","input":{"question":"I can't sign in on my new phone."},"expected":{"label":"account"}}
{"id":"other_04","input":{"question":"I don't want a refund, I just need a copy of my receipt."},"expected":{"label":"other"}}

Fonksiyon her vaka için {"answer": "Use password reset, ...", "label": "account"} gibi bir nesne döndürür.

Değerlendiricileri seçme

KriterDeğerlendiriciexpected gerekir miNeyi ölçer
exact_labellabel üzerinde exact_matchevetgörev başarısı: etiket doğru olandır
format_validtüm çıktı üzerinde json_schemahayırbiçim: nesnede tam olarak iki metin alanı vardır
pii_freeanswer üzerinde regex, pass_if: no_matchhayırmetnin bir güvenlik özelliği

Bir biçim denetimi iyi biçimlendirilmiş yanlış bir yanıtı geçirir, bu yüzden asla görev başarısının yerini tutamaz. Bir görev denetimi her vaka için bir referansa ihtiyaç duyar; bir vakada referans yoksa exact_match onu puanlayamaz. Deterministik değerlendiriciler insanlara karşı doğrulama gerektirmez: birini iki kez çalıştırmak aynı hükmü verir.

Politika

release.yaml, çalıştırmanın karşısında karara bağlandığı şeydir:

version: 1
confidence_level: 0.95
block_on: [FAIL, INSUFFICIENT_EVIDENCE, MANUAL_REVIEW]
warn_on: []
rules:
  - id: exact-label-floor
    metric: exact_label
    min: 0.70
  - id: valid-format
    metric: format_valid
    kind: observed_count
    max_failures: 0
  - id: pii-free
    metric: pii_free
    kind: observed_count
    max_failures: 0

exact-label-floor, etiketin zamanın en az %70'inde doğru olması gerektiğini söyler ve yalnızca %95 aralığın tamamı 0.70 ya da üzerinde olduğunda geçer. İki observed_count kuralı, çalıştırdığınız vakalarda hiçbir başarısızlığa izin vermez; kullanıcıların soracağı her soruyu değil, bu vakaları tarif eder.

Çalıştırın

oloproof run

Gerçek çıktı, kısaltılmış:

Run run_01M4... [DECIDED/COMPLETE]
Gate: BLOCK (exit 3)
│ exact-label-floor │ exact_label  │ INSUFFICIENT_EVIDENCE │ interval_overlaps_threshold    │
│ valid-format      │ format_valid │ PASS                  │ observed_failures_within_limit │
│ pii-free          │ pii_free     │ PASS                  │ observed_failures_within_limit │
│ exact_label  │ 72.2%    │ [46.5%, 90.4%]  │ 13 / 18 observed · 0 missing · 0 excluded │
│ format_valid │ 100.0%   │ [81.4%, 100.0%] │ 18 / 18 observed · 0 missing · 0 excluded │
│ pii_free     │ 100.0%   │ [81.4%, 100.0%] │ 18 / 18 observed · 0 missing · 0 excluded │
Cache: execution 0 hit/18 miss; judgment 0 hit/54 miss

Nasıl okunur:

  • 18 etiketten 13'ü doğru, %72,2. Bu 0.70'in üzerinde, ama aralık %46,5'e kadar iniyor: 18 vaka gerçek oranın en az 0.70 olduğunu gösteremez. Bu yüzden kural PASS ya da FAIL değil, INSUFFICIENT_EVIDENCE olur.
  • Her çıktı doğru biçimde ve hiçbiri SSN'ye benzeyen bir sayı içermiyor, bu yüzden iki biçim kuralı da geçer.
  • block_on, INSUFFICIENT_EVIDENCE değerini listeler, bu yüzden kapı engeller ve komut 3 ile çıkar. 0 çıkışı, politikanın engellediği hiçbir şey olmadığı anlamına gelirdi; CI'da kapı denetimi tüm kodları listeler.

Yeniden çalıştırdığınızda önbellek satırı execution 18 hit/0 miss olur: hiçbir şey değişmedi, bu yüzden fonksiyon çağrılmaz.

Başarısızlıkları inceleyin

oloproof inspect RUN_ID --failures
oloproof inspect RUN_ID --case refund_04

RUN_ID, çalıştırma çıktısının ilk satırındaki kimliktir.

5 of 18 cases failed, errored or did not finish

refund_04
  output: {"answer": "A support specialist will follow up with the next step.", "label": "other"}
  exact_label: failed
...
other_04
  output: {"answer": "Refunds are available within 30 days when the order is eligible.", "label": "refund"}
  exact_label: failed
case refund_04
input: {
  "question": "I was charged twice this month and want my money back."
}
expected: {
  "label": "refund"
}
execution: OK, 1 ms
output: {
  "answer": "A support specialist will follow up with the next step.",
  "label": "other"
}
judgments:
  exact_label: failed
  format_valid: passed
  pii_free: passed

Girdileri okuduğunuzda örüntü açıktır: "money back", "reverse the payment", "sign in" ve "two-factor" anahtar sözcük listelerinde yok, other_04 ise "I don't want a refund" diyor ve "refund" sözcüğü yine de eşleşiyor. refund_04'ün yanlış olduğu halde iki biçim denetimini de geçtiğine dikkat edin: biçimi denetlemekle başarıyı ölçmek arasındaki boşluk budur.

Burada iki sonraki eylem anlamlıdır. Kaçırılanları düzeltin (aşağıda) ya da vaka ekleyin: aynı doğrulukta daha fazla vakayla aralık daralır ve oloproof plan RUN_ID --run kaç tane gerektiğini tahmin eder.

Gerçek bir değişiklik yapın

../support-change/app.py dosyasını app.py üzerine kopyalayın. Kaçırılan ifadeleri ekler:

REFUND_WORDS = ("refund", "money back", "reverse the payment")
ACCOUNT_WORDS = ("password", "login", "sign in", "two-factor")


@system(name="support-bot", version="keywords-v2")
def answer(case: dict[str, Any]) -> dict[str, str]:
    question = str(case["question"]).lower()
    if any(word in question for word in REFUND_WORDS):
        ...

ve oloproof.yaml içinde system altında version: keywords-v2 ayarlayın; böylece çalıştırma yeni sürüm olarak kaydedilir. Sonra:

oloproof run
Gate: ALLOW (exit 0)
│ exact-label-floor │ exact_label  │ PASS  │ lower_bound_meets_minimum      │
│ exact_label  │ 94.4%    │ [72.7%, 99.9%]  │ 17 / 18 observed · 0 missing · 0 excluded │

18'den 17'si doğru ve aralığın alt sınırı olan %72,7, 0.70'i aşıyor; bu yüzden kural geçer ve komut 0 ile çıkar. other_04 hâlâ başarısız: düzeltme olumsuzluğa dokunmadı.

Adayı temelle karşılaştırın

Çalıştırma kuralı, adayın tabanınızı karşılayıp karşılamadığını sorar. Bir karşılaştırma ise onun temelden vaka vaka nasıl farklılaştığını sorar. ../support-change/compare.yaml dosyasını projeye kopyalayın; tek bir karşılaştırma kuralı içerir:

version: 1
confidence_level: 0.95
block_on: [FAIL, INSUFFICIENT_EVIDENCE, MANUAL_REVIEW]
rules:
  - id: label-no-regression
    kind: non_inferiority
    metric: exact_label
    margin: 0.10
oloproof compare CANDIDATE_RUN_ID BASELINE_RUN_ID --policy compare.yaml
Comparison sha256:de76... of run_01M4...TJAD against run_01M4...ECVEF · 18 paired cases
exact_label: +22.2 points [-12.9, +57.0] · 18 paired · 0 missing · 0 excluded
format_valid: +0.0 points [-25.8, +25.8] · 18 paired · 0 missing · 0 excluded
pii_free: +0.0 points [-25.8, +25.8] · 18 paired · 0 missing · 0 excluded
Decisions
  label-no-regression  exact_label  non-inferiority, margin 10.0 points  INSUFFICIENT_EVIDENCE  interval_overlaps_margin
    about 3 more paired cases would decide it, if the difference holds (21 in total at 22% discordance)
Gate: BLOCK (exit 3)

Aday dört vakayı düzeltti ve hiçbirini bozmadı; tahmini kazanç 22 puan. Ama yalnızca dört vaka değişti ve 18 eşleştirilmiş vaka, 12,9 puan daha kötüden 57 puan daha iyiye uzanan bir aralık bırakır; bu aralık 10 puanlık marjı keser. Karşılaştırma, adayın kabul ettiğinizden daha fazla kötü olduğunu henüz dışlayamaz; bu yüzden sonuç INSUFFICIENT_EVIDENCE olur ve 3 ile çıkar. Altındaki satır boyutlandırma tahminidir. --policy olmadan compare farkları yazdırır, projenin release.yaml dosyasının hiçbir karşılaştırma kuralı bildirmediğini söyler ve hiçbir şey karara bağlanmadığı için 0 ile çıkar.

Bir adayı bir temelle karşılaştırma, marjı ve diğer kural türlerini açıklar.

Sorun giderme

BelirtiNeden ve çözüm
app için ModuleNotFoundErrorapp.py dosyasını içeren dizinden çalıştırın ya da callable için oradan içe aktarılabilen bir modül yolu verin.
Bir kural hiçbir değerlendiricinin üretmediği bir metriği adlandırıyorKuralın metric değeri bir değerlendiricinin criterion değerine eşit olmalıdır; hata var olan metrikleri listeler.
Sınıflandırıcıyı düzenlediniz ve çalıştırma her çıktıyı yeniden kullandıÖnbellek callable'ın kaynağını izler; onun okuduğu bir yardımcı dosya system.code_paths altında listelenmelidir.
exact_label vakaları eksik olarak bildiriyorBu yürütmeler hata fırlattı ya da zaman aşımına uğradı; oloproof inspect RUN_ID --failures her hatayı gösterir.
Çalıştırma yüksek bir tahminle 3 ile çıkıyorKarar veren tahmin değil aralıktır. Vaka ekleyin ya da çalıştırmadan önce kararlaştırılmış daha düşük bir taban kabul edin.

Sınırlamalar

  • SDK ve YAML her değerlendirici için geçme oranlarını bildirir. Bunun gibi bir sınıflandırıcı için karışıklık matrisi ya da sınıf başına kesinlik ve duyarlılık yoktur; bir predictive: bloğu bunları puan üreten bir model için yapar (Tahminsel modeller).
  • observed_count kuralları çalıştırdığınız vakaları tarif eder; görülmemiş girdiler hakkında hiçbir iddiada bulunmaz.
  • 18 vaka üzerinden bir karşılaştırma yalnızca büyük farkları çözer. Elli ya da daha fazla gerçek vaka daha yararlı bir tabandır.
  • oloproof.yaml özel bir @evaluator adlandıramaz; bunun için SDK gerekir (SDK).