05 Tutup siklusnya
Mengubah satu kegagalan produksi yang telah ditinjau menjadi golden data, evaluator kebijakan bisnis yang terkalibrasi, dan perlindungan untuk trafik di masa depan.
Titik awal
Modul 04 berakhir dengan anotasi manusia
yang sudah selesai untuk chat_turn otoritatif dari Modul 03. Simpan SQL yang telah
dikoreksi dan lembar kerja provenance-nya agar tetap tersedia:
source=production-feedback
source_trace_id=<authoritative Chat trace ID>
failure_category=stale-business-policy
source_policy_version=policy-v1
annotation_id=<completed task ID when available>Trace produksi asli memiliki sql-execution-success=true dan
user-thumbs=false. Thumbs-down tersebut menemukan trace yang perlu ditinjau;
anotasi yang sudah selesai memberikan diagnosis dan ground truth yang telah dikoreksi.
Siklus evaluasi dan perbaikan berkelanjutan
Modul ini menutup satu putaran siklus:
- umpan balik pengguna mengungkap titik buta pada evaluator online saat ini;
- seorang manusia menyelidiki dan menyetujui koreksi;
- insiden yang telah ditinjau tersebut memperluas golden dataset;
- rilis baseline dan candidate dijalankan pada dataset yang telah diperluas yang sama;
- evaluator umum dikalibrasi secara offline sebelum diaktifkan secara online; dan
- trafik di masa depan terus mengumpulkan skor evaluator maupun umpan balik pengguna.
Langkah terakhir ini penting: menyebarkan evaluator yang lebih baik tidak mengakhiri umpan balik pengguna. Sebuah evaluator hanya dapat mengukur dimensi yang direpresentasikan dalam katalog kebijakan dan prompt-nya. ๐ di masa depan dapat mengungkap kebijakan lain yang belum tercakup, permintaan yang ambigu, atau mode kegagalan lain, dan memulai siklus yang sama lagi.
Tujuan
Lewati lima evidence gate: promote, baseline, candidate, calibrate, lalu enable dan replay. Gunakan winner dari Modul 02 untuk kedua eksperimen, sehingga versi kebijakan menjadi satu-satunya perubahan yang memang disengaja.
Jalankan setiap perintah di bawah ini dari ClickHouse_Demos/workshops/agent_arena:
cd ClickHouse_Demos/workshops/agent_arena
source .env
export WINNER_MODEL="${WINNER_MODEL:-qwen3.7-flash}"
export WINNER_PROMPT="${WINNER_PROMPT:-P2_fewshot}"
export WINNER_CONFIG_ID="${WINNER_CONFIG_ID:-qwen3.7-flash__P2_fewshot}"Nilai default di atas adalah winner workshop yang telah terverifikasi. Jika room Anda
memilih config_id lain, atur ketiga nilai tersebut ke model/prompt itu, dan jaga
agar tidak berubah sepanjang setiap gate.
Evidence gate 1 โ Promote insiden yang telah ditinjau
Buat reviewed.json di root lab dengan tiga record berikut. Ganti kedua nilai
placeholder di semua tempat sebelum menjalankan promosi. Jika Langfuse tidak
mengekspos ID annotation task, hapus annotation_id dari ketiga record tersebut
alih-alih membiarkannya sebagai placeholder; field itu opsional, sedangkan field
production provenance lainnya wajib diisi.
[
{
"id": "prod-active-001",
"question": "How many active customers do we have?",
"golden_sql": "SELECT uniqExact(customer_id) FROM v_orders WHERE order_ts >= now() - INTERVAL 30 DAY AND status NOT IN ('cancelled', 'returned')",
"tier": 2,
"ordered": false,
"source": "production-feedback",
"source_trace_id": "<paste the Module 03 Chat trace ID>",
"failure_category": "stale-business-policy",
"source_policy_version": "policy-v1",
"annotation_id": "<paste the completed task ID>"
},
{
"id": "prod-active-002",
"question": "What is our active customer count right now?",
"golden_sql": "SELECT uniqExact(customer_id) FROM v_orders WHERE order_ts >= now() - INTERVAL 30 DAY AND status NOT IN ('cancelled', 'returned')",
"tier": 2,
"ordered": false,
"source": "production-feedback",
"source_trace_id": "<paste the Module 03 Chat trace ID>",
"failure_category": "stale-business-policy",
"source_policy_version": "policy-v1",
"annotation_id": "<paste the completed task ID>"
},
{
"id": "prod-active-003",
"question": "How many customers qualify as active under our business definition?",
"golden_sql": "SELECT uniqExact(customer_id) FROM v_orders WHERE order_ts >= now() - INTERVAL 30 DAY AND status NOT IN ('cancelled', 'returned')",
"tier": 2,
"ordered": false,
"source": "production-feedback",
"source_trace_id": "<paste the Module 03 Chat trace ID>",
"failure_category": "stale-business-policy",
"source_policy_version": "policy-v1",
"annotation_id": "<paste the completed task ID>"
}
]Hanya prod-active-001 yang merupakan pertanyaan persis dari trace user-feedback
tersebut. prod-active-002 dan prod-active-003 adalah paraphrase yang ditulis oleh
reviewer, diturunkan dari insiden yang sama yang telah diselidiki. Ketiganya memakai
source trace dan completed annotation yang sama demi keterlacakan (auditability);
mereka bukan dua trace production feedback tambahan. Ketiga input tersebut secara
sengaja sama-sama memanggil metrik active-customer yang telah digovernansi, sehingga
baseline tidak bisa tampak sehat hanya dengan menguji hitungan yang tidak terkait.
Promote batch yang telah ditinjau:
source .env
.venv/bin/python -m scripts.promote_to_golden reviewed.jsonHarapkan tiga baris prepared prod-active-* diikuti oleh:
promoted 3 question(s) into the 'arena-golden' datasetBuka Langfuse โ Datasets โ arena-golden dan periksa metadata setiap item baru.
Verifikasi source=production-feedback, source_trace_id asli yang sama,
failure_category=stale-business-policy, dan source_policy_version=policy-v1.
Korpus sumber repo berisi 20 pertanyaan YAML. q019 dan q020 adalah holdout untuk
prompt few-shot, sehingga project bersih dimulai dengan 18 item Experiment
arena-golden. Promosi tiga item ini membuat dataset bersih berisi 21 item. Project
yang digunakan ulang dapat memiliki item lain yang sudah disetujui; catat provenance-nya
alih-alih menghapusnya demi memaksakan jumlah, dan wajibkan baseline serta candidate
memakai ID item yang identik.
reviewed.json adalah mutable operator state yang di-ignore, dan merupakan jalur
utama workshop ini. --synthetic-fixture yang tracked hanyalah fallback rehearsal
yang reproducible. Itu tidak merepresentasikan anotasi manusia dan tidak dapat
memenuhi evidence gate modul ini. Kedua mode saling eksklusif; jangan pernah
menjalankan synthetic fallback setelah promosi yang genuine.
Promosi memvalidasi seluruh batch, SQL yang read-only, dan provenance yang diwajibkan sebelum melakukan query ke ClickHouse atau menulis dataset item. Setelah itu ia membaca metadata dataset yang sudah ada dan menolak ID yang bertabrakan (collide) dengan production provenance yang berbeda. Jika preflight yang terautentikasi itu tidak dapat menetapkan provenance secara aman, prosesnya berhenti tanpa melakukan write. Mengulang promosi yang genuine hanya aman ketika production provenance yang bertabrakan itu identik.
Evidence gate 2 โ Jalankan baseline policy-v1
Terlebih dahulu, provision judge yang catalog-driven untuk eksperimen. Ini membuat rule observasi online-nya dalam keadaan disabled:
source .env
.venv/bin/python -m scripts.provision_online_evaluators \
--business-policy-experimentsHarapkan experiment rule enabled=True; online rule enabled=False. Konfirmasikan di
Langfuse bahwa online rule tersebut masih disabled sebelum melanjutkan.
Beri suffix unik untuk percobaan workshop ini, lalu jalankan model dan prompt yang terpilih pada dataset yang telah diperluas, dengan kebijakan yang usang (stale):
export LOOP_RUN_SUFFIX="${LOOP_RUN_SUFFIX:-$(date +%Y%m%d-%H%M%S)}"
export BASELINE_RUN_ID="online-loop-baseline-${LOOP_RUN_SUFFIX}"
export CANDIDATE_RUN_ID="online-loop-candidate-${LOOP_RUN_SUFFIX}"
.venv/bin/python -m eval.harness --run-id "$BASELINE_RUN_ID" \
--policy-version policy-v1 --models "$WINNER_MODEL" --prompts "$WINNER_PROMPT" \
--wait-for-score business-policy-adherenceHarness ini menambahkan --policy-v1 ke release ID. Ia menunggu tiga nama skor
Experiment yang eksak pada setiap trace: correctness, agent-arena-llm-judge, dan
business-policy-adherence. Jangan lanjutkan jika run tersebut timeout atau ada
skor yang tidak muncul.
Di Langfuse Experiments, catat jumlah dataset item dari baseline serta agregat correctness-nya. Setelah promosi, project bersih seharusnya berisi 21 item. Project yang digunakan ulang bisa memiliki lebih banyak item yang sudah disetujui, dan respons provider dapat berbeda, sehingga release gate-nya adalah paired comparison di bawah ini, bukan score agregat yang di-hard-code.
Evidence gate 3 โ Jalankan candidate policy-v2
Tanpa mengubah dataset, model, prompt, atau run suffix, jalankan candidate:
.venv/bin/python -m eval.harness --run-id "$CANDIDATE_RUN_ID" \
--policy-version policy-v2 --models "$WINNER_MODEL" --prompts "$WINNER_PROMPT" \
--wait-for-score business-policy-adherenceCatat agregat aktual candidate, lalu bandingkan kedua run tersebut di Langfuse dan wajibkan:
- dataset item ID dan jumlah item yang identik;
- ketiga item
prod-active-*berpindah daricorrectness=0di bawahpolicy-v1menjadicorrectness=1di bawahpolicy-v2; - setiap item yang sudah ada sebelum
prod-active-*dibandingkan per item, tanpa regresicorrectness=1menjadicorrectness=0; dan - correctness agregat candidate tidak lebih rendah dari correctness baseline.
Hentikan jika ada item pra-eksisting yang regresi. Candidate yang memperbaiki insiden tersebut dengan cara merusak perilaku yang sudah diketahui belum melewati release gate.
Evidence gate 4 โ Kalibrasi satu policy judge umum
business-policy-adherence bukan "evaluator active-customer." Ia menerima
pertanyaan, SQL yang dihasilkan, dan katalog metrik policy-v2 yang lengkap. Ia
menentukan metrik yang tergovernansi mana yang berlaku, lalu mengembalikan PASS,
FAIL, atau NOT_APPLICABLE. Desain yang sama dapat memeriksa active customers,
revenue, conversion, dan gross margin tanpa perlu membuat satu evaluator per
formulasi pertanyaan.
Sebelum mengaktifkannya untuk observasi produksi, periksa item Experiment berikut:
| Probe kalibrasi | Run/item | business-policy-adherence yang diwajibkan |
|---|---|---|
| SQL active-customer yang usang | baseline prod-active-001 | FAIL |
| SQL active-customer yang telah dikoreksi | candidate prod-active-001 | PASS |
| kebijakan revenue | candidate q005 | PASS |
| kebijakan view-to-purchase conversion | candidate q018 | PASS |
| hitungan customer biasa | candidate q001 | NOT_APPLICABLE |
Ulangi pemeriksaan active-customer untuk prod-active-002 dan prod-active-003.
Baca juga reasoning dari judge, bukan hanya kategorinya: ia harus menyebutkan
kebijakan katalog yang berlaku dan mengevaluasi SQL yang dihasilkan terhadap
kebijakan tersebut. Hitungan biasa harus tetap NOT_APPLICABLE, yang menunjukkan
bahwa judge tidak memaksakan setiap pertanyaan hitungan ke dalam kebijakan
active-customer.
Biarkan online rule tetap disabled jika ada kategori yang salah, ada skor wajib yang tidak muncul, structured output-nya malformed, atau perbandingan correctness-nya regresi. Kalibrasi Experiment secara offline didahulukan karena memungkinkan Anda memeriksa false pass dan false fail terhadap contoh yang sudah diketahui, sebelum evaluator tersebut memengaruhi monitoring produksi.
Evidence gate 5 โ Enable dan replay pada policy-v2
Hanya setelah semua gate kalibrasi lolos, aktifkan observation rule-nya:
source .env
.venv/bin/python -m scripts.provision_online_evaluators \
--enable-business-policy-onlineHarapkan nama rule yang eksak, agent-arena-business-policy-online, dengan
enabled=True. Perintah ini fail closed ketika tidak dapat menemukan
dataset-scoped Experiment score bernama business-policy-adherence; pemeriksaan
kalibrasi manual Anda di atas tetap menjadi quality gate-nya.
Hentikan server policy-v1. Di terminal pertama, jalankan candidate dan biarkan
tetap berjalan:
source .env
AGENT_ARENA_POLICY_VERSION=policy-v2 \
.venv/bin/uvicorn serving.api:app --port 8100Di terminal kedua, definisikan helper yang menerima sebuah pertanyaan dan
mengembalikan trace ID-nya hanya setelah mengonfirmasi respons policy-v2 yang
berhasil:
source .env
export WINNER_CONFIG_ID="${WINNER_CONFIG_ID:-qwen3.7-flash__P2_fewshot}"
ask_trace() {
local question="$1"
local body
body=$(.venv/bin/python -c \
'import json,sys; print(json.dumps({"question": sys.argv[1], "config_id": sys.argv[2]}))' \
"$question" "$WINNER_CONFIG_ID")
curl -fsS http://localhost:8100/ask \
-H 'content-type: application/json' -d "$body" | \
.venv/bin/python -c \
'import json,sys; data=json.load(sys.stdin); assert data["policy_version"] == "policy-v2" and data["outcome"] == "ok"; print(data["trace_id"])'
}Ajukan pertanyaan active-customer dan revenue masing-masing satu kali. Skor
observasi online memakai nama rule agent-arena-business-policy-online, bukan
nama skor Experiment:
ACTIVE_TRACE=$(ask_trace "How many active customers do we have?")
.venv/bin/python -m scripts.verify_online_scores "$ACTIVE_TRACE" \
sql-execution-success=true agent-arena-business-policy-online=PASS
REVENUE_TRACE=$(ask_trace "What was revenue in the last 30 days?")
.venv/bin/python -m scripts.verify_online_scores "$REVENUE_TRACE" \
sql-execution-success=true agent-arena-business-policy-online=PASSPertanyaan conversion memiliki boundary stokastik yang sudah terverifikasi.
Ajukan sekali dan pertahankan trace tersebut. Jika outcome dari serving bukan
ok, atau skor eksak yang diwajibkan tidak muncul atau gagal, coba ulang
pertanyaan dan config yang sama paling banyak satu kali. Blok ini menjaga
kedua percobaan tetap terlihat:
ask_conversion() {
local body
body=$(.venv/bin/python -c \
'import json,sys; print(json.dumps({"question": sys.argv[1], "config_id": sys.argv[2]}))' \
"What is our view-to-purchase conversion rate for the last 7 days?" \
"$WINNER_CONFIG_ID")
curl -fsS http://localhost:8100/ask \
-H 'content-type: application/json' -d "$body" | \
.venv/bin/python -c \
'import json,sys; data=json.load(sys.stdin); assert data["policy_version"] == "policy-v2"; print("\t".join((data["trace_id"], data["outcome"])))'
}
IFS=$'\t' read -r CONVERSION_TRACE_1 CONVERSION_OUTCOME_1 <<< \
"$(ask_conversion)"
if .venv/bin/python -m scripts.verify_online_scores "$CONVERSION_TRACE_1" \
sql-execution-success=true agent-arena-business-policy-online=PASS; then
CONVERSION_SCORES_1=pass
else
CONVERSION_SCORES_1=fail
fi
if [ "$CONVERSION_OUTCOME_1" = ok ] && [ "$CONVERSION_SCORES_1" = pass ]; then
CONVERSION_RESULT_1=pass
else
CONVERSION_RESULT_1=fail
fi
printf 'conversion_attempt=1 trace_id=%s outcome=%s exact_scores=%s result=%s\n' \
"$CONVERSION_TRACE_1" "$CONVERSION_OUTCOME_1" \
"$CONVERSION_SCORES_1" "$CONVERSION_RESULT_1"
CONVERSION_TRACE_2=not-run
CONVERSION_OUTCOME_2=not-run
CONVERSION_SCORES_2=not-run
CONVERSION_RESULT_2=not-run
if [ "$CONVERSION_RESULT_1" != pass ]; then
IFS=$'\t' read -r CONVERSION_TRACE_2 CONVERSION_OUTCOME_2 <<< \
"$(ask_conversion)"
if .venv/bin/python -m scripts.verify_online_scores "$CONVERSION_TRACE_2" \
sql-execution-success=true agent-arena-business-policy-online=PASS; then
CONVERSION_SCORES_2=pass
else
CONVERSION_SCORES_2=fail
fi
if [ "$CONVERSION_OUTCOME_2" = ok ] && [ "$CONVERSION_SCORES_2" = pass ]; then
CONVERSION_RESULT_2=pass
else
CONVERSION_RESULT_2=fail
fi
fi
printf 'conversion_attempt=2 trace_id=%s outcome=%s exact_scores=%s result=%s\n' \
"$CONVERSION_TRACE_2" "$CONVERSION_OUTCOME_2" \
"$CONVERSION_SCORES_2" "$CONVERSION_RESULT_2"
if [ "$CONVERSION_RESULT_1" != pass ] && \
[ "$CONVERSION_RESULT_2" != pass ]; then
printf '%s\n' \
'STOP: conversion failed twice; preserve both traces and investigate.' >&2
false
fiJangan mengulang sampai berhasil (green). Jika kedua percobaan gagal, simpan kedua trace tersebut, jaga hasilnya tetap terlihat, dan arahkan bukti baru ini melalui anotasi manusia, perbaikan golden data, dan paired calibration loop yang sama.
Hanya setelah conversion lolos, ajukan pertanyaan plain-count sekali:
PRODUCT_TRACE=$(ask_trace "How many products are there?")
.venv/bin/python -m scripts.verify_online_scores "$PRODUCT_TRACE" \
sql-execution-success=true agent-arena-business-policy-online=NOT_APPLICABLEEvaluator online berjalan secara asinkron. Verifier melakukan polling hingga 180 detik secara default; skor yang masih pending tidak sama dengan skor yang gagal.
Jaga siklus tetap berjalan
Biarkan ๐/๐ tetap aktif setelah rollout. Pantau ketidaksesuaian seperti
agent-arena-business-policy-online=PASS berdampingan dengan user-thumbs=false:
kasus-kasus ini adalah kandidat bernilai tinggi untuk annotation queue berikutnya.
Tinjauan manusia memutuskan apakah yang perlu dikoreksi adalah kebijakan, prompt,
data, atau evaluator itu sendiri. Kasus yang disetujui kembali masuk ke
arena-golden, lalu candidate berikutnya mengulang urutan yang sama:
baseline โ candidate โ calibration โ guarded enablement.
Aturan workshop ini men-sample 100% trace yang eligible agar setiap peserta melihat buktinya. Itu adalah setelan untuk pengajaran, bukan default produksi. Sampling yang sesungguhnya harus mencerminkan trafik, biaya evaluator, latensi, risiko, dan cakupan insiden yang Anda butuhkan.
Bukti penyelesaian
- Root trace produksi masih menunjukkan
sql-execution-success=truedan Booleanuser-thumbs=false. - Task human-annotation
production-investigation-<session>selesai dengan koreksi yang telah terverifikasi danapproved-for-golden=true. - Ketiga golden item ada dengan provenance
production-feedbackyang asli; Anda dapat membedakan satu pertanyaan pengguna dari dua paraphrase yang ditulis oleh reviewer. - Baseline dan candidate memakai dataset, model, dan prompt yang diperluas sama; candidate memperbaiki ketiga item yang dipromosikan dan tidak menimbulkan regresi correctness pada item yang sudah ada.
- Kalibrasi Experiment menghasilkan
FAIL,PASS, danNOT_APPLICABLEdengan nama skor eksakbusiness-policy-adherence. - Observation rule tetap disabled selama kalibrasi, lalu diaktifkan hanya setelah gate-nya lolos.
- Trace active-customer, revenue, dan conversion memiliki
agent-arena-business-policy-online=PASS; plain product count memilikiagent-arena-business-policy-online=NOT_APPLICABLE. - Anda dapat menjelaskan mengapa evaluasi online dan umpan balik pengguna terus memperbaiki satu sama lain setelah deployment.