Agent ArenaClickHouse Workshops

04 ตรวจสอบโดยมนุษย์

บันทึกผู้สอนสำหรับการสืบสวนโดยมนุษย์ที่ยึดหลักฐานเป็นหลัก และการส่งต่อแหล่งที่มาจากระบบจริง

คู่มือประกอบสำหรับวิทยากร 04 ตรวจสอบโดยมนุษย์

เวลา

รวม ~20 นาที

  • 3 นาที — กรองความคิดเห็นเชิงลบและยืนยัน Chat root ที่เป็นข้อมูลอ้างอิงหลัก
  • 4 นาที — สร้าง score config ทั้งสามรายการ จากนั้นจึงสร้างคิวพร้อมไฟล์แนบที่ตายตัว
  • 4 นาที — เปิดโค้ดพฤติกรรมที่สังเกตได้ก่อนพูดคุยเรื่องการวินิจฉัย
  • 5 นาที — ตรวจสอบหลักฐานในเทรซและรัน SQL ของ policy-v1/policy-v2 เทียบกัน
  • 4 นาที — กรอกการแก้ไข อนุมัติ ทำงานให้เสร็จสิ้น และบันทึกแหล่งที่มา

การเตรียมล่วงหน้าของผู้สอน

ก่อนที่ผู้เรียนจะมาถึง ให้ยืนยันว่าโมดูล 03 สร้าง chat_turn ที่เป็นข้อมูลอ้างอิงหลักเพียงหนึ่งรายการ พร้อม Boolean user-thumbs=false และ sql-execution-success=true เก็บ trace ID ไว้เป็นความลับ และยืนยันว่าเอาต์พุตของ root มีคำถาม, SQL ที่สร้างขึ้น, แถวข้อมูลที่ส่งคืน และผลลัพธ์ครบถ้วน

สร้าง score config ทั้งสามรายการในโปรเจกต์ทดสอบแบบใช้แล้วทิ้งได้ หากต้องการฝึกซ้อมก่อน แต่อย่าสร้างคิวจริงของผู้เรียนไว้ล่วงหน้า ชุด score-config ID ที่แนบกับคิวจะถูกกำหนดตายตัว ตั้งแต่ตอนสร้างคิว ดังนั้นห้องเรียนควรสร้าง config ทั้งหมดก่อน แล้วแนบให้ครบทั้ง สามรายการ:

ชื่อชนิดค่า
observed-issueTEXTหลักฐานแบบข้อความอิสระ
failure-categoryCATEGORICALstale-business-policy, incorrect-sql, ambiguous-request, not-actionable
approved-for-goldenBOOLEANtrue / false

แบบฝึกหัดการทำ annotation นี้ทำผ่าน UI เท่านั้น สคริปต์ที่รันแบบ runtime ตรวจสอบ score ของเทรซและส่งเสริม (promote) ผลการตรวจทานที่ export ออกมาในภายหลังได้ แต่ไม่สามารถ สร้างคิว บันทึกการตัดสินของมนุษย์ หรือทำงาน annotation ให้เสร็จสิ้นแทนได้

