ในฐานะวิศวกรที่ดูแลระบบ AI มาหลายปี ผมเคยเจอสถานการณ์ที่บิล API พุ่งจากหลักร้อยเป็นหลักหมื่นบาทภายในไม่กี่วัน เพราะ loop ที่ไม่มีจำกัดหรือการทดสอบที่ลืมปิด วันนี้ผมจะมาแชร์วิธีสร้างระบบควบคุมค่าใช้จ่ายที่ใช้งานได้จริงใน production
เปรียบเทียบค่าใช้จ่าย API รายเดือน
| บริการ | ราคาต่อล้าน Token | ความหน่วง (Latency) | วิธีการชำระเงิน | ประหยัดเมื่อเทียบกับ Official |
|---|---|---|---|---|
| HolySheep AI | DeepSeek V3.2: $0.42 Gemini 2.5 Flash: $2.50 Claude Sonnet 4.5: $15 GPT-4.1: $8 |
<50 มิลลิวินาที | WeChat, Alipay, บัตรต่างประเทศ | 85%+ |
| API อย่างเป็นทางการ | Claude 3.5: $15 GPT-4o: $15 Gemini 1.5: $7 |
100-300 มิลลิวินาที | บัตรเครดิตระหว่างประเทศเท่านั้น | - |
| บริการ Relay ทั่วไป | $3-10 ต่อล้าน Token | 150-500 มิลลิวินาที | หลากหลาย | 30-60% |
หมายเหตุ: อัตราแลกเปลี่ยน HolySheep ¥1 = $1 ทำให้ค่าใช้จ่ายต่ำกว่าตลาดอย่างมาก นอกจากนี้ยังมี เครดิตฟรีเมื่อลงทะเบียน สำหรับทดสอบระบบ
ทำไมต้องควบคุมค่าใช้จ่าย API
จากประสบการณ์ที่เคยต้องอธิบายบิลหลัก 50,000 บาทต่อ CTO ผมจึงเข้าใจดีว่า AI API cost สามารถบินได้ถ้าไม่มีระบบควบคุม ปัญหาหลักมักเกิดจาก:
- การทดสอบโค้ดที่ไม่ได้ limit จำนวน request
- Recursive loop ที่ไม่มีจุดหยุด
- การใช้โมเดลขนาดใหญ่เกินความจำเป็น
- การ retry ที่ไม่มี exponential backoff
- Cache ที่หมดอายุทำให้เรียก API ซ้ำ
สร้างระบบติดตามการใช้งาน API
เริ่มจากสร้าง class สำหรับติดตามการใช้งานและค่าใช้จ่ายแบบ real-time
import time
import httpx
from datetime import datetime, timedelta
from dataclasses import dataclass, field
from typing import Dict, List, Optional
import json
import asyncio
@dataclass
class UsageRecord:
timestamp: datetime
tokens_used: int
cost: float
model: str
endpoint: str
@dataclass
class BudgetAlert:
threshold_percent: float
current_spend: float
budget_limit: float
notified: bool = False
class APICostTracker:
"""ระบบติดตามค่าใช้จ่าย API แบบ real-time"""
# ราคาต่อล้าน token (อัปเดตตาม HolySheep)
PRICE_PER_MILLION = {
'deepseek-v3.2': 0.42,
'gemini-2.5-flash': 2.50,
'claude-sonnet-4.5': 15.00,
'gpt-4.1': 8.00,
}
def __init__(self, monthly_budget: float = 100.0):
self.monthly_budget = monthly_budget
self.total_spent = 0.0
self.daily_spent = 0.0
self.daily_reset = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
self.usage_history: List[UsageRecord] = []
self.alerts: List[BudgetAlert] = []
self.request_count = 0
self.last_request_time = None
# สร้าง alert thresholds
for threshold in [50, 75, 90, 100]:
self.alerts.append(BudgetAlert(
threshold_percent=threshold,
current_spend=0.0,
budget_limit=monthly_budget
))
def calculate_cost(self, model: str, input_tokens: int, output_tokens: int) -> float:
"""คำนวณค่าใช้จ่ายจากจำนวน token"""
price = self.PRICE_PER_MILLION.get(model.lower(), 8.0)
total_tokens = input_tokens + output_tokens
cost = (total_tokens / 1_000_000) * price
return round(cost, 6)
def record_usage(self, model: str, input_tokens: int, output_tokens: int,
endpoint: str = "/chat/completions") -> UsageRecord:
"""บันทึกการใช้งานและคำนวณค่าใช้จ่าย"""
# Reset daily counter ถ้าเป็นวันใหม่
now = datetime.now()
if now >= self.daily_reset + timedelta(days=1):
self.daily_spent = 0.0
self.daily_reset = now.replace(hour=0, minute=0, second=0, microsecond=0)
cost = self.calculate_cost(model, input_tokens, output_tokens)
record = UsageRecord(
timestamp=now,
tokens_used=input_tokens + output_tokens,
cost=cost,
model=model,
endpoint=endpoint
)
self.usage_history.append(record)
self.total_spent += cost
self.daily_spent += cost
self.request_count += 1
self.last_request_time = now
# อัปเดต alert status
for alert in self.alerts:
alert.current_spend = self.total_spent
return record
def get_budget_status(self) -> Dict:
"""ดึงสถานะงบประมาณปัจจุบัน"""
percent_used = (self.total_spent / self.monthly_budget) * 100
return {
"total_spent": round(self.total_spent, 2),
"daily_spent": round(self.daily_spent, 2),
"monthly_budget": self.monthly_budget,
"percent_used": round(percent_used, 2),
"remaining": round(self.monthly_budget - self.total_spent, 2),
"request_count": self.request_count,
"next_alert_threshold": next(
(a.threshold_percent for a in self.alerts if not a.notified and a.current_spend / self.monthly_budget * 100 >= a.threshold_percent),
None
)
}
def check_and_alert(self) -> Optional[str]:
"""ตรวจสอบและส่งการแจ้งเตือนถ้าถึง threshold"""
percent_used = (self.total_spent / self.monthly_budget) * 100
for alert in self.alerts:
if percent_used >= alert.threshold_percent and not alert.notified:
alert.notified = True
return f"⚠️ แจ้งเตือน: ใช้งบประมาณไปแล้ว {alert.threshold_percent}% (${alert.current_spend:.2f} / ${self.monthly_budget:.2f})"
return None
ตัวอย่างการใช้งาน
tracker = APICostTracker(monthly_budget=100.0)
record = tracker.record_usage("deepseek-v3.2", input_tokens=1000, output_tokens=500)
print(tracker.get_budget_status())
ระบบจำกัดการใช้งานและ Rate Limiting
นอกจากติดตามค่าใช้จ่ายแล้ว ต้องมีระบบจำกัด request rate ด้วย เพื่อป้องกันการเรียก API มากเกินไป
import time
from collections import defaultdict
from threading import Lock
from functools import wraps
class RateLimiter:
"""ระบบจำกัดอัตราการเรียก API แบบ Token Bucket"""
def __init__(self, requests_per_minute: int = 60, requests_per_day: int = 10000):
self.rpm_limit = requests_per_minute
self.rpd_limit = requests_per_day
# เก็บ timestamp ของ request ล่าสุด
self.minute_requests = []
self.day_requests = []
# สำหรับ daily token limit
self.daily_token_limit = 10_000_000 # 10 ล้าน token ต่อวัน
self.daily_tokens_used = 0
self.last_reset = time.time()
self.lock = Lock()
def _reset_if_new_day(self):
"""รีเซ็ต counters ถ้าเป็นวันใหม่"""
current_time = time.time()
if current_time - self.last_reset >= 86400: # 24 ชั่วโมง
self.day_requests = []
self.daily_tokens_used = 0
self.last_reset = current_time
def _cleanup_old_requests(self):
"""ลบ request ที่เก่ากว่า 1 นาที"""
current_time = time.time()
cutoff = current_time - 60
self.minute_requests = [
ts for ts in self.minute_requests if ts > cutoff
]
def can_proceed(self, tokens_needed: int = 0) -> tuple[bool, str]:
"""ตรวจสอบว่าสามารถส่ง request ได้หรือไม่"""
with self.lock:
self._reset_if_new_day()
self._cleanup_old_requests()
current_time = time.time()
# ตรวจสอบ RPM
if len(self.minute_requests) >= self.rpm_limit:
oldest = min(self.minute_requests)
wait_time = 60 - (current_time - oldest)
return False, f"Rate limit: รอ {wait_time:.1f} วินาที (RPM: {self.rpm_limit})"
# ตรวจสอบ RPD
if len(self.day_requests) >= self.rpd_limit:
return False, f"Rate limit: เกิน RPD limit ({self.rpd_limit})"
# ตรวจสอบ daily token limit
if self.daily_tokens_used + tokens_needed > self.daily_token_limit:
return False, f"Token limit: เกิน daily limit ({self.daily_token_limit:,})"
return True, "OK"
def record_request(self, tokens_used: int = 0):
"""บันทึก request ที่ส่งไปแล้ว"""
with self.lock:
current_time = time.time()
self.minute_requests.append(current_time)
self.day_requests.append(current_time)
self.daily_tokens_used += tokens_used
def get_status(self) -> dict:
"""ดึงสถานะ rate limiter"""
with self.lock:
self._cleanup_old_requests()
return {
"requests_this_minute": len(self.minute_requests),
"rpm_limit": self.rpm_limit,
"rpm_remaining": self.rpm_limit - len(self.minute_requests),
"requests_today": len(self.day_requests),
"rpd_limit": self.rpd_limit,
"tokens_today": self.daily_tokens_used,
"daily_token_limit": self.daily_token_limit,
}
def with_rate_limit(rate_limiter: RateLimiter):
"""Decorator สำหรับจำกัด rate ก่อนเรียก API"""
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
can_proceed, message = rate_limiter.can_proceed()
if not can_proceed:
raise Exception(f"Rate limit exceeded: {message}")
return func(*args, **kwargs)
return wrapper
return decorator
ตัวอย่างการใช้งาน
limiter = RateLimiter(requests_per_minute=30, requests_per_day=5000)
can_do, msg = limiter.can_proceed(tokens_needed=5000)
print(f"สถานะ: {msg}")
print(f"รายละเอียด: {limiter.get_status()}")
ผนึกทุกอย่างเข้าด้วยกัน: AI Client พร้อมระบบควบคุม
import os
from typing import Optional, Dict, Any
import httpx
class HolySheepAIClient:
"""AI Client ที่มีระบบควบคุมค่าใช้จ่ายและ rate limiting ในตัว"""
BASE_URL = "https://api.holysheep.ai/v1"
def __init__(self, api_key: str, monthly_budget: float = 100.0):
self.api_key = api_key
self.cost_tracker = APICostTracker(monthly_budget=monthly_budget)
self.rate_limiter = RateLimiter(requests_per_minute=60)
self.client = httpx.Client(
base_url=self.BASE_URL,
headers={
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
},
timeout=30.0
)
def chat(self, model: str, messages: list,
max_tokens: int = 2048) -> Dict[str, Any]:
"""ส่ง chat request พร้อมตรวจสอบ limits"""
# ประมาณ token ล่วงหน้า (rough estimation)
estimated_tokens = sum(len(m.get('content', '')) for m in messages) * 2
# ตรวจสอบ rate limit
can_proceed, msg = self.rate_limiter.can_proceed(estimated_tokens)
if not can_proceed:
raise Exception(f"Cannot proceed: {msg}")
# ตรวจสอบ budget
status = self.cost_tracker.get_budget_status()
if status['remaining'] <= 0:
raise Exception(f"งบประมาณหมดแล้ว (${status['total_spent']:.2f} / ${status['monthly_budget']:.2f})")
try:
response = self.client.post("/chat/completions", json={
"model": model,
"messages": messages,
"max_tokens": max_tokens,
"temperature": 0.7
})
response.raise_for_status()
data = response.json()
# บันทึกการใช้งานจริง
usage = data.get('usage', {})
input_tokens = usage.get('prompt_tokens', 0)
output_tokens = usage.get('completion_tokens', 0)
self.cost_tracker.record_usage(model, input_tokens, output_tokens)
self.rate_limiter.record_request(input_tokens + output_tokens)
# ตรวจสอบ alert
alert = self.cost_tracker.check_and_alert()
if alert:
print(f"📢 {alert}") # หรือส่งไป Slack/Discord
return data
except httpx.HTTPStatusError as e:
if e.response.status_code == 429:
raise Exception("Rate limit exceeded - กรุณารอสักครู่")
elif e.response.status_code == 401:
raise Exception("API key ไม่ถูกต้อง - ตรวจสอบ key ที่ https://www.holysheep.ai")
else:
raise Exception(f"HTTP Error: {e}")
except Exception as e:
raise Exception(f"Request failed: {str(e)}")
def get_cost_report(self) -> Dict:
"""ดึงรายงานค่าใช้จ่าย"""
return {
**self.cost_tracker.get_budget_status(),
"rate_limiter": self.rate_limiter.get_status()
}
def close(self):
self.client.close()
=== ตัวอย่างการใช้งาน ===
if __name__ == "__main__":
# สร้าง client พร้อมงบประมาณ 100 ดอลลาร์ต่อเดือน
client = HolySheepAIClient(
api_key="YOUR_HOLYSHEEP_API_KEY", # แทนที่ด้วย key จริง
monthly_budget=100.0
)
try:
# ส่ง request
response = client.chat(
model="deepseek-v3.2", # โมเดลราคาถูกที่สุด
messages=[
{"role": "system", "content": "คุณเป็นผู้ช่วยภาษาไทย"},
{"role": "user", "content": "อธิบายเรื่อง AI API สั้นๆ"}
],
max_tokens=500
)
print(f"Response: {response['choices'][0]['message']['content']}")
print(f"\n💰 รายงานค่าใช้จ่าย: {client.get_cost_report()}")
except Exception as e:
print(f"❌ Error: {e}")
finally:
client.close()