Hướng dẫn
Hướng dẫn: một bộ phân loại hoặc đầu ra có cấu trúc
Đánh giá một hàm Python gán nhãn cho các câu hỏi hỗ trợ, đọc lý do bản phát hành bị chặn, sửa các chỗ sai, và so sánh bản sửa với bản gốc, tất cả trên máy của bạn, không cần tài khoản, không cần mạng và không cần mô hình.
Bạn sẽ xây dựng gì
Một bot hỗ trợ trả về một đối tượng JSON có answer và label (refund, account hoặc other). Bạn sẽ đặt nó trước ba yêu cầu: nhãn đúng đủ thường xuyên, đầu ra luôn có đúng hình dạng, và không câu trả lời nào làm lộ thứ gì trông giống một số an sinh xã hội Hoa Kỳ. Hai trong số đó là kiểm tra định dạng không cần câu trả lời tham chiếu; một cái đo mức thành công của tác vụ so với một nhãn tham chiếu. Sự khác biệt này quan trọng, và trang này giữ chúng tách biệt.
Các thuật ngữ dùng bên dưới (trường hợp, lần chạy, chỉ số, khoảng, quy tắc, cổng) được định nghĩa trong Khái niệm.
Điều kiện tiên quyết
- Python 3.11 trở lên.
- Oloproof, được cài vào một môi trường ảo:
python3 -m venv .venv
. .venv/bin/activate
pip install oloproof- Dự án ví dụ và thay đổi ứng viên, đi kèm với gói. Sao chép cả hai vào các thư mục mới và làm việc trong thư mục thứ nhất; mọi tệp cũng được liệt kê bên dưới, nên bạn có thể tự gõ chúng:
oloproof init --example support_bot support-classifier
oloproof init --example classification support-change
cd support-classifierKhông có khóa API, tài khoản nhà cung cấp hay truy cập mạng nào được dùng ở bất cứ đâu trên trang này.
Các tệp
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 hereChạy mọi lệnh từ thư mục support-classifier/. Oloproof giữ kho lưu trữ của nó trong .oloproof/ ở đó; xóa thư mục đó để bắt đầu lại từ đầu.
Ứng dụng và adapter của nó
Ứng dụng của bạn được gọi qua một adapter. Với một ứng dụng Python, adapter chính là hàm đó: Oloproof import nó, gọi nó một lần cho mỗi trường hợp với input của trường hợp, và ghi lại dictionary mà nó trả về làm đầu ra của trường hợp đó.
# 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"}Để đánh giá bộ phân loại của chính bạn, hãy giữ mã của nó ở nguyên chỗ và viết một hàm mỏng như hàm này để gọi nó và trả về một dictionary. Hàm có thể là async. Oloproof gọi nó; nó không lưu trữ, cô lập hay đặt lại ứng dụng của bạn, nên mọi trạng thái mà ứng dụng giữ giữa các lần gọi là do bạn quản lý.
oloproof.yaml nêu tên hàm đó và các bộ đánh giá:
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Đầu ra được lưu đệm theo mã nguồn của hàm, version đã khai báo và config. Nếu hàm đọc các tệp khác (một prompt, một bảng quy tắc), hãy liệt kê chúng dưới system.code_paths, để việc sửa chúng sẽ chạy lại hệ thống.
Tập dữ liệu
Mỗi dòng một trường hợp. input chính xác là thứ hàm của bạn nhận làm case; expected là tham chiếu mà bộ đánh giá exact_match so sánh với:
{"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"}}Với mỗi trường hợp, hàm trả về một đối tượng như {"answer": "Use password reset, ...", "label": "account"}.
Chọn các bộ đánh giá
| Tiêu chí | Bộ đánh giá | Cần expected | Nó đo gì |
|---|---|---|---|
| exact_label | exact_match trên label | có | thành công của tác vụ: nhãn là nhãn đúng |
| format_valid | json_schema trên toàn bộ đầu ra | không | định dạng: đối tượng có đúng hai trường chuỗi |
| pii_free | regex trên answer, pass_if: no_match | không | một thuộc tính an toàn của văn bản |
Một kiểm tra định dạng cho qua một câu trả lời sai nhưng đúng hình thức, nên nó không bao giờ có thể thay thế cho thành công của tác vụ. Một kiểm tra tác vụ cần một tham chiếu cho mọi trường hợp; khi một trường hợp không có, exact_match không thể chấm điểm nó. Các bộ đánh giá tất định không cần xác thực so với con người: chạy một bộ hai lần cho cùng một phán quyết.
Chính sách
release.yaml là thứ mà lần chạy được quyết định theo:
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 nói rằng nhãn phải đúng ít nhất 70% số lần, và chỉ đạt khi toàn bộ khoảng 95% nằm ở hoặc trên 0.70. Hai quy tắc observed_count không cho phép một thất bại nào trên các trường hợp bạn đã chạy; chúng mô tả các trường hợp này, không phải mọi câu hỏi mà người dùng sẽ hỏi.
Chạy
oloproof runĐầu ra thật, đã rút gọn:
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 missCách đọc:
- 13 trên 18 nhãn đúng, 72,2%. Con số đó cao hơn 0.70, nhưng khoảng kéo xuống tới 46,5%: 18 trường hợp không thể cho thấy tỷ lệ thật ít nhất là 0.70. Vì vậy quy tắc là INSUFFICIENT_EVIDENCE, không phải PASS và cũng không phải FAIL.
- Mọi đầu ra đều có đúng hình dạng và không cái nào chứa một số giống SSN, nên cả hai quy tắc định dạng đều đạt.
- block_on liệt kê INSUFFICIENT_EVIDENCE, nên cổng chặn và lệnh thoát với 3. Thoát với 0 nghĩa là không có gì mà chính sách chặn; Cổng trong CI liệt kê mọi mã.
Chạy lại và dòng bộ nhớ đệm ghi execution 18 hit/0 miss: không có gì thay đổi, nên hàm không bị gọi.
Xem xét các thất bại
oloproof inspect RUN_ID --failures
oloproof inspect RUN_ID --case refund_04RUN_ID là mã ở dòng đầu tiên trong đầu ra của lần chạy.
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: passedQuy luật trở nên rõ ràng khi bạn đọc các đầu vào: "money back", "reverse the payment", "sign in" và "two-factor" không có trong danh sách từ khóa, và other_04 nói "I don't want a refund", mà từ "refund" vẫn khớp. Lưu ý rằng refund_04 đạt cả hai kiểm tra định dạng trong khi lại sai: đó là khoảng cách giữa việc kiểm tra định dạng và việc đo lường thành công.
Có hai hành động tiếp theo có ý nghĩa ở đây. Sửa các chỗ sai (bên dưới), hoặc thêm trường hợp: với nhiều trường hợp hơn ở cùng độ chính xác, khoảng thu hẹp lại, và oloproof plan RUN_ID --run ước lượng cần bao nhiêu.
Thực hiện một thay đổi thật
Sao chép ../support-change/app.py đè lên app.py. Nó thêm các cách diễn đạt bị bỏ sót:
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):
...và đặt version: keywords-v2 dưới system trong oloproof.yaml, để lần chạy được ghi lại là phiên bản mới. Rồi:
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 trên 18 đúng và cận dưới của khoảng, 72,7%, vượt qua 0.70, nên quy tắc đạt và lệnh thoát với 0. other_04 vẫn thất bại: bản sửa không đụng tới phủ định.
So sánh ứng viên với đường cơ sở
Quy tắc của lần chạy hỏi xem ứng viên có đạt mức sàn của bạn hay không. Một phép so sánh hỏi nó khác đường cơ sở thế nào, từng trường hợp một. Sao chép ../support-change/compare.yaml vào dự án; nó chứa một quy tắc so sánh:
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)Ứng viên đã sửa bốn trường hợp và không làm hỏng trường hợp nào, mức tăng ước lượng là 22 điểm. Nhưng chỉ bốn trường hợp thay đổi, và 18 trường hợp ghép cặp để lại một khoảng từ tệ hơn 12,9 điểm tới tốt hơn 57 điểm, vắt ngang biên 10 điểm. Phép so sánh chưa thể loại trừ khả năng ứng viên tệ hơn quá mức bạn chấp nhận, nên kết quả là INSUFFICIENT_EVIDENCE và thoát với 3. Dòng bên dưới là ước lượng định cỡ. Không có --policy, compare in ra các khác biệt, nói rằng release.yaml của dự án không khai báo quy tắc so sánh nào, và thoát với 0 vì không có gì được quyết định.
So sánh một ứng viên với một đường cơ sở giải thích biên và các loại quy tắc khác.
Khắc phục sự cố
| Triệu chứng | Nguyên nhân và cách sửa |
|---|---|
| ModuleNotFoundError cho app | Chạy từ thư mục chứa app.py, hoặc đưa cho callable một đường dẫn module có thể import từ đó. |
| Một quy tắc nêu một chỉ số mà không bộ đánh giá nào tạo ra | metric của quy tắc phải bằng criterion của một bộ đánh giá; lỗi liệt kê các chỉ số hiện có. |
| Bạn đã sửa bộ phân loại nhưng lần chạy tái sử dụng mọi đầu ra | Bộ nhớ đệm theo mã nguồn của callable; một tệp phụ trợ mà nó đọc phải được liệt kê dưới system.code_paths. |
| exact_label báo các trường hợp bị thiếu | Các lần thực thi đó đã ném lỗi hoặc hết thời gian; oloproof inspect RUN_ID --failures cho thấy từng lỗi. |
| Lần chạy thoát với 3 dù ước lượng cao | Khoảng, không phải ước lượng, mới quyết định. Thêm trường hợp hoặc chấp nhận một mức sàn thấp hơn, được quyết định trước lần chạy. |
Giới hạn
- SDK và YAML báo tỷ lệ đạt theo từng bộ đánh giá. Không có ma trận nhầm lẫn hay precision và recall theo từng lớp cho một bộ phân loại như thế này; một khối predictive: làm những việc đó cho một mô hình có điểm số (Mô hình dự đoán).
- Các quy tắc observed_count mô tả các trường hợp bạn đã chạy; chúng không khẳng định gì về các đầu vào chưa thấy.
- Một phép so sánh trên 18 trường hợp chỉ phân giải được các khác biệt lớn. Năm mươi trường hợp thật trở lên là một mức sàn hữu ích hơn.
- oloproof.yaml không thể nêu một @evaluator tùy chỉnh; việc đó cần SDK (SDK).