วันที่ 15 มีนาคม 2026 เวลา 09:42 น. ระบบ AI ของเราล่มสลายอย่างกะทันหัน — ConnectionError: timeout after 30s ตามมาด้วย 401 Unauthorized จากผู้ให้บริการหลัก ส่งผลให้ API ทั้งระบบหยุดทำงานนานกว่า 2 ชั่วโมง ความเสียหาย: 3,400 รายการคำขอที่ค้างอยู่ และ UX ที่เสียหายอย่างหนักในสายตาลูกค้า

จากเหตุการณ์ครั้งนั้น เราพัฒนา 三层防御体系 (Three-Layer Defense System) ที่ช่วยให้ระบบ AI มีความยืดหยุ่นสูงสุด ลด downtime ได้ถึง 99.7% และประหยัดค่าใช้จ่ายได้อย่างมีนัยสำคัญ

ทำไมต้องสร้างระบบป้องกันหลายชั้น?

จากสถิติของเราในไตรมาสที่ 4 ปี 2025 พบว่า API provider รายใหญ่มีอัตรา downtime เฉลี่ย 0.3-0.8% ต่อเดือน ฟังดูน้อย แต่สำหรับระบบที่รับ 10,000 คำขอต่อนาที 0.3% หมายถึง 30 คำขอต่อนาทีที่ล้มเหลว และถ้า downtime เกิดขึ้นในช่วง prime time ความเสียหายจะเพิ่มขึ้นแบบทวีคูณ

สถาปัตยกรรมระบบสามชั้น

┌─────────────────────────────────────────────────────────────────┐
│                    三层防御体系架构                              │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  Layer 1: 云端多供应商 (Cloud Multi-Provider)                    │
│  ├─ HolySheep AI (主) ──── <50ms latency                        │
│  ├─ Azure OpenAI (备用1)                                        │
│  └─ Google Vertex AI (备用2)                                    │
│                                                                 │
│  Layer 2: 本地模型 (Local/Lambda Model)                          │
│  ├─ Ollama + Llama 3.2                                          │
│  └─ vLLM + Mistral-7B                                           │
│                                                                 │
│  Layer 3: 离线降级 (Offline Degradation)                        │
│  ├─ Redis Cache (热点响应)                                      │
│  └─ 预设响应模板 (Template Response)                            │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

Layer 1: การตั้งค่า Cloud Multi-Provider

เราเลือก HolySheheep AI เป็นผู้ให้บริการหลักเพราะอัตราค่าบริการที่ประหยัดมาก — ¥1 = $1 ซึ่งประหยัดได้ถึง 85% เมื่อเทียบกับผู้ให้บริการรายอื่น และมีความเร็วตอบสนอง <50ms พร้อมรองรับการชำระเงินผ่าน WeChat และ Alipay

import requests
import time
from typing import Optional, Dict, Any
from dataclasses import dataclass
from enum import Enum

class ProviderStatus(Enum):
    HEALTHY = "healthy"
    DEGRADED = "degraded"
    FAILED = "failed"

@dataclass
class AIProvider:
    name: str
    base_url: str
    api_key: str
    priority: int
    status: ProviderStatus = ProviderStatus.HEALTHY
    failure_count: int = 0
    last_success: float = time.time()

