AI Engineer › Agents และ tool use
ชุดฝึกท้าย module: Agents และ tool use
โจทย์คละหัวข้อทั้ง module โดยไม่บอกว่าต้องใช้เทคนิคไหน ให้เลือกวิธีเองเหมือนตอนทำงานจริง
TOOL_SCHEMAS มีกี่เครื่องมือ (รวม cancel_order ที่ลงทะเบียนเพิ่ม) เก็บไว้ใน n_tools และมีกี่ตัวที่ไม่ใช่เครื่องมือเขียน (ไม่อยู่ใน WRITE_TOOLS) เก็บไว้ใน n_safe
get_product(50) คืนชื่อและราคาอะไร เก็บไว้ในตัวแปร name_50 และ price_50
ลูกค้าหมายเลข 3015 มีออเดอร์กี่รายการ (count_orders) เก็บไว้ในตัวแปร n_3015
ส่ง get_product โดยไม่มีอาร์กิวเมนต์ ({"name": "get_product", "input": {}}) เข้า dispatch แล้วเก็บข้อความ error ไว้ในตัวแปร missing_msg
make_plan ("Order 5 and customer 8" ไม่สนตัวพิมพ์ใหญ่เล็ก) วางแผนกี่ขั้นตอน (n_steps) และชื่อเครื่องมือตามลำดับเป็น list (step_tools)
run_agent (ให้ไว้ คืน dict) กับ mock_model และคำถาม "What is order 2 and order 3?": เก็บข้อความสุดท้ายไว้ใน final_text และจำนวนรอบไว้ใน steps
รันคำถามสองส่วน (question ที่ให้ไว้) ด้วย run_agent แล้วรวมความยาวของ content ที่เป็นสตริงของทุก tool_result ในประวัติ เก็บไว้ใน result_chars
ใน cases (ให้ไว้) มีกี่กรณีที่คาดว่าต้องเรียกเครื่องมืออย่างน้อยหนึ่งตัว (n_tool_cases) และจำนวนการเรียกเครื่องมือที่คาดไว้รวมทั้งหมด (n_expected_calls)
ชื่อเครื่องมือใน TOOL_SCHEMAS ที่ผ่าน allowlist READ_ONLY (เรียงตามตัวอักษร list) เก็บไว้ใน permitted_tools และที่ถูกปฏิเสธ (list เรียงตามตัวอักษร) ไว้ใน blocked_tools — ตัดสินจากผลของ safe_dispatch ที่ให้ไว้: เรียกแต่ละเครื่องมือด้วย input ว่างเปล่า ({}) และ confirmed=True (การรันอาจไม่สำเร็จเพราะขาดอาร์กิวเมนต์ ไม่เป็นไร) แล้วดูเฉพาะว่า error ขึ้นต้นด้วย "tool not allowed" หรือไม่
เรียก cancel_order(1) ที่ยืนยันแล้วผ่าน safe_dispatch สามครั้งด้วยคำขอเดิมและ seen = set() เดียวกัน (allowed = READ_ONLY | WRITE_TOOLS): เก็บจำนวนการกระทำที่เกิดจริงไว้ใน n_actions และจำนวนครั้งที่ถูกมองเป็นซ้ำ (ผลเป็น "duplicate ignored") ไว้ใน n_duplicates
ขนาดของประวัติที่ส่งให้โมเดลในแต่ละรอบ: ครอบ mock_model ด้วยฟังก์ชันที่บันทึก len(json.dumps(messages)) ทุกครั้งที่ถูกเรียกใน run_agent(question, wrapped) — เก็บ list ของขนาดไว้ใน sizes และอัตราส่วนขนาดสุดท้าย ÷ ขนาดแรก (ปัด 2 ตำแหน่ง) ไว้ใน growth
รันทุกกรณีใน cases กับ sloppy_model แล้วหา index (เริ่มที่ 0) ของกรณีที่ลำดับเครื่องมือ (tools_used) ไม่ตรงกับ expected_tools เก็บเป็น list ไว้ใน failing_idx
เขียน run_limited(question, model, max_calls) ที่หยุดเมื่อจำนวนครั้งที่ขอเรียกเครื่องมือ (tool_use) เท่ากับ max_calls โดยยังไม่ได้ข้อความสุดท้าย คืน (สถานะ, จำนวนครั้งที่เรียกเครื่องมือ) โดยสถานะเป็น "done" หรือ "tool_limit" — ใช้กับ looping_model ที่ max_calls = 3 เก็บไว้ใน limit_status, calls_used
เรียก get_order ด้วย order_id เป็นสตริง "1" ผ่าน dispatch: ถ้าผิดด้วยข้อความที่ขึ้นต้น "bad type" ให้แปลงค่าเป็น int แล้วลองใหม่หนึ่งครั้ง เก็บ True/False ว่าสำเร็จในที่สุดไว้ใน final_ok และจำนวนครั้งที่เรียก dispatch ไว้ใน attempts
วัดตัวตรวจ injection (INJECTION, re.I) กับผลลัพธ์ของเครื่องมือใน labelled (ข้อความ, มีคำสั่งแฝงจริงหรือไม่): เก็บ precision = TP ÷ (TP + FP) และ recall = TP ÷ (TP + FN) ปัด 4 ตำแหน่งไว้ใน precision, recall
บันทึก audit log: รันแต่ละคำขอใน calls (ให้ไว้) ผ่าน safe_dispatch ด้วย allowed = READ_ONLY (ไม่ยืนยัน) แล้วเก็บสรุปจำนวนต่อข้อความ error (คำขอที่สำเร็จนับเป็น "ok") เป็น dict ไว้ใน error_summary