ENDEAVOR AGENT LITE ทำงานอย่างไร — เจาะลึกสถาปัตยกรรม

ภาพประกอบ: ENDEAVOR AGENT LITE ทำงานอย่างไร — เจาะลึกสถาปัตยกรรม

บทความ เริ่มต้นใช้งาน อธิบายวิธีติดตั้ง ส่วนบทนี้อธิบายโครงสร้างภายใน จุดสำคัญของ LITE ไม่ได้อยู่แค่การใช้โมเดลขนาดเล็ก แต่อยู่ที่การใช้โค้ดและ guardrail ช่วยชดเชยข้อจำกัดของโมเดล แทนการพยายามแก้ทุกอย่างด้วย prompt ที่ยาวขึ้น

หลักคิดเบื้องหลัง: โค้ด ไม่ใช่ prompt

จากคอมเมนต์ในซอร์สโค้ดจริงของโปรเจกต์: ทีมพัฒนาทดสอบ Qwen3.5-2B-OptiQ-4bit แบบ live แล้วพบว่าโมเดลนี้ แก้ปัญหาตัวเองไม่ได้อย่างสม่ำเสมอ หลังคำสั่งล้มเหลว เคยรันคำสั่ง find / ที่ล้มเหลวซ้ำ 4 ครั้งติดกันโดยไม่ปรับขอบเขตให้แคบลง — บทสรุปของทีมคือ “โมเดล 2B จะไม่ฉลาดขึ้นแค่เพราะ prompt ดีขึ้น” ดังนั้นการตรวจสอบเหล่านี้จึงเขียนเป็นโค้ด Python ที่รันแน่นอน ไม่ใช่ฝากความหวังไว้กับ prompt

นี่คือกุญแจที่ทำให้ agent ที่ใช้โมเดลเล็กมากยัง “รู้สึกน่าเชื่อถือ” ได้ในการใช้งานจริง

วงจรการทำงานของ ReAct Agent

LITE ใช้ LangGraph’s create_react_agent เป็นแกนหลัก (ไม่ได้เขียน loop เองทั้งหมด) โครงสร้างคร่าวๆ ต่อ 1 คำถาม:

  1. บีบอัดประวัติสนทนา — ประวัติที่เก็บข้ามคำถามไม่ใช่บทสนทนาดิบทั้งหมด แต่เป็นคู่ (คำถาม, สรุปคำตอบ) ที่ผ่านการบีบอัดแล้ว เก็บย้อนหลังสูงสุด 5 รอบ หรือไม่เกิน 20,000 ตัวอักษร (สองเงื่อนไขไหนถึงก่อนใช้ก่อน) — กัน context ยาวเกินจนโมเดลเล็กสับสน
  2. ฉีดบริบทวันที่/เวลาปัจจุบัน เข้าไปในคำถามอัตโนมัติ ก่อนส่งให้โมเดล
  3. โมเดลตัดสินใจ ว่าจะเรียก tool ไหน หรือตอบตรงๆ — ระบบ prompt เดิมทุกตัวอักษรในทุกรอบ (byte-identical) เพื่อให้ prompt caching ของ MLX ทำงานได้เต็มประสิทธิภาพ ไม่ต้องประมวลผล system prompt ใหม่ทุกครั้ง
  4. รัน tool → ตรวจสอบผล → วนกลับให้โมเดลตัดสินใจต่อ จนกว่าจะได้คำตอบสุดท้าย หรือชนเพดานจำนวนรอบ (recursion_limit)
  5. ผ่านชั้น guardrail หลังบ้าน ก่อนส่งกลับให้ผู้ใช้ (รายละเอียดหัวข้อถัดไป)
คำถาม ──▶ [ agent node ] ──(มี tool_calls)──▶ [ tool node ]
              ▲                                    │
              └────────── วนกลับจนกว่าจะจบ ─────────┘

        (ไม่มี tool_calls)

         guardrail ──▶ ตอบผู้ใช้

(กลไกเบื้องหลัง create_react_agent แบบเต็ม — state, reducer, tool_calls, recursion limit — อยู่ใน ReAct Agent ทำงานอย่างไร)

ระบบ Guardrail: ส่วนที่น่าสนใจที่สุด

จากการทดสอบจริงกับผู้ใช้ (บันทึกไว้ในซอร์สโค้ดเป็น “live-observed” พร้อมวันที่) ทีมพัฒนาพบพฤติกรรมผิดพลาดเฉพาะของโมเดลเล็ก แล้วเขียนตัวตรวจจับ+แก้ไขแบบ deterministic สำหรับแต่ละกรณี:

กันเรียกคำสั่งซ้ำ (Repeat Call Guard)

ถ้า agent เรียก tool เดิมด้วย argument เดิมซ้ำ ระบบจะเตือนในรอบที่ 2 (“คำสั่งนี้เพิ่งล้มเหลวไปแล้ว ห้ามรันซ้ำ”) และบล็อกจริงถ้ายังพยายามซ้ำอีกในรอบที่ 3

กันวนซ้ำคำเดิม (Degenerate Repetition)

พบจริงว่าโมเดลเคยตอบคำถาม “ค้นไฟล์” แล้วเขียนซ้ำ "*.gz" "*.bz2" "*.xz" วนไปเรื่อยๆ หลายสิบครั้งจนหมด token budget ก่อนที่ tool call จะปิด tag ได้สมบูรณ์ ระบบตรวจจับ pattern การซ้ำแบบต่อเนื่อง (span ซ้ำ ≥4 ครั้งติดกัน) แล้วตัดจบทันที แทนคำตอบด้วยข้อความสำรอง

