Agent ArenaClickHouse Workshops

03 ปล่อยใช้งานและตรวจจับ

ปล่อยใช้งานเอเจนต์ที่เลือกไว้พร้อมจุดบอดของนโยบายที่รู้อยู่แล้ว จากนั้นใช้การประเมินระหว่างปฏิบัติงานร่วมกับคำติชมจริงจากผู้ใช้เพื่อตรวจจับจุดบอดนั้น

จุดเริ่มต้น

โมดูล 02 เสร็จสมบูรณ์แล้ว บันทึก config_id ของผู้ชนะที่เลือกจากการรัน Arena จริง จากนั้นเอ็กซ์พอร์ตค่านี้จากรากของแล็บ (ClickHouse_Demos/workshops/agent_arena):

source .env
export WINNER_CONFIG_ID="${WINNER_CONFIG_ID:-qwen3.7-flash__P2_fewshot}"

การรันเวิร์กชอปที่ตรวจสอบแล้วเลือก qwen3.7-flash__P2_fewshot หากผู้ชนะของห้องคุณ ต่างจากนี้ ให้ใช้ค่าของห้องคุณเอง คุณจะใช้โมเดลและพรอมป์ตัวเดียวกับที่คุณวัดผลไว้ —ไม่ใช่เอเจนต์พิเศษที่สร้างขึ้นเพื่อให้ล้มเหลวโดยเฉพาะ

ถ้าผู้ชนะของคุณคือ Qwen จะต้องปิดใช้งาน OpenRouter Settings → Privacy → Data Policies → Zero Data Retention → Non-frontier เส้นทาง Alibaba ที่มีให้ใช้จะถูก ปฏิเสธเมื่อมีการบังคับใช้ non-frontier ZDR ตรวจสอบข้อกำหนดด้านความเป็นส่วนตัวของคุณ ก่อนเปลี่ยนการตั้งค่านี้กับข้อมูลจริง

เหตุใดผู้ประเมินที่ผ่านการทดสอบยังพลาดคุณค่าของผู้ใช้ได้

ผู้ประเมินออนไลน์วัดเฉพาะมิติที่ถูกออกแบบมาให้วัดเท่านั้น ในที่นี้ sql-execution-success ตอบคำถามด้านการปฏิบัติงานที่สำคัญข้อหนึ่ง: เอเจนต์สร้าง SQL ที่ ClickHouse รันได้จริงหรือไม่? แต่มันไม่รู้ว่า SQL นั้นเป็นไปตามคำนิยาม ทางธุรกิจปัจจุบันของคำว่า ลูกค้าที่ยังใช้งานอยู่ หรือเปล่า

นั่นทำให้เกิดช่องว่างในการเฝ้าตรวจที่สมจริงมาก:

สัญญาณคำถามที่มันตอบค่าที่คาดหวังในเหตุการณ์นี้
sql-execution-successSQL ที่สร้างขึ้นรันสำเร็จหรือไม่true
user-thumbsคำตอบนี้ตอบสนองความต้องการของผู้ใช้รายนี้หรือไม่false

การประเมินระหว่างปฏิบัติงานจับได้เฉพาะ SQL ที่พัง การหมดเวลา และข้อผิดพลาดในการ รัน ส่วนการประเมินเชิงความหมายหรือการประเมินโดยผู้ใช้จะถามว่าคำตอบที่รันได้นั้นมี ประโยชน์และตรงกับความหมายทางธุรกิจหรือไม่ ทั้งสองอย่างไม่สามารถแทนที่กันได้ การกดยกนิ้วโป้งลงเป็นสัญญาณสำหรับจัดลำดับความสำคัญ ไม่ใช่ความจริงที่ยืนยันได้ในตัวเอง มนุษย์จะเป็นผู้สืบสวนเรื่องนี้ต่อในโมดูล 04

เป้าหมาย

สร้าง chat_turn trace จริงหนึ่งรายการ ซึ่งผู้ประเมินระหว่างปฏิบัติงานผ่าน แต่ผู้ใช้ให้คะแนนคำตอบว่าไม่ดี บันทึก trace นั้นพร้อมค่านับสองค่าที่ขัดแย้งกัน เพื่อส่งต่อให้มนุษย์สืบสวน