แนวทางการบรรยาย

  1. กรอง Tracing ด้วย user-thumbs = false และจับคู่กับ trace ID จาก worksheet ของโมดูล 03 พูดว่า: “feedback เป็นตัวกำหนดว่าเราจะสืบสวนอะไรต่อ ไม่ใช่ตัวสรุปว่า ข้อสรุปคืออะไร”

  2. ใช้ Settings → Scores → Create สร้าง score config แต่ละรายการ จากนั้นใช้ Annotations → Queues → Create ตั้งชื่อคิวว่า production-investigation-<session> โดยมีส่วนต่อท้ายเฉพาะของเซสชัน และแนบ config ทั้งสามรายการเข้าไป

  3. เลือก root observation chat_turn เปิดเมนู Annotate แล้วเลือก คิวที่สร้างใหม่ ให้ดู llm_call ซึ่งเป็น child ด้วย แต่อธิบายว่าเหตุใดจึงเป็นเป้าหมายที่ผิด: เพราะมันขาดผลลัพธ์การทำงานแบบมีโครงสร้างตั้งแต่ต้นจนจบ และไม่ใช่จุดเกิดเหตุ (incident) ของ feedback ในเชิงตรรกะ

  4. เตือนผู้เรียนว่าโมดูล 03 ได้เปิดเผยการตั้งค่าที่จำลองไว้แล้ว จากนั้นขอให้พวกเขาพักความรู้ นั้นไว้ก่อนชั่วคราว และฝึกทำ open-coding โดยสังเกตพฤติกรรมจริง บันทึกแรกที่ดีตัวอย่างคือ:

    The SQL executed and returned a count. The observed count differs from the second
    reference count. The query uses a 90-day customer signup window, and the trace
    metadata reports policy-v1.
  5. เมื่อห้องเรียนบันทึกข้อสังเกตนั้นแล้วเท่านั้น จึงเปิดเผยหลักฐานทั้งหมด: metadata ที่ปล่อยออกมา คือ policyversion=policy-v1, SQL/ผลลัพธ์ที่อิงตามการลงทะเบียนใช้งาน (signup) และ score ทั้งสองตัว ฟิลด์ต้นทางคือ policy_version ส่วน OpenTelemetry adapter จะปล่อย key ที่ผ่านการ sanitize ของ Langfuse ออกมาเป็น policyversion

  6. รันนิยามของนโยบายทั้งสองเวอร์ชันเทียบกัน ข้อมูลอ้างอิงของ policy-v1 คือ:

    SELECT count() FROM v_customers
    WHERE signup_date >= today() - INTERVAL 90 DAY

    ข้อมูลอ้างอิงของนโยบายปัจจุบัน policy-v2 คือ:

    SELECT uniqExact(customer_id) FROM v_orders
    WHERE order_ts >= now() - INTERVAL 30 DAY
    AND status NOT IN ('cancelled', 'returned')
  7. เมื่อเปรียบเทียบเสร็จแล้วเท่านั้น จึงให้ลงข้อวินิจฉัย: บันทึก failure-category=stale-business-policy สลับ Corrected Output ไปเป็น plain-text mode แล้ววาง query ปัจจุบันแบบดิบลงไป Langfuse ไม่รัน SQL ให้ ดังนั้นต้องตรวจสอบข้อความเดียวกันเป๊ะ ๆ ผ่าน read-only client ของขั้นตอนที่ 6 ก่อนตั้งค่า approved-for-golden=true และทำงานให้เสร็จสิ้น

  8. เก็บรักษา source_trace_id, failure_category, source_policy_version, ค่าที่แก้ไข และ annotation task ID (ถ้ามี) ไว้สำหรับโมดูล 05

สามข้อวินิจฉัยที่ดูน่าเชื่อแต่ผิด

  • “โมเดลไม่ทำตามพรอมป์” SQL ในเทรซเป็นไปตามบริบท policy-v1 ที่ระบุไว้อย่างชัดเจน ความล้มเหลวอยู่ที่นโยบายที่ deploy ไว้ล้าสมัย ไม่ใช่การไม่ทำตาม คำสั่งที่ให้มา
  • “sql-execution-success เสีย” SQL รันสำเร็จจริง ดังนั้น evaluator ด้านการทำงานจึงคืนค่า true ได้อย่างถูกต้อง การออกแบบของมันไม่ได้ทดสอบความถูกต้องเชิง ความหมายทางธุรกิจที่อยู่ภายใต้การกำกับ (governed)
  • “thumbs-down พิสูจน์ว่า SQL ผิด” feedback บอกแค่ว่าเทรซนี้ควรค่าแก่การตรวจทาน มันไม่ได้ชี้ชัดเจตนาของผู้ใช้หรือให้ query ที่แก้ไขแล้วผ่านการยืนยัน; การเทียบนโยบาย เคียงข้างกันและการตรวจสอบโดยมนุษย์ต่างหากที่ทำหน้าที่นั้น

เก็บทางเลือกเหล่านี้ให้ผู้เรียนเห็นไว้จนกว่าพวกเขาจะได้ open-code เทรซด้วยตนเอง แม้ ผู้สอนจะรู้คำตอบที่จำลองไว้อยู่แล้ว แต่การสืบสวนก็ควรยังคงจำลองกระบวนการตรวจทานที่ ยึดหลักฐานเป็นหลักแบบที่ใช้งานจริง

การเลือก root observation ให้ถูกต้อง

มี observation ที่เกี่ยวข้องอยู่สองรายการในเทรซ:

