Panduan
Tutorial: classifier atau keluaran terstruktur
Evaluasi fungsi Python yang memberi label pada pertanyaan dukungan, baca mengapa rilis diblokir, perbaiki kesalahannya, dan bandingkan perbaikan itu dengan versi aslinya, semuanya di mesin Anda sendiri tanpa akun, tanpa jaringan, dan tanpa model.
Apa yang akan Anda bangun
Bot dukungan yang mengembalikan objek JSON dengan answer dan label (refund, account, atau other). Anda akan mengukurnya terhadap tiga persyaratan: label cukup sering benar, keluaran selalu memiliki bentuk yang benar, dan tidak ada jawaban yang membocorkan sesuatu yang tampak seperti nomor jaminan sosial AS. Dua di antaranya adalah pemeriksaan format yang tidak memerlukan jawaban acuan; satu mengukur keberhasilan tugas terhadap label acuan. Perbedaannya penting, dan halaman ini memisahkan keduanya.
Istilah yang digunakan di bawah (kasus, eksekusi, metrik, interval, aturan, gerbang) didefinisikan dalam Konsep.
Prasyarat
- Python 3.11 atau yang lebih baru.
- Oloproof, dipasang ke dalam lingkungan virtual:
python3 -m venv .venv
. .venv/bin/activate
pip install oloproof- Proyek contoh dan perubahan kandidat, yang disertakan dalam paket. Salin keduanya ke direktori baru dan bekerjalah di direktori pertama; setiap file juga dicantumkan di bawah, sehingga Anda dapat mengetiknya sendiri:
oloproof init --example support_bot support-classifier
oloproof init --example classification support-change
cd support-classifierTidak ada kunci API, akun penyedia, atau akses jaringan yang digunakan di halaman ini.
File-filenya
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 hereJalankan setiap perintah dari direktori support-classifier/. Oloproof menyimpan store-nya di .oloproof/ di sana; hapus direktori itu untuk memulai lagi dari nol.
Aplikasi dan adapternya
Aplikasi Anda dijangkau melalui sebuah adapter. Untuk aplikasi Python, adapternya adalah fungsi itu sendiri: Oloproof mengimpornya, memanggilnya sekali per kasus dengan input kasus, dan merekam dictionary yang dikembalikannya sebagai keluaran kasus itu.
# 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"}Untuk mengevaluasi classifier Anda sendiri, biarkan kodenya di tempatnya dan tulis fungsi tipis seperti ini yang memanggilnya dan mengembalikan dictionary. Fungsi itu boleh async. Oloproof memanggilnya; Oloproof tidak meng-hosting, mengisolasi, atau mengatur ulang aplikasi Anda, sehingga state apa pun yang disimpan aplikasi Anda di antara panggilan menjadi tanggung jawab Anda.
oloproof.yaml menyebut fungsi itu dan evaluatornya:
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_matchKeluaran di-cache berdasarkan source fungsi, version yang dideklarasikan, dan config. Jika fungsi membaca file lain (sebuah prompt, sebuah tabel aturan), cantumkan di bawah system.code_paths, sehingga mengeditnya menjalankan sistem lagi.
Dataset
Satu kasus per baris. input persis apa yang diterima fungsi Anda sebagai case; expected adalah acuan yang dibandingkan oleh evaluator exact_match:
{"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"}}Untuk setiap kasus, fungsi mengembalikan objek seperti {"answer": "Use password reset, ...", "label": "account"}.
Memilih evaluator
| Kriteria | Evaluator | Memerlukan expected | Apa yang diukurnya |
|---|---|---|---|
| exact_label | exact_match pada label | ya | keberhasilan tugas: labelnya adalah label yang benar |
| format_valid | json_schema atas seluruh keluaran | tidak | format: objek memiliki tepat dua field string |
| pii_free | regex pada answer, pass_if: no_match | tidak | properti keamanan dari teks |
Pemeriksaan format meloloskan jawaban salah yang bentuknya benar, sehingga tidak pernah dapat menggantikan keberhasilan tugas. Pemeriksaan tugas memerlukan acuan untuk setiap kasus; jika sebuah kasus tidak memilikinya, exact_match tidak dapat menilainya. Evaluator deterministik tidak memerlukan validasi terhadap manusia: menjalankannya dua kali memberi putusan yang sama.
Kebijakannya
release.yaml adalah dasar keputusan eksekusi:
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: 0exact-label-floor menyatakan bahwa label harus benar setidaknya 70% dari waktu, dan hanya lolos ketika seluruh interval 95% berada pada atau di atas 0.70. Kedua aturan observed_count tidak mengizinkan satu kegagalan pun pada kasus yang Anda jalankan; aturan itu menggambarkan kasus-kasus ini, bukan setiap pertanyaan yang akan diajukan pengguna.
Jalankan
oloproof runKeluaran nyata, dipangkas:
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 missCara membacanya:
- 13 dari 18 label benar, 72.2%. Itu di atas 0.70, tetapi interval mencapai turun ke 46.5%: 18 kasus tidak dapat menunjukkan bahwa tingkat sebenarnya setidaknya 0.70. Jadi aturannya INSUFFICIENT_EVIDENCE, bukan PASS dan bukan FAIL.
- Setiap keluaran memiliki bentuk yang benar dan tidak ada yang memuat angka mirip SSN, sehingga kedua aturan format lolos.
- block_on mencantumkan INSUFFICIENT_EVIDENCE, sehingga gerbang memblokir dan perintah keluar dengan 3. Keluar 0 berarti tidak ada yang diblokir kebijakan; Gerbang CI mencantumkan setiap kode.
Jalankan lagi dan baris cache berbunyi execution 18 hit/0 miss: tidak ada yang berubah, sehingga fungsi tidak dipanggil.
Periksa kegagalannya
oloproof inspect RUN_ID --failures
oloproof inspect RUN_ID --case refund_04RUN_ID adalah id pada baris pertama keluaran eksekusi.
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: failedcase 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: passedPolanya jelas begitu Anda membaca inputnya: "money back", "reverse the payment", "sign in", dan "two-factor" tidak ada dalam daftar kata kunci, dan other_04 mengatakan "I don't want a refund", yang tetap cocok dengan kata "refund". Perhatikan bahwa refund_04 lolos kedua pemeriksaan format padahal salah: itulah celah antara memeriksa format dan mengukur keberhasilan.
Dua tindakan berikutnya bermakna di sini. Perbaiki kesalahannya (di bawah), atau tambahkan kasus: dengan lebih banyak kasus pada akurasi yang sama intervalnya menyempit, dan oloproof plan RUN_ID --run memperkirakan berapa banyak.
Lakukan perubahan nyata
Salin ../support-change/app.py menimpa app.py. File itu menambahkan frasa yang terlewat:
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):
...lalu tetapkan version: keywords-v2 di bawah system di oloproof.yaml, sehingga eksekusi direkam sebagai versi baru. Lalu:
oloproof runGate: 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 │17 dari 18 benar dan batas bawah interval, 72.7%, melampaui 0.70, sehingga aturan lolos dan perintah keluar dengan 0. other_04 masih gagal: perbaikan itu tidak menyentuh negasi.
Bandingkan kandidat dengan baseline
Aturan eksekusi menanyakan apakah kandidat memenuhi batas bawah Anda. Perbandingan menanyakan bagaimana kandidat berbeda dari baseline, kasus demi kasus. Salin ../support-change/compare.yaml ke dalam proyek; file itu memuat satu aturan perbandingan:
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.10oloproof compare CANDIDATE_RUN_ID BASELINE_RUN_ID --policy compare.yamlComparison 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)Kandidat memperbaiki empat kasus dan tidak merusak satu pun, perkiraan peningkatan 22 poin. Tetapi hanya empat kasus yang berubah, dan 18 kasus berpasangan menyisakan interval dari 12.9 poin lebih buruk hingga 57 poin lebih baik, yang melintasi margin 10 poin. Perbandingan belum dapat menyingkirkan kemungkinan bahwa kandidat lebih buruk melebihi yang Anda terima, sehingga hasilnya INSUFFICIENT_EVIDENCE dan keluar dengan 3. Baris di bawahnya adalah perkiraan ukuran. Tanpa --policy, compare mencetak selisihnya, menyatakan bahwa release.yaml proyek tidak mendeklarasikan aturan perbandingan, dan keluar dengan 0 karena tidak ada yang diputuskan.
Membandingkan kandidat dengan baseline menjelaskan margin dan jenis aturan lainnya.
Pemecahan masalah
| Gejala | Penyebab dan perbaikan |
|---|---|
| ModuleNotFoundError untuk app | Jalankan dari direktori yang memuat app.py, atau beri callable path modul yang dapat diimpor dari sana. |
| Aturan menyebut metrik yang tidak dihasilkan evaluator mana pun | metric aturan harus sama dengan criterion sebuah evaluator; error mencantumkan metrik yang ada. |
| Anda mengedit classifier dan eksekusi memakai ulang setiap keluaran | Cache mengikuti source callable; file pembantu yang dibacanya harus dicantumkan di bawah system.code_paths. |
| exact_label melaporkan kasus sebagai hilang | Eksekusi itu memunculkan exception atau habis waktu; oloproof inspect RUN_ID --failures menampilkan setiap error. |
| Eksekusi keluar dengan 3 meski estimasinya tinggi | Yang memutuskan adalah interval, bukan estimasi. Tambahkan kasus atau terima batas bawah yang lebih rendah, yang diputuskan sebelum eksekusi. |
Keterbatasan
- SDK dan YAML melaporkan tingkat kelulusan per evaluator. Tidak ada confusion matrix atau presisi dan recall per kelas untuk classifier seperti ini; blok predictive: menyediakannya untuk model yang memberi skor (Model prediktif).
- Aturan observed_count menggambarkan kasus yang Anda jalankan; aturan itu tidak membuat klaim tentang input yang tidak terlihat.
- Perbandingan atas 18 kasus hanya dapat memisahkan selisih yang besar. Lima puluh kasus nyata atau lebih adalah batas bawah yang lebih berguna.
- oloproof.yaml tidak dapat menyebut @evaluator kustom; itu memerlukan SDK (SDK).