← กลับไปหน้าบทความ
ขั้นสูง (MarTech)

ทำไมทีมพัฒนาเริ่มย้าย AI Workflow มารันบน Supabase Edge Functions

ทีมบรรณาธิการ linli12 ส.ค. 04:52อัปเดต 12 ส.ค. 04:52อ่าน 4 นาที
ทำไมทีมพัฒนาเริ่มย้าย AI Workflow มารันบน Supabase Edge Functions
บทความนี้จัดทำเพื่อความรู้ ชื่อธุรกิจ ตัวเลข หรือบทสนทนาที่ไม่มีแหล่งอ้างอิงกำกับเป็นกรณีตัวอย่างเพื่ออธิบายแนวคิด ดูรายละเอียดที่ นโยบายกองบรรณาธิการ

สรุปสั้น ๆ

ทีมพัฒนาย้าย AI Workflow มารันบน Supabase Edge Functions เพราะสามคุ้มค่าหลัก คือซ่อน API key ของโมเดลไม่ให้หลุดไปกับ client, รองรับ streaming response แบบมาตรฐาน Web API และอยู่ใกล้ฐานข้อมูลพอที่จะบันทึกผลลัพธ์หรือ log การเรียกใช้ได้ทันทีโดยไม่ต้องเพิ่ม service ตัวกลางอีกชั้น

ช่วงหลังมานี้แทบทุกแอปที่พัฒนาใหม่มีจุดที่ต้องเรียก AI Model สักจุดหนึ่ง ไม่ว่าจะเป็นการสรุปข้อความ การค้นหาแบบ semantic search หรือการสร้างคำแนะนำอัตโนมัติ คำถามที่ตามมาคือควรเรียก AI จากตรงไหนของระบบ เรียกตรงจาก client เลย เรียกผ่าน backend เดิมที่มีอยู่แล้ว หรือแยกไปเรียกผ่าน Edge Functions

หลายทีมเริ่มต้นด้วยการเรียกจาก client ตรง ๆ เพราะเร็วและง่ายที่สุดตอน prototype แต่พอใกล้ขึ้น production จริงเริ่มเจอปัญหาเรื่อง API key รั่ว ค่าใช้จ่ายที่ควบคุมไม่ได้ และไม่มีที่บันทึกว่าใครเรียกอะไรไปบ้าง จุดนี้เองที่ทำให้หลายทีมย้าย logic การเรียก AI มาไว้ที่ Edge Functions แทน

บทความนี้จะอธิบายว่าทำไมรูปแบบนี้ถึงเป็นที่นิยม พร้อมตัวอย่างการวาง AI Workflow แบบ streaming และข้อควรระวังที่พบบ่อยเมื่อเริ่มทำจริง

ทำไมเรียก AI Model ตรงจาก client ถึงเป็นความเสี่ยง

การเรียก AI Model ตรงจากฝั่ง client หมายความว่า API key ของบริการ AI ต้องถูกฝังอยู่ในโค้ดที่ browser หรือแอปมือถือดาวน์โหลดไปเก็บไว้ ต่อให้พยายามซ่อนแค่ไหน ใครก็ตามที่เปิด developer tools หรือแกะ APK ก็หาเจอได้ในที่สุด

ผลที่ตามมาไม่ใช่แค่เรื่องความปลอดภัย แต่เป็นเรื่องเงินโดยตรง เพราะ API key ที่หลุดออกไปสามารถถูกเอาไปใช้เรียก AI Model ในนามบัญชีของคุณโดยที่คุณไม่รู้ตัว จนกว่าจะเห็นบิลพุ่งสูงผิดปกติ

อีกปัญหาคือการควบคุม rate limit และ business logic เช่น จำกัดจำนวนครั้งที่ผู้ใช้แต่ละคนเรียกได้ต่อวัน ถ้า logic นี้อยู่ฝั่ง client ก็แก้ไข bypass ได้ง่าย ๆ ด้วยการแก้โค้ดฝั่งเดียวกัน ต้องยกไปไว้ฝั่งเซิร์ฟเวอร์ที่ผู้ใช้แตะต้องไม่ได้เท่านั้น

