การจัดการ API Key Scope Limitations เป็นหัวใจสำคัญของการ Deploy ระบบ AI ในระดับ Production โดยเฉพาะเมื่อต้องควบคุมการใช้งานของผู้ใช้หลายรายบนแพลตฟอร์มเดียว บทความนี้จะพาคุณสร้างระบบ Scope ที่ครอบคลุม ตั้งแต่พื้นฐานจนถึง Advanced Use Cases โดยใช้ HolySheep AI เป็นตัวอย่างหลัก

ทำไมต้อง Implement API Key Scope Limitations

ในการพัฒนา SaaS ที่ใช้ AI คุณต้องควบคุมหลายปัจจัย:

Architecture ของระบบ Scope Limitations

ระบบ Scope ที่ดีต้องมี 4 ชั้นหลัก:

Implementation ด้วย Python + HolySheep API

ด้านล่างคือตัวอย่างการสร้าง API Key Scope Manager ที่ใช้งานได้จริง:

import httpx
import time
import hashlib
from dataclasses import dataclass, field
from typing import Optional, List, Dict
from datetime import datetime, timedelta
import json

@dataclass
class APIKeyScope:
    """โครงสร้างข้อมูล Scope สำหรับ API Key"""
    key_id: str
    scopes: List[str] = field(default_factory=list)
    daily_limit: int = 10000  # token ต่อวัน
    monthly_limit: int = 100000
    allowed_models: List[str] = field(default_factory=list)
    rate_limit_per_minute: int = 60
    current_daily_usage: int = 0
    current_monthly_usage: int = 0
    last_reset: datetime = field(default_factory=datetime.now)
    