รายการสังเกต (observation)เนื้อหาที่มีใช้ทำ annotation หรือไม่
รายการราก chat_turnคำถาม พร้อม SQL/ผลลัพธ์/เอาต์พุตแบบมีโครงสร้างใช่
รายการลูก llm_callบทสนทนาของโมเดล, SQL ที่สร้างขึ้น, การใช้โทเค็นไม่ใช่

หากผู้เรียนเผลอเพิ่ม child เข้าคิวโดยไม่ได้ตั้งใจ อย่าทำงานนั้นให้เสร็จเสมือนเป็นการสืบสวน production ที่ถูกต้อง ให้เพิ่ม root chat_turn เข้าคิวที่ถูกต้อง และเก็บ/ลบ task ที่ผิดพลาดตามนโยบายการเก็บรักษาข้อมูลของโปรเจกต์ ให้เก็บ trace ID ไว้ ไม่ใช่ ID ของ child observation ในฟิลด์ source_trace_id

ไฟล์แนบของคิวที่ตายตัว และการตั้งชื่อให้ปลอดภัยสำหรับการรีเซ็ต

Langfuse จะกำหนดชุด score-config ID ที่แนบกับคิวให้ตายตัวตอนที่คิวถูก สร้าง คิวไม่สามารถแนบ config ที่ตกหล่นไปเพิ่มในภายหลังได้ ดังนั้นการสร้าง config ทั้งหมดก่อนจึงเป็นแนวทางที่ปลอดภัยที่สุด ตัว score config เองสามารถแก้ไขได้: การแก้ไข name, schema หรือค่าของ categorical ที่รองรับต้องผ่านการอัปเดต score config แบบมี audit และการอัปเดตนั้นจะไม่เขียนทับ score ที่มีอยู่แล้ว

ใช้ suffix ที่ปลอดภัยสำหรับการรีเซ็ต เช่น:

production-investigation-<session>-retry-1

หากคิวตกหล่น config บางรายการ หรือแนบ config ID ผิด ให้สร้างคิวใหม่ที่มี suffix ต่างออกไปโดยแนบ ID ที่ถูกต้องครบทั้งสามรายการ เพิ่ม root ที่เป็นข้อมูลอ้างอิงหลักเข้าไปอีกครั้ง และทำเครื่องหมายคิวเก่าให้เห็นชัดว่าถูกแทนที่แล้ว (หรือลบออกได้เฉพาะเมื่อนโยบายของโปรเจกต์อนุญาต) ส่วนการแก้ไขที่รองรับกับ config ที่แนบอยู่แล้ว ให้ใช้การอัปเดต score config แบบมี audit แทนการสร้างคิวใหม่ อย่านำชื่อคิวที่เสร็จสมบูรณ์แล้วมาใช้ซ้ำในทางที่ทำให้ สับสนว่า task ใดเป็นตัวที่ให้ผลการตัดสินใจจริง

ความน่าเชื่อถือของ corrected output

ค่าที่แก้ไขจะกลายเป็น golden ground truth ในอนาคต ดังนั้นทั้งไวยากรณ์และความถูกต้อง ตามนโยบายจึงสำคัญทั้งคู่ สลับ Corrected Output ไปเป็น plain-text mode ก่อนวาง raw SQL Langfuse จะเก็บข้อความไว้แต่ไม่รันมัน ก่อนอนุมัติ ให้รัน ข้อความที่ตรงกันเป๊ะ ๆ ผ่าน read-only ClickHouse client ของขั้นตอนที่ 6 query ที่ดู ถูกต้องแต่มีรูปแบบผิดพลาด อ้างอิงตาราง raw ตรง ๆ มีหลายคำสั่งรวมกัน หรือรันไม่ผ่านใน ClickHouse ต้องไม่ได้รับการอนุมัติ

สำหรับ SQL ที่มีรูปแบบผิดพลาด:

  1. ตั้งค่าหรือคงค่า approved-for-golden=false ไว้;
  2. อย่าทำงานให้เสร็จสิ้นเสมือนได้รับการอนุมัติ;
  3. แก้ไขค่าที่ป้อนให้ตรงตาม view v_* ที่ได้รับอนุญาต;
  4. รันใหม่และตรวจสอบผลลัพธ์; และ
  5. อนุมัติและทำงานให้เสร็จสิ้นเมื่อผ่านการยืนยันแล้วเท่านั้น