ขั้นตอนที่ 1 — พิสูจน์ว่าเหตุการณ์ที่ปลูกไว้สามารถทำซ้ำได้

รัน preflight จากรากของแล็บก่อนเริ่มเซิร์ฟเวอร์สาธิต:

source .env
export WINNER_CONFIG_ID="${WINNER_CONFIG_ID:-qwen3.7-flash__P2_fewshot}"
.venv/bin/python -m schema.gen_schema_context
.venv/bin/python -m scripts.check_online_eval_scenario \
  --config-id "$WINNER_CONFIG_ID"

คำสั่งนี้จะรันทั้งสองคำนิยาม และถามคอนฟิกที่เลือกไว้ด้วยคำถามที่เขียนต่างกัน สามแบบ ผลลัพธ์ต้องพิมพ์ค่า stale_count และ current_count ที่ต่างกัน พร้อม บรรทัด classification_N=policy-v1 สามบรรทัด และ:

หากคำถามรูปแบบใดคืนค่า ok/unknown การตรวจสอบ preflight จะลองซ้ำเฉพาะคำถาม รูปแบบเดิมและคอนฟิกเดิมเพียงหนึ่งครั้ง จะไม่ลองซ้ำเมื่อผลเป็น policy-v2 หรือเกิด ความล้มเหลวที่ผู้ให้บริการ/โมเดล/เอเจนต์ และหากครั้งที่สองยังเป็น ok/unknown จะยังคงถูกบล็อก

OK: seeded online-evaluation incident is reproducible

หากค่านับทั้งสองเท่ากัน หรือการจำแนกใดจำแนกหนึ่งไม่ใช่ policy-v1 ให้หยุดทันที เพราะความแตกต่างนี้จะไม่ปรากฏให้เห็นในข้อมูล/โมเดลที่รันอยู่นี้

คำนิยามทางธุรกิจปัจจุบันคือ SQL นี้เป๊ะๆ:

SELECT uniqExact(customer_id) FROM v_orders
WHERE order_ts >= now() - INTERVAL 30 DAY
AND status NOT IN ('cancelled', 'returned')

ในขณะที่คำนิยาม policy-v1 แบบเก่านับลูกค้าที่ลงทะเบียนในช่วง 90 วันที่ผ่านมา แทน ดังนั้น SQL ที่โมเดลสร้างขึ้นในโมดูลนี้จึงถูกต้องเมื่อเทียบกับคำสั่ง policy-v1 ที่ระบุไว้อย่างชัดเจน ประเด็นสำคัญไม่ใช่ว่าโมเดลไม่ฉลาด แต่เป็นเพราะ บริบทของนโยบายที่ปล่อยใช้งานล้าสมัยไปแล้ว ในขณะที่ผู้ประเมิน SQL-execution นั้น มองแค่มุมแคบเกินกว่าจะสังเกตเห็นความล้าสมัยนี้

ขั้นตอนที่ 2 — จัดเตรียมผู้ประเมินระหว่างปฏิบัติงาน

การจัดเตรียมนี้เป็น idempotent ดังนั้นรันซ้ำได้อย่างปลอดภัย:

source .env
.venv/bin/python -m scripts.provision_online_evaluators --operational

ผลลัพธ์ที่คาดไว้ควรระบุชื่อผู้ประเมิน sql-execution-success และกฎที่เปิดใช้งาน agent-arena-sql-execution-online

ขั้นตอนที่ 3 — เริ่มการปล่อยใช้งานแบบนโยบายเก่าที่ปลูกไว้

ในเทอร์มินัลแรก จากรากของแล็บ ให้เริ่มเซิร์ฟเวอร์โดยเลือกนโยบายเก่าไว้อย่าง ชัดเจน และปล่อยให้รันต่อไป:

source .env
AGENT_ARENA_POLICY_VERSION=policy-v1 \
  .venv/bin/uvicorn serving.api:app --port 8100