ยังมีอีกประเด็นที่มักถูกมองข้ามคือการตรวจสอบว่าใครเป็นคนเรียกจริง ถ้าไม่มีการยืนยันตัวตนก่อนเรียก AI Model ใครก็สามารถยิง request จำนวนมากเข้ามาโดยไม่ต้องล็อกอินเลยด้วยซ้ำ ทำให้ต้นทุนพุ่งสูงจากผู้ใช้ที่ไม่ได้เป็นลูกค้าจริงของระบบเลยแม้แต่คนเดียว ซึ่งต่างจากการวาง logic ไว้ฝั่งเซิร์ฟเวอร์ที่บังคับตรวจ JWT ก่อนทุกครั้งได้

เหตุผลที่ Edge Functions เหมาะกับงานนี้เป็นพิเศษ

เหตุผลแรกคือการซ่อน secret ตามที่กล่าวไปแล้ว Edge Functions เก็บ API key ไว้เป็นตัวแปรแวดล้อมฝั่งเซิร์ฟเวอร์ ไม่มีทางถูกส่งออกไปกับ JavaScript bundle ที่ client ดาวน์โหลด

เหตุผลที่สองคือ Edge Functions รองรับ Streaming Response ตามมาตรฐาน Web API ได้โดยตรง ซึ่งสำคัญมากสำหรับ AI Workflow ที่ต้องการแสดงคำตอบทีละคำแบบ real-time แทนที่จะรอให้โมเดลตอบครบทั้งก้อนแล้วค่อยส่งกลับ ประสบการณ์ผู้ใช้จะลื่นไหลกว่ามาก

เหตุผลที่สามคือความใกล้ชิดกับฐานข้อมูล เพราะหลาย AI Workflow ไม่ได้จบแค่เรียกโมเดลแล้วส่งคำตอบกลับ แต่ต้องบันทึก log การใช้งาน เก็บ embedding ลง pgvector หรือปรับ credit ของผู้ใช้ในตารางเดียวกัน การทำทุกอย่างในฟังก์ชันเดียวที่อยู่ใกล้ database ลดความซับซ้อนของระบบลงมาก เมื่อเทียบกับการมี service กลางแยกอีกตัวที่ต้องดูแลเพิ่ม

ตัวอย่างสมมติ: วาง AI Workflow แบบ Streaming ผ่าน Edge Functions

ลองดูโครงสร้างคร่าว ๆ ของ Edge Function ที่รับคำถามจากผู้ใช้ แล้ว stream คำตอบจาก AI Model กลับไป (ตัวอย่างสมมติเพื่อประกอบการอธิบายแนวคิด ไม่ใช่โค้ด production จริง):

  1. ฟังก์ชันรับ request พร้อมตรวจ JWT ของผู้ใช้ก่อน เพื่อยืนยันว่าเป็นผู้ใช้ที่ล็อกอินจริง ไม่เปิดให้เรียกแบบไม่มีการยืนยันตัวตน
  2. เช็ค credit หรือ rate limit ของผู้ใช้จากตาราง Postgres ก่อนเรียกโมเดล ถ้าเกินโควตาให้ตอบกลับทันทีโดยไม่เสียค่าใช้จ่ายเรียกโมเดล
  3. เรียก AI Model พร้อมเปิดโหมด stream แล้วส่งต่อ chunk ของคำตอบกลับไปยัง client ทันทีที่ได้รับ ไม่ต้องรอให้ครบทั้งก้อน
  4. หลัง stream จบ บันทึก log การเรียกใช้ลงตาราง เช่นจำนวน token ที่ใช้ วันเวลาที่เรียก และหักโควตาของผู้ใช้ในทรานแซกชันเดียวกัน
  5. ถ้าการเรียกโมเดลล้มเหลวกลางทาง ให้ดักจับ error แล้วส่งข้อความที่อ่านรู้เรื่องกลับไป ไม่ปล่อยให้ connection ค้างจนฝั่ง client timeout แบบไม่รู้สาเหตุ