กันหลุด format tool call

บางครั้งโมเดลพิมพ์ tag แบบ <tool_call><function=...> ออกมาเป็นข้อความธรรมดา แทนที่จะเรียก tool จริงผ่านกลไก structured call — ระบบตรวจจับ tag เหล่านี้ในข้อความโดยตรง (ไม่ต้องรอให้ซ้ำถึงเกณฑ์ก่อน) แล้วตัดจบเช่นกัน

กันคำตอบปฏิเสธภาษาอังกฤษที่ไม่ตรงคำสั่ง

พบว่าบางครั้งหลัง tool ทำงานสำเร็จแล้ว โมเดลกลับตอบ "Sorry, need more steps to process this request." แทนที่จะสรุปผลเป็นภาษาไทยตามที่สั่งไว้ — ระบบตรวจจับวลีปฏิเสธซ้ำๆ แบบนี้ (สั้น, ไม่มีอักษรไทยปน) แล้วแทนที่ด้วยสรุปผลจริงจาก log การเรียก tool แทน

บังคับแนบแหล่งที่มาแบบ deterministic

แทนที่จะหวังให้โมเดล “จำ” ที่จะแนบลิงก์ทุกครั้งหลังค้นเว็บ (ทดลองแล้วว่าไม่เสถียร — บางครั้งสรุปถูกแต่ลืมแนบลิงก์) ระบบดึง URL จาก marker [source: URL] ที่ tool ค้นเว็บติดไว้อัตโนมัติ แล้วต่อท้ายคำตอบเองทุกครั้ง ไม่ให้โมเดลเป็นคนตัดสินใจว่าจะแนบหรือไม่

กันตัวเลข/เปอร์เซ็นต์ที่ไม่มีหลักฐานรองรับ

ระบบเทียบตัวเลขทุกตัวในคำตอบสุดท้ายกับตัวเลขที่ปรากฏจริงในผลลัพธ์จาก tool — ถ้าโมเดลใส่เปอร์เซ็นต์ที่ไม่มีในแหล่งข้อมูลจริง (สงสัยว่าเดา/จำผิด) ระบบจะตัดออกหรือเปลี่ยนเป็นข้อความบอกตรงๆ ว่ายังไม่ยืนยันตัวเลข

ป้องกันข้อมูลลับหลุด (DLP)

มี 2 ชั้น: (1) บล็อกการอ่านไฟล์/โฟลเดอร์ที่เข้าข่ายเก็บ credential ตั้งแต่ระดับ path เช่น .ssh, .aws, .env, browser profile folder และ (2) สแกนเนื้อหาคำตอบสุดท้ายหา pattern รูปแบบ credential จริง เช่น AWS access key, GitHub token, OpenAI-style sk- key, Slack token, JWT, PEM private key block — ถ้าเจอ จะบล็อกไม่แสดงคำตอบนั้นเลย

การจัดการรูปภาพ (Vision)

เวลาสั่ง “อ่านรูป X” agent จะเรียก read_image ก่อน ได้ผล OCR กลับมา และคิวภาพนั้นไว้แนบเข้ากับข้อความคำถามล่าสุดก่อนเรียกโมเดลรอบถัดไป (แปลงเป็น base64 data URI ตามฟอร์แมตที่ MLX vision server ต้องการ) — วิธีนี้ทำให้โมเดล “เห็น” ภาพในรอบเดียวกับที่สั่งอ่าน ไม่ต้องรอสองรอบ ภาพที่คิวไว้เป็นแบบ per-turn เท่านั้น ถ้า process ล่มกลางทางระหว่างสองรอบ ภาพเก่าจะไม่ถูกนำไปแนบผิดคำถามในรอบถัดไป

เมื่อโมเดลอ้างว่าบันทึกไฟล์แล้วแต่ไม่ได้ทำจริง

Session ยาวๆ อาจทำให้โมเดลลืมเรียก write_file ทั้งที่ผู้ใช้ขอให้บันทึกไฟล์ แล้วตอบราวกับว่าบันทึกเสร็จแล้ว ระบบตรวจจับ pattern คำขอ “บันทึก/เขียน/สร้างไฟล์” ในคำถาม แล้วเช็คว่า log การเรียก tool รอบนั้นมี write_file จริงไหม — ถ้าไม่มี จะสั่งให้โมเดลลองใหม่อีกครั้งแบบ explicit (retry ครั้งเดียว) ก่อนจะยอมรับคำตอบเดิม

ทำไมเรื่องนี้ถึงสำคัญ

เครื่องมือ AI agent ที่ใช้โมเดลใหญ่ (35B ขึ้นไป อย่าง ENDEAVOR LOCAL AGENT TH) พึ่งพาความสามารถของโมเดลเองได้มากกว่า แต่ LITE ต้องเลือกอีกทาง: ยอมรับว่าโมเดล 2B จะพลาดแน่นอนในบางกรณี แล้วออกแบบระบบให้จับพลาดเหล่านั้นได้แบบตรวจสอบได้ (deterministic) ไม่ใช่หวังให้โมเดลไม่พลาด

นี่คือเหตุผลเชิงวิศวกรรมที่ทำให้เครื่อง RAM 8GB ใช้ AI agent ที่ “รู้สึกน่าเชื่อถือ” ได้จริง ทั้งที่ตัวโมเดลเองมีขนาดเล็กกว่าโมเดลระดับ production ทั่วไปมาก

อ่านเพิ่มเติม

ความคิดเห็น

กำลังโหลดความคิดเห็น...