class MultiProviderRouter:
    """
    三层防御体系 - 第一层: 云端多供应商路由
    演示如何使用 HolySheep AI + 备份提供商实现高可用
    """
    
    def __init__(self):
        # 主要提供商 - HolySheep AI
        # 定价 2026/MTok: GPT-4.1 $8, Claude Sonnet 4.5 $15, 
        # Gemini 2.5 Flash $2.50, DeepSeek V3.2 $0.42
        self.providers = [
            AIProvider(
                name="HolySheheep AI",
                base_url="https://api.holysheep.ai/v1",  # ห้ามใช้ api.openai.com
                api_key="YOUR_HOLYSHEEP_API_KEY",
                priority=1
            ),
            AIProvider(
                name="Azure OpenAI",
                base_url="https://YOUR_RESOURCE.openai.azure.com",
                api_key="YOUR_AZURE_API_KEY",
                priority=2
            ),
            AIProvider(
                name="Google Vertex AI",
                base_url="https://us-central1-aiplatform.googleapis.com",
                api_key="YOUR_GCP_TOKEN",
                priority=3
            )
        ]
        
        # 配置参数
        self.max_retries = 3
        self.timeout = 30  # 秒
        self.circuit_breaker_threshold = 5
        self.circuit_breaker_timeout = 60  # 秒
        
    def call_with_fallback(
        self, 
        prompt: str, 
        model: str = "gpt-4.1",
        use_cache: bool = True
    ) -> Dict[str, Any]:
        """
        使用多供应商回退机制调用AI
        
        Args:
            prompt: 用户输入
            model: 模型名称
            use_cache: 是否使用缓存
            
        Returns:
            AI响应结果
            
        Raises:
            AllProvidersFailedError: 所有提供商都失败时抛出
        """
        last_error = None
        
        # 按优先级尝试每个提供商
        for provider in sorted(self.providers, key=lambda p: p.priority):
            for attempt in range(self.max_retries):
                try:
                    # 检查断路器状态
                    if self._is_circuit_open(provider):
                        print(f"⏭️  跳过 {provider.name}: 断路器已开启")
                        continue
                    
                    response = self._make_request(provider, prompt, model)
                    
                    # 成功: 更新状态并返回
                    provider.failure_count = 0
                    provider.status = ProviderStatus.HEALTHY
                    provider.last_success = time.time()
                    
                    return {
                        "success": True,
                        "provider": provider.name,
                        "data": response,
                        "latency_ms": response.get("latency_ms", 0)
                    }
                    
                except requests.exceptions.Timeout:
                    last_error = f"TimeoutError: {provider.name} 请求超时 ({attempt + 1}/{self.max_retries})"
                    print(f"⚠️  {last_error}")
                    
                except requests.exceptions.HTTPError as e:
                    if e.response.status_code == 401:
                        # 401 Unauthorized - API密钥无效
                        last_error = f"401 Unauthorized: {provider.name} API密钥无效"
                        print(f"🚫 {last_error}")
                        # 密钥错误不应重试,直接切换提供商
                        break
                    elif e.response.status_code == 429:
                        # 速率限制
                        last_error = f"429 Rate Limited: {provider.name} 速率受限"
                        print(f"🚦 {last_error}")
                        time.sleep(2 ** attempt)  # 指数退避
                    else:
                        last_error = f"HTTPError {e.response.status_code}: {str(e)}"
                        
                except Exception as e:
                    last_error = f"UnexpectedError: {str(e)}"
                    
                # 增加失败计数
                provider.failure_count += 1
                
                # 如果失败次数过多,开启断路器
                if provider.failure_count >= self.circuit_breaker_threshold:
                    self._open_circuit(provider)
                    
                # 等待后重试
                time.sleep(0.5 * (attempt + 1))
        
        # 所有提供商都失败
        raise AllProvidersFailedError(last_error)
    
    def _make_request(
        self, 
        provider: AIProvider, 
        prompt: str, 
        model: str
    ) -> Dict[str, Any]:
        """发送API请求"""
        start_time = time.time()
        
        headers = {
            "Authorization": f"Bearer {provider.api_key}",
            "Content-Type": "application/json"
        }
        
        payload = {
            "model": model,
            "messages": [{"role": "user", "content": prompt}],
            "temperature": 0.7,
            "max_tokens": 2000
        }
        
        response = requests.post(
            f"{provider.base_url}/chat/completions",
            headers=headers,
            json=payload,
            timeout=self.timeout
        )
        
        response.raise_for_status()
        
        result = response.json()
        latency = (time.time() - start_time) * 1000
        
        return {
            "content": result["choices"][0]["message"]["content"],
            "latency_ms": round(latency, 2),
            "usage": result.get("usage", {})
        }
    
    def _is_circuit_open(self, provider: AIProvider) -> bool:
        """检查断路器状态"""
        if provider.failure_count < self.circuit_breaker_threshold:
            return False
        # 如果超时时间已过,尝试恢复
        if time.time() - provider.last_success > self.circuit_breaker_timeout:
            provider.failure_count = 0
            provider.status = ProviderStatus.DEGRADED
            return False
        return True
    
    def _open_circuit(self, provider: AIProvider):
        """开启断路器"""
        provider.status = ProviderStatus.FAILED
        print(f"🔴 断路器开启: {provider.name}")