ควบคุมต้นทุนและ rate limit ยังไงไม่ให้บิลระเบิด

AI Model ส่วนใหญ่คิดเงินตามจำนวน token ที่ใช้ ถ้าไม่มีการควบคุมที่ชัดเจน ผู้ใช้บางคนอาจยิง request รัว ๆ จนบิลพุ่งเกินงบที่ตั้งไว้โดยไม่รู้ตัว การควบคุมควรทำอย่างน้อยสองชั้น

ชั้นแรกคือ rate limit ระดับผู้ใช้ เช่น จำกัดจำนวนครั้งต่อชั่วโมงหรือต่อวัน เก็บตัวนับไว้ในตาราง Postgres แล้วเช็คก่อนเรียกโมเดลทุกครั้ง ชั้นที่สองคือการตั้ง budget alert ฝั่งผู้ให้บริการ AI เอง เพื่อให้รู้ทันทีถ้าค่าใช้จ่ายรวมของระบบพุ่งผิดปกติ ไม่ต้องรอเห็นบิลตอนสิ้นเดือน

อีกเทคนิคที่ช่วยลดต้นทุนได้จริงคือ cache คำตอบของคำถามที่ซ้ำกันบ่อย ๆ ไว้ในตาราง แทนที่จะเรียกโมเดลใหม่ทุกครั้งสำหรับคำถามที่แทบไม่ต่างกัน โดยเฉพาะงานประเภทสรุปเนื้อหาที่ input เดิมมักได้คำตอบใกล้เคียงเดิมเสมอ

ตัวอย่างสมมติ: ประเมินต้นทุนก่อนเปิดใช้งานจริง

ก่อนเปิดฟีเจอร์ AI ให้ผู้ใช้จริงใช้งาน ควรทำตัวเลขประเมินคร่าว ๆ ไว้ก่อนว่าถ้ามีคนใช้งานตามที่คาดการณ์ ต้นทุนจะอยู่ระดับไหน ตัวอย่างต่อไปนี้เป็นตัวอย่างสมมติเพื่อประกอบกรอบคิด ไม่ใช่ตัวเลขราคาจริงของผู้ให้บริการรายใด

สมมติแอปมีผู้ใช้ที่ใช้ฟีเจอร์สรุปข้อความวันละ 500 คน แต่ละครั้งใช้ input เฉลี่ยประมาณ 1,500 token และได้ output ประมาณ 300 token ถ้าไม่มีการควบคุมจำนวนครั้งต่อคนต่อวัน ผู้ใช้บางคนอาจกดซ้ำสิบกว่ารอบเพราะไม่พอใจคำตอบแรก ทำให้ต้นทุนรวมสูงกว่าที่ประเมินไว้หลายเท่าโดยไม่มีใครรู้ตัวจนเห็นบิลปลายเดือน

การตั้ง rate limit เช่นจำกัดไว้ที่ 10 ครั้งต่อคนต่อวันสำหรับผู้ใช้แพ็กเกจฟรี และเปิดเพดานสูงขึ้นสำหรับผู้ใช้ที่จ่ายเงิน ช่วยให้ต้นทุนแปรผันตามรายได้ที่เข้ามาจริง แทนที่จะเป็นต้นทุนคงที่ที่ควบคุมไม่ได้ และช่วยให้วางแผนงบประมาณล่วงหน้าได้แม่นยำขึ้นด้วย

สถานการณ์ตัวแปรที่ควบคุมผลลัพธ์ที่คาดหวัง
ไม่มี rate limitไม่มีต้นทุนแปรปรวนสูง ควบคุมไม่ได้
จำกัดครั้งต่อวันตามแพ็กเกจจำนวนครั้ง/วันต้นทุนแปรผันตามรายได้
cache คำตอบคำถามซ้ำinput ที่ซ้ำกันบ่อยลดจำนวนครั้งที่ต้องเรียกโมเดลจริง