class HolySheepScopeManager:
    """ตัวจัดการ Scope Limitations สำหรับ HolySheep AI"""
    
    BASE_URL = "https://api.holysheep.ai/v1"
    
    def __init__(self, master_key: str):
        self.master_key = master_key
        self.client = httpx.Client(timeout=30.0)
        self.scopes: Dict[str, APIKeyScope] = {}
        self.request_history: Dict[str, List[float]] = {}
        
    def create_scoped_key(
        self,
        key_id: str,
        allowed_models: List[str],
        daily_limit: int = 10000,
        monthly_limit: int = 100000
    ) -> APIKeyScope:
        """สร้าง API Key ใหม่พร้อมกำหนด Scope"""
        
        scope = APIKeyScope(
            key_id=key_id,
            scopes=["chat:read", "chat:write"],
            daily_limit=daily_limit,
            monthly_limit=monthly_limit,
            allowed_models=allowed_models,
            rate_limit_per_minute=60
        )
        
        self.scopes[key_id] = scope
        self.request_history[key_id] = []
        
        print(f"✅ สร้าง Scoped Key: {key_id}")
        print(f"   โมเดลที่อนุญาต: {', '.join(allowed_models)}")
        print(f"   วงเงินรายวัน: {daily_limit:,} tokens")
        print(f"   วงเงินรายเดือน: {monthly_limit:,} tokens")
        
        return scope
    
    def validate_request(self, key_id: str, model: str, estimated_tokens: int) -> tuple[bool, str]:
        """ตรวจสอบคำขอก่อนส่งไปยัง API"""
        
        if key_id not in self.scopes:
            return False, "API Key ไม่ถูกต้อง"
        
        scope = self.scopes[key_id]
        
        # ตรวจสอบการ reset รายวัน
        if datetime.now() - scope.last_reset > timedelta(days=1):
            scope.current_daily_usage = 0
            scope.last_reset = datetime.now()
            print(f"🔄 Reset Daily Quota สำหรับ {key_id}")
        
        # ตรวจสอบ Rate Limit
        current_time = time.time()
        self.request_history[key_id] = [
            t for t in self.request_history[key_id]
            if current_time - t < 60
        ]
        
        if len(self.request_history[key_id]) >= scope.rate_limit_per_minute:
            return False, f"Rate Limit: เกิน {scope.rate_limit_per_minute} requests/นาที"
        
        # ตรวจสอบโมเดล
        if model not in scope.allowed_models:
            return False, f"โมเดล '{model}' ไม่อยู่ใน Scope ที่อนุญาต"
        
        # ตรวจสอบ Quota
        if scope.current_daily_usage + estimated_tokens > scope.daily_limit:
            return False, f"Daily Quota เกิน ({scope.current_daily_usage}/{scope.daily_limit})"
        
        if scope.current_monthly_usage + estimated_tokens > scope.monthly_limit:
            return False, f"Monthly Quota เกิน ({scope.current_monthly_usage}/{scope.monthly_limit})"
        
        self.request_history[key_id].append(current_time)
        return True, "OK"
    
    def execute_chat_completion(
        self,
        key_id: str,
        model: str,
        messages: List[Dict],
        temperature: float = 0.7,
        max_tokens: int = 2048
    ) -> Dict:
        """ส่ง request ไปยัง HolySheep AI พร้อม Scope Validation"""
        
        # Estimate tokens (rough calculation)
        estimated_tokens = sum(len(str(m)) for m in messages) + max_tokens
        
        # Validate
        is_valid, error_msg = self.validate_request(key_id, model, estimated_tokens)
        
        if not is_valid:
            return {
                "error": True,
                "message": error_msg,
                "key_id": key_id,
                "timestamp": datetime.now().isoformat()
            }
        
        # Execute request
        headers = {
            "Authorization": f"Bearer {self.master_key}",
            "Content-Type": "application/json"
        }
        
        payload = {
            "model": model,
            "messages": messages,
            "temperature": temperature,
            "max_tokens": max_tokens
        }
        
        try:
            response = self.client.post(
                f"{self.BASE_URL}/chat/completions",
                headers=headers,
                json=payload
            )
            response.raise_for_status()
            result = response.json()
            
            # Update usage
            usage = result.get("usage", {})
            tokens_used = usage.get("total_tokens", estimated_tokens)
            
            self.scopes[key_id].current_daily_usage += tokens_used
            self.scopes[key_id].current_monthly_usage += tokens_used
            
            # Log
            self._log_request(key_id, model, tokens_used)
            
            return {
                "error": False,
                "data": result,
                "usage": tokens_used,
                "remaining_daily": self.scopes[key_id].daily_limit - self.scopes[key_id].current_daily_usage,
                "remaining_monthly": self.scopes[key_id].monthly_limit - self.scopes[key_id].current_monthly_usage
            }
            
        except httpx.HTTPStatusError as e:
            return {
                "error": True,
                "message": f"HTTP Error: {e.response.status_code}",
                "detail": e.response.text
            }
    
    def _log_request(self, key_id: str, model: str, tokens: int):
        """บันทึก Log การใช้งาน"""
        log_entry = {
            "timestamp": datetime.now().isoformat(),
            "key_id": key_id,
            "model": model,
            "tokens": tokens
        }
        print(f"📊 {log_entry['timestamp']} | {key_id} | {model} | {tokens} tokens")
    
    def get_scope_status(self, key_id: str) -> Dict:
        """ดึงสถานะ Scope ปัจจุบัน"""
        if key_id not in self.scopes:
            return {"error": "Key ไม่พบ"}
        
        scope = self.scopes[key_id]
        return {
            "key_id": key_id,
            "daily_usage": scope.current_daily_usage,
            "daily_limit": scope.daily_limit,
            "daily_remaining": scope.daily_limit - scope.current_daily_usage,
            "monthly_usage": scope.current_monthly_usage,
            "monthly_limit": scope.monthly_limit,
            "monthly_remaining": scope.monthly_limit - scope.current_monthly_usage,
            "allowed_models": scope.allowed_models,
            "rate_limit_per_minute": scope.rate_limit_per_minute,
            "requests_last_minute": len(self.request_history.get(key_id, []))
        }


ตัวอย่างการใช้งาน

manager = HolySheepScopeManager("YOUR_HOLYSHEEP_API_KEY")

สร้าง Key สำหรับ Developer Tier