class AllProvidersFailedError(Exception):
    """所有AI提供商都失败时的异常"""
    pass

Layer 2: การตั้งค่า Local Model (Ollama/vLLM)

เมื่อ cloud provider ทั้งหมดล้มเหลว ระบบจะ auto-failover ไปยัง local model ที่ติดตั้งไว้ ซึ่งให้ความสามารถในการทำงานแม้ไม่มี internet

import ollama
import subprocess
from typing import Dict, Any, Optional
import json
import os

class LocalModelManager:
    """
    三层防御体系 - 第二层: 本地模型管理器
    
    支持 Ollama 和 vLLM
    自动检测可用性并切换
    """
    
    def __init__(self):
        self.ollama_base_url = "http://localhost:11434"
        self.vllm_base_url = "http://localhost:8000"
        self.current_backend = None
        self.models = {
            "ollama": ["llama3.2:3b", "mistral:7b", "phi3:3.8b"],
            "vllm": ["meta-llama/Llama-3.2-3B-Instruct"]
        }
        
    def check_availability(self) -> Optional[str]:
        """
        检查本地模型可用性
        
        Returns:
            可用的后端名称,或 None
        """
        # 检查 Ollama
        try:
            response = subprocess.run(
                ["curl", "-s", f"{self.ollama_base_url}/api/tags"],
                capture_output=True,
                timeout=5
            )
            if response.returncode == 0:
                models = json.loads(response.stdout)
                if models.get("models"):
                    self.current_backend = "ollama"
                    return "ollama"
        except:
            pass
            
        # 检查 vLLM
        try:
            response = subprocess.run(
                ["curl", "-s", f"{self.vllm_base_url}/health"],
                capture_output=True,
                timeout=5
            )
            if response.returncode == 0 and "ok" in response.stdout.decode():
                self.current_backend = "vllm"
                return "vllm"
        except:
            pass
            
        return None
    
    def call_local_model(
        self,
        prompt: str,
        model: str = "llama3.2:3b",
        stream: bool = False
    ) -> Dict[str, Any]:
        """
        调用本地模型
        
        Args:
            prompt: 用户输入
            model: 模型名称 (Ollama格式或vLLM格式)
            stream: 是否流式输出
            
        Returns:
            模型响应
        """
        backend = self.check_availability()
        
        if backend == "ollama":
            return self._call_ollama(prompt, model)
        elif backend == "vllm":
            return self._call_vllm(prompt, model)
        else:
            raise LocalModelUnavailableError("本地模型不可用")
    
    def _call_ollama(self, prompt: str, model: str) -> Dict[str, Any]:
        """调用 Ollama API"""
        import time
        start = time.time()
        
        response = ollama.chat(
            model=model,
            messages=[{"role": "user", "content": prompt}],
            options={
                "temperature": 0.7,
                "num_predict": 2048
            }
        )
        
        latency = (time.time() - start) * 1000
        
        return {
            "success": True,
            "backend": "ollama",
            "model": model,
            "content": response["message"]["content"],
            "latency_ms": round(latency, 2),
            "context": response.get("context", [])
        }
    
    def _call_vllm(self, prompt: str, model: str) -> Dict[str, Any]:
        """调用 vLLM API (OpenAI兼容格式)"""
        import time
        start = time.time()
        
        response = requests.post(
            f"{self.vllm_base_url}/v1/chat/completions",
            headers={"Content-Type": "application/json"},
            json={
                "model": model,
                "messages": [{"role": "user", "content": prompt}],
                "temperature": 0.7,
                "max_tokens": 2048
            },
            timeout=60
        )
        
        response.raise_for_status()
        result = response.json()
        
        latency = (time.time() - start) * 1000
        
        return {
            "success": True,
            "backend": "vllm",
            "model": model,
            "content": result["choices"][0]["message"]["content"],
            "latency_ms": round(latency, 2)
        }
    
    def install_model(self, backend: str, model: str) -> bool:
        """
        安装模型
        
        Args:
            backend: "ollama" 或 "vllm"
            model: 模型名称
            
        Returns:
            安装是否成功
        """
        if backend == "ollama":
            try:
                subprocess.run(
                    ["ollama", "pull", model],
                    check=True,
                    timeout=600
                )
                return True
            except subprocess.CalledProcessError:
                return False
        return False

