Trung cấpKỹ thuậtClaude APINguồn: Anthropic

Speculative Caching — Giảm time-to-first-token với cache dự đoán

Nghe bài viết
00:00

Điểm nổi bật

Nhấn để đến mục tương ứng

  1. 1 Tận dụng Claude hiệu quả: Anthropic Prompt Caching cho phép bạn cache phần đầu của prompt system prompt + documents và tái sử dụng ở các requests — mẹo quan trọng là cung cấp đủ ngữ cảnh để AI trả về kết quả chính xác hơn 80% so với prompt chung chung.
  2. 2 Không có giải pháp hoàn hảo: Ví dụ: User đang xem product page cho "iPhone 15 Pro". Bài viết phân tích rõ trade-off giúp bạn đưa ra quyết định phù hợp với tình huống thực tế.
  3. 3 Điểm nhấn quan trọng: class JourneyBasedSpeculator: """ Dự đoán next context dựa trên user journey patterns. Đây là phần mang lại giá trị thực tiễn cao nhất trong toàn bài viết.
  4. 4 Bước đầu tiên bạn nên làm: """ def initself, refreshinterval: int = 240: 4 minutes before 5-min TTL self.contexts = {} contextid -> {content,. Áp dụng đúng cách sẽ thấy kết quả rõ rệt từ tuần đầu tiên.
  5. 5 Thành thật mà nói: Metric Không có Speculative Cache Với Speculative Cache TTFT lần đầu 2,000-5,000ms 300-800ms TTFT lần tiếp. Phương pháp này hiệu quả trong hầu hết trường hợp, nhưng bạn cần điều chỉnh cho phù hợp ngữ cảnh riêng.
white robot near brown wall

Trong các ứng dụng conversational AI, time-to-first-token (TTFT) là metric quan trọng nhất ảnh hưởng đến user experience. Khi user gửi message, họ không muốn nhìn màn hình trống 3-5 giây. Speculative Caching là kỹ thuật pre-warm cache với context được dự đoán — để khi request thực sự đến, cache đã sẵn sàng.

Prompt Caching — Nền tảng cần hiểu trước

Anthropic Prompt Caching cho phép bạn cache phần đầu của prompt (system prompt + documents) và tái sử dụng ở các requests tiếp theo:

import anthropic

client = anthropic.Anthropic()

# Không có caching — mỗi request trả tiền đầy đủ input tokens
response_no_cache = client.messages.create(
    model="claude-haiku-4-5",
    max_tokens=1000,
    system="You are a helpful assistant with extensive knowledge of Vietnamese law...",  # 5000 tokens
    messages=[{"role": "user", "content": "Giải thích Điều 32 Bộ luật Dân sự"}]
)

# Với caching — system prompt được cache sau lần đầu
response_with_cache = client.messages.create(
    model="claude-haiku-4-5",
    max_tokens=1000,
    system=[{
        "type": "text",
        "text": "You are a helpful assistant with extensive knowledge of Vietnamese law...",
        "cache_control": {"type": "ephemeral"}  # Mark for caching
    }],
    messages=[{"role": "user", "content": "Giải thích Điều 32 Bộ luật Dân sự"}]
)

# Lần 2 trở đi: system prompt tokens được đọc từ cache
# Cost giảm 90% cho cached tokens
# TTFT giảm vì không cần process lại system prompt

Cache tồn tại tối thiểu 5 phút và được extend mỗi khi hit. Đây là foundation của Speculative Caching.

Speculative Caching là gì?

Standard caching reactive: cache được warm khi user thực sự gọi API. Speculative Caching proactive: bạn dự đoán user sẽ cần gì và warm cache trước khi họ hỏi.

Ví dụ: User đang xem product page cho "iPhone 15 Pro". Khả năng cao họ sẽ hỏi về specs, giá, hoặc so sánh. Bạn có thể pre-warm cache với product context ngay khi họ load page — trước khi họ gõ bất cứ điều gì.

Pattern 1: Page-Based Prefetching

import anthropic
import asyncio
import time
from typing import Optional

client = anthropic.Anthropic()
async_client = anthropic.AsyncAnthropic()

class SpeculativeCacheManager:
    def __init__(self):
        self.cache_registry = {}  # track what's been pre-warmed

    def warm_cache_for_context(self, context_id: str, context_content: str,
                                system_role: str = "helpful assistant") -> dict:
        """
        Pre-warm cache với một context cụ thể.
        Gọi hàm này ngay khi user bắt đầu interact với một page/resource.
        """
        if context_id in self.cache_registry:
            age_seconds = time.time() - self.cache_registry[context_id]["warmed_at"]
            if age_seconds < 240:  # Cache still warm (5 min TTL - 1 min buffer)
                return {"status": "already_warm", "age_seconds": int(age_seconds)}

        # Gửi request nhỏ để warm cache
        start = time.time()
        response = client.messages.create(
            model="claude-haiku-4-5",
            max_tokens=1,  # Minimal output — chỉ cần warm cache
            system=[
                {
                    "type": "text",
                    "text": f"You are a {system_role}.",
                    "cache_control": {"type": "ephemeral"}
                },
                {
                    "type": "text",
                    "text": context_content,
                    "cache_control": {"type": "ephemeral"}
                }
            ],
            messages=[{"role": "user", "content": "Ready."}]
        )

        warm_time = int((time.time() - start) * 1000)
        cache_tokens = getattr(response.usage, 'cache_creation_input_tokens', 0) or 0

        self.cache_registry[context_id] = {
            "warmed_at": time.time(),
            "cache_tokens": cache_tokens,
            "warm_time_ms": warm_time
        }

        print(f"Cache warmed: {context_id} | {cache_tokens} tokens | {warm_time}ms")
        return {"status": "warmed", "cache_tokens": cache_tokens, "warm_time_ms": warm_time}

    def query_with_cache(self, context_id: str, context_content: str,
                          system_role: str, user_message: str) -> dict:
        """Query Claude using pre-warmed cache"""
        start = time.time()

        response = client.messages.create(
            model="claude-haiku-4-5",
            max_tokens=2000,
            system=[
                {
                    "type": "text",
                    "text": f"You are a {system_role}.",
                    "cache_control": {"type": "ephemeral"}
                },
                {
                    "type": "text",
                    "text": context_content,
                    "cache_control": {"type": "ephemeral"}
                }
            ],
            messages=[{"role": "user", "content": user_message}]
        )

        latency_ms = int((time.time() - start) * 1000)
        cache_read = getattr(response.usage, 'cache_read_input_tokens', 0) or 0
        cache_written = getattr(response.usage, 'cache_creation_input_tokens', 0) or 0
        cache_hit = cache_read > 0

        return {
            "response": response.content[0].text,
            "latency_ms": latency_ms,
            "cache_hit": cache_hit,
            "cache_read_tokens": cache_read,
            "cache_write_tokens": cache_written,
            "input_tokens": response.usage.input_tokens,
            "output_tokens": response.usage.output_tokens
        }

cache_manager = SpeculativeCacheManager()

Pattern 2: User Journey Prediction

class JourneyBasedSpeculator:
    """
    Dự đoán next context dựa trên user journey patterns.
    Pre-warm cache cho predicted next step.
    """

    # Định nghĩa journey maps: current_page -> likely_next_pages
    JOURNEY_GRAPH = {
        "product_listing": ["product_detail", "category_filter"],
        "product_detail": ["checkout", "comparison", "reviews"],
        "checkout_cart": ["checkout_shipping", "product_detail"],
        "checkout_shipping": ["checkout_payment"],
        "checkout_payment": ["order_confirmation"],
        "user_profile": ["order_history", "settings", "wishlist"],
        "order_history": ["order_detail", "return_request"],
    }

    def __init__(self, content_loader: callable):
        self.content_loader = content_loader  # Function to load page content
        self.cache_manager = SpeculativeCacheManager()
        self.prefetch_tasks = {}

    async def prefetch_predicted_contexts(self, current_page: str, current_entity_id: str):
        """Async prefetch predicted next pages"""
        predicted_pages = self.JOURNEY_GRAPH.get(current_page, [])

        async def warm_single(page: str):
            content = await self.async_load_content(page, current_entity_id)
            if content:
                return await self.async_warm_cache(f"{page}_{current_entity_id}", content)

        tasks = [warm_single(page) for page in predicted_pages]
        results = await asyncio.gather(*tasks, return_exceptions=True)

        print(f"Pre-warmed {len([r for r in results if not isinstance(r, Exception)])} contexts for '{current_page}' journey")
        return results

    async def async_warm_cache(self, context_id: str, content: str):
        """Async version của cache warming"""
        response = await async_client.messages.create(
            model="claude-haiku-4-5",
            max_tokens=1,
            system=[{
                "type": "text",
                "text": content,
                "cache_control": {"type": "ephemeral"}
            }],
            messages=[{"role": "user", "content": "Ready."}]
        )
        return context_id

    async def async_load_content(self, page: str, entity_id: str) -> Optional[str]:
        """Load content cho một page — implement với real data source"""
        # Mock implementation
        content_map = {
            "product_detail": f"Product ID: {entity_id}
Name: Sample Product
Price: $99
Specs: ...",
            "checkout": f"Cart for user: {entity_id}
Items: 3
Total: $297",
            "reviews": f"Reviews for product {entity_id}
5 stars: 80%
4 stars: 15%
Latest: ..."
        }
        return content_map.get(page)

Pattern 3: Time-Based Refresh

class AutoRefreshCacheManager:
    """
    Tự động refresh cache cho contexts có high access frequency.
    Đảm bảo cache luôn warm cho popular content.
    """

    def __init__(self, refresh_interval: int = 240):  # 4 minutes (before 5-min TTL)
        self.contexts = {}  # context_id -> {content, system_role, last_refresh}
        self.refresh_interval = refresh_interval
        self.running = False

    def register_hot_context(self, context_id: str, content: str, system_role: str = "assistant"):
        """Đăng ký một context để auto-refresh"""
        self.contexts[context_id] = {
            "content": content,
            "system_role": system_role,
            "last_refresh": 0,
            "hit_count": 0
        }
        # Warm immediately
        self._warm_cache(context_id)

    def _warm_cache(self, context_id: str):
        ctx = self.contexts[context_id]
        client.messages.create(
            model="claude-haiku-4-5",
            max_tokens=1,
            system=[{
                "type": "text",
                "text": ctx["content"],
                "cache_control": {"type": "ephemeral"}
            }],
            messages=[{"role": "user", "content": "Ready."}]
        )
        self.contexts[context_id]["last_refresh"] = time.time()

    async def run_refresh_loop(self):
        """Background loop để refresh expiring caches"""
        self.running = True
        while self.running:
            now = time.time()
            for context_id, ctx in self.contexts.items():
                age = now - ctx["last_refresh"]
                if age >= self.refresh_interval:
                    print(f"Auto-refreshing cache: {context_id}")
                    self._warm_cache(context_id)

            await asyncio.sleep(60)  # Check every minute

    def stop(self):
        self.running = False

Đo lường hiệu quả Speculative Caching

def benchmark_speculative_caching(context_content: str, test_queries: list[str]) -> dict:
    """So sánh latency: cold cache vs warm cache"""

    manager = SpeculativeCacheManager()

    print("Benchmarking Speculative Caching...")
    print("=" * 50)

    # Test 1: Cold cache (no pre-warming)
    cold_latencies = []
    for query in test_queries[:3]:
        start = time.time()
        result = manager.query_with_cache(
            f"cold_{time.time()}", context_content, "assistant", query
        )
        cold_latencies.append(result["latency_ms"])
        print(f"Cold: {result['latency_ms']}ms | Cache hit: {result['cache_hit']}")

    # Test 2: Pre-warm then query
    warm_latencies = []
    ctx_id = "benchmark_warm"

    # Pre-warm
    warm_result = manager.warm_cache_for_context(ctx_id, context_content)
    print(f"
Pre-warm: {warm_result['warm_time_ms']}ms | {warm_result['cache_tokens']} tokens cached")

    # Now query with warm cache
    for query in test_queries[:3]:
        start = time.time()
        result = manager.query_with_cache(ctx_id, context_content, "assistant", query)
        warm_latencies.append(result["latency_ms"])
        print(f"Warm: {result['latency_ms']}ms | Cache hit: {result['cache_hit']}")

    avg_cold = sum(cold_latencies) / len(cold_latencies) if cold_latencies else 0
    avg_warm = sum(warm_latencies) / len(warm_latencies) if warm_latencies else 0
    improvement = ((avg_cold - avg_warm) / avg_cold * 100) if avg_cold > 0 else 0

    print(f"
Results:")
    print(f"  Avg Cold TTFT: {avg_cold:.0f}ms")
    print(f"  Avg Warm TTFT: {avg_warm:.0f}ms")
    print(f"  TTFT Improvement: {improvement:.1f}%")

    return {
        "avg_cold_ms": avg_cold,
        "avg_warm_ms": avg_warm,
        "ttft_improvement_pct": improvement
    }

# Benchmark
test_context = "Vietnamese Legal Code Content:
" + "Article text... " * 100  # Long context
test_queries = [
    "Điều 32 quy định gì về quyền cá nhân?",
    "Hình phạt cho vi phạm Điều 15?",
    "Giải thích khái niệm 'pháp nhân' theo bộ luật"
]

benchmark_results = benchmark_speculative_caching(test_context, test_queries)

Chi phí và ROI của Speculative Caching

Metric Không có Speculative Cache Với Speculative Cache
TTFT (lần đầu) 2,000-5,000ms 300-800ms
TTFT (lần tiếp) 2,000-5,000ms 200-400ms
Input token cost 100% (full price) 10% (cache read)
Pre-warm cost N/A Một lần cache write = 125% của input
Break-even Sau 1.4 cache hits

Với bất kỳ context nào được hit 2+ lần, Speculative Caching tiết kiệm cả chi phí lẫn latency.

Khi nào dùng Speculative Caching

  • Documentation chatbots — Pre-warm khi user mở doc page
  • Customer support — Pre-warm product/order context khi user login
  • E-commerce — Pre-warm product catalog khi user browse category
  • Legal/Medical AI — Pre-warm case/patient file khi practitioner opens it
  • Code assistants — Pre-warm codebase context khi dev opens project

Tổng kết

Speculative Caching là kỹ thuật high-impact, low-complexity. Bằng cách dự đoán user journey và pre-warm cache, bạn giảm TTFT từ giây xuống còn milliseconds — cải thiện UX đáng kể mà không cần thay đổi model hay infrastructure.

Key implementation steps:

  • Add cache_control: {type: "ephemeral"} vào system prompt và documents dài
  • Gọi warm cache API ngay khi user bắt đầu session hoặc navigate đến page
  • Refresh cache mỗi 4 phút cho hot contexts để tránh expiry
  • Monitor cache hit rate để đánh giá prediction accuracy

Đọc thêm: Usage & Cost API để theo dõi cache hit rates và tối ưu chiến lược caching.


Bài viết liên quan

Tính năng liên quan:Speculative CachingPrompt CachingTTFTPerformanceLatency Optimization

Bai viet co huu ich khong?

Bản quyền thuộc về tác giả. Vui lòng dẫn nguồn khi chia sẻ.

Bình luận (0)
Ảnh đại diện
Đăng nhập để bình luận...
Đăng nhập để bình luận
  • Đang tải bình luận...

Đăng ký nhận bản tin

Nhận bài viết hay nhất về sản phẩm và vận hành, gửi thẳng vào hộp thư của bạn.

Bảo mật thông tin. Hủy đăng ký bất cứ lúc nào. Chính sách bảo mật.