dev_scope = manager.create_scoped_key( key_id="dev_001", allowed_models=["gpt-4.1", "claude-sonnet-4.5", "gemini-2.5-flash"], daily_limit=50000, monthly_limit=500000 )

สร้าง Key สำหรับ Free Tier

free_scope = manager.create_scoped_key( key_id="free_001", allowed_models=["deepseek-v3.2", "gemini-2.5-flash"], daily_limit=5000, monthly_limit=50000 )

ทดสอบ request

messages = [{"role": "user", "content": "อธิบายเรื่อง API Scope"}] result = manager.execute_chat_completion( key_id="dev_001", model="gpt-4.1", messages=messages )

แสดงสถานะ

status = manager.get_scope_status("dev_001") print(f"\n📈 สถานะ: {json.dumps(status, indent=2, ensure_ascii=False)}")

Middleware สำหรับ FastAPI

หากคุณใช้ FastAPI เป็น Backend Framework ด้านล่างคือ Middleware ที่พร้อมใช้งาน:

from fastapi import FastAPI, HTTPException, Request, Depends
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from pydantic import BaseModel
from typing import Optional, List
import time
import jwt
from datetime import datetime, timedelta

app = FastAPI(title="AI API Gateway with Scope Control")
security = HTTPBearer()

class ScopeConfig(BaseModel):
    allowed_models: List[str]
    daily_token_limit: int
    monthly_token_limit: int
    rate_limit_rpm: int

class APIKeyPayload(BaseModel):
    sub: str  # user_id
    scopes: ScopeConfig
    exp: datetime

ฐานข้อมูล Scope (ใช้ Redis ใน Production)

scope_db = { "user_premium_001": ScopeConfig( allowed_models=["gpt-4.1", "claude-sonnet-4.5", "gemini-2.5-flash", "deepseek-v3.2"], daily_token_limit=500000, monthly_token_limit=5000000, rate_limit_rpm=120 ), "user_basic_001": ScopeConfig( allowed_models=["gemini-2.5-flash", "deepseek-v3.2"], daily_token_limit=50000, monthly_token_limit=500000, rate_limit_rpm=30 ), "user_free_001": ScopeConfig( allowed_models=["deepseek-v3.2"], daily_token_limit=5000, monthly_token_limit=50000, rate_limit_rpm=10 ) }

ติดตามการใช้งาน