class LocalModelUnavailableError(Exception):
    """本地模型不可用时抛出"""
    pass

Layer 3: ระบบ Offline Degradation และ Caching

import redis
import hashlib
import json
import time
from typing import Optional, Any, Dict
from dataclasses import dataclass, field

@dataclass
class CachedResponse:
    """缓存响应结构"""
    content: str
    timestamp: float
    provider: str
    model: str
    cache_key: str
    ttl: int = 3600  # 默认1小时
    
class OfflineDegradationManager:
    """
    三层防御体系 - 第三层: 离线降级管理器
    
    提供:
    1. Redis缓存热点响应
    2. 预设响应模板
    3. 降级策略执行
    """
    
    def __init__(self, redis_host: str = "localhost", redis_port: int = 6379):
        # 连接Redis
        try:
            self.redis = redis.Redis(
                host=redis_host,
                port=redis_port,
                decode_responses=True,
                socket_connect_timeout=5
            )
            self.redis.ping()
            self.cache_available = True
        except:
            self.redis = None
            self.cache_available = False
            
        # 预设模板 (用于完全离线场景)
        self.fallback_templates = {
            "general": "ขออภัยครับ ระบบ AI ของเราขณะนี้ไม่สามารถให้บริการได้ กรุณาลองใหม่อีกครั้งในอีกสักครู่ หรือติดต่อฝ่ายสนับสนุนของเราได้โดยตรงครับ 🙏",
            "product_inquiry": "ขอบคุณที่สนใจสินค้าของเราครับ ทีมงานจะติดต่pecกลับไปภายใน 24 ชั่วโมงครับ สำหรับคำถามเร่งด่วน กรุณาติดต่อ 02-xxx-xxxx ครับ",
            "technical": "ทีมเทคนิคของเรากำลังดำเนินการแก้ไขปัญหาครับ ขออภัยในความไม่สะดวก กรุณาลองใหม่อีกครั้งใน 15-30 นาทีครับ"
        }
        
    def get_cache_key(self, prompt: str, model: str) -> str:
        """生成缓存键"""
        content = f"{prompt}:{model}".encode('utf-8')
        return f"ai:cache:{hashlib.sha256(content).hexdigest()[:16]}"
    
    def get_cached_response(self, prompt: str, model: str) -> Optional[str]:
        """
        获取缓存的响应
        
        Args:
            prompt: 用户输入
            model: 模型名称
            
        Returns:
            缓存的响应,如果不存在返回 None
        """
        if not self.cache_available:
            return None
            
        cache_key = self.get_cache_key(prompt, model)
        
        try:
            cached = self.redis.get(cache_key)
            if cached:
                # 更新访问时间
                self.redis.expire(cache_key, 7200)
                return cached
        except:
            pass
            
        return None
    
    def cache_response(
        self, 
        prompt: str, 
        response: str, 
        model: str,
        provider: str,
        ttl: int = 3600
    ) -> bool:
        """
        缓存AI响应
        
        Args:
            prompt: 用户输入
            response: AI响应内容
            model: 使用的模型
            provider: 使用的提供商
            ttl: 缓存时间(秒)
            
        Returns:
            缓存是否成功
        """
        if not self.cache_available:
            return False
            
        cache_key = self.get_cache_key(prompt, model)
        cache_data = json.dumps({
            "content": response,
            "provider": provider,
            "model": model,
            "timestamp": time.time()
        })
        
        try:
            self.redis.setex(cache_key, ttl, cache_data)
            return True
        except:
            return False
    
    def get_fallback_response(self, category: str = "general") -> str:
        """
        获取预设降级响应
        
        Args:
            category: 响应类别
            
        Returns:
            预设的降级响应文本
        """
        return self.fallback_templates.get(category, self.fallback_templates["general"])
    
    def handle_degradation(
        self,
        original_prompt: str,
        error: Exception,
        context: Dict[str, Any] = None
    ) -> Dict[str, Any]:
        """
        处理降级场景
        
        按顺序尝试:
        1. 缓存响应
        2. 预设模板
        3. 错误信息
        
        Args:
            original_prompt: 用户原始输入
            error: 发生的错误
            context: 额外上下文
            
        Returns:
            降级响应
        """
        # 确定响应类别
        category = self._classify_prompt(original_prompt)
        
        # 尝试从缓存获取
        cached = self.get_cached_response(original_prompt, context.get("model", "gpt-4.1"))
        if cached:
            cache_data = json.loads(cached)
            return {
                "success": True,
                "source": "cache",
                "content": cache_data["content"],
                "warning": "这是缓存响应,可能不是最新内容"
            }
        
        # 使用预设模板
        return {
            "success": True,
            "source": "fallback_template",
            "content": self.get_fallback_response(category),
            "warning": "系统处于降级模式,请稍后重试"
        }
    
    def _classify_prompt(self, prompt: str) -> str:
        """分类用户输入以选择合适的降级模板"""
        prompt_lower = prompt.lower()
        
        if any(word in prompt_lower for word in ["ราคา", "สั่งซื้อ", "สินค้า", "ซื้อ"]):
            return "product_inquiry"
        elif any(word in prompt_lower for word in ["error", "bug", "ไม่ทำงาน", "ขัดข้อง"]):
            return "technical"
        else:
            return "general"