ผูก AI Workflow เข้ากับฟีเจอร์อื่นของ Supabase

จุดแข็งอีกอย่างของการวาง AI Workflow ไว้ที่ Edge Functions คือทำงานร่วมกับฟีเจอร์อื่นของ Supabase ได้ในระบบเดียวกัน ไม่ต้องเชื่อมหลาย service เข้าด้วยกันเอง

ตัวอย่างเช่น ถ้าต้องการแจ้งเตือนผู้ใช้แบบ real-time เมื่อ AI ประมวลผลเสร็จ (สำหรับงานที่ใช้เวลานานเกินจะ stream ตรง ๆ) สามารถผูกกับ Supabase Realtime เพื่อส่งสถานะอัปเดตกลับไปยัง client ได้ทันทีที่บันทึกผลลัพธ์ลงตาราง

ถ้าต้องการเก็บผลลัพธ์เป็นไฟล์ เช่นภาพที่ AI สร้าง หรือเอกสารที่สรุปออกมา ก็ต่อกับ Supabase Storage ได้โดยตรงจากฟังก์ชันเดียวกัน โดยใช้ service role key เขียนไฟล์ลง bucket แล้วบันทึก path กลับลงตาราง

ข้อควรระวังด้านความปลอดภัยที่มักถูกมองข้าม

แม้จะย้าย logic มาอยู่ฝั่งเซิร์ฟเวอร์แล้ว ก็ยังมีจุดที่พลาดได้ถ้าไม่ระวัง

  • ไม่ sanitize input ก่อนส่งเข้าโมเดล — ผู้ใช้บางคนอาจพยายามใส่คำสั่งพิเศษเพื่อหลอกให้โมเดลทำงานนอกขอบเขตที่ตั้งใจไว้ (prompt injection) ควรมีการกรองหรือกำหนดขอบเขตของ system prompt ให้ชัดเจน
  • เก็บ log ที่มีข้อมูลส่วนบุคคลไว้แบบไม่จำกัดเวลา — ถ้า log การเรียก AI มีข้อความที่ผู้ใช้พิมพ์เข้ามาซึ่งอาจมีข้อมูลส่วนตัวปนอยู่ ควรมีนโยบายเก็บและลบข้อมูลที่ชัดเจน ไม่ใช่เก็บไว้ตลอดไปโดยไม่มีเหตุผล
  • ไม่ตรวจสอบขนาด input ก่อนส่ง — ผู้ใช้ส่ง input ยาวเกินจำเป็นทำให้ต้นทุนต่อครั้งสูงขึ้นโดยไม่จำเป็น ควรตั้งขีดจำกัดความยาว input ที่สมเหตุสมผลตั้งแต่ต้นทาง
  • ไม่แยกสิทธิ์ระหว่างผู้ใช้ทั่วไปกับผู้ดูแลระบบ — ถ้าฟังก์ชันเดียวรับทั้ง request จากผู้ใช้ทั่วไปและงานเชิงดูแลระบบโดยไม่แยก path การตรวจสอบสิทธิ์ อาจเปิดช่องให้ผู้ใช้ทั่วไปเรียกใช้ความสามารถที่ควรสงวนไว้เฉพาะทีมงานภายในได้โดยไม่ตั้งใจ

เทียบตำแหน่งที่ควรเรียก AI Model ตามลักษณะงาน

สรุปเป็นตารางให้เห็นภาพว่างานแบบไหนควรเรียก AI จากตรงไหนของระบบ:

ลักษณะงานตำแหน่งที่ควรเรียกเหตุผลหลัก
ต้องซ่อน API key ราคาแพงEdge Functionssecret ไม่หลุดไปกับ client
ต้องการ streaming คำตอบแบบ real-timeEdge Functionsรองรับ Web API streaming มาตรฐาน
งานประมวลผลนานเกินเพดานเวลาBackground job/Queue แยกหลีกเลี่ยง request timeout
prototype ทดสอบไอเดียเร็ว ๆ ในเครื่องเรียกตรงจาก local scriptไม่ต้อง deploy อะไรก่อน validate ไอเดีย