usage_tracker = {} rate_limiter = {} def verify_api_key(credentials: HTTPAuthorizationCredentials = Depends(security)): """ตรวจสอบ API Key และ Decode JWT""" token = credentials.credentials try: # ใน Production ใช้ JWT library ที่เหมาะสม # ตัวอย่างนี้ใช้ decode อย่างง่าย payload = decode_jwt_token(token) if payload["exp"] < datetime.now().timestamp(): raise HTTPException(status_code=401, detail="Token หมดอายุ") return payload except Exception as e: raise HTTPException(status_code=401, detail=f"การยืนยันตัวตนล้มเหลว: {str(e)}") def decode_jwt_token(token: str) -> dict: """Decode JWT Token (ตัวอย่าง)""" # ใน Production ใช้ PyJWT: jwt.decode(token, SECRET, algorithms=["HS256"]) parts = token.split(".") if len(parts) != 3: raise ValueError("Invalid Token Format") # Decode payload (simplified) import base64 import json padding = 4 - len(parts[1]) % 4 if padding != 4: parts[1] += "=" * padding payload = json.loads(base64.urlsafe_b64decode(parts[1])) return payload def check_rate_limit(user_id: str, limit: int) -> bool: """ตรวจสอบ Rate Limit ต่อนาที""" current_time = time.time() if user_id not in rate_limiter: rate_limiter[user_id] = [] # ลบ request ที่เก่ากว่า 60 วินาที rate_limiter[user_id] = [ t for t in rate_limiter[user_id] if current_time - t < 60 ] if len(rate_limiter[user_id]) >= limit: return False rate_limiter[user_id].append(current_time) return True def check_quota(user_id: str, requested_tokens: int, scope: ScopeConfig) -> tuple[bool, str]: """ตรวจสอบ Quota รายวันและรายเดือน""" today = datetime.now().strftime("%Y-%m-%d") this_month = datetime.now().strftime("%Y-%m") if user_id not in usage_tracker: usage_tracker[user_id] = {"daily": {}, "monthly": {}} # Initialize if not exists if today not in usage_tracker[user_id]["daily"]: usage_tracker[user_id]["daily"][today] = 0 if this_month not in usage_tracker[user_id]["monthly"]: usage_tracker[user_id]["monthly"][this_month] = 0 daily_usage = usage_tracker[user_id]["daily"][today] monthly_usage = usage_tracker[user_id]["monthly"][this_month] if daily_usage + requested_tokens > scope.daily_token_limit: return False, f"เกินวงเงินรายวัน ({daily_usage}/{scope.daily_token_limit})" if monthly_usage + requested_tokens > scope.monthly_token_limit: return False, f"เกินวงเงินรายเดือน ({monthly_usage}/{scope.monthly_token_limit})" return True, "OK" @app.post("/v1/chat/completions") async def chat_completions( request: Request, payload: dict, auth: dict = Depends(verify_api_key) ): """Endpoint หลักสำหรับ Chat Completions""" user_id = auth["sub"] model = payload.get("model", "") messages = payload.get("messages", []) # ตรวจสอบ Scope if user_id not in scope_db: raise HTTPException(status_code=403, detail="ไม่พบ Scope สำหรับผู้ใช้นี้") scope = scope_db[user_id] # 1. ตรวจสอบ Rate Limit if not check_rate_limit(user_id, scope.rate_limit_rpm): raise HTTPException( status_code=429, detail=f"Rate Limit: เกิน {scope.rate_limit_rpm} requests/นาที" ) # 2. ตรวจสอบโมเดลที่อนุญาต if model not in scope.allowed_models: raise HTTPException( status_code=403, detail=f"โมเดล '{model}' ไม่อยู่ใน Scope ที่อนุญาต. อนุญาต: {scope.allowed_models}" ) # 3. ประมาณการ tokens estimated_tokens = sum(len(str(m.get("content", ""))) for m in messages) estimated_tokens += payload.get("max_tokens", 2048) # 4. ตรวจสอบ Quota is_valid, msg = check_quota(user_id, estimated_tokens, scope) if not is_valid: raise HTTPException(status_code=402, detail=msg) # 5. ส่งต่อไปยัง HolySheep API import httpx async with httpx.AsyncClient(timeout=30.0) as client: response = await client.post( "https://api.holysheep.ai/v1/chat/completions", headers={ "Authorization": f"Bearer YOUR_HOLYSHEEP_API_KEY", "Content-Type": "application/json" }, json=payload ) if response.status_code != 200: raise HTTPException(status_code=response.status_code, detail=response.text) result = response.json() # 6. อัปเดต Usage actual_tokens = result.get("usage", {}).get("total_tokens", estimated_tokens) today = datetime.now().strftime("%Y-%m-%d") this_month = datetime.now().strftime("%Y-%m") usage_tracker[user_id]["daily"][today] += actual_tokens usage_tracker[user_id]["monthly"][this_month] += actual_tokens return result @app.get("/v1/scope/status") async def get_scope_status(auth: dict = Depends(verify_api_key)): """ดึงสถานะ Scope ของผู้ใช้ปัจจุบัน""" user_id = auth["sub"] if user_id not in scope_db: raise HTTPException(status_code=404, detail="ไม่พบ Scope") scope = scope_db[user_id] today = datetime.now().strftime("%Y-%m-%d") this_month = datetime.now().strftime("%Y-%m") daily_usage = usage_tracker.get(user_id, {}).get("daily", {}).get(today, 0) monthly_usage = usage_tracker.get(user_id, {}).get("monthly", {}).get(this_month, 0) return { "user_id": user_id, "allowed_models": scope.allowed_models, "daily": { "used": daily_usage, "limit": scope.daily_token_limit, "remaining": scope.daily_token_limit - daily_usage }, "monthly": { "used": monthly_usage, "limit": scope.monthly_token_limit, "remaining": scope.monthly_token_limit - monthly_usage }, "rate_limit": { "per_minute": scope.rate_limit_rpm, "current_count": len(rate_limiter.get(user_id, [])) } } if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000)