อย่าลืมระบุ AGENT_ARENA_POLICY_VERSION เพราะไม่เช่นนั้น service จะใช้ค่าเริ่ม ต้นเป็น policy-v2 ปัจจุบัน ซึ่งจะตัดคำสั่งซื้อที่ยกเลิกและคืนสินค้าออกอย่าง ถูกต้อง

ขั้นตอนที่ 4 — ถามและให้คะแนนผ่าน Chat

ในอีกเทอร์มินัลหนึ่ง เริ่มแดชบอร์ดหากยังไม่ได้รันอยู่:

scripts/arena.sh serve

เปิด http://localhost:5174 เลือกแท็บ Chat และ $WINNER_CONFIG_ID จากนั้นถาม ว่า:

How many active customers do we have?

อ่าน SQL ที่ถูกสร้างขึ้นและผลลัพธ์ ควรเป็นไปตามคำนิยามแบบลงทะเบียน 90 วันที่ปลูก ไว้จาก policy-v1 คลิก 👎 ที่คำตอบนี้ และรอจนกว่า UI จะแสดงข้อความ feedback sent

trace รากของ Chat นี้คือเหตุการณ์ที่เชื่อถือได้เพียงเหตุการณ์เดียวที่คุณจะให้ คะแนนและส่งต่อให้โมดูล 04

ขั้นตอนที่ 5 — ค้นหาและตรวจสอบ trace ของ Chat

ใน Langfuse เปิด Tracing และกรองด้วย user-thumbs = false เปิด root chat_turn ล่าสุดที่คำถามคือ How many active customers do we have? ที่คอนฟิก ตรงกับ $WINNER_CONFIG_ID และมี metadata แสดง policyversion=policy-v1 คัดลอก trace ID และ trace URL ของมัน แล้วตั้งค่า ID ไว้ในเครื่อง:

export CHAT_TRACE_ID="<paste the Chat trace ID>"
.venv/bin/python -m scripts.verify_online_scores "$CHAT_TRACE_ID" \
  sql-execution-success=true user-thumbs=false

ตรวจสอบว่า user-thumbs เป็นสกอร์ Boolean false ไม่ใช่สกอร์ตัวเลขหรือข้อความ ต้นทางฝั่ง serving เรียกฟิลด์ metadata นี้ว่า policy_version ส่วน adapter ของ OpenTelemetry จะแปลงให้เป็นคีย์ที่ปล่อยออกมาใน Langfuse คือ policyversion

ขั้นตอนที่ 6 — ทำซ้ำด้วย curl ที่ไม่ให้คะแนน

การเรียก API แบบตรงนี้เป็นการทำซ้ำและตรวจสอบระดับคำสั่งที่จำเป็นต้องทำ มันจะ สร้าง trace แยกต่างหากขึ้นมา แต่ ไม่ใช่ เหตุการณ์ที่มีคำติชม และต้องไม่ให้ คะแนนกับมัน:

source .env
export WINNER_CONFIG_ID="${WINNER_CONFIG_ID:-qwen3.7-flash__P2_fewshot}"
ASK_BODY=$(.venv/bin/python -c \
  'import json,sys; print(json.dumps({"question": sys.argv[1], "config_id": sys.argv[2]}))' \
  "How many active customers do we have?" "$WINNER_CONFIG_ID")
CURL_RESPONSE=$(curl -fsS http://localhost:8100/ask \
  -H 'content-type: application/json' -d "$ASK_BODY")
printf '%s\n' "$CURL_RESPONSE" | .venv/bin/python -m json.tool
CURL_TRACE_ID=$(printf '%s\n' "$CURL_RESPONSE" | .venv/bin/python -c \
  'import json,sys; data=json.load(sys.stdin); assert data.get("policy_version") == "policy-v1"; assert data.get("outcome") == "ok"; trace_id=data.get("trace_id"); assert isinstance(trace_id, str) and trace_id; print(trace_id)')

การตอบกลับต้องมี outcome: "ok", trace_id ที่ไม่ว่างเปล่า และ policy_version: "policy-v1"

รอผู้ประเมินแบบ asynchronous แล้วตรวจสอบเฉพาะสกอร์ด้านการปฏิบัติงานของมันเท่านั้น:

