AI API Gateway คืออะไร: หกช่วงของการส่งคำขอหนึ่งครั้ง และขอบเขตที่มันทำได้
AI API Gateway คืออะไร: หกช่วงของการส่งคำขอหนึ่งครั้ง
AI API Gateway คือบริการที่รับคำขอในรูปแบบมาตรฐาน แล้วแปลงคำขอนั้นให้ชี้ไปยังโมเดลหนึ่งบนผู้ให้บริการต้นทางที่กำหนด ส่งต่อไป และคืนผลลัพธ์กลับมาในรูปแบบมาตรฐานเดิม ฝั่งไคลเอนต์คุยกับ gateway เท่านั้น ส่วนคีย์ของผู้ให้บริการ การตัดสินใจเรื่องเส้นทาง และการตั้งชื่อโมเดล อยู่ฝั่ง gateway ทั้งหมด
นิยามนี้ตั้งใจเขียนให้เป็นกลไก เพราะความสับสนส่วนใหญ่เกี่ยวกับ gateway มาจากการรวมสามเรื่องเข้าด้วยกัน ได้แก่ การแปลงโปรโตคอล การจัดการคีย์ และการจัดเส้นทาง บทความนี้จะไล่ทีละช่วงของการส่งคำขอหนึ่งครั้ง แล้วอธิบายว่า relay เปลี่ยนอะไรได้และเปลี่ยนอะไรไม่ได้
ขอบเขตของสิ่งที่ตรวจสอบในบทความนี้
endpoint และรหัสโมเดลในบทความนี้อ้างอิงจากเอกสารสาธารณะและแค็ตตาล็อกสดของ EXAIV (/docs/api/chat-completions และ /models) พอร์ตท้องถิ่นของ Ollama, llama.cpp และ vLLM เป็นค่าดีฟอลต์ตามเอกสารของโครงการนั้น และแก้ไขได้ผ่านการตั้งค่า ส่วนว่าโมเดลหนึ่งรับพารามิเตอร์หนึ่งหรือไม่ ขึ้นอยู่กับโมเดลและเส้นทาง — ตัวอย่างในบทความคือวิธีตรวจสอบด้วยตัวเอง ไม่ใช่การยืนยันความสามารถของโมเดลใดโมเดลหนึ่ง
หกช่วงของคำขอเดียว
ยกตัวอย่างคำขอแชตธรรมดาที่ส่งไปที่ https://exaiv.com/api/ai/v1/chat/completions มันไม่ได้เดินทางในก้าวเดียว แต่ผ่านช่วงที่แยกออกจากกันได้ และแต่ละช่วงล้มเหลวได้ไม่เหมือนกัน
สองช่วงในนั้นอธิบายคำถามฝ่ายสนับสนุนเกือบทั้งหมด ช่วงที่ 3 อธิบายว่าทำไมชื่อโมเดลที่ใช้ได้ที่อื่นอาจคืนข้อผิดพลาดว่าไม่พบโมเดลที่นี่ เพราะสิ่งที่ตัดสินคือแค็ตตาล็อกฝั่งนี้ ไม่ใช่ชื่อที่คุณจำมาจากเจ้าอื่น ช่วงที่ 4 เป็นช่วงที่เกี่ยวกับความปลอดภัย คีย์ของคุณใช้บอกตัวตนกับ gateway เท่านั้น และผู้ให้บริการต้นทางไม่เคยเห็นมัน
gateway ทำอะไร และไม่ทำอะไร
| gateway ทำ | gateway ไม่ทำ |
|---|---|
| ใช้คีย์เดียวและโปรโตคอลเดียวกับหลายโมเดล | เปลี่ยนความรู้ของโมเดลหรือวิธีที่มันถูกฝึก |
| เก็บคีย์ของผู้ให้บริการและหมุนเวียนมัน | รับประกันความหน่วงค่าหนึ่งในภูมิภาคของคุณ |
| แปลงชื่อโมเดลเป็นผู้ให้บริการ และสลับเมื่อการตั้งค่าอนุญาต | ทำให้พารามิเตอร์ที่ไม่รองรับกลายเป็นรองรับ |
| ปรับผลลัพธ์และอีเวนต์สตรีมให้เป็นมาตรฐาน | แคชพรอมป์ของคุณ (เว้นแต่เอกสารระบุว่ามีความสามารถนี้) |
| วัดการใช้งานตามคีย์และตามโมเดล | แทนที่การตรวจสอบผลลัพธ์ด้วยโค้ดของคุณเอง |
แถวสุดท้ายของคอลัมน์ขวาคือสิ่งที่ทีมมักลืม gateway ทำให้การเรียกสม่ำเสมอ แต่ไม่ได้ทำให้ผลลัพธ์ของโมเดลถูกต้อง การแยกวิเคราะห์ การตรวจสอบตามสคีมา และนโยบายลองใหม่ ยังเป็นงานของโค้ดคุณ
ทำไม relay จึงมีอยู่
ถ้า gateway เป็นเพียงช่วงกลางเพิ่มหนึ่งช่วง ทำไมไม่เรียกผู้ให้บริการโดยตรง มีเหตุผลในทางปฏิบัติสามข้อที่เจอซ้ำ ๆ และไม่มีข้อใดเกี่ยวกับการปิดบังข้อมูล
คีย์เดียว หลายผู้ให้บริการ ผลิตภัณฑ์ที่ใช้โมเดลเร็วสำหรับงานจำแนกและใช้โมเดลใหญ่สำหรับงานให้เหตุผล ต้องมีบัญชีสองบัญชี ความสัมพันธ์ด้านการเรียกเก็บเงินสองชุด และชุดคีย์สองชุดในโปรดักชัน ถ้าใช้ relay แอปพลิเคชันถือคีย์ชุดเดียว
สัญญาที่มั่นคงตรงหน้าแค็ตตาล็อกที่เปลี่ยนตลอด ผู้ให้บริการเปลี่ยนชื่อโมเดล ออกสแนปช็อตที่มีวันที่ และเลิกรุ่นเก่า ถ้ารหัสโมเดลอยู่ในที่เดียวฝั่ง gateway แอปพลิเคชันสามารถซึมซับการเปลี่ยนแปลงส่วนหนึ่งด้วยการแก้การตั้งค่า ไม่ใช่แก้โค้ด
ทางออกเส้นทางเดียวสำหรับไคลเอนต์ในภูมิภาค สำหรับนักพัฒนาในเอเชียตะวันออกเฉียงใต้หรือสหภาพยุโรป เส้นทางเครือข่ายไปยังผู้ให้บริการรายหนึ่งเป็นตัวแปรด้านปฏิบัติการ อาจเร็วบนผู้ให้บริการเครือข่ายรายหนึ่งและช้าบนอีกราย relay มี endpoint เดียวที่พฤติกรรมเป็นที่รู้จัก แทนที่จะเป็น endpoint ของผู้ให้บริการหลายรายที่พฤติกรรมไม่แน่นอน มันไม่ได้ลบความหน่วง แต่ทำให้ endpoint ที่คุณผูกโค้ดไว้กลายเป็นค่าคงที่
จุดที่คนมักมองข้าม: โปรโตคอลเดียวกันใช้ได้กับโมเดลในเครื่อง
เหตุผลที่แข็งแรงที่สุดในการเรียนรู้รูปแบบคำขอแบบ OpenAI-compatible ไม่ใช่เพราะ relay ใช้มัน แต่เพราะเซิร์ฟเวอร์อนุมานในเครื่องที่จริงจังแทบทุกรายก็ใช้มันเช่นกัน Ollama, เซิร์ฟเวอร์ของ llama.cpp และ vLLM ต่างมี endpoint ที่รองรับ OpenAI ดังนั้นไลบรารีไคลเอนต์ชุดเดียวกัน อาร์เรย์ messages ชุดเดียวกัน และตัวแยกอีเวนต์สตรีมชุดเดียวกัน ใช้ได้ทั้งกับ relay และกับโมเดลที่รันบนแล็ปท็อป
นั่นหมายความว่าในสถาปัตยกรรมที่สมเหตุสมผล ตำแหน่งของโมเดลควรเป็นเพียงตัวแปรเดียว:
import os
from openai import OpenAI
# สองปลายทาง โค้ดชุดเดียว: เปลี่ยนแค่ base_url กับ model
TARGETS = {
"relay": {
"base_url": "https://exaiv.com/api/ai/v1",
"api_key": os.environ["EXAIV_API_KEY"],
"model": "deepseek-v4.1-flash",
},
"local": {
"base_url": "http://localhost:11434/v1", # endpoint ดีฟอลต์ของ Ollama
"api_key": "ollama", # เซิร์ฟเวอร์ในเครื่องมักไม่ตรวจคีย์
"model": "qwen3.8-flash",
},
}
def ask(target: str, prompt: str) -> str:
cfg = TARGETS[target]
client = OpenAI(base_url=cfg["base_url"], api_key=cfg["api_key"])
r = client.chat.completions.create(
model=cfg["model"],
messages=[{"role": "user", "content": prompt}],
temperature=0,
)
return r.choices[0].message.content
print(ask("relay", "สรุปบันทึกการเปลี่ยนแปลงนี้เป็นสามข้อ"))
การตรวจแบบเดียวกันด้วย curl ใช้บรรทัดเดียว เหมาะกับการยืนยัน endpoint ก่อนนำ SDK เข้ามาเกี่ยวข้อง:
curl -s https://exaiv.com/api/ai/v1/chat/completions \\
-H "Authorization: Bearer $EXAIV_API_KEY" \\
-H "Content-Type: application/json" \\
-d '{
"model": "kimi-k3",
"messages": [{"role": "user", "content": "ตอบเพียงคำเดียว: ปกติ"}],
"temperature": 0
}'
ถ้าตอบ 401 แปลว่าคีย์หายหรือผิด ถ้าตอบ 404 ที่ระบุชื่อโมเดล แปลว่ารหัสนั้นไม่อยู่ในแค็ตตาล็อก สองกรณีนี้ครอบคลุมความล้มเหลวครั้งแรกเกือบทั้งหมด และแยกออกจากกันได้โดยไม่ต้องเปิดเอกสาร
เมื่อใดที่ไม่ควรใช้ relay
gateway เป็นการเลือกเชิงสถาปัตยกรรมที่มีข้อแลกเปลี่ยน และมีกรณีที่การเรียกผู้ให้บริการโดยตรงถูกต้องกว่า
- ข้อกำหนดด้านที่ตั้งของข้อมูลที่ระบุตัวผู้ประมวลผล ถ้ากฎกำหนดว่าใครประมวลผลข้อมูลได้ relay คือฝ่ายเพิ่มเติมในการวิเคราะห์นั้น ควรอ่านข้อกำหนดก่อนสรุปว่าเข้ากันได้
- ผู้ให้บริการรายเดียวและงบความหน่วงระดับมิลลิวินาที ทุกช่วงที่เพิ่มคือที่ที่เวลาถูกใช้ไป ถ้างานไวต่อความหน่วงและใช้ผู้ให้บริการรายเดียว การต่อตรงอธิบายง่ายกว่า
- สภาพแวดล้อมที่แยกจากเครือข่ายทั้งหมด ถ้าเครือข่ายออกอินเทอร์เน็ตไม่ได้ endpoint เดียวที่ใช้ได้คือตัวที่รันอยู่ข้างโมเดล นี่คือจุดที่เซิร์ฟเวอร์ OpenAI-compatible ในเครื่องคือคำตอบทั้งหมด
ไม่มีข้อใดทำให้ relay แย่ มีแต่ทำให้มันเป็นเรื่องของความเหมาะสม ไม่ใช่ค่าดีฟอลต์
ประเมิน relay ในสิบนาที
เอกสารบอกเจตนา ห้าข้อทดสอบต่อไปนี้บอกพฤติกรรม ควรรันก่อนผูกโค้ดกับ endpoint ใด endpoint หนึ่ง
หนึ่ง ส่งคำขอเล็กที่สุดและเก็บผลลัพธ์ดิบไว้ เทียบชื่อฟิลด์ที่ได้กับฟิลด์ที่โค้ดของคุณอ่าน คำขอแรกที่ตอบ 200 แต่ขาดฟิลด์ที่คุณพึ่งพา คือปัญหาเชิงออกแบบ ไม่ใช่บั๊กที่จะค่อยไปแก้ทีหลัง
สอง ส่งรหัสโมเดลที่ตั้งใจให้ผิด อ่านเนื้อหาข้อผิดพลาด endpoint ที่ระบุชื่อโมเดลที่ไม่รู้จักได้ ดูแลง่ายกว่า endpoint ที่คืนความล้มเหลวแบบกว้าง ๆ เพราะตรรกะลองใหม่ของคุณแยก "ตั้งค่าผิด" ออกจาก "ความขัดข้องชั่วคราว" ได้
สาม เปิดคำขอแบบสตรีมค้างไว้นานกว่าหมดเวลาของพร็อกซีใด ๆ ในเส้นทาง พร็อกซีองค์กรและ CDN บางรายตัดการเชื่อมต่อที่ว่าง สตรีมที่ค้างหลังหกสิบวินาทีอาจทำงานได้บนแล็ปท็อปแต่ล้มเหลวในออฟฟิศ การทดสอบนี้ยังบอกด้วยว่าไคลเอนต์ต้องตั้งเวลาอ่านหมดเวลาเองหรือไม่
สี่ ดันคำขอให้เกินขีดจำกัดบริบทโดยตั้งใจ การปฏิเสธควรปรากฏเป็นข้อผิดพลาดชัดเจนก่อนมีการคิดค่าใช้จ่ายใด ๆ ไม่ใช่กลายเป็นคำตอบที่ถูกตัดทอนซึ่งคุณเพิ่งรู้ตัวในโปรดักชัน
ห้า เรียกโมเดลเดิมสองครั้งด้วยอินพุตเดิมและ temperature เป็นศูนย์ ผลลัพธ์จะไม่เหมือนกันทุกไบต์ และนั่นเป็นเรื่องปกติ สิ่งที่คุณกำลังตรวจคือโครงสร้างผลลัพธ์นิ่งหรือไม่: คีย์เดิม ชนิดเดิม การซ้อนเดิม การเลื่อนของโครงสร้างคือรูปแบบความล้มเหลวที่ทำลายโค้ดปลายทางอย่างเงียบ ๆ
เก็บผลลัพธ์ทั้งห้าไว้
เก็บผลลัพธ์ดิบจากการทดสอบทั้งห้าไว้ในรีโพซิทอรีข้างโค้ดที่เชื่อมต่อ เมื่อมีอะไรเปลี่ยนในอีกหลายเดือน คุณจะมีข้อมูลเทียบก่อนและหลัง ไม่ใช่ความทรงจำว่าเดิมมันเป็นอย่างไร
การแก้ปัญหาตามช่วง
| อาการ | ช่วงที่อาจผิด | ตรวจอะไรก่อน |
|---|---|---|
| 401 ทุกคำขอ | ช่วงที่ 2 | มีคีย์ในเฮดเดอร์หรือไม่ มีช่องว่างเกินหรือไม่ คีย์หมดอายุหรือยัง |
| 404 ที่ระบุชื่อโมเดล | ช่วงที่ 3 | รหัสนั้นอยู่ในแค็ตตาล็อกสดฝั่ง gateway หรือไม่ |
| 429 เมื่อมีโหลด | ช่วงที่ 2 | ความพร้อมกันของตัวเองเทียบขีดจำกัดอัตรา ถอยกลับแทนที่จะลองใหม่ทันที |
| สตรีมเริ่มแล้วค้าง | ช่วงที่ 5 | เวลาอ่านหมดเวลาฝั่งไคลเอนต์ และการบัฟเฟอร์ของพร็อกซีระหว่างคุณกับ gateway |
| เครือข่ายหนึ่งใช้ได้ อีกเครือข่ายล้มเหลว | ช่วงที่ 4/5 | พร็อกซีหรือไฟร์วอลล์ขององค์กรรบกวนการเชื่อมต่อแบบสตรีมหรือไม่ |
| ได้คำตอบแต่ไม่พบฟิลด์ที่อ่าน | ช่วงที่ 5/6 | พารามิเตอร์ถูกรับแต่โมเดลที่จัดเส้นทางไปไม่รองรับ ตรวจด้วยคำขอเล็กที่สุด |
รูปแบบที่ควรจำคือ รหัสสถานะบอกว่าช่วงไหนล้มเหลว 401 ไม่เคยเป็นปัญหาโมเดล และการไม่พบโมเดลไม่เคยเป็นปัญหาเรื่องการยืนยันตัวตน เมื่อเลิกมอง gateway เป็นกล่องทึบ การแก้ปัญหาจะเร็วขึ้นมาก
เช็กลิสต์ก่อนเลือกใช้
- ฉันรู้ว่ารหัสโมเดลต้องมาจากแค็ตตาล็อกใด และอ่านได้ที่ไหน
- ฉันรู้ว่าส่วนใดของคำขอที่แอปพลิเคชันฉันตรวจสอบเอง และส่วนใดที่ gateway ปรับให้
- ฉันมีแผนสำรองเมื่อรหัสโมเดลหนึ่งหายไปจากแค็ตตาล็อก
- ฉันทดสอบสตรีมผ่านเครือข่ายของตัวเอง ไม่ใช่แค่บนแล็ปท็อปที่เน็ตสะอาด
- ฉันตัดสินใจแล้วว่างานนี้ต้องใช้ relay ต่อตรง หรือเซิร์ฟเวอร์ในเครื่อง
- ฉันตรวจแล้วว่าโค้ดไคลเอนต์ชุดเดียวกันรันได้ทั้งกับ relay และ endpoint ในเครื่อง