Local vs API: ออกแบบ Router 3 โซน ให้ AI Agent ประหยัดค่าโทเคนในงาน Data
ทำไมการส่งทุกงานเข้าโมเดลแพงสุดถึงเผาเงินฟรี ๆ — กฎ routing 3 โซน (sensitive/ขนาดเล็ก/ขนาดใหญ่) พร้อมฟังก์ชัน route() ที่ก็อปไปใช้ได้เลย จากคนทำ model risk
Local vs API: ออกแบบ Router 3 โซน ให้ AI Agent ประหยัดค่าโทเคนในงาน Data
ทำไมการส่งทุกงานเข้าโมเดลแพงสุดถึงเผาเงินฟรี ๆ — กฎ routing 3 โซน (sensitive/ขนาดเล็ก/ขนาดใหญ่) พร้อมฟังก์ชัน route() ที่ก็อปไปใช้ได้เลย จากคนทำ model risk
ผมรันงาน AI หลายสิบครั้งต่อวันในระบบ agentic ที่ใช้ทำงานจริง แต่บิลไม่บาน — และไม่ใช่เพราะผมจ่ายแพงแล้วทน มันตรงกันข้าม: เคล็ดลับคือ ไม่ส่งทุกงานไปหาโมเดลที่แพงและเก่งที่สุด งานส่วนใหญ่ในไปป์ไลน์จริง — จัดรูปตาราง สรุปสั้น ๆ แปลง schema ตรวจ format — ไม่ต้องใช้โมเดลเรือธงเลย ถ้าคุณส่งงานพวกนี้เข้าโมเดลตัวท็อปทุกครั้ง คุณกำลังจ่ายค่ารถสปอร์ตเพื่อไปซื้อของหน้าปากซอย บทความนี้ผมจะวางกรอบการ route งานเป็น 3 โซน แล้วให้ฟังก์ชันจริงที่ก็อปไปวางแล้วเริ่มประหยัดได้เลย
1. ทำไม "ส่งทุกงานเข้าโมเดลแพงสุด" ถึงเป็นการเผาเงิน
เวลาคนเริ่มต่อ AI เข้างานจริง สิ่งที่มักเกิดคือ hardcode โมเดลตัวเดียว — ตัวที่เก่งสุด — ไว้ทุก call เพราะมันง่ายและได้ผลลัพธ์ดีแน่ ๆ ปัญหาคือ workload จริงไม่ได้ยากเท่ากันหมด งานในระบบ automation ของผมแบ่งหยาบ ๆ ได้เป็นสองกอง: กองที่ต้องใช้ การตัดสินใจ/เหตุผลลึก (ออกแบบ, review โค้ด, ตัดสิน edge case) กับกองที่เป็น งานโครงสร้างซ้ำ ๆ (extract, format, สรุป, transform) กองหลังนี่แหละที่มีจำนวนเยอะกว่ามาก และเป็นกองที่โมเดลเล็ก/ฟรีทำได้ดีพอ
หลักคิดนี้ไม่ใช่เรื่องใหม่สำหรับคนทำ data — มันคือ least-privilege ในเวอร์ชันต้นทุน: ให้ทรัพยากรเท่าที่งานต้องการจริง ไม่ใช่เท่าที่มากที่สุดเผื่อไว้ ผมเคยเขียนเรื่องการมอบงานให้โมเดลรองแบบเป็นระบบไว้ในสถาปัตยกรรม Gemma Delegation 3 ชั้น — บทนี้จะโฟกัสที่ "กฎการตัดสินใจ" ว่างานไหนไปไหน
ทำไมมันสำคัญกับเรา: ต้นทุนที่ต่ำไม่ใช่แค่เรื่องประหยัด มันคือ staying power — ระบบที่รันได้ด้วยค่าใช้จ่ายเกือบศูนย์ต่องาน คือระบบที่คุณเปิดทิ้งไว้ทำงาน 24 ชั่วโมงได้โดยไม่ต้องกลัวบิล และนั่นคือสิ่งที่ทำให้ automation กลายเป็นสินทรัพย์ ไม่ใช่ภาระรายเดือน
2. โซนที่ 1 — กฎที่มาก่อนเรื่องเงิน: sensitive → local เสมอ
ก่อนจะคิดเรื่อง route ตามขนาด มีกฎหนึ่งที่ต้องมาก่อนทุกอย่าง และมันไม่ใช่เรื่องต้นทุน — ข้อมูลอ่อนไหวต้องอยู่บนเครื่องตัวเอง (local) เสมอ ไม่ว่าจะประหยัดหรือไม่ ถ้า payload มีข้อมูลส่วนบุคคล ข้อมูลลูกค้า หรืออะไรที่อยู่ใต้ PDPA การส่งมันขึ้น cloud API คือการ egress ข้อมูลออกนอกขอบเขตที่คุณควบคุม ต่อให้ผู้ให้บริการน่าเชื่อถือแค่ไหน ในมุมคนทำ risk นี่คือความเสี่ยงที่ไม่คุ้มจะรับเพื่อประหยัดเวลาไม่กี่วินาที
เพราะฉะนั้นในกรอบของผม เงื่อนไข sensitive ถูกเช็คเป็นอย่างแรก และถ้าจริง งานจะถูก pin ไปที่โมเดล local ทันที ไม่ต้องดูขนาด ไม่ต้องคิดเรื่องความเร็ว — เรื่อง data boundary ชนะทุกอย่าง ผมลงรายละเอียดเรื่องนี้ไว้ในการจัดการข้อมูลส่วนบุคคล/PDPA ด้วย Claude Code
ทำไมมันสำคัญกับเรา: การเอา cost logic มาก่อน privacy logic เป็นความผิดพลาดที่แก้ทีหลังแพงมาก เพราะข้อมูลที่รั่วออกไปแล้วเรียกคืนไม่ได้ วางลำดับให้ถูก — เช็ค sensitive ก่อน แล้วค่อยเข้าเรื่องขนาดงาน — คือการออกแบบ guardrail ที่ fail ไปทางปลอดภัย
3. โซนที่ 2 และ 3 — ขนาดงานเป็นตัวตัดสินที่เหลือ
พอกันงาน sensitive ออกไปแล้ว ที่เหลือตัดสินด้วยขนาด ผมประเมินขนาดจากจำนวน token โดยประมาณของ input:
- โซนเล็ก (งานสั้น/ซ้ำ) — extract, format, สรุปย่อ, ตอบสั้น ๆ งานพวกนี้โมเดล local ฟรีทำได้ดีพอและเร็ว ส่งเข้า local
- โซนใหญ่ (งานยาว/ต้องใช้เหตุผล) — วิเคราะห์เอกสารยาว, สังเคราะห์หลายแหล่ง, งานที่ context เยอะ ส่งเข้า API ที่ context ยาวและเก่งกว่า (ในเคสผมใช้ free tier ของผู้ให้บริการที่ให้โควตาฟรีระดับพัน request ต่อวัน จึงยัง "ฟรี" อยู่)
เส้นแบ่งระหว่างสองโซนนี้คือ threshold ที่ต้อง calibrate เอง ไม่มีเลขวิเศษ ผมได้ค่าที่ใช้อยู่มาจากการวัดจริงว่าโมเดล local เริ่มคุณภาพตกที่งานขนาดไหน แล้วตั้งเส้นต่ำกว่านั้นไว้หน่อยเพื่อความปลอดภัย หลักการเดียวกับการคุมต้นทุน LLM คือวัดก่อน อย่าเดา
ทำไมมันสำคัญกับเรา: จุดที่คนพลาดคือตั้ง threshold จากความรู้สึก แล้วeither เผาเงิน (เส้นต่ำไป งานง่ายหลุดไป cloud หมด) หรือได้งานห่วย (เส้นสูงไป งานยากไปตกที่โมเดลเล็ก) การ calibrate ด้วยข้อมูลจริงคือส่วนที่แยกระบบที่ใช้ได้จริงออกจาก demo
4. Artifact: ฟังก์ชัน route() ที่ก็อปไปใช้ได้เลย
พอแล้วสำหรับหลักการ มาดูของจริง นี่คือ router ขั้นต่ำที่ห่อ logic ทั้ง 3 โซนไว้ในฟังก์ชันเดียว ก็อปไปวางแล้วเสียบ backend ของคุณเองได้เลย — ไม่ผูกกับ SDK เจ้าไหน:
# router.py — เลือก backend ตาม sensitivity ก่อน แล้วค่อยตามขนาดงาน
from dataclasses import dataclass
@dataclass
class Task:
prompt: str
sensitive: bool = False # มีข้อมูลส่วนบุคคล/ลูกค้า/PDPA ไหม
est_tokens: int | None = None # ประเมินขนาด input; None = ให้ฟังก์ชันเดา
# ปรับ 3 ค่านี้ให้ตรง setup ของคุณ
LOCAL_MODEL = "local-small" # โมเดลบนเครื่องคุณ (Ollama / LM Studio ฯลฯ)
CLOUD_MODEL = "cloud-large" # API ที่ context ยาว/เก่งกว่า (มี free tier ยิ่งดี)
SIZE_LIMIT = 6000 # เส้นแบ่งเล็ก/ใหญ่ (token) — ต้อง calibrate เอง!
def estimate_tokens(text: str) -> int:
# ประมาณหยาบ ๆ: ~4 ตัวอักษร/token พอสำหรับการตัดสินใจ route
return max(1, len(text) // 4)
def route(task: Task) -> str:
# โซน 1 — privacy ชนะทุกอย่าง เช็คก่อนเสมอ
if task.sensitive:
return LOCAL_MODEL
n = task.est_tokens if task.est_tokens is not None else estimate_tokens(task.prompt)
# โซน 2 — งานเล็ก/ซ้ำ: โมเดล local ฟรีพอ
if n < SIZE_LIMIT:
return LOCAL_MODEL
# โซน 3 — งานใหญ่/ต้องใช้เหตุผล: ส่ง cloud
return CLOUD_MODEL
if __name__ == "__main__":
samples = [
Task("จัดตารางนี้ให้เป็น markdown", est_tokens=300),
Task("สรุปงบการเงินลูกค้ารายนี้", sensitive=True),
Task("x" * 40000), # เอกสารยาว ~10k tokens
]
for t in samples:
print(f"{route(t):11s} <- sensitive={t.sensitive} est={t.est_tokens or estimate_tokens(t.prompt)}")
อ่านทีละส่วนว่าแต่ละอย่างกันอะไร:
if task.sensitiveมาก่อนreturnอื่นทั้งหมด — นี่คือการบังคับลำดับให้ privacy ชนะ cost ไม่ว่าโค้ดจะยาวขึ้นแค่ไหน เงื่อนไขนี้ต้องอยู่บนสุดเสมอestimate_tokensแบบ ~4 ตัวอักษร/token — ไม่ต้องแม่นระดับ tokenizer จริง เพราะเราแค่ต้องการตัดสินใจ route ไม่ได้เก็บเงินตามนี้ ความหยาบระดับนี้พอSIZE_LIMITเป็นค่าเดียวที่ต้อง tune — เริ่มที่ค่ากลาง ๆ แล้ววัดคุณภาพ output ของ local ที่งานขนาดต่าง ๆ ค่อยขยับ นี่คือจุดที่ระบบของคุณจะต่างจากของคนอื่น- บล็อก
__main__— รันไฟล์นี้ตรง ๆ ได้เลยเพื่อดูว่างานตัวอย่างถูก route ไปไหน ก่อนเอาไปเสียบ backend จริง
รันแล้วคุณจะเห็นงาน sensitive ไป local-small, งานสั้นไป local-small, เอกสารยาวไป cloud-large — นั่นคือ 3 โซนทำงานครบในฟังก์ชันเดียว
5. เลขที่ทำให้มันคุ้ม: เศรษฐศาสตร์ของ arbitrage
ทำไมกรอบนี้ถึงลดต้นทุนได้จริง เพราะสองโซนที่รับงานส่วนใหญ่ — sensitive กับงานเล็ก — วิ่งไปที่โมเดล local ที่ต้นทุนต่อ call เกือบเป็นศูนย์ (จ่ายแค่ค่าไฟ/เครื่องที่มีอยู่แล้ว) ส่วนงานใหญ่ที่ไป cloud ในเคสผมยังตกอยู่ใน free tier รายวันของผู้ให้บริการ เท่ากับ workload ส่วนใหญ่รันได้โดยไม่มีค่า API ต่อชิ้นเลย เงินก้อนเดียวที่ผมจ่ายจริงคือค่า subscription ของ "คนขับ" ระบบ ซึ่งเป็นต้นทุนคงที่ ไม่ผันตามจำนวนงาน
จุดสำคัญที่คนมองข้ามคือ โครงสร้างต้นทุนสำคัญกว่าราคาต่อหน่วย ระบบที่ต้นทุนเป็นแบบคงที่ (จ่ายเท่าเดิมไม่ว่าจะรัน 10 หรือ 100 งาน) ต่างจากระบบที่จ่ายตามการใช้อย่างสิ้นเชิงเมื่อคุณเริ่ม scale — ตัวหลังบิลโตตามงาน ตัวแรกไม่โต นี่คือเหตุผลว่าทำไมผมถึงยอมลงแรงตั้ง router ตั้งแต่ต้น แทนที่จะ hardcode โมเดลเดียวไปก่อนแล้วค่อยแก้ ระบบ automation ที่รันงานเยอะ ๆ ต่อวันแบบที่ผมเล่าไว้ในการออกแบบ Autonomous Task Queue จะคุ้มก็ต่อเมื่อต้นทุนต่องานไม่วิ่งขึ้นตามปริมาณ
ทำไมมันสำคัญกับเรา: เวลาประเมินว่า automation คุ้มไหม อย่าดูแค่ราคาต่อ call ให้ดูว่าพอ scale ขึ้น 10 เท่า บิลขึ้นกี่เท่า router ที่ดันงานส่วนใหญ่ไป local + free tier ทำให้เส้นนั้นเกือบแบน — และเส้นที่แบนคือสิ่งที่ทำให้คุณกล้าเปิดระบบทิ้งไว้ทำงานให้ตัวเองจริง ๆ
ภาพรวม
การประหยัดค่า AI ที่ยั่งยืนไม่ได้มาจากการหาโมเดลถูกสุด แต่มาจากการ ส่งงานให้ถูกตัว: เช็ค sensitive ก่อนเสมอแล้ว pin ไป local, งานเล็กไป local ฟรี, งานใหญ่ไป cloud (ยิ่งอยู่ใน free tier ยิ่งดี) สามโซนนี้ห่อได้ในฟังก์ชัน route() เดียวที่คุณก็อปไปเริ่มใช้วันนี้ได้ ค่าที่เหลือให้ทำคือ calibrate SIZE_LIMIT ด้วยข้อมูลจริงของคุณเอง
ฟังก์ชันข้างบนคือแกนของระบบ — แต่ของจริงในโปรดักชันมีมากกว่านั้น: threshold ที่ calibrate มาแล้วจากการวัด, การ fallback เมื่อ backend ล่ม, การ log ทุกครั้งที่ route ผิดเพื่อปรับ threshold อัตโนมัติ, และ QC ที่ตรวจ output ของโมเดลเล็กก่อนปล่อยผ่าน ทั้งหมดนี้ประกอบเป็น workspace เดียวที่ผมรวบรวมไว้ในคอร์ส Claude Code — ถ้าอยากได้ router ที่ tune แล้วพร้อมเสียบใช้ พร้อมระบบรอบ ๆ ที่ทำให้มันเชื่อถือได้จริง เริ่มจากตรงนั้นได้เลย