ทำแบบนี้แล้วพัง เพราะอะไร

อีกด้านหนึ่งของ AI Workflow ที่เพิ่งเริ่มทำ มักเจอปัญหาซ้ำ ๆ แบบนี้

  • ลืมตั้ง timeout ฝั่งเรียกโมเดล ทำให้ถ้าโมเดลตอบช้าผิดปกติ ฟังก์ชันค้างจนชนเพดานเวลาของ Edge Functions เองแล้ว error แบบไม่มีข้อความชัดเจน
  • ไม่ handle กรณีโมเดลตอบผิด format ที่คาดไว้ เช่น คาดว่าจะได้ JSON แต่ได้ข้อความปนมาด้วย ทำให้โค้ดฝั่ง parse พังกลางทาง
  • หักโควตาผู้ใช้ก่อนเรียกโมเดล แล้วถ้าโมเดล error กลางทางไม่มีการคืนโควตาให้ ทำให้ผู้ใช้เสียสิทธิ์ไปฟรี ๆ ทั้งที่ไม่ได้คำตอบ

สรุป

การย้าย AI Workflow มาไว้ที่ Edge Functions ไม่ใช่เทรนด์ที่ไม่มีเหตุผลรองรับ แต่เกิดจากปัญหาจริงที่ทีมพัฒนาเจอเมื่อเรียก AI ตรงจาก client แล้วเจอเรื่อง secret รั่วและควบคุมต้นทุนไม่ได้ การย้ายมาไว้ฝั่งเซิร์ฟเวอร์ที่อยู่ใกล้ฐานข้อมูลช่วยแก้ทั้งสองปัญหาไปพร้อมกัน

สิ่งที่ควรทำก่อนเริ่มใช้งานจริงคือวางระบบ rate limit และ log การใช้งานให้ครบตั้งแต่ต้น ไม่ใช่ไปแก้ทีหลังตอนบิลเริ่มพุ่ง เพราะการแก้ไขระบบควบคุมต้นทุนหลังผู้ใช้เยอะแล้วมักยากกว่าการวางไว้ตั้งแต่แรกมาก

  • เรียก AI ตรงจาก client เสี่ยง API key รั่วและควบคุมต้นทุนไม่ได้
  • Edge Functions ซ่อน secret ได้ รองรับ streaming และอยู่ใกล้ฐานข้อมูลสำหรับบันทึก log
  • ควบคุม rate limit และ cache คำตอบซ้ำ ๆ ไว้ตั้งแต่ต้น ไม่ใช่แก้ทีหลังตอนบิลพุ่ง

คำถามที่พบบ่อย

จำเป็นต้องใช้ Edge Functions เสมอไปเวลาต่อ AI Model ไหม

ไม่จำเป็นเสมอไป ถ้ามี backend เดิมอยู่แล้วและงานไม่ต้องอยู่ใกล้ Supabase database เป็นพิเศษ จะเรียกจาก backend เดิมก็ได้ แต่ถ้าต้องการ deploy แยก ซ่อน secret และผูกกับข้อมูลใน Postgres ไปด้วย Edge Functions มักสะดวกกว่า

Streaming Response ทำงานยังไงในทางเทคนิคคร่าว ๆ

ฟังก์ชันจะเปิด ReadableStream แล้วเขียนข้อมูลแต่ละ chunk ที่ได้จากโมเดลลงไปทันทีที่ได้รับ โดยไม่รอให้คำตอบครบทั้งก้อน ฝั่ง client จะอ่านข้อมูลทีละ chunk แล้วแสดงผลแบบ real-time

ควรเก็บประวัติการสนทนากับ AI ไว้ที่ไหน

เก็บในตาราง Postgres ปกติได้ โดยผูกกับ user_id และตั้ง RLS ให้ผู้ใช้เห็นเฉพาะประวัติของตัวเอง ถ้าต้องการค้นหาเชิงความหมายเพิ่มเติมสามารถเก็บ embedding คู่กันไว้ใน pgvector

