ช่วงที่ 1โจทย์: GPU สำหรับงานที่มาเป็นพักๆ กับงบหนึ่งพันบาท
ระบบทดลองแกะบิลของเราให้คนอัปบิลฟรีเดือนละ 30 ใบ เพดานทั้งระบบ 3,000 ใบ งบที่ตั้งไว้คือ ฿1,000 ต่อเดือน คิดง่ายๆ ต้นทุนต่อใบห้ามเกิน ฿0.30 ไม่งั้นเกินงบ
ปัญหาคือโมเดล vision ที่อ่านบิลต้องการ GPU จริง เช่าเครื่องรายเดือนเริ่มที่หลักพันถึงหลักหมื่น จ่ายทั้งเดือนเพื่องานที่วิ่งจริงอาจไม่กี่ชั่วโมง ส่วน API สำเร็จรูปก็คิดต่อใบแพงกว่าเส้นที่ตั้งไว้หลายเท่า
โจทย์เลยแคบลงเหลือข้อเดียว หา GPU ที่จ่ายเฉพาะวินาทีที่ทำงาน แล้วปล่อยให้เครื่องดับตัวเองตอนไม่มีคิว นั่นคือเหตุผลที่เราลงเอยกับ Modal
ช่วงที่ 2โครงที่ทำให้จ่ายน้อย: คิวถูก ตัวประมวลแพง แยกกันเด็ดขาด
หลักคิดมีบรรทัดเดียว อย่าให้ GPU ตื่นมารอใคร
- คิวรับบิลอยู่บน Cloudflare Worker กับ D1 ต้นทุนแทบเป็นศูนย์
- ทุก 5 นาที มี cron ตัวเล็กบน Modal วิ่งมาเช็คคิว ตัวนี้เป็น CPU ล้วน ราคาถูกมาก
- เจอคิวว่างก็จบ ไม่มีอะไรเกิดขึ้น เจองานเมื่อไหร่ค่อยปลุกคลาส GPU ขึ้นมาประมวลทั้งชุด เสร็จแล้วเครื่องดับตัวเองใน 2 นาที
โครงแบบนี้ทำให้เดือนที่ไม่มีใครใช้ ระบบทั้งระบบกินเงินเป็นหลักสิบบาท ส่วนเดือนที่คิวแน่นก็จ่ายตามใบจริง
ช่วงที่ 3ตอทั้ง 7 ที่ชนมากับตัว
ของจริงไม่ได้ไหลลื่นแบบย่อหน้าข้างบน นี่คือรายการตอใต้น้ำที่เราชนเรียงตามลำดับเวลา จดไว้ให้คนมาทีหลังไม่ต้องชนซ้ำ
- Base image ต้องเป็น cuda-devel ไม่ใช่ runtime vLLM ต้อง compile kernel ตอนติดตั้ง ถ้าใช้ image ที่ไม่มี nvcc จะพังตั้งแต่ build โดยข้อความ error ไม่บอกตรงๆ ว่าขาดอะไร
- เวอร์ชัน vLLM กับ tokenizer ของโมเดลต้องเข้าคู่กัน โมเดลใหม่บางตัวต้องการ vLLM ใหม่กว่าที่ pip เลือกให้ อาการคือโหลดโมเดลไม่ขึ้นทั้งที่ไฟล์ครบ
- เรียกงานข้าม timeout ต้องใช้ .spawn() ไม่ใช่ .remote() cron ของเรามีอายุแค่ 120 วินาที แต่ cold start ของ GPU กินไป 344.6 วินาที ถ้าเรียกแบบรอผล cron ตายก่อนงานเริ่ม ต้องยิงแบบปล่อยมือ (fire-and-forget) ให้งานวิ่งต่อเองหลัง cron จบ
- .spawn() ใช้ได้เฉพาะใน deployed app รันทดสอบจากเครื่องด้วย modal run แล้ว spawn จะหาคลาสไม่เจอ ต้อง deploy ก่อนแล้วปล่อยให้ cron เป็นคนเรียก บทเรียนคือ ทดสอบผ่านเส้นทางเดียวกับ production ตั้งแต่แรก
- โค้ดพังใน @enter คือ crash-loop ที่เผาเงินเงียบๆ ฟังก์ชันที่รันตอนเครื่องตื่น ถ้า throw ตัว Modal จะพยายามปลุกใหม่วนไปเรื่อยๆ GPU ขึ้นๆ ดับๆ อยู่อย่างนั้นเกือบชั่วโมงกว่าเราจะเห็นจาก dashboard วิธีหยุดคือ modal app stop ทันที แล้วค่อยหาสาเหตุ ตั้งใจดู dashboard ช่วงแรกของทุก deploy
- โมเดล transcription ไม่คาย JSON ต่อให้ขอสวยแค่ไหน ตัวแรกที่เราใช้ถูกจูนมาให้ถอดข้อความ พอสั่งให้ตอบเป็น JSON ก็เล่าเรื่อยเปื่อยจนหมดโควตา token คำตอบไม่ใช่เขียน prompt ให้เข้มขึ้น แต่คือเปลี่ยนไปใช้โมเดล instruct แล้วบังคับรูปแบบด้วย structured outputs ให้ grammar เป็นคนคุม ไม่ใช่คำขอร้อง
- API ที่หายไปเงียบๆ ตอนอัปเวอร์ชัน อันตรายกว่า API ที่พัง vLLM 0.24 เปลี่ยนชื่อคลาส GuidedDecodingParams เป็น StructuredOutputsParams โค้ดเราเขียน fallback ไว้เผื่อ import ไม่ได้ ผลคือระบบไม่ล้มแต่แอบถอยไปโหมดเดิมโดยไม่มีใครรู้ กว่าจะจับได้ก็ตอนไล่ log บรรทัดต่อบรรทัด บทเรียนที่แพงที่สุดของรอบนี้ ถ้า fallback สำคัญกับความถูกต้อง ต้อง assert ให้ log ยืนยันว่าโหมดหลักทำงานอยู่ ไม่ใช่แค่ไม่ error
ช่วงที่ 4เลขจริง จาก log
- Cold start รอบแรก (โหลดโมเดล + compile): 344.6 วินาที จ่ายครั้งเดียวต่อการตื่นหนึ่งรอบ ไม่ใช่ต่อใบ
- พอเครื่องตื่นเสร็จแล้ว โมเดล 2B อ่านบิลได้ใบละ 7-10 วินาที คิดเป็น ~฿0.144 ต่อใบ
- รวมเป็นชุด 30 ใบต่อการตื่นหนึ่งครั้ง เฉลี่ยเหลือ ~฿0.236 ต่อใบ ยังต่ำกว่าเส้น ฿0.30 ที่ตั้งไว้
- พออัปเป็นโมเดล 4B เพื่อความแม่น เวลาต่อใบขยับเป็น 12-22 วินาที ต้นทุนเฉียดเส้นพอดี แลกกับยอดเงินที่อ่านถูกครบทุกใบที่ทดสอบ
ตัวเลขพวกนี้มาจาก log ของระบบเราเอง บิลของคนอื่นเครื่องอื่นย่อมต่างออกไป แต่ลำดับขั้นแบบนี้แหละ (cold start แพงครั้งเดียว รวมชุดแล้วถูกลง) ใช้ได้ทุกที่
ช่วงที่ 5อีเมลฉบับ ที่รอ
หลังชนตอครบเจ็ด เช้ามืดวันหนึ่งอีเมลจากระบบก็เข้ามา บิลค่าส่วนกลางใบหนึ่งผ่านทุกด่านตรวจ ตัวเลขตรง ยอดตรง แถมมีเลขที่ใบรับรองแทนใบเสร็จรันมาให้เสร็จ นั่นคือครั้งแรกที่ทั้งเส้นทำงานจริงตั้งแต่อัปโหลดจนถึงกล่องจดหมาย
มองย้อนกลับไป เงินที่เสียให้ crash-loop กับเวลาที่หายไปกับ fallback เงียบๆ คือค่าเทอมของระบบนี้ ถูกกว่าเช่าเครื่องทั้งเดือนอยู่ดี
ใครกำลังจะรันงาน AI แบบเป็นพักๆ ด้วยงบจำกัด ลิสต์ตอทั้งเจ็ดข้างบนคือของฝากจากเรา เอาไปเช็คก่อน deploy รอบแรก แล้วถ้าอยากเห็นระบบตัวนี้ที่ไปประกอบร่างอยู่จริง ตอนนี้เปิดให้ลองที่หน้าAI แกะบิล
คำถามที่พบบ่อย
Modal คิดเงิน ยังไง
คิดตามเวลาที่ container ทำงานจริงเป็นวินาที แยกตามชนิดเครื่อง งานเราใช้ GPU L4 สำหรับช่วงประมวลผล และ CPU เล็กๆ สำหรับ cron เช็คคิวทุก 5 นาที ไม่มีคิวก็แทบไม่มีค่าใช้จ่าย
cold start ของ Modal นานแค่ไหน
ของระบบเรา รอบแรกที่ตื่นกิน 344.6 วินาที เพราะต้องโหลดโมเดลและ compile ก่อน จ่ายครั้งเดียวต่อการตื่นหนึ่งรอบ วิธีลดผลกระทบคือรวมงานเป็นชุดให้การตื่นแต่ละครั้งคุ้มที่สุด
รัน OCR บน Modal แพงไหม
จากที่วัดเอง โมเดล 2B ตกใบละ ~฿0.144 ช่วงที่เครื่องทำงานต่อเนื่อง และ ~฿0.236 เมื่อเฉลี่ยทั้งชุด 30 ใบ ส่วนโมเดล 4B ที่แม่นกว่าจะเฉียด ฿0.30 ต่อใบ ตัวเลขขึ้นกับขนาดโมเดลและความยาวเอกสารเป็นหลัก
ควรใช้ Modal หรือเช่า GPU รายเดือน
งานมาเป็นพักๆ คิวไม่แน่นอน Modal ได้เปรียบเพราะไม่มีงานไม่จ่าย ส่วนงานที่ GPU ต้องวิ่งต่อเนื่องเกินราววันละหลายชั่วโมงทุกวัน เช่าเครื่องประจำหรือ on-premise จะเริ่มถูกกว่า จุดตัดจริงต้องคิดจากชั่วโมง GPU ต่อเดือนของงานคุณเอง
- อย่าขอร้องให้โมเดลตอบ JSON บังคับด้วย schema เจาะลึกตอที่ 6-7 แบบลงมือทำตาม
- Productize Blog รวมบทความเรื่องเทคนิคและต้นทุนที่เขียนจากงานจริง
- เอาโมเดล 27B ขึ้น GPU เช่าด้วย vLLM ภาคก่อนหน้าของเรื่อง GPU เช่ารายชั่วโมง กับกับดักที่เจอตอนติดตั้งจริง
- Cloudflare Workers AI อีกทางเลือกฝั่งที่ไม่ต้องคิดเรื่อง GPU เลย ถ้างานเบาพอ
- Modal pricing และเอกสาร serverless GPU modal.com/pricing (ยืนยันลิงก์ 2026-07-10)
- vLLM structured outputs docs docs.vllm.ai/en/latest/features/structured_outputs.html (ยืนยันลิงก์ 2026-07-10)
- ตัวเลขต้นทุน/เวลาทั้งหมดวัดจาก log ระบบของเราเอง (2026-07-09 ถึง 10)