การ Monitoring และ Alerting

ระบบ Scope ที่ดีต้องมี Dashboard สำหรับติดตามการใช้งานแบบ Real-time:

import asyncio
from datetime import datetime
from collections import defaultdict
import json

class ScopeMonitor:
    """ระบบ Monitoring สำหรับ API Key Scopes"""
    
    def __init__(self):
        self.metrics = defaultdict(lambda: {
            "total_requests": 0,
            "total_tokens": 0,
            "successful_requests": 0,
            "failed_requests": 0,
            "cost_by_model": defaultdict(float),
            "hourly_usage": defaultdict(int),
            "error_types": defaultdict(int)
        })
        
        # ราคาต่อ 1M tokens (อ้างอิงจาก HolySheep 2026)
        self.pricing = {
            "gpt-4.1": 8.0,              # $8/M tokens
            "claude-sonnet-4.5": 15.0,   # $15/M tokens
            "gemini-2.5-flash": 2.50,    # $2.50/M tokens
            "deepseek-v3.2": 0.42        # $0.42/M tokens
        }
    
    def record_request(
        self,
        key_id: str,
        model: str,
        tokens: int,
        success: bool,
        error_type: str = None
    ):
        """บันทึก metrics ของ request"""
        m = self.metrics[key_id]
        m["total_requests"] += 1
        m["total_tokens"] += tokens
        m["hourly_usage"][datetime.now().strftime("%Y-%m-%d %H:00")] += tokens
        
        if success:
            m["successful_requests"] += 1
            # คำนวณค่าใช้จ่าย
            cost = (tokens / 1_000_000) * self.pricing.get(model, 0)
            m["cost_by_model"][model] += cost
        else:
            m["failed_requests"] += 1
            if error_type:
                m["error_types"][error_type] += 1
    
    def get_dashboard_data(self, key_id: str) -> dict:
        """สร้างข้อมูลสำหรับ Dashboard"""
        m = self.metrics[key_id]
        
        total_cost = sum(m["cost_by_model"].values())
        success_rate = (
            m["successful_requests"] / m["total_requests"] * 100
            if m["total_requests"] > 0 else 0
        )
        
        # หา peak hour
        peak_hour = max(
            m["hourly_usage"].items(),
            key=lambda x: x[1],
            default=("N/A", 0)
        )
        
        return {
            "key_id": key_id,
            "summary": {
                "total_requests": m["total_requests"],
                "total_tokens": m["total_tokens"],
                "total_cost_usd": round(total_cost, 4),
                "success_rate": round(success_rate, 2)
            },
            "cost_by_model": dict(m["cost_by_model"]),
            "hourly_usage": dict(m["hourly_usage"]),
            "error_summary": dict(m["error_types"]),
            "peak_hour": {"time": peak_hour[0], "tokens": peak_hour[1]}
        }
    
    def check_anomalies(self, key_id: str, threshold_tokens_per_minute: int = 10000):
        """ตรวจจับความผิดปกติ"""
        m = self.metrics[key_id]
        anomalies = []
        
        # ตรวจจับการใช้งานสูงผิดปกติ
        current_hour = datetime.now().strftime("%Y-%m-%d %H:00")
        if current_hour in m["hourly_usage"]:
            hourly_tokens = m["hourly_usage"][current_hour]
            if hourly_tokens > threshold_tokens_per_minute * 60:
                anomalies.append({
                    "type": "HIGH_USAGE",
                    "message": f"ใช้งานสูงผิดปกติ: {hourly_tokens} tokens ในชั่วโมงนี้",
                    "severity": "WARNING"
                })
        
        # ตรวจจับอัตราความล้มเหลวสูง
        if m["total_requests"] > 10:
            failure_rate = m["failed_requests"] / m["total_requests"]
            if failure_rate > 0.2:  # > 20%
                anomalies.append({
                    "type": "HIGH_FAILURE_RATE",
                    "message": f"อัตราความล้มเหลว: {failure_rate*100:.1f}%",
                    "severity": "CRITICAL"
                })
        
        return anomalies
    
    def generate_report(self, key_id: str) -> str:
        """สร้างรายงานแบบ Text"""
        data = self.get_dashboard_data(key_id)
        anomalies = self.check_anomalies(key_id)
        
        report = f"""
╔══════════════════════════════════════════════════════════════╗
║           API KEY SCOPE REPORT - {key_id:<20}         ║
╠══════════════════════════════════════════════════════════════╣
║  Total Requests:        {data['summary']['total_requests']:>10,}                           ║
║  Total Tokens:         {data['summary']['total_tokens']:>10,}                           ║
║  Total Cost (USD):     ${data['summary']['total_cost_usd']:>10.4f}                           ║
║  Success Rate:         {data['summary']['success_rate']:>10.1f}%                          ║
╠══════════════════════════════════════════════════════════════╣
║  COST BY MODEL                                               ║"""
        
        for model, cost in data["cost_by_model"].items():
            report += f"\n║  {model:<20}  ${cost:>10.4f}                       ║"
        
        report += """
╠══════════════════════════════════════════════════════════════╣
║  PEAK USAGE                                                   ║
║  Peak Hour: {time:<20} Tokens: {tokens:>10,}       ║
╚══════════════════════════════════════════════════════════════╝""".format(
            time=data["peak_hour"]["time"],
            tokens=data["peak_hour"]["tokens"]
        )
        
        if anomalies:
            report += "\n\n⚠️  ANOMALIES DETECTED:"
            for a in anomalies:
                report += f"\n  [{a['severity']}] {a['message']}"
        
        return report