หากมีคนทำงานที่มีค่าแก้ไขผิดรูปแบบให้เสร็จสิ้นไปแล้ว ให้สร้างคิว/suffix ของ task ใหม่และทำ การตรวจทานซ้ำ อย่าแก้ไขข้อมูลอย่างเงียบ ๆ จนลบล้างเส้นทางการตรวจสอบ (audit trail) คำสั่ง promotion ของโมดูล 05 ก็ตรวจสอบความเป็น read-only ของ SQL และรันมันด้วยเช่นกัน แต่การป้องกันนั้นไม่ใช่สิ่งที่ใช้แทนการตรวจสอบโดยมนุษย์ได้

ความล้มเหลวที่พบบ่อย

  • ไม่พบ trace หลังกรอง — ยืนยันว่า score type เป็น Boolean และตัวกรองคือ user-thumbs=false; อย่าค้นหาชื่อ score เก่า ให้จับคู่กับ trace ID จาก worksheet แทนการเลือก curl diagnostic ที่ไม่มีการให้คะแนน
  • เป้าหมายผิด — task แสดงเฉพาะ transcript/SQL เพราะเพิ่ม llm_call เข้าไป ให้กลับไปที่เทรซและเพิ่ม root chat_turn เข้าไปแทน
  • คิวขาดมิติที่ต้องมี — คิวถูกสร้างขึ้นโดยไม่ได้แนบ config ID ที่จำเป็นให้ครบ ให้สร้างคิวใหม่ที่มี suffix ต่างออกไป อย่าดำเนินการต่อด้วยแบบฟอร์มตรวจทานที่ไม่สมบูรณ์ ใช้การอัปเดต config แบบมี audit ไม่ใช่การสร้างคิวใหม่ สำหรับการแก้ไขที่รองรับกับ config ที่แนบอยู่แล้ว
  • ดูเหมือนไม่มี policy metadata — มองหา policyversion ที่ถูกปล่อยออกมา ไม่ใช่ฟิลด์ต้นทาง policy_version แล้วยืนยัน tag policy-v1 ของ root
  • ตัวเลขตรงกันโดยไม่คาดคิด — หยุดการวินิจฉัยไว้ก่อน ให้กลับไปรัน preflight ของ สถานการณ์ในโมดูล 03 อีกครั้ง และอย่าสร้างหลักฐานขึ้นจาก data snapshot ที่ไม่มีการเทียบเคียง
  • ค่าที่แก้ไขเป็น SQL ที่จัดรูปแบบแล้วไม่ใช่แบบดิบ — สลับ Corrected Output ไปเป็น plain-text mode และวางเฉพาะตัว query เท่านั้น
  • ค่าที่แก้ไขรันไม่ผ่าน — Langfuse จะไม่ตรวจจับสิ่งนี้ให้ คงค่า approval ไว้เป็น false แก้ไข แล้วรันข้อความที่ตรงกันเป๊ะ ๆ ผ่าน client ของขั้นตอนที่ 6 อีกครั้งก่อนทำ task ให้เสร็จสิ้น

การทำให้เสร็จสิ้นและการส่งต่อ

ก่อนย้ายไปโมดูล 05 ให้ยืนยันว่า task ที่เสร็จสิ้นนั้นเป็นของ chat_turn ที่เป็นข้อมูลอ้างอิงหลัก, ข้อสังเกตถูกบันทึกไว้ก่อนการวินิจฉัย, ค่าที่แก้ไขเป็น SQL ของนโยบายปัจจุบันที่ถูกต้องเป๊ะ ๆ และ task ได้รับการอนุมัติแล้ว worksheet ของผู้เรียนต้องมี:

source=production-feedback
source_trace_id=<authoritative Chat trace ID>
failure_category=stale-business-policy
source_policy_version=policy-v1
annotation_id=<task ID when available>

score เชิงลบจากผู้ใช้ยังคงอยู่บนเทรซ production เดิม ในฐานะสัญญาณคัดกรอง (triage) ส่วน annotation ของมนุษย์ให้ ground truth ที่ผ่านการตรวจทานแล้ว โมดูล 05 จะรักษาแหล่งที่มา ทั้งสองส่วนนี้ไว้ตอนที่ทำการ promote ค่าที่แก้ไขและสร้าง evaluator เพื่อป้องกันไว้ล่วงหน้า

ในหน้านี้

TH