ถ้าโมเดล AI ตอบช้าเกินไปควรทำยังไง

ควรตั้ง timeout ที่เหมาะสมและมีข้อความแจ้งผู้ใช้ระหว่างรอ ถ้างานใช้เวลานานเกินไปควรพิจารณาย้ายไปทำแบบ background job แล้วแจ้งผลกลับผ่าน Realtime แทนการรอใน request เดียว

ต้องเข้ารหัส API key ของ AI เพิ่มเติมไหมนอกจากเก็บใน secrets

การเก็บผ่าน supabase secrets set เพียงพอสำหรับกรณีทั่วไป เพราะค่าจะไม่ถูกเปิดเผยในโค้ดหรือ log ทั่วไป แต่ควรจำกัดสิทธิ์คนที่เข้าถึง dashboard ของโปรเจกต์ให้แคบด้วย

AI Workflow แบบนี้ปรับใช้กับแอปที่มีผู้ใช้จำนวนมากได้ไหม

ปรับใช้ได้ แต่ต้องออกแบบ rate limit, การ cache และการจัดคิวให้รองรับ concurrent request จำนวนมาก ไม่ใช่พึ่งพาแค่ตัวฟังก์ชันเดี่ยว ๆ โดยไม่มีชั้นควบคุมโหลดเพิ่มเติม

ควรแจ้งผู้ใช้ยังไงถ้าโควตา AI ใกล้หมด

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

วัด Conversion LINE ทุกแบรนด์ รวมศูนย์ที่เดียว

องค์กรที่มีหลายแบรนด์ หลายสาขา หลาย LINE OA — linli รวม Tracking และส่ง Conversion กลับทุกแพลตฟอร์ม พร้อม Custom Limit เริ่มฟรี 14 วัน

ติดต่อทีม Sales

บทความที่เกี่ยวข้อง

เปิด Database ให้ Frontend เรียกตรงได้ยังไงโดยไม่มีใครขโมยข้อมูลคนอื่นได้

เปิด Database ให้ Frontend เรียกตรงได้ยังไงโดยไม่มีใครขโมยข้อมูลคนอื่นได้

หลายทีมกลัวการให้ frontend เรียกฐานข้อมูลตรง ๆ เพราะกลัวข้อมูลรั่ว แต่ Row Level Security ของ Supabase คือกลไกที่ทำให้เรื่องนี้ปลอดภัยได้จริง บทความนี้อธิบายว่า RLS ทำงานยังไงและเขียน policy ถูกต้องแบบไหน
แชทสดหรือแดชบอร์ดที่อัปเดตเองต้องใช้ Supabase Realtime เมื่อไหร่ ไม่ใช่ทุกโปรเจกต์

แชทสดหรือแดชบอร์ดที่อัปเดตเองต้องใช้ Supabase Realtime เมื่อไหร่ ไม่ใช่ทุกโปรเจกต์

หลายทีมเปิด Supabase Realtime ทันทีที่เห็นว่ามีให้ใช้ โดยไม่ได้ประเมินว่าโปรเจกต์ตัวเองต้องการจริงไหม บทความนี้ชี้เงื่อนไขว่าเมื่อไรใช้ Realtime คุ้มค่า และเมื่อไรควรใช้ polling ธรรมดาแทน
ทดสอบ schema ใหม่บน production ตรง ๆ ได้ไหมหรือต้องแยก branch ก่อนเสมอ

ทดสอบ schema ใหม่บน production ตรง ๆ ได้ไหมหรือต้องแยก branch ก่อนเสมอ

ทีมพัฒนาหลายทีมยังแก้ schema production ตรง ๆ เพราะไม่รู้ว่า Supabase มีฟีเจอร์ branching ให้แยกฐานข้อมูลทดสอบออกจากของจริงได้ บทความนี้อธิบายว่า branching ทำงานยังไงและช่วยลดความเสี่ยงตรงไหนบ้าง