.venv/bin/python -m scripts.verify_online_scores "$CURL_TRACE_ID" \
  sql-execution-success=true

อย่าเรียก /feedback สำหรับ CURL_TRACE_ID และอย่านำมันไปใส่ในเวิร์กชีต มันเป็น เพียงการวินิจฉัยผ่าน API ที่ทำซ้ำได้เท่านั้น CHAT_TRACE_ID ยังคงเป็น trace ที่ ใช้ส่งต่อ

ขั้นตอนที่ 7 — เปรียบเทียบกับนโยบายปัจจุบัน

รัน SQL ตามนโยบายปัจจุบันผ่าน read-only ClickHouse client ตัวเดียวกันกับที่ เอเจนต์ใช้ จากนั้นเปรียบเทียบผลลัพธ์เดี่ยวของมันกับผลลัพธ์แบบนโยบายเก่าใน CURL_RESPONSE:

.venv/bin/python - <<'PY'
from arena.config import load_config
from agents.chclient import ROClickHouseClient

sql = """SELECT uniqExact(customer_id) FROM v_orders
WHERE order_ts >= now() - INTERVAL 30 DAY
AND status NOT IN ('cancelled', 'returned')"""
result = ROClickHouseClient(load_config().clickhouse).query(sql)
print(result.rows[0][0])
PY

นี่คือคิวรีที่คุณเพิ่งรันไปเป๊ะๆ:

SELECT uniqExact(customer_id) FROM v_orders
WHERE order_ts >= now() - INTERVAL 30 DAY
AND status NOT IN ('cancelled', 'returned')

ค่านับที่แตกต่างกันนี้คือความล้มเหลวที่ผู้ใช้มองเห็นได้ SQL รันสำเร็จ แต่มันตอบ ตามคำนิยามทางธุรกิจที่ผิด บันทึกค่านับนี้ไว้ควบคู่กับหลักฐาน trace ของ Chat ที่ เชื่อถือได้

เวิร์กชีตการสืบสวน

เก็บข้อมูลส่งต่อนี้ไว้สำหรับโมดูล 04:

หลักฐานค่าของคุณ
config_id ของผู้ชนะ
Trace ID ของ Chat ที่เชื่อถือได้
Trace URL ของ Chat ที่เชื่อถือได้
ค่านับแบบ policy-v1 เก่า
ค่านับแบบ policy-v2 ปัจจุบัน
sql-execution-successtrue
user-thumbsfalse

วิธีตรวจสอบว่าคุณทำเสร็จแล้ว

  • preflight แสดงค่านับ stale/current ที่ต่างกัน และคำถามที่ปลูกไว้ทั้งสามข้อถูก จำแนกเป็น policy-v1
  • service รันด้วย AGENT_ARENA_POLICY_VERSION=policy-v1 และ /ask คืนค่า outcome: "ok"
  • trace ของ Chat ที่เชื่อถือได้มี sql-execution-success=true และ user-thumbs=false ใน Langfuse
  • การวินิจฉัยด้วย curl ที่จำเป็นคืนค่า outcome: "ok" สร้าง CURL_TRACE_ID ที่ แยกจากกัน และไม่ได้ถูกให้คะแนนหรือส่งต่อ
  • คุณบันทึก trace ID/URL ของ Chat ที่เชื่อถือได้ และค่านับทั้งสองค่าไว้แล้ว โดย ไม่มีการแบ่งปัน credential ใดๆ
  • คุณสามารถอธิบายได้ว่าทำไมการรัน SQL สำเร็จจึงไม่ได้พิสูจน์ความถูกต้องเชิง ความหมาย

ไปยัง โมดูล 04 — ตรวจสอบ เพื่อ เปลี่ยนสัญญาณนี้ให้เป็นการวินิจฉัยที่ผ่านการตรวจสอบโดยมนุษย์

ในหน้านี้

Track your progress?

Optional. We email a link to confirm your address; progress records once you open it.

Please use your work email address, not a personal one.

Progress tracking also requires accepting the current Terms of Service in Privacy settings.

TH