Panduan
Tutorial: aplikasi di balik endpoint HTTP
Evaluasi layanan yang Anda jangkau lewat HTTP, tanpa mengimpor kodenya: arahkan Oloproof ke URL-nya, jalankan suite, temukan apa yang terlewat, deploy perubahan, lalu bandingkan. Layanan lokal kecil menggantikan layanan Anda, sehingga semuanya berjalan offline.
Apa yang akan Anda bangun
Layanan penerimaan pesanan yang membaca pesan pelanggan dan mengekstrak dua field: intent (where_is_order, cancel, return, atau other) dan order_id (empat digit, atau null). Anda akan memeriksa format setiap respons, yang tidak memerlukan acuan, dan mengukur apakah setiap field benar, yang memerlukannya. Istilah seperti kasus, eksekusi, metrik, dan gerbang didefinisikan dalam Konsep.
Prasyarat
- Python 3.11 atau yang lebih baru, dan Oloproof di lingkungan virtual:
python3 -m venv .venv
. .venv/bin/activate
pip install oloproof- Proyek contoh, yang disertakan dalam paket. Salin ke direktori baru dan bekerjalah di sana (httpx, yang diimpor client.py, dipasang bersama Oloproof):
oloproof init --example http order-intake
cd order-intake- Port 8765 kosong di mesin ini. Jika sudah dipakai, pilih yang lain dan ubah baik di perintah server maupun di oloproof.yaml.
Tidak ada yang di sini menggunakan penyedia, kunci API, atau internet: layanan mendengarkan di 127.0.0.1.
File-filenya
order-intake/
server.py the stand-in service (Python standard library only)
client.py a callable that calls the service with a token (used near the end)
oloproof.yaml the suite: dataset, HTTP system, evaluators
release.yaml rules for a run
compare.yaml a rule for a comparison
data/messages.jsonl 20 casesJalankan perintah dari order-intake/. Jalankan layanan di terminal kedua dan biarkan tetap berjalan:
python server.py --port 8765intake service (v1) on http://127.0.0.1:8765/extractKontrak HTTP
Untuk setiap kasus Oloproof mengirim satu permintaan: input kasus sebagai body JSON, dengan metode yang Anda deklarasikan (POST secara bawaan). Oloproof membaca respons sebagai JSON. Status 400 atau lebih, batas waktu habis, atau koneksi yang ditolak direkam sebagai error eksekusi untuk kasus itu, tidak pernah sebagai jawaban yang salah.
Permintaan dan respons untuk satu kasus:
POST /extract
{"message": "Where is order 1042? It has not arrived."}
200 OK
{"result": {"intent": "where_is_order", "order_id": "1042"}, "service": {"rules": "v1"}}output_path: result memberi tahu Oloproof untuk hanya menyimpan result sebagai keluaran kasus; tanpanya seluruh body adalah keluarannya. Path bertitik seperti data.answer menjangkau lebih dalam.
version: 1
project: order-intake
dataset: data/messages.jsonl
system:
name: order-intake
http:
url: http://127.0.0.1:8765/extract
method: POST
version: rules-v1
output_path: result
timeout_s: 30
evaluators:
- type: json_schema
criterion: format_valid
field: null
schema:
type: object
required: [intent, order_id]
properties:
intent: {enum: [where_is_order, cancel, return, other]}
order_id: {type: [string, "null"], pattern: '^\d{4}$'}
additionalProperties: false
- type: exact_match
criterion: intent_correct
field: intent
- type: exact_match
criterion: order_id_correct
field: order_idSistem HTTP harus mendeklarasikan version. Oloproof tidak dapat melihat sebuah deployment: Oloproof meng-cache keluaran setiap kasus berdasarkan URL, metode, path keluaran, dan versi itu, sehingga versi adalah cara Anda memberitahunya bahwa layanan berubah. Lupa mengubahnya, dan deployment baru tidak pernah dipanggil.
Header dan autentikasi belum dapat dikonfigurasi pada system.http. Bagian tentang token di bawah menunjukkan cara mengatasinya.
Dataset
{"id":"m04","input":{"message":"Has order #5120 shipped yet?"},"expected":{"intent":"where_is_order","order_id":"5120"}}
{"id":"m07","input":{"message":"Do you ship to Canada?"},"expected":{"intent":"other","order_id":null}}
{"id":"m16","input":{"message":"Please refund and take back the lamp from order #1560."},"expected":{"intent":"return","order_id":"1560"}}input persis body permintaan. expected memuat acuan untuk setiap field; null adalah nilai acuan yang nyata, yang berarti "tidak ada id pesanan dalam pesan ini".
Memilih evaluator
| Kriteria | Evaluator | Memerlukan expected | Mengukur |
|---|---|---|---|
| format_valid | json_schema atas keluaran | tidak | format: intent yang dikenal dan id yang bentuknya benar |
| intent_correct | exact_match pada intent | ya | keberhasilan tugas untuk field pertama |
| order_id_correct | exact_match pada order_id | ya | keberhasilan tugas untuk field kedua |
Skema akan meloloskan {"intent": "other", "order_id": null} untuk setiap pesan: bentuknya benar dan tidak berguna. Hanya pemeriksaan acuan yang mengatakan apakah layanan menjalankan tugasnya. Menilai field secara terpisah menunjukkan field mana yang gagal, yang akan disembunyikan oleh satu pemeriksaan gabungan.
release.yaml tidak mengizinkan kegagalan format dan meminta setiap field benar setidaknya 70% dari waktu, dinilai pada interval 95%:
version: 1
confidence_level: 0.95
block_on: [FAIL, INSUFFICIENT_EVIDENCE, MANUAL_REVIEW]
rules:
- id: valid-format
metric: format_valid
kind: observed_count
max_failures: 0
- id: intent-floor
metric: intent_correct
min: 0.70
- id: order-id-floor
metric: order_id_correct
min: 0.70Jalankan
oloproof runRun run_01M4... [DECIDED/COMPLETE]
Gate: BLOCK (exit 3)
│ valid-format │ format_valid │ PASS │ observed_failures_within_limit │
│ intent-floor │ intent_correct │ INSUFFICIENT_EVIDENCE │ interval_overlaps_threshold │
│ order-id-floor │ order_id_correct │ INSUFFICIENT_EVIDENCE │ interval_overlaps_threshold │
│ format_valid │ 100.0% │ [83.1%, 100.0%] │ 20 / 20 observed · 0 missing · 0 excluded │
│ intent_correct │ 75.0% │ [50.8%, 91.4%] │ 15 / 20 observed · 0 missing · 0 excluded │
│ order_id_correct │ 75.0% │ [50.8%, 91.4%] │ 15 / 20 observed · 0 missing · 0 excluded │
Cache: execution 0 hit/20 miss; judgment 0 hit/60 missSetiap respons berbentuk benar. Setiap field benar 15 kali dari 20, tetapi 20 kasus menyisakan interval yang turun hingga 50.8%, sehingga tidak satu pun batas bawah 70% terbukti: INSUFFICIENT_EVIDENCE, dan gerbang memblokir dengan keluar 3.
Periksa kegagalannya
oloproof inspect RUN_ID --failures8 of 20 cases failed, errored or did not finish
m04
output: {"intent": "where_is_order", "order_id": null}
order_id_correct: failed
m06
output: {"intent": "other", "order_id": "7011"}
intent_correct: failed
...
m18
output: {"intent": "other", "order_id": null}
intent_correct: failed
order_id_correct: failedBaca input di sampingnya (oloproof inspect RUN_ID --case m04) dan dua kesalahan muncul: pola id hanya cocok dengan "order 1234", bukan "order #5120", "order no. 8123", atau "#1673" saja; dan frasa seperti "send back", "stop order", dan "where's my parcel" tidak dipetakan ke intent mana pun. Itulah tindakan berikutnya: perluas kedua aturan.
Deploy perubahan
Hentikan layanan dan jalankan kandidat, yang membawa perbaikan tersebut:
python server.py --port 8765 --rules v2Ubah version: rules-v1 menjadi version: rules-v2 di oloproof.yaml, karena URL tidak berubah dan Oloproof jika tidak akan memakai ulang keluaran lama. Lalu:
oloproof runGate: ALLOW (exit 0)
│ intent_correct │ 100.0% │ [83.1%, 100.0%] │ 20 / 20 observed · 0 missing · 0 excluded │
│ order_id_correct │ 100.0% │ [83.1%, 100.0%] │ 20 / 20 observed · 0 missing · 0 excluded │Kedua batas bawah lolos dan perintah keluar dengan 0.
Bandingkan kedua deployment
compare.yaml menanyakan apakah intent kandidat lebih baik daripada intent baseline:
version: 1
confidence_level: 0.95
block_on: [FAIL, INSUFFICIENT_EVIDENCE, MANUAL_REVIEW]
rules:
- id: intent-better
kind: superiority
metric: intent_correctoloproof compare CANDIDATE_RUN_ID BASELINE_RUN_ID --policy compare.yamlformat_valid: +0.0 points [-23.6, +23.6] · 20 paired · 0 missing · 0 excluded
intent_correct: +25.0 points [-8.5, +58.3] · 20 paired · 0 missing · 0 excluded
order_id_correct: +25.0 points [-8.5, +58.3] · 20 paired · 0 missing · 0 excluded
Decisions
intent-better intent_correct superiority INSUFFICIENT_EVIDENCE interval_overlaps_zero
Gate: BLOCK (exit 3)Kandidat lolos batas bawahnya sendiri, tetapi perbandingan tidak dapat menunjukkan bahwa kandidat lebih baik: lima kasus berubah, dan atas 20 kasus berpasangan interval peningkatannya masih memuat nol. Kedua pernyataan itu benar sekaligus. "Memenuhi persyaratan" dan "mengalahkan baseline" adalah pertanyaan yang terpisah, dan suite sekecil ini hanya menjawab yang kedua untuk efek yang besar. Lebih banyak pesan nyata adalah obatnya.
Layanan yang memerlukan token
Jalankan layanan sehingga menuntut bearer token:
INTAKE_TOKEN=s3cret python server.py --port 8765 --rules v2 --require-tokensystem.http tidak mengirim header kustom, sehingga dengan version baru (misalnya rules-v2-auth) setiap panggilan ditolak:
Gate: BLOCK (exit 3)
│ valid-format │ format_valid │ INSUFFICIENT_EVIDENCE │ no_observations │
│ intent_correct │ │ [0.0%, 100.0%] │ 0 / 0 observed · 20 missing · 0 excluded │dan oloproof inspect RUN_ID --failures menampilkan execution ERROR: TransientError: system returned HTTP 401 pada setiap kasus. Error eksekusi adalah bukti yang hilang, bukan kegagalan: tidak ada yang teramati, sehingga setiap aturan berstatus INSUFFICIENT_EVIDENCE.
Cara mengatasinya adalah callable Python yang membuat permintaan sendiri. client.py menambahkan header dari variabel lingkungan, sehingga token tidak pernah masuk ke oloproof.yaml atau rekaman tersimpan mana pun:
URL = os.environ.get("INTAKE_URL", "http://127.0.0.1:8765/extract")
def extract(case: dict[str, Any]) -> dict[str, Any]:
headers = {"Authorization": f"Bearer {os.environ['INTAKE_TOKEN']}"}
response = httpx.post(URL, json=case, headers=headers, timeout=30)
response.raise_for_status()
return response.json()["result"]Ganti blok http: di oloproof.yaml dengan:
system:
name: order-intake
version: rules-v2
callable: client:extractdan jalankan dengan token di lingkungan:
INTAKE_TOKEN=s3cret oloproof runKe-20 kasus kembali teramati dan gerbang mengizinkan. Cache callable mengikuti source dan version miliknya sendiri, bukan layanan di baliknya, sehingga aturan yang sama berlaku: ubah version saat Anda melakukan deploy.
Pemecahan masalah
| Gejala | Penyebab dan perbaikan |
|---|---|
| system connection failed (ConnectError) pada setiap kasus | Layanan tidak berjalan, atau mendengarkan di port lain. |
| system connection failed (RemoteProtocolError) | Sesuatu yang lain menjawab di port itu. Pilih port yang kosong. |
| KeyError: "missing output path 'results'" | output_path menyebut field yang tidak ada dalam respons. |
| system returned HTTP 401 atau 403 | Endpoint memerlukan kredensial: gunakan cara callable. |
| Anda men-deploy perubahan dan baris cache berisi semua hit | version tidak berubah, sehingga keluaran tersimpan dipakai ulang. |
| an HTTP system needs a declared version | Tambahkan version di bawah system atau system.http. |
Keterbatasan
- Tidak ada header kustom, autentikasi, parameter query, atau templat permintaan pada system.http: input kasus adalah body JSON apa adanya. Gunakan callable untuk hal lain.
- Respons harus JSON. Respons streaming tidak dibaca sebagai stream.
- Oloproof tidak dapat mendeteksi deployment; version yang dideklarasikan adalah seluruh identitas dari apa yang menjawab.
- Layanan Anda memiliki state-nya sendiri: Oloproof mengirim permintaan dan merekam jawaban; Oloproof tidak mengatur ulang, mengisolasi, atau membatalkan apa pun yang diubah sebuah permintaan.