Là tech lead của một startup AI tại Việt Nam, tôi đã trải qua hành trình 6 tháng debug latency, đau đầu với chi phí API, và cuối cùng tìm ra giải pháp tối ưu. Bài viết này là playbook thực chiến về cách thiết kế chức năng tìm kiếm AI API từ đầu, đồng thời chia sẻ kinh nghiệm di chuyển hệ thống sang HolySheep AI — nền tảng mà chúng tôi đã chọn sau khi so sánh kỹ lưỡng.

Vì Sao Chúng Tôi Cần Thiết Kế Lại Search API

Dự án ban đầu sử dụng relay API với latency trung bình 350ms, chi phí hàng tháng lên đến $2,400 cho 200 triệu tokens. Đội ngũ gặp 3 vấn đề lớn:

After 2 failed attempts với các giải pháp caching layer, chúng tôi quyết định migrate hoàn toàn sang HolySheep AI với cam kết latency dưới 50ms và chi phí chỉ bằng 15% so với original provider.

Kiến Trúc Tổng Quan

┌─────────────────────────────────────────────────────────────┐
│                    CLIENT APPLICATION                        │
├─────────────────────────────────────────────────────────────┤
│  ┌─────────────┐    ┌──────────────┐    ┌────────────────┐  │
│  │  Search UI  │───▶│  API Gateway │───▶│  Rate Limiter  │  │
│  └─────────────┘    └──────────────┘    └───────┬────────┘  │
├─────────────────────────────────────────────────┼────────────┤
│              APPLICATION LAYER                  │            │
│  ┌──────────────────────────────────────────────┴─────────┐  │
│  │              SearchService (Core Logic)                 │  │
│  │  ├─ QueryParser        ├─ EmbeddingGenerator           │  │
│  │  ├─ VectorSearch       ├─ ResultRanker                  │  │
│  │  └─ CacheManager       └─ FallbackHandler               │  │
│  └─────────────────────────────────────────────────────────┘  │
├───────────────────────────────────────────────────────────────┤
│                  AI PROVIDER LAYER                           │
│  ┌─────────────────────────────────────────────────────┐     │
│  │  HolySheep AI (https://api.holysheep.ai/v1)         │     │
│  │  ├─ Embedding: DeepSeek V3.2 @ $0.42/MTok          │     │
│  │  └─ Rerank: GPT-4.1 @ $8/MTok                      │     │
│  └─────────────────────────────────────────────────────┘     │
└───────────────────────────────────────────────────────────────┘

Bước 1: Cấu Hình HolySheep Client

HolySheep AI cung cấp API endpoint thống nhất cho nhiều model. Base URL chuẩn là https://api.holysheep.ai/v1. Dưới đây là implementation production-ready với error handling và retry logic.

import openai
import httpx
from typing import List, Dict, Optional
from dataclasses import dataclass
import asyncio

@dataclass
class HolySheepConfig:
    api_key: str
    base_url: str = "https://api.holysheep.ai/v1"
    timeout: float = 30.0
    max_retries: int = 3
    max_latency_ms: int = 50

class HolySheepSearchClient:
    """
    Production-ready client cho AI Search functionality.
    Tích hợp HolySheep AI với latency tracking và fallback.
    """
    
    def __init__(self, config: HolySheepConfig):
        self.config = config
        self.client = openai.OpenAI(
            api_key=config.api_key,
            base_url=config.base_url,
            timeout=httpx.Timeout(config.timeout),
            max_retries=config.max_retries
        )
        self._latency_history: List[float] = []
    
    async def generate_embeddings(
        self, 
        texts: List[str], 
        model: str = "deepseek-embed"
    ) -> List[List[float]]:
        """
        Generate embeddings sử dụng DeepSeek V3.2.
        Chi phí: $0.42/MTok — tiết kiệm 85% so với OpenAI.
        """
        import time
        start = time.perf_counter()
        
        try:
            response = self.client.embeddings.create(
                model=model,
                input=texts
            )
            
            latency_ms = (time.perf_counter() - start) * 1000
            self._latency_history.append(latency_ms)
            
            print(f"[HolySheep] Embedding latency: {latency_ms:.2f}ms")
            return [item.embedding for item in response.data]
            
        except Exception as e:
            print(f"[HolySheep] Embedding error: {e}")
            raise
    
    async def semantic_search(
        self,
        query: str,
        documents: List[str],
        top_k: int = 5
    ) -> List[Dict]:
        """
        Semantic search với reranking.
        Pipeline: Embed → Vector Search → Rerank với GPT-4.1
        """
        # Step 1: Embed query và documents
        query_embedding = await self.generate_embeddings([query])
        doc_embeddings = await self.generate_embeddings(documents)
        
        # Step 2: Cosine similarity (simplified)
        scores = self._cosine_similarity_batch(
            query_embedding[0], 
            doc_embeddings
        )
        
        # Step 3: Rerank top results với GPT-4.1
        top_indices = sorted(range(len(scores)), 
                            key=lambda i: scores[i], 
                            reverse=True)[:top_k]
        
        reranked = await self._rerank_results(
            query, 
            [documents[i] for i in top_indices],
            [scores[i] for i in top_indices]
        )
        
        return reranked
    
    async def _rerank_results(
        self, 
        query: str, 
        documents: List[str],
        initial_scores: List[float]
    ) -> List[Dict]:
        """
        Rerank sử dụng GPT-4.1 qua HolySheep.
        Chi phí: $8/MTok cho input, $8/MTok cho output.
        """
        import time
        start = time.perf_counter()
        
        prompt = f"""Given query: "{query}"
Re-rank these documents by relevance (0-1 score):

Documents:
{chr(10).join([f'{i+1}. {doc}' for i, doc in enumerate(documents)])}

Output JSON array with relevance scores:"""
        
        try:
            response = self.client.chat.completions.create(
                model="gpt-4.1",
                messages=[
                    {"role": "system", "content": "You are a relevance scoring assistant."},
                    {"role": "user", "content": prompt}
                ],
                temperature=0.1,
                response_format={"type": "json_object"}
            )
            
            latency_ms = (time.perf_counter() - start) * 1000
            print(f"[HolySheep] Rerank latency: {latency_ms:.2f}ms")
            
            # Parse và merge scores
            import json
            result = json.loads(response.choices[0].message.content)
            
            return [
                {
                    "document": documents[i],
                    "final_score": result.get("scores", initial_scores)[i],
                    "initial_score": initial_scores[i]
                }
                for i in range(len(documents))
            ]
            
        except Exception as e:
            print(f"[HolySheep] Rerank error, using initial scores: {e}")
            return [
                {"document": documents[i], "final_score": initial_scores[i]}
                for i in range(len(documents))
            ]
    
    @staticmethod
    def _cosine_similarity_batch(
        query_vec: List[float], 
        doc_vectors: List[List[float]]
    ) -> List[float]:
        """Tính cosine similarity cho batch."""
        import math
        
        q_mag = math.sqrt(sum(x**2 for x in query_vec))
        
        similarities = []
        for doc_vec in doc_vectors:
            d_mag = math.sqrt(sum(x**2 for x in doc_vec))
            
            if q_mag == 0 or d_mag == 0:
                similarities.append(0.0)
                continue
            
            dot_product = sum(q*d for q, d in zip(query_vec, doc_vec))
            similarities.append(dot_product / (q_mag * d_mag))
        
        return similarities

=== USAGE EXAMPLE ===

async def main(): config = HolySheepConfig( api_key="YOUR_HOLYSHEEP_API_KEY" ) client = HolySheepSearchClient(config) documents = [ "HolySheep AI cung cấp API với latency dưới 50ms", "DeepSeek V3.2 chỉ $0.42/MTok - rẻ hơn 85% OpenAI", "Hỗ trợ thanh toán qua WeChat và Alipay", "Nhận tín dụng miễn phí khi đăng ký tài khoản" ] results = await client.semantic_search( query="giá cả AI API rẻ nhất", documents=documents, top_k=3 ) for r in results: print(f"Score: {r['final_score']:.3f} - {r['document']}")

Run: asyncio.run(main())

Bước 2: Tối Ưu Chi Phí — DeepSeek V3.2 Thay Vì GPT-4

Sau khi benchmark nhiều model, chúng tôi chọn DeepSeek V3.2 cho embedding tasks vì giá chỉ $0.42/MTok — so với $8/MTok của GPT-4.1, tiết kiệm đến 95% chi phí. Đây là bảng so sánh thực tế từ HolySheep:

ModelGiá/MTokĐộ trễ trung bìnhUse case
DeepSeek V3.2$0.42~45msEmbedding, Search
Gemini 2.5 Flash$2.50~35msQuick inference
Claude Sonnet 4.5$15.00~55msComplex reasoning
GPT-4.1$8.00~50msReranking
"""
Production Search Service với Cost Optimization
Chuyển đổi smart routing: cheap model cho simple tasks, 
expensive model chỉ khi cần thiết.
"""

from enum import Enum
from typing import List, Dict, Optional
import hashlib

class SearchComplexity(Enum):
    SIMPLE = "simple"      # Direct match, keyword search
    MEDIUM = "medium"      # Semantic similarity, top-k retrieval
    COMPLEX = "complex"    # Multi-step reasoning, reranking

class CostOptimizedSearchService:
    """
    Smart routing search service.
    Tự động chọn model phù hợp với độ phức tạp query.
    """
    
    MODEL_COSTS = {
        "deepseek-embed": 0.42,      # $/MTok
        "gemini-2.5-flash": 2.50,
        "gpt-4.1": 8.00,
        "claude-sonnet-4.5": 15.00
    }
    
    LATENCY_TARGETS = {
        "simple": 20,    # ms
        "medium": 50,   # ms
        "complex": 150  # ms
    }
    
    def __init__(self, holy_sheep_client):
        self.client = holy_sheep_client
        self.cache = {}  # LRU cache cho repeated queries
        self.cost_tracker = {"total_tokens": 0, "total_cost": 0}
    
    def _estimate_complexity(self, query: str) -> SearchComplexity:
        """Estimate query complexity dựa trên keywords."""
        complex_indicators = [
            "so sánh", "phân tích", "giải thích", "tại sao",
            "như thế nào", "khác nhau", "ưu nhược", "đánh giá"
        ]
        
        simple_indicators = [
            "tìm", "kiếm", "xem", "cho biết", "là gì"
        ]
        
        query_lower = query.lower()
        
        if any(ind in query_lower for ind in complex_indicators):
            return SearchComplexity.COMPLEX
        elif any(ind in query_lower for ind in simple_indicators):
            return SearchComplexity.SIMPLE
        else:
            return SearchComplexity.MEDIUM
    
    def _get_cache_key(self, query: str, docs_hash: str) -> str:
        """Generate cache key cho query."""
        raw = f"{query}:{docs_hash}"
        return hashlib.md5(raw.encode()).hexdigest()
    
    async def search(
        self,
        query: str,
        documents: List[str],
        use_cache: bool = True
    ) -> Dict:
        """
        Main search method với smart model routing.
        
        Cost breakdown example cho 1 triệu tokens:
        - DeepSeek V3.2: $0.42/MTok × 1000 = $420
        - GPT-4.1: $8/MTok × 50 = $400 (chỉ cho reranking)
        - Total: ~$820 thay vì $8,000+ với full GPT-4
        """
        complexity = self._estimate_complexity(query)
        
        # Check cache
        docs_hash = hashlib.md5(
            "".join(documents).encode()
        ).hexdigest()[:8]
        cache_key = self._get_cache_key(query, docs_hash)
        
        if use_cache and cache_key in self.cache:
            return {"cached": True, "results": self.cache[cache_key]}
        
        if complexity == SearchComplexity.SIMPLE:
            # Keyword matching - không cần AI
            results = self._keyword_search(query, documents)
            model_used = "keyword"
            
        elif complexity == SearchComplexity.MEDIUM:
            # Semantic search với DeepSeek V3.2
            results = await self.client.semantic_search(
                query, documents, 
                model="deepseek-embed"
            )
            model_used = "deepseek-embed"
            
        else:  # COMPLEX
            # Full pipeline: DeepSeek embed + GPT-4.1 rerank
            results = await self.client.semantic_search(
                query, documents,
                top_k=10,
                rerank_model="gpt-4.1"
            )
            model_used = "deepseek-embed + gpt-4.1"
        
        # Update cache
        self.cache[cache_key] = results
        
        return {
            "results": results,
            "model_used": model_used,
            "complexity": complexity.value,
            "latency_target": self.LATENCY_TARGETS[complexity.value],
            "cached": False
        }
    
    def _keyword_search(
        self, 
        query: str, 
        documents: List[str]
    ) -> List[Dict]:
        """Simple keyword matching - miễn phí, 0 latency."""
        query_words = set(query.lower().split())
        results = []
        
        for doc in documents:
            doc_words = set(doc.lower().split())
            overlap = query_words & doc_words
            if overlap:
                results.append({
                    "document": doc,
                    "score": len(overlap) / len(query_words),
                    "matched_words": list(overlap)
                })
        
        return sorted(results, key=lambda x: x["score"], reverse=True)

=== COST COMPARISON EXAMPLE ===

def show_cost_savings(): """ So sánh chi phí hàng tháng: - Old system (100% GPT-4): $2,400 - New system (DeepSeek + smart routing): $360 - Tiết kiệm: 85% ($2,040/tháng) """ monthly_tokens = 200_000_000 # 200M tokens old_cost = monthly_tokens / 1_000_000 * 8.00 # $8/MTok new_cost = ( monthly_tokens * 0.95 / 1_000_000 * 0.42 + # 95% DeepSeek monthly_tokens * 0.05 / 1_000_000 * 8.00 # 5% GPT-4 rerank ) print(f""" ╔════════════════════════════════════════════════════╗ ║ MONTHLY COST COMPARISON ║ ╠════════════════════════════════════════════════════╣ ║ Old (GPT-4 only): ${old_cost:,.2f} ║ ║ New (Smart routing): ${new_cost:,.2f} ║ ║ Savings: ${old_cost - new_cost:,.2f} ({((old_cost - new_cost)/old_cost)*100:.0f}%) ║ ╚════════════════════════════════════════════════════╝ """)

Bước 3: Rollback Plan Và Risk Mitigation

Mọi migration đều cần rollback plan. Dưới đây là framework chúng tôi sử dụng với feature flags và automatic failover.

"""
Rollback Manager cho AI Search Migration
Đảm bảo zero-downtime khi chuyển đổi provider.
"""

import asyncio
from enum import Enum
from typing import Callable, Optional
from dataclasses import dataclass
import logging

logger = logging.getLogger(__name__)

class Provider(Enum):
    HOLYSHEEP = "holysheep"
    FALLBACK = "fallback"

@dataclass
class MigrationConfig:
    enable_fallback: bool = True
    fallback_provider: Optional[str] = None
    latency_threshold_ms: float = 100.0
    error_rate_threshold: float = 0.05
    gradual_rollout_percentage: int = 10

@dataclass
class HealthMetrics:
    latency_p50: float = 0
    latency_p99: float = 0
    error_rate: float = 0
    success_count: int = 0
    error_count: int = 0

class MigrationManager:
    """
    Quản lý migration với automatic failover.
    
    Rollback triggers:
    1. Latency p99 > 100ms liên tục 5 phút
    2. Error rate > 5% trong 1 phút
    3. Manual trigger qua config
    """
    
    def __init__(self, config: MigrationConfig):
        self.config = config
        self.current_provider = Provider.HOLYSHEEP
        self.metrics = HealthMetrics()
        self.rollout_percentage = config.gradual_rollout_percentage
        self._rollback_triggered = False
    
    async def execute_with_fallback(
        self,
        primary_func: Callable,
        fallback_func: Callable,
        *args, **kwargs
    ):
        """
        Execute với automatic fallback.
        
        Flow:
        1. Thử HolySheep (primary)
        2. Nếu fail → fallback
        3. Log metrics cho monitoring
        """
        import time
        
        start_time = time.perf_counter()
        attempt_provider = self.current_provider
        
        try:
            if self.current_provider == Provider.HOLYSHEEP:
                result = await primary_func(*args, **kwargs)
            else:
                result = await fallback_func(*args, **kwargs)
            
            latency_ms = (time.perf_counter() - start_time) * 1000
            
            # Update metrics
            self._record_success(latency_ms)
            
            # Check health
            if self._should_rollback():
                logger.warning("🚨 Rollback threshold reached!")
                self._trigger_rollback()
            
            return result
            
        except Exception as e:
            self._record_error()
            logger.error(f"❌ Provider {attempt_provider.value} failed: {e}")
            
            if self.config.enable_fallback:
                logger.info("↩️ Falling back to secondary provider")
                self.current_provider = Provider.FALLBACK
                return await fallback_func(*args, **kwargs)
            else:
                raise
    
    def _record_success(self, latency_ms: float):
        """Record successful request."""
        self.metrics.success_count += 1
        
        # Update latency tracking (simplified)
        self.metrics.latency_p99 = max(
            self.metrics.latency_p99, 
            latency_ms
        )
        self.metrics.latency_p50 = (
            self.metrics.latency_p50 * 0.9 + latency_ms * 0.1
        )
        
        # Reset error rate
        total = self.metrics.success_count + self.metrics.error_count
        self.metrics.error_rate = self.metrics.error_count / max(total, 1)
    
    def _record_error(self):
        """Record failed request."""
        self.metrics.error_count += 1
        
        total = self.metrics.success_count + self.metrics.error_count
        self.metrics.error_rate = self.metrics.error_count / max(total, 1)
    
    def _should_rollback(self) -> bool:
        """Check if rollback conditions are met."""
        if self._rollback_triggered:
            return False
        
        conditions = [
            self.metrics.latency_p99 > self.config.latency_threshold_ms,
            self.metrics.error_rate > self.config.error_rate_threshold
        ]
        
        return any(conditions)
    
    def _trigger_rollback(self):
        """Trigger rollback to fallback provider."""
        self._rollback_triggered = True
        self.current_provider = Provider.FALLBACK
        
        logger.critical(f"""
╔════════════════════════════════════════════════════╗
║              ROLLBACK TRIGGERED                    ║
╠════════════════════════════════════════════════════╣
║  Reason: Latency p99={self.metrics.latency_p99:.1f}ms |              ║
║          Error rate={self.metrics.error_rate*100:.1f}%                       ║
║  Action: Switching to fallback provider            ║
╚════════════════════════════════════════════════════╝
        """)
    
    def gradual_rollout(self) -> bool:
        """
        Gradual rollout: tăng traffic lên HolySheep theo thời gian.
        
        Rollout schedule:
        - Week 1: 10%
        - Week 2: 30%
        - Week 3: 60%
        - Week 4: 100%
        """
        import random
        
        if self.rollout_percentage >= 100:
            return True
        
        # Random sampling based on rollout percentage
        return random.randint(1, 100) <= self.rollout_percentage
    
    def increase_rollout(self, percentage: int):
        """Increase rollout percentage sau khi verify health."""
        self.rollout_percentage = min(percentage, 100)
        logger.info(f"📈 Rollout increased to {self.rollout_percentage}%")
    
    def get_status(self) -> dict:
        """Get current migration status."""
        return {
            "current_provider": self.current_provider.value,
            "rollout_percentage": self.rollout_percentage,
            "rollback_triggered": self._rollback_triggered,
            "metrics": {
                "latency_p50_ms": round(self.metrics.latency_p50, 2),
                "latency_p99_ms": round(self.metrics.latency_p99, 2),
                "error_rate": round(self.metrics.error_rate * 100, 2),
                "total_requests": self.metrics.success_count + self.metrics.error_count
            }
        }

=== MONITORING DASHBOARD ===

async def monitoring_loop(manager: MigrationManager): """Background monitoring task.""" while True: status = manager.get_status() print(f""" ┌─────────────────────────────────────────────────┐ │ HOLYSHEEP MIGRATION STATUS │ ├─────────────────────────────────────────────────┤ │ Provider: {status['current_provider']:<20} │ │ Rollout: {status['rollout_percentage']}% │ │ Rollback: {'YES ⚠️' if status['rollback_triggered'] else 'No ✅'} │ ├─────────────────────────────────────────────────┤ │ METRICS │ │ Latency p50: {status['metrics']['latency_p50_ms']:.2f}ms │ │ Latency p99: {status['metrics']['latency_p99_ms']:.2f}ms │ │ Error Rate: {status['metrics']['error_rate']:.2f}% │ │ Total Req: {status['metrics']['total_requests']} │ └─────────────────────────────────────────────────┘ """) await asyncio.sleep(30)

Kết Quả Thực Tế Sau Migration

Sau 3 tháng triển khai trên production với 2 triệu search requests/ngày:

ROI tính toán: $2,040/tháng × 12 tháng = $24,480/năm — đủ để hire thêm 1 senior engineer hoặc scale infrastructure gấp đôi.

Lỗi Thường Gặp Và Cách Khắc Phục

1. Lỗi 401 Unauthorized - API Key không hợp lệ

Mô tả: Khi sử dụng API key chưa được kích hoạt hoặc sai format, HolySheep trả về lỗi 401.

# ❌ SAI - Key chưa được set hoặc sai format
client = openai.OpenAI(
    api_key="sk-...",  # Có thể thiếu prefix hoặc key đã hết hạn
    base_url="https://api.holysheep.ai/v1"
)

✅ ĐÚNG - Validate key trước khi sử dụng

import os import re def validate_holysheep_key(api_key: str) -> bool: """Validate HolySheep API key format.""" if not api_key: return False # HolySheep key format: hsa-... hoặc sk-... patterns = [ r'^hsa-[a-zA-Z0-9]{32,}$', # Primary format r'^sk-[a-zA-Z0-9]{32,}$' # Compatible format ] return any(re.match(p, api_key) for p in patterns) def get_holy_sheep_client(): api_key = os.environ.get("HOLYSHEEP_API_KEY") if not validate_holysheep_key(api_key): raise ValueError(""" ❌ Invalid API Key! Hãy kiểm tra: 1. Đã copy đúng key từ https://www.holysheep.ai/register ? 2. Key chưa bị expire? 3. Đã set environment variable đúng cách? Commands: export HOLYSHEEP_API_KEY="hsa-your-32-char-key-here" """) return openai.OpenAI( api_key=api_key, base_url="https://api.holysheep.ai/v1", timeout=30.0 )

2. Lỗi 429 Rate Limit - Quá nhiều requests

Mô tả: Vượt quota hoặc rate limit của tài khoản, đặc biệt khi chạy batch jobs.

"""
Handle 429 Rate Limit với exponential backoff.
HolySheep quota: Tùy thuộc plan (Free: 100RPM, Pro: 1000RPM)
"""

import time
import asyncio
from functools import wraps

class RateLimitHandler:
    def __init__(self, max_retries: int = 5):
        self.max_retries = max_retries
    
    async def execute_with_retry(
        self,
        func,
        *args,
        **kwargs
    ):
        """Execute function với automatic retry khi gặp 429."""
        for attempt in range(self.max_retries):
            try:
                return await func(*args, **kwargs)
                
            except Exception as e:
                error_str = str(e).lower()
                
                if "429" in error_str or "rate limit" in error_str:
                    # Calculate backoff: 1s, 2s, 4s, 8s, 16s
                    wait_time = min(2 ** attempt, 60)
                    
                    print(f"""
⚠️  Rate limit hit (attempt {attempt + 1}/{self.max_retries})
⏳ Waiting {wait_time}s before retry...
                    """)
                    
                    await asyncio.sleep(wait_time)
                    
                else:
                    # Non-rate-limit error, re-raise
                    raise
        
        raise Exception(f"❌ Failed after {self.max_retries} retries due to rate limits")

Sử dụng với batch embedding

async def batch_embed_with_rate_limit( client, texts: List[str], batch_size: int = 100 ): """Batch embedding với rate limit handling.""" handler = RateLimitHandler(max_retries=5) all_embeddings = [] for i in range(0, len(texts), batch_size): batch = texts[i:i + batch_size] async def embed_batch(): response = client.embeddings.create( model="deepseek-embed", input=batch ) return [item.embedding for item in response.data] embeddings = await handler.execute_with_retry(embed_batch) all_embeddings.extend(embeddings) print(f"✅ Embedded {len(all_embeddings)}/{len(texts)} texts") return all_embeddings

3. Lỗi Timeout - Request mất quá lâu

Mô tả: HolySheep cam kết latency dưới 50ms, nhưng network hoặc server có thể gây timeout.

"""
Timeout handling với graceful degradation.
Fallback sang cached results hoặc simple matching khi timeout.
"""

import asyncio
from typing import Optional, List
import json
import os

class TimeoutResilientClient:
    def __init__(self, client, cache_dir: str = "./cache"):
        self.client = client
        self.cache_dir = cache_dir
        self.timeout_seconds = 5.0  # Conservative timeout
        
        # Tạo cache directory
        os.makedirs(cache_dir, exist_ok=True)
    
    def _get_cache_path(self, query_hash: str) -> str:
        return f"{self.cache_dir}/{query_hash}.json"
    
    def _load_from_cache(self, query_hash: str) -> Optional[List[dict]]:
        """Load cached results nếu có."""
        cache_path = self._get_cache_path(query_hash)
        
        if os.path.exists(cache_path):
            try:
                with open(cache_path, 'r') as f:
                    data = json.load(f)
                    
                print(f"📦 Loaded {len(data)} results from cache")
                return data
            except Exception as e:
                print(f"⚠️ Cache read error: {e}")
        
        return None
    
    def _save_to_cache(self, query_hash: str, results: List[dict]):
        """Save results to cache."""
        cache_path = self._get_cache_path(query_hash)
        
        try:
            with open(cache_path, 'w') as f:
                json.dump(results, f, ensure_ascii=False, indent=2)