ตัวอย่างการใช้งาน

monitor = ScopeMonitor()

จำลองข้อมูล

for i in range(100): monitor.record_request( key_id="dev_001", model=["gpt-4.1", "gemini-2.5-flash", "deepseek-v3.2"][i % 3], tokens=500 + (i * 10), success=(i % 10 != 0), error_type="TIMEOUT" if i % 20 == 0 else None )

แสดงรายงาน

print(monitor.generate_report("dev_001")) print("\n" + "="*60)

Dashboard JSON

dashboard = monitor.get_dashboard_data("dev_001") print(json.dumps(dashboard, indent=2, ensure_ascii=False))

ข้อผิดพลาดที่พบบ่อยและวิธีแก้ไข

1. Error 401: Authentication Failed

สาเหตุ: API Key ไม่ถูกต้องหรือหมดอายุ

# ❌ วิธีผิด - Hardcode API Key ในโค้ด
response = httpx.post(
    "https://api.holysheep.ai/v1/chat/completions",
    headers={"Authorization": "Bearer sk-1234567890"}
)

✅ วิธีถูก - ใช้ Environment Variable

import os API_KEY = os.environ.get("HOLYSHEEP_API_KEY") if not API_KEY: raise ValueError("HOLYSHEEP_API_KEY environment variable ไม่ได้กำหนดค่า") response = httpx.post( "https://api.holysheep.ai/v1/chat/completions", headers={"Authorization": f"Bearer {API_KEY}"} )

2. Error 429: Rate Limit Exceeded

สาเหตุ: ส่ง Request เกินจำนวนที่กำหนดต่อนาที

import time
import asyncio

✅ วิธีแก้ไข - Implement Retry with Exponential Backoff

async def call_with_retry(prompt: str, max_retries: int = 3): for attempt in range(max_retries): try: response = await httpx.AsyncClient().post( "https://api.holysheep.ai/v1/chat/completions", headers={"Authorization": f"Bearer {API_KEY}"}, json={"model": "gpt-4.1", "messages": [{"role": "user", "content": prompt}]} ) if response.status_code == 429: wait_time = 2 ** attempt # 1, 2, 4 วินาที print(f"Rate Limited. รอ {wait_time} วินาที...") await asyncio