เมื่อผมเริ่มใช้งาน AI API ในงาน Production สิ่งที่เจอบ่อยที่สุดคือการเรียก API แล้วได้รหัสข้อผิดพลาดกลับมา โดยเฉพาะ 429 Too Many Requests และ 500 Internal Server Error ที่ทำให้ระบบหยุดทำงานกะทันหัน บทความนี้จะสอนวิธีวิเคราะห์รหัสข้อผิดพลาดแต่ละประเภท พร้อมโค้ดระบบลองใหม่อัตโนมัติที่พร้อมนำไปใช้งานจริง โดยใช้ HolySheep AI เป็นตัวอย่างหลัก
สรุปคำตอบ: สิ่งที่ต้องทำเมื่อ API ล้มเหลว
- รหัส 429 — รอตาม
Retry-Afterที่เซิร์ฟเวอร์ส่งมา เฉลี่ย 5-60 วินาที - รหัส 500-503 — ลองใหม่อัตโนมัติ 3-5 ครั้งด้วย exponential backoff
- รหัส 401/403 — ตรวจสอบ API Key และสิทธิ์การเข้าถึงทันที
- รหัส 400 — ตรวจสอบ format ของ request body
- Network Timeout — ตั้งค่า timeout ที่เหมาะสม (30-120 วินาที)
ตารางเปรียบเทียบ AI API Providers ปี 2026
| Provider | ราคา $/MTok | ความหน่วง (Latency) | วิธีชำระเงิน | รุ่นโมเดล | ทีมที่เหมาะสม |
|---|---|---|---|---|---|
| HolySheep AI | GPT-4.1: $8, Claude 4.5: $15, Gemini 2.5: $2.50, DeepSeek V3.2: $0.42 | <50ms | WeChat, Alipay, บัตรเครดิต | GPT-4, Claude, Gemini, DeepSeek, Llama | Startup, ทีมเล็ก, นักพัฒนาไทย |
| OpenAI | GPT-4o: $15, GPT-4o-mini: $0.60 | 80-200ms | บัตรเครดิตเท่านั้น | GPT-4, GPT-3.5 | องค์กรใหญ่, ทีมที่มีงบประมาณสูง |
| Anthropic | Claude 3.5: $15, Claude 3 Haiku: $0.80 | 100-300ms | บัตรเครดิตเท่านั้น | Claude 3.5, Claude 3 | งานที่ต้องการความแม่นยำสูง |
| Google Gemini | Gemini 2.0 Flash: $0.10 | 150-400ms | บัตรเครริต | Gemini 2.0, 1.5 | งานที่ต้องการประหยัดค่าใช้จ่าย |
| DeepSeek | V3: $0.27 | 200-500ms | Alipay, บัตรเครดิต | DeepSeek V3, R1 | ทีมที่ต้องการโมเดลราคาถูก |
หมายเหตุ: อัตราแลกเปลี่ยน HolySheep ¥1=$1 ประหยัด 85%+ เมื่อเทียบกับราคาต้นทาง
รหัสข้อผิดพลาด HTTP ที่พบบ่อยใน AI API
2xx — สำเร็จ
- 200 OK — สำเร็จ ได้ผลลัพธ์กลับมาตามปกติ
- 201 Created — สร้าง resource สำเร็จ (เช่น fine-tuning job)
- 202 Accepted — คำขอถูกรับแล้ว กำลังประมวลผลแบบ async
4xx — ข้อผิดพลาดจาก Client
- 400 Bad Request — Request body ไม่ถูก format หรือ missing required fields
- 401 Unauthorized — API Key ไม่ถูกต้อง หรือหมดอายุ
- 403 Forbidden — API Key ไม่มีสิทธิ์เข้าถึง endpoint นี้
- 404 Not Found — Endpoint หรือ resource ไม่มีอยู่
- 422 Unprocessable Entity — Request valid ทาง syntax แต่ไม่ถูกต้องทาง semantic
- 429 Too Many Requests — เกิน rate limit ที่กำหนด
5xx — ข้อผิดพลาดจาก Server
- 500 Internal Server Error — เซิร์ฟเวอร์ภายในมีปัญหา ลองใหม่ได้
- 502 Bad Gateway — Gateway/proxy มีปัญหา ลองใหม่ได้
- 503 Service Unavailable — เซิร์ฟเวอร์ปิดซ่อมบำรุง หรือ overload
- 504 Gateway Timeout — เซิร์ฟเวอร์ upstream timeout ลองใหม่ได้
โครงสร้าง Error Response จาก AI API
{
"error": {
"message": "You exceeded your current quota, please check your plan and billing details.",
"type": "insufficient_quota",
"code": "insufficient_quota",
"param": null,
"status": 429
}
}
จากโครงสร้างด้านบน เราสามารถอ่านค่าสำคัญได้ดังนี้:
error.message— ข้อความอธิบายข้อผิดพลาด (มนุษย์อ่านได้)error.type— ประเภทของ error (ใช้จัดการในโค้ด)error.code— รหัสเฉพาะของ providererror.status— HTTP status code
ระบบลองใหม่อัตโนมัติด้วย Exponential Backoff
import requests
import time
import json
from typing import Dict, Any, Optional
class HolySheepAPIClient:
"""Client สำหรับ HolySheep AI API พร้อมระบบลองใหม่อัตโนมัติ"""
def __init__(self, api_key: str):
self.api_key = api_key
self.base_url = "https://api.holysheep.ai/v1"
self.max_retries = 5
self.timeout = 120
def _is_retryable_error(self, status_code: int, error_response: Optional[Dict]) -> bool:
"""ตรวจสอบว่า error นี้ลองใหม่ได้หรือไม่"""
# 5xx errors — เซิร์ฟเวอร์มีปัญหา ลองใหม่ได้
if 500 <= status_code < 600:
return True
# 429 Too Many Requests — rate limit
if status_code == 429:
return True
# 401/403 — ไม่ควรลองใหม่ ยกเว้น token expired
if status_code in [401, 403]:
if error_response:
error_type = error_response.get("error", {}).get("type", "")
if "invalid_api_key" in error_type or "authentication" in error_type:
return False # API Key ผิด ลองใหม่ก็ไม่ช่วย
return False
# 400 Bad Request — ปกติไม่ลองใหม่ แต่บางกรณีลองได้
if status_code == 400:
if error_response:
error_type = error_response.get("error", {}).get("type", "")
# some transient errors อาจลองใหม่ได้
if "server_error" in error_type:
return True
return False
return False
def _get_retry_delay(self, attempt: int, error_response: Optional[Dict] = None) -> float:
"""คำนวณ delay ด้วย exponential backoff + jitter"""
# ดู Retry-After header ก่อน (สำหรับ 429)
if error_response and "retry_after" in error_response:
return float(error_response["retry_after"])
# Exponential backoff: 1, 2, 4, 8, 16 วินาที
base_delay = min(2 ** attempt, 32) # สูงสุด 32 วินาที
# เพิ่ม random jitter ±25% เพื่อป้องกัน thundering herd
import random
jitter = base_delay * random.uniform(0.75, 1.25)
return jitter
def chat_completions(self, messages: list, model: str = "gpt-4", **kwargs) -> Dict[str, Any]:
"""เรียก Chat Completions API พร้อมระบบลองใหม่"""
url = f"{self.base_url}/chat/completions"
headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
}
payload = {
"model": model,
"messages": messages,
**kwargs
}
last_error = None
for attempt in range(self.max_retries):
try:
response = requests.post(
url,
headers=headers,
json=payload,
timeout=self.timeout
)
# ถ้าสำเร็จ (2xx) คืนผลลัพธ์
if 200 <= response.status_code < 300:
return response.json()
# ถ้าไม่สำเร็จ ลองตรวจสอบว่าลองใหม่ได้หรือไม่
try:
error_data = response.json()
except:
error_data = {"error": {"message": response.text}}
if not self._is_retryable_error(response.status_code, error_data):
# ไม่ลองใหม่ คืน error
error_data["error"]["status_code"] = response.status_code
error_data["error"]["attempted"] = attempt + 1
return error_data
# คำนวณ delay และรอ
delay = self._get_retry_delay(attempt, error_data)
print(f"Attempt {attempt + 1} failed: {response.status_code}")
print(f"Retrying in {delay:.2f} seconds...")
time.sleep(delay)
last_error = error_data
except requests.exceptions.Timeout:
print(f"Attempt {attempt + 1} timed out, retrying...")
time.sleep(self._get_retry_delay(attempt))
last_error = {"error": {"message": "Request timeout"}}
except requests.exceptions.ConnectionError as e:
print(f"Attempt {attempt + 1} connection error: {e}")
time.sleep(self._get_retry_delay(attempt))
last_error = {"error": {"message": str(e)}}
# ลองครบทุกครั้งแล้ว คืน error สุดท้าย
last_error["error"]["max_retries_exceeded"] = True
return last_error
ตัวอย่างการใช้งาน
client = HolySheepAPIClient("YOUR_HOLYSHEEP_API_KEY")
result = client.chat_completions(
messages=[
{"role": "system", "content": "คุณเป็นผู้ช่วยภาษาไทย"},
{"role": "user", "content": "อธิบายเรื่อง API error handling"}
],
model="gpt-4",
temperature=0.7
)
if "error" in result:
print(f"Error after retries: {result['error']}")
else:
print(f"Success: {result['choices'][0]['message']['content']}")
การตรวจจับ Error Type แบบละเอียด
import re
from dataclasses import dataclass
from typing import Optional
@dataclass
class APIError:
"""Data class สำหรับเก็บข้อมูล error"""
status_code: int
error_type: str
message: str
retryable: bool
retry_after: Optional[float] = None
def parse_holysheep_error(response_json: dict, status_code: int) -> APIError:
"""แปลง error response เป็น structured object"""
error = response_json.get("error", {})
error_type = error.get("type", "unknown")
message = error.get("message", "No message provided")
# กำหนดว่า error นี้ลองใหม่ได้หรือไม่
retryable_types = {
"rate_limit_exceeded",
"server_error",
"service_unavailable",
"gateway_error",
"temporary_unavailable"
}
retryable = (
status_code in [429, 500, 502, 503, 504] or
error_type in retryable_types or
"rate_limit" in error_type.lower()
)
# ดึงค่า retry_after จาก response
retry_after = None
if status_code == 429:
retry_after = error.get("retry_after") or error.get("param")
if retry_after:
try:
retry_after = float(retry_after)
except:
retry_after = None
return APIError(
status_code=status_code,
error_type=error_type,
message=message,
retryable=retryable,
retry_after=retry_after
)
def handle_error(error: APIError, attempt: int, max_attempts: int) -> bool:
"""จัดการ error และตัดสินใจว่าจะลองใหม่หรือไม่"""
print(f"[Attempt {attempt}/{max_attempts}] Error {error.status_code}: {error.error_type}")
print(f" Message: {error.message}")
if not error.retryable:
print(" → Error is not retryable, stopping.")
return False
if attempt >= max_attempts:
print(f" → Max attempts ({max_attempts}) reached, stopping.")
return False
# คำนวณ delay
if error.retry_after:
delay = error.retry_after
else:
delay = min(2 ** attempt, 60) # exponential backoff สูงสุด 60 วินาที
print(f" → Retrying in {delay:.1f} seconds...")
return True
ตัวอย่างการใช้งาน
sample_error_response = {
"error": {
"message": "Rate limit reached for default-global with IP 123.45.67.89",
"type": "rate_limit_exceeded",
"code": "ratelimit_exceeded",
"retry_after": 30
}
}
error = parse_holysheep_error(sample_error_response, 429)
print(f"Error Type: {error.error_type}")
print(f"Retryable: {error.retryable}")
print(f"Retry After: {error.retry_after}s")
การตั้งค่า Circuit Breaker Pattern
import time
from datetime import datetime, timedelta
from collections import deque
class CircuitBreaker:
"""
Circuit Breaker ป้องกันไม่ให้ระบบพยายามเรียก API ต่อเมื่อเซิร์ฟเวอร์มีปัญหา
สถานะ: CLOSED (ปกติ) → OPEN (เปิดเมื่อ fail) → HALF_OPEN (ทดสอบ)
"""
CLOSED = "closed" # ทำงานปกติ
OPEN = "open" # หยุดเรียกชั่วคราว
HALF_OPEN = "half_open" # ลองเรียกดู
def __init__(
self,
failure_threshold: int = 5, # fail กี่ครั้งถึงเปิด circuit
recovery_timeout: int = 60, # รอกี่วินาทีก่อนลองใหม่
expected_exception: type = Exception
):
self.failure_threshold = failure_threshold
self.recovery_timeout = recovery_timeout
self.expected_exception = expected_exception
self.failure_count = 0
self.last_failure_time = None
self.state = self.CLOSED
self.success_count = 0
self.half_open_success_threshold = 3
def call(self, func, *args, **kwargs):
"""เรียก function ผ่าน circuit breaker"""
if self.state == self.OPEN:
# ตรวจสอบว่าถึงเวลา transition เป็น HALF_OPEN หรือยัง
if self.last_failure_time:
elapsed = time.time() - self.last_failure_time
if elapsed >= self.recovery_timeout:
print("⏳ Circuit transitioning to HALF_OPEN (testing recovery)")
self.state = self.HALF_OPEN
self.success_count = 0
else:
remaining = self.recovery_timeout - elapsed
raise Exception(
f"Circuit is OPEN. Retry after {remaining:.1f} seconds. "
f"Last failure: {self.last_failure_time}"
)
# HALF_OPEN: อนุญาตให้เรียกได้จำกัด
if self.state == self.HALF_OPEN:
if self.success_count >= self.half_open_success_threshold:
print("✅ Circuit CLOSED (recovered successfully)")
self.state = self.CLOSED
self.failure_count = 0
self.success_count = 0
try:
result = func(*args, **kwargs)
self._on_success()
return result
except self.expected_exception as e:
self._on_failure()
raise e
def _on_success(self):
"""จัดการเมื่อเรียกสำเร็จ"""
if self.state == self.HALF_OPEN:
self.success_count += 1
print(f" Half-open success: {self.success_count}/{self.half_open_success_threshold}")
elif self.state == self.CLOSED:
# reset failure count เมื่อ success ติดกัน
if self.failure_count > 0:
self.failure_count = max(0, self.failure_count - 1)
def _on_failure(self):
"""จัดการเมื่อเรียกล้มเหลว"""
self.failure_count += 1
self.last_failure_time = time.time()
print(f" ❌ Circuit failure #{self.failure_count}/{self.failure_threshold}")
if self.failure_count >= self.failure_threshold:
print(f" 🔴 Circuit OPEN (threshold reached)")
self.state = self.OPEN
def get_status(self) -> dict:
"""ดึงสถานะ circuit breaker"""
return {
"state": self.state,
"failure_count": self.failure_count,
"last_failure": self.last_failure_time,
"recovery_timeout": self.recovery_timeout
}
ตัวอย่างการใช้งานกับ API client
breaker = CircuitBreaker(
failure_threshold=3,
recovery_timeout=30
)
def call_api_with_breaker(messages):
def api_call():
client = HolySheepAPIClient("YOUR_HOLYSHEEP_API_KEY")
return client.chat_completions(messages)
return breaker.call(api_call, messages)
ข้อผิดพลาดที่พบบ่อยและวิธีแก้ไข
กรณีที่ 1: ได้รับ 429 Rate Limit Exceeded
# ❌ วิธีผิด: เรียกซ้ำทันทีโดยไม่รอ
for i in range(100):
response = requests.post(url, json=payload) # จะ fail ทั้งหมด
✅ วิธีถูก: ตรวจสอบ Retry-After และรอตามเวลาที่เซิร์ฟเวอร์กำหนด
headers = response.headers
if "Retry-After" in headers:
retry_after = int(headers["Retry-After"])
print(f"Rate limited. Waiting {retry_after} seconds...")
time.sleep(retry_after)
หรือใช้ exponential backoff
for attempt in range(max_retries):
try:
response = requests.post(url, json=payload)
response.raise_for_status()
break
except requests.exceptions.HTTPError as e:
if e.response.status_code == 429:
wait_time = 2 ** attempt + random.uniform(0, 1)
print(f"Rate limited. Retrying in {wait_time:.2f}s...")
time.sleep(wait_time)
else:
raise
กรณีที่ 2: 401 Unauthorized — Invalid API Key
# ❌ วิธีผิด: Hardcode API key ในโค้ด
headers = {
"Authorization": "Bearer sk-1234567890abcdef"
}
✅ วิธีถูก: ใช้ environment variable
import os
api_key = os.environ.get("HOLYSHEEP_API_KEY")
if not api_key:
raise ValueError("HOLYSHEEP_API_KEY environment variable not set")
headers = {
"Authorization": f"Bearer {api_key}"
}
✅ วิธีที่ดีที่สุด: ใช้ .env file กับ pydantic settings
.env file:
HOLYSHEEP_API_KEY=your_api_key_here
HOLYSHEEP_BASE_URL=https://api.holysheep.ai/v1
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
holysheep_api_key: str
holysheep_base_url: str = "https://api.holysheep.ai/v1"
class Config:
env_file = ".env"
env_prefix = "HOLYSHEEP_"
settings = Settings()
กรณีที่ 3: 500 Internal Server Error เมื่อส่ง Request ขนาดใหญ่
# ❌ วิธีผิด: ส่งข้อความยาวเกิน limit
messages = [
{"role": "user", "content": very_long_text} # อาจเกิน 32k tokens
]
✅ วิธีถูก: ตรวจสอบขนาดก่อนส่ง
def estimate_tokens(text: str) -> int:
"""ประมาณจำนวน tokens (ภาษาไทย ~2.5 ตัวอักษร = 1 token)"""
return len(text) // 2
MAX_TOKENS = 30000 # เผื่อ buffer
def truncate_if_needed(messages: list, max_tokens: int = MAX_TOKENS) -> list:
"""ตัดข้อความถ้าเกิน limit"""
truncated = []
total_tokens = 0
for msg in messages:
content = msg.get("content", "")
tokens = estimate_tokens(content)
if total_tokens + tokens > max_tokens:
# ตัดข้อความตามสัดส่วน
remaining = max_tokens - total_tokens
chars_to_keep = int(remaining * 2)
truncated.append({
**msg,
"content": content[:chars_to_keep] + "... [truncated]"
})
break
else:
truncated.append(msg)
total_tokens += tokens
return truncated
ใช้งาน
safe_messages = truncate_if_needed(messages)
response = client.chat_completions(safe_messages)
กรณีที่ 4: Connection Timeout เมื่อเรียกจาก Server ต่างประเทศ
# ❌ วิธีผิด: ใช้ timeout default (ซึ่งอาจเป็น None)
response = requests.post(url, json=payload)
✅ วิธีถูก: ตั้งค่า timeout ที่เหมาะสม
TIMEOUT = (10, 120) # (connect_timeout, read_timeout) วินาที
response = requests.post(
url,
json=payload,
headers=headers,
timeout=TIMEOUT
)
✅ วิธีที่ดีกว่า: ใช้ session พร้อม retry adapter
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry
session = requests.Session()
ตั้งค่า retry strategy
retry_strategy = Retry(
total=3,
backoff_factor=1,
status_forcelist=[429, 500, 502, 503, 504],
allowed_methods=["POST"]
)
adapter = HTTPAdapter(
max_retries=retry_strategy,
pool_connections=10,
pool_maxsize=20
)
session.mount("https://", adapter)
response = session.post(
"https://api.holysheep.ai/v1/chat/completions",
json=payload,
headers=headers,
timeout=(10, 120)
)
Best Practices สำหรับ Production
- ใช้ Environment Variable สำหรับ API Key อย่างเดียว ห้าม hardcode
- Implement Circuit Breaker ป้องกันระบบล่มเมื่อ API มีปัญหาต่อเนื่อง
- Log ทุกการ retry เพื่อวิเคราะห์ปัญหาและปรับปรุง
- ใช้ Queue สำ