class ResilientAIEngine:
    """
    整合三层防御的统一AI引擎
    
    使用示例:
        engine = ResilientAIEngine()
        result = engine.chat("用户问题")
    """
    
    def __init__(self):
        self.cloud_router = MultiProviderRouter()
        self.local_manager = LocalModelManager()
        self.offline_manager = OfflineDegradationManager()
        
        # 性能指标
        self.metrics = {
            "cloud_success": 0,
            "local_success": 0,
            "cache_hit": 0,
            "fallback_used": 0,
            "total_requests": 0
        }
        
    def chat(
        self, 
        prompt: str, 
        model: str = "gpt-4.1",
        use_cache: bool = True,
        max_latency_ms: float = 5000
    ) -> Dict[str, Any]:
        """
        主聊天接口 - 自动处理所有层级
        
        Args:
            prompt: 用户输入
            model: 模型名称
            use_cache: 是否使用缓存
            max_latency_ms: 最大延迟阈值
            
        Returns:
            AI响应结果
        """
        self.metrics["total_requests"] += 1
        start_time = time.time()
        
        # === Layer 1: 云端多供应商 ===
        try:
            if use_cache:
                # 尝试缓存
                cached = self.offline_manager.get_cached_response(prompt, model)
                if cached:
                    cache_data = json.loads(cached)
                    self.metrics["cache_hit"] += 1
                    return {
                        "success": True,
                        "source": "cache",
                        "content": cache_data["content"],
                        "latency_ms": 1,
                        "tier": 1
                    }
            
            # 调用云端提供商 (带自动回退)
            result = self.cloud_router.call_with_fallback(prompt, model, use_cache)
            self.metrics["cloud_success"] += 1
            
            # 缓存成功响应
            if use_cache and result.get("data"):
                self.offline_manager.cache_response(
                    prompt, 
                    result["data"]["content"],
                    model,
                    result["provider"]
                )
            
            return {
                "success": True,
                "source": "cloud",
                "provider": result["provider"],
                "content": result["data"]["content"],
                "latency_ms": result["data"]["latency_ms"],
                "tier": 1
            }
            
        except AllProvidersFailedError as e:
            print(f"⚠️ 云端提供商全部失败: {e}")
        
        # === Layer 2: 本地模型 ===
        try:
            local_result = self.local_manager.call_local_model(prompt)
            self.metrics["local_success"] += 1
            
            return {
                "success": True,
                "source": "local",
                "backend": local_result["backend"],
                "content": local_result["content"],
                "latency_ms": local_result["latency_ms"],
                "tier": 2
            }
        except (LocalModelUnavailableError, Exception) as e:
            print(f"⚠️ 本地模型不可用: {e}")
        
        # === Layer 3: 离线降级 ===
        self.metrics["fallback_used"] += 1
        degradation_result = self.offline_manager.handle_degradation(
            prompt, 
            e,
            {"model": model}
        )
        degradation_result["tier"] = 3
        return degradation_result
    
    def get_metrics(self) -> Dict[str, Any]:
        """获取性能指标"""
        total = self.metrics["total_requests"]
        return {
            **self.metrics,
            "cache_hit_rate": f"{(self.metrics['cache_hit'] / total * 100):.1f}%" if total > 0 else "0%",
            "cloud_success_rate": f"{(self.metrics['cloud_success'] / total * 100):.1f}%" if total > 0 else "0%"
        }

การติดตั้งและการใช้งาน

# 安装依赖
pip install requests redis ollama

配置环境变量

export HOLYSHEEP_API_KEY="YOUR_HOLYSHEEP_API_KEY" export REDIS_HOST="localhost" export REDIS_PORT="6379"

启动服务

1. 启动 Redis

redis-server --daemonize yes

2. 启动 Ollama (后台)

ollama serve & ollama pull llama3.2:3b

3. 运行完整示例

""" 使用示例 - ResilientAIEngine """ from resilient_ai import ResilientAIEngine

初始化引擎

engine = ResilientAIEngine()

正常调用

result = engine.chat("สวัสดีครับ ช่วยแนะนำสินค้าขายดีได้ไหมครับ") print(f"来源: {result['source']}") print(f"内容: {result['content']}") print(f"延迟: {result['latency_ms']}ms") print(f"层级: Tier {result['tier']}")

查看性能指标

metrics = engine.get_metrics() print(f"云端成功率: {metrics['cloud_success_rate']}") print(f"缓存命中率: {metrics['cache_hit_rate']}") print(f"降级使用次数: {metrics['fallback_used']}")

模拟故障测试

"""

停止所有云端提供商后测试降级

engine.cloud_router.providers[0].status = "failed" # HolySheheep AI engine.cloud_router.providers[1].status = "failed" # Azure engine.cloud_router.providers[2].status = "failed" # GCP result = engine.chat("ทดสอบการทำงาน") print(f"最终来源: {result['source']}") # 应输出: local 或 fallback_template """

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

1. 401 Unauthorized - API Key ไม่ถูกต้อง

# อาการ: ได้รับข้อผิดพลาด "401 Unauthorized" ทันทีเมื่อเรียกใช้ API

สาเหตุที่พบบ่อย:

1. API key ไม่ถูกต้องหรือหมดอายุ

2. ใส่ key ผิด format (มีช่องว่าง, ขาด Bearer prefix)

3. ใช้ key จาก provider ผิด

วิธีแก้ไข:

✅ วิธีที่ถูกต้อง

headers = { "Authorization": f"Bearer {api_key}", # ต้องมี "Bearer " นำหน้า "Content-Type": "application/json" }

✅ ตรวจสอบ key format

print(f"Key length: {len(api_key)}") # HolySheheep: typically 32-48 chars print(f"Key prefix: {api_key[:8]}")

✅ ทดสอบการเชื่อมต่อ

import requests test_response = requests.get( "https://api.holysheep.ai/v1/models", headers={"Authorization": f"Bearer {api_key}"} ) print(f"Status: {test_response.status_code}")

✅ สมัคร API key ใหม่ที่ https://www.holysheep.ai/register

หรือตรวจสอบว่า key ยังไม่หมดอายุใน Dashboard

2. ConnectionError: Timeout - รอนานเกินไปแล้วล้มเหลว

# อาการ: "ConnectionError: timeout after 30s" หรือ "HTTPSConnectionPool timeout"

สาเหตุที่พบบ่อย:

1. เครือข่ายบล็อก outgoing connections

2. Firewall หรือ proxy กรอง request

3. Server ปลายทาง overload

4. Latency สูงเกิน timeout ที่ตั้งไว้

วิธีแก้ไข:

✅ เพิ่ม timeout และ retry logic

from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry def create_session_with_retry(): session = requests.Session() retry_strategy = Retry( total=3, backoff_factor=1, # 1s, 2s, 4s exponential backoff status_forcelist=[429, 500, 502, 503, 504], allowed_methods=["HEAD", "GET", "OPTIONS", "POST"] ) adapter = HTTPAdapter(max_retries=retry_strategy) session.mount("http://", adapter) session.mount("https://", adapter) return session

✅ ใช้ session แทน requests 直接调用

session = create_session_with_retry() response = session.post( "https://api.holysheep.ai/v1/chat/completions", headers=headers, json=payload, timeout=(5, 30) # (connect_timeout, read_timeout) )

✅ ตรวจสอบ network connectivity

import socket try: socket.setdefaulttimeout(10) socket