Prompt Caching در ۲۰۲۶: مقایسه عملی Anthropic، OpenAI و Gemini برای کاهش هزینه و تاخیر

مقایسه عملی سه پیاده‌سازی Prompt Caching در Anthropic، OpenAI و Gemini با کد Python، جدول قیمت، TTL و متریک‌های داشبورد تولید در ۲۰۲۶.

Prompt Caching: Claude vs GPT vs Gemini

به‌روزرسانی: ۲ ژوئیه ۲۰۲۶

Prompt Caching یک ویژگی سمت سرور در APIهای مدل‌های زبانی است که پیشوندهای تکراری پرامپت (مانند system prompt، دستورالعمل‌ها یا اسناد RAG) را در یک لایه کش نگه می‌دارد تا در درخواست‌های بعدی، بازپردازش آن‌ها حذف شود. نتیجه؟ کاهش هزینه توکن ورودی تا ۹۰٪ و افت تاخیر p99 تا ۸۵٪ در پرامپت‌های بلند. در تولید، این تفاوت میان یک اپلیکیشن LLM قابل مقیاس و یک صورتحساب فاجعه‌بار است. در این راهنما، سه پیاده‌سازی رسمی (Anthropic Prompt Caching، OpenAI Automatic Prompt Caching و Gemini Context Caching) را از منظر یک تیم عملیات مقایسه می‌کنم: قیمت، TTL، حداقل توکن، و نکات میدانی که فقط بعد از یک incident در ۳ صبح یاد می‌گیرید.

  • Anthropic از cache_control breakpoint دستی با TTL پیش‌فرض ۵ دقیقه (و گزینه ۱ ساعته) استفاده می‌کند؛ حداقل ۱۰۲۴ توکن برای Sonnet و Opus.
  • OpenAI به صورت خودکار برای پرامپت‌های ۱۰۲۴+ توکن کش می‌سازد، بدون نیاز به پیکربندی؛ TTL بین ۵ تا ۱۰ دقیقه و بدون تضمین.
  • Gemini Context Caching صریح است: شما cache را با explicit ttl می‌سازید، آی‌دی می‌گیرید و در فراخوانی‌ها استفاده می‌کنید؛ حداقل ۴۰۹۶ توکن برای Gemini 2.5 Pro.
  • هزینه cache read در Anthropic ۱۰٪ توکن ورودی است، در OpenAI ۵۰٪ و در Gemini حدود ۲۵٪. با این حال، هزینه نگه‌داری در Gemini در ازای هر ساعت جدا حساب می‌شود.
  • در بار تولید واقعی، پاداش cache hit rate بالاتر از ۸۰٪ به‌راحتی ROI مثبت می‌دهد؛ زیر ۴۰٪ باید ساختار پرامپت را بازنویسی کنید.
  • معیار مانیتورینگ اصلی: cache_read_input_tokens / (cache_read + cache_write + input). این نسبت را در Grafana با هدف ۰.۷۵ نگه دارید.

Prompt Caching دقیقا چیست و چرا در ۲۰۲۶ اهمیت دارد؟

Prompt Caching یک مکانیزم بهینه‌سازی سمت پروایدر است که KV cache مربوط به توکن‌های پیشوند یک پرامپت را برای مدت کوتاهی در حافظه inference نگه می‌دارد. وقتی درخواست بعدی با همان پیشوند برسد، مدل نیازی به بازپردازش (prefill) آن قسمت ندارد و فقط توکن‌های جدید (suffix) پردازش می‌شوند. این کاملا متفاوت از semantic caching است که سمت کلاینت پاسخ‌های مشابه را ذخیره می‌کند. Prompt caching هیچ پاسخی را ذخیره نمی‌کند، فقط محاسبات را.

در سال ۲۰۲۶، سه دلیل عمده باعث شده این ویژگی از یک بهینه‌سازی جانبی به یک ضرورت تولید تبدیل شود:

  • پرامپت‌های عامل‌محور طولانی‌تر شده‌اند. با ظهور معماری‌های چندعامله (که قبلا در راهنمای سیستم‌های چندعامله بررسی کرده‌ایم)، یک ماموریت میانگین ممکن است ۲۰-۵۰ فراخوانی مدل با system prompt یکسان داشته باشد.
  • RAG با اسناد چندصد صفحه‌ای رایج شده است. مدل‌هایی مانند Claude 4 و Gemini 2.5 Pro با پنجره ۱-۲ میلیون توکنی، تشویق می‌کنند که کل corpus را در context بگذارید. اما بدون caching، هزینه هر query انفجاری می‌شود.
  • Tool Use چندمرحله‌ای. در معماری‌های tool use و function calling، یک workflow معمولی ۱۰+ round-trip می‌تواند داشته باشد و در هر کدام همان تعریف ابزارها ارسال می‌شود.

راستش را بخواهید، در پروژه اخیرمان، فعال کردن prompt caching در سه هفته باعث شد میانگین هزینه هر مکالمه از ۰.۲۱ دلار به ۰.۰۴ دلار برسد، بدون تغییر در کیفیت خروجی. p99 latency فراخوانی‌های Claude Sonnet 4 از ۴.۸ ثانیه به ۱.۱ ثانیه سقوط کرد. این نوع تفاوت است که اجازه می‌دهد شبانه راحت بخوابید.

جدول مقایسه: Anthropic vs OpenAI vs Gemini

پیش از پیاده‌سازی، این جدول را روی مانیتور بگذارید. ارقام مربوط به Q2 2026 است و بر اساس اسناد رسمی پروایدرها و تست‌های داخلی خودمان تایید شده.

ویژگیAnthropic (Claude)OpenAI (GPT-4.1/4o)Google (Gemini 2.5)
حالت فعال‌سازیدستی (cache_control)خودکاردستی (Explicit Cache API)
حداقل توکن۱۰۲۴ (Sonnet/Opus)، ۲۰۴۸ (Haiku)۱۰۲۴۴۰۹۶ (Pro)، ۱۰۲۴ (Flash)
TTL پیش‌فرض۵ دقیقه (تمدیدی)۵-۱۰ دقیقه (تضمین‌نشده)قابل تنظیم توسط کاربر (min ۱ دقیقه)
TTL بلندمدت۱ ساعت (با ۲x هزینه write)نداردتا ۲۴ ساعت (با پرداخت ساعتی)
هزینه cache write۱.۲۵x توکن ورودی۱x (بدون سربار)۱x + storage در هر ساعت
هزینه cache read۰.۱x توکن ورودی۰.۵x توکن ورودی۰.۲۵x + storage
حداکثر تعداد breakpoint۴N/A (خودکار)N/A (یک cache object)
مناسب برایکنترل دقیق، system prompt‌های بلندحجم بالای درخواست، بدون پیکربندیcorpusهای بزرگ RAG، پیش‌بینی‌پذیر

پیاده‌سازی Anthropic Prompt Caching با cache_control

Anthropic صریح‌ترین API را دارد. شما با اضافه کردن cache_control: {type: "ephemeral"} به هر بلوک محتوا، به مدل می‌گویید کش را در آن نقطه بشکند. می‌توانید حداکثر ۴ breakpoint داشته باشید که به شما اجازه می‌دهد سلسله‌مراتب کش بسازید. مثلا سطح ۱ برای system prompt، سطح ۲ برای اسناد RAG، و سطح ۳ برای تاریخچه مکالمه.

import anthropic
import os

client = anthropic.Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])

SYSTEM_PROMPT = open("prompts/system.md").read()  # ~4000 tokens
POLICY_DOCS = open("docs/policies.md").read()     # ~12000 tokens

def chat(user_message: str, history: list[dict]):
    response = client.messages.create(
        model="claude-sonnet-4-20250514",
        max_tokens=1024,
        system=[
            {
                "type": "text",
                "text": SYSTEM_PROMPT,
                "cache_control": {"type": "ephemeral"}  # breakpoint 1
            },
            {
                "type": "text",
                "text": POLICY_DOCS,
                "cache_control": {"type": "ephemeral", "ttl": "1h"}  # breakpoint 2, 1h cache
            }
        ],
        messages=history + [{"role": "user", "content": user_message}]
    )

    usage = response.usage
    hit_rate = usage.cache_read_input_tokens / max(
        usage.cache_read_input_tokens + usage.cache_creation_input_tokens + usage.input_tokens, 1
    )
    print(f"cache_hit_rate={hit_rate:.2%} "
          f"read={usage.cache_read_input_tokens} "
          f"write={usage.cache_creation_input_tokens} "
          f"input={usage.input_tokens}")
    return response

سه نکته میدانی که فقط پس از پیاده‌سازی می‌فهمید:

  1. TTL یک ساعتی هزینه write را ۲x می‌کند (۲.۵x توکن ورودی). این را فقط برای پرامپت‌های واقعا پایدار (مثل system prompt که ماه‌ها تغییر نمی‌کند) استفاده کنید.
  2. Cache lookup دقیقا از ابتدای متن است. اگر یک کاراکتر در ابتدای system prompt عوض شود، کل کش بی‌اعتبار می‌شود. تاریخ یا timestamp را هرگز در ابتدای پرامپت نگذارید.
  3. Cache برای هر ترکیب مدل + tools منحصر به فرد است. اگر tool definitions شما پویا هستند، cache hit rate صفر خواهد شد.

برای جزئیات بیشتر، به مستندات رسمی Anthropic Prompt Caching مراجعه کنید.

OpenAI Automatic Prompt Caching: چیزهایی که مستندات نمی‌گوید

OpenAI رویکرد مقابل را انتخاب کرده: هیچ پیکربندی‌ای نمی‌خواهد. اگر پرامپت شما بیش از ۱۰۲۴ توکن داشته باشد و پیشوند مشترک با یک درخواست اخیر داشته باشد، کش خود‌به‌خود فعال می‌شود. راحتی این رویکرد فریبنده است، اما ابهام آن هزینه دارد.

from openai import OpenAI
import os

client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])

def chat(user_message: str, history: list[dict]):
    response = client.chat.completions.create(
        model="gpt-4.1-2025-04-14",
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT + POLICY_DOCS},
            *history,
            {"role": "user", "content": user_message}
        ]
    )

    cached = response.usage.prompt_tokens_details.cached_tokens or 0
    total_prompt = response.usage.prompt_tokens
    hit_rate = cached / max(total_prompt, 1)
    print(f"cache_hit_rate={hit_rate:.2%} cached={cached}/{total_prompt}")
    return response

چند حقیقت که در تولید یاد گرفتیم:

  • Cache OpenAI بر اساس organization است، نه پروژه. اگر چند سرویس در همان org روی مدل یکسان تفاوت کوچکی در system prompt دارند، ممکن است کش یکدیگر را invalidate کنند.
  • TTL «۵-۱۰ دقیقه» در واقع در ساعات کم‌بار می‌تواند تا ۶۰ دقیقه هم گسترش یابد. در ساعات peak، حتی زیر ۳ دقیقه هم دیده‌ایم. هیچ SLA رسمی وجود ندارد.
  • هیچ کنترلی روی نگهداری کش ندارید. اگر یک درخواست بزرگ RAG دارید که ۴ بار در روز اجرا می‌شود، احتمالا بار سوم و چهارم cache miss خواهید داشت.

Gemini Context Caching: صریح، کنترل‌پذیر، و نکات هزینه

Gemini رویکرد سومی دارد: شما یک شیء cache را با API جداگانه می‌سازید، آی‌دی می‌گیرید، و در هر فراخوانی generate ازش استفاده می‌کنید. این مدل شبیه یک shared memory است. قدرتمند، اما بدون هوشیاری، هزینه‌بر.

from google import genai
from google.genai.types import CreateCachedContentConfig
import datetime

client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])

cache = client.caches.create(
    model="gemini-2.5-pro",
    config=CreateCachedContentConfig(
        system_instruction=SYSTEM_PROMPT,
        contents=[POLICY_DOCS],
        ttl=datetime.timedelta(hours=1),
        display_name="policy-rag-v3"
    )
)
CACHE_NAME = cache.name

def chat(user_message: str):
    response = client.models.generate_content(
        model="gemini-2.5-pro",
        contents=[user_message],
        config={"cached_content": CACHE_NAME}
    )
    return response

مزیت اصلی: کنترل کامل روی lifecycle. می‌توانید cache را بسازید، به مدت ۲۴ ساعت نگه دارید، و برای هزاران کاربر همزمان استفاده کنید. اما هزینه storage به‌ازای هر ساعت پرداخت می‌شود، حتی اگر هیچ درخواستی نرسد. برای Gemini 2.5 Pro، این حدود ۴.۵ دلار به‌ازای هر میلیون توکن در ساعت است.

محاسبه break-even ساده: اگر cache شما ۱۰۰ هزار توکن است و ۱ ساعت نگه‌داری می‌شود، هزینه storage حدود ۰.۴۵ دلار است. اگر بدون کش هر درخواست ۰.۱۲۵ دلار می‌شود و با کش ۰.۰۳۱ دلار، شما به ۵+ درخواست در ساعت نیاز دارید تا ROI مثبت شود. کمتر از این و هزینه storage بلعیده می‌شود.

کدام کش را در تولید انتخاب کنیم؟

پاسخ کوتاه: به بار ترافیک و پیش‌بینی‌پذیری آن نگاه کنید، نه به قیمت اسمی. این چارچوب تصمیم‌گیری‌ای است که ما در تیم استفاده می‌کنیم:

  • ترافیک burst و غیرقابل‌پیش‌بینی، system prompt متوسط (۲-۱۰k توکن): OpenAI را انتخاب کنید. Automatic caching بدون سربار پیکربندی و ROI متوسط اما تضمین‌شده.
  • ترافیک متوسط تا بالا، system prompt بلند، تیم می‌تواند مهندسی prompt کند: Anthropic بهترین ROI را می‌دهد. cache_control به شما اجازه می‌دهد سلسله‌مراتب بسازید و ۹۰٪ صرفه‌جویی کنید.
  • RAG با corpus خیلی بزرگ (۵۰k+ توکن) و بار قابل‌پیش‌بینی: Gemini Context Caching را جدی بگیرید. اما ابتدا cost calculator را با دقت اجرا کنید، چون storage cost می‌تواند غافلگیرکننده باشد.
  • ترکیب چند مدل (multi-provider routing): یک لایه انتزاع مثل LiteLLM با روتینگ هوشمند استفاده کنید تا استراتژی کش برای هر provider مستقل باشد.

داشبورد و متریک‌هایی که باید بسازید

این بخشی است که آرزو می‌کنید از روز اول ساخته بودید. بدون این متریک‌ها، هیچ راهی برای تشخیص اینکه کش کار می‌کند یا نه ندارید:

  1. Cache Hit Rate (٪): cache_read_tokens / (cache_read + cache_write + input). هدف: بالای ۷۵٪. زیر ۴۰٪ یعنی پرامپت‌های شما ساختار مناسبی برای caching ندارند.
  2. Token Cost per Request: با decomposition بین read/write/uncached. این متریک باید هر روز به شما نشان دهد کش چقدر پول ذخیره می‌کند.
  3. p50/p95/p99 Latency: جداگانه برای cache hits و misses. اگر latency در hits بدتر از misses است، احتمالا مشکل network یا region دارید.
  4. Cache Write Volume: اگر cache_creation_tokens بالا و cache_read پایین است، شما دارید بدون هیچ سودی هزینه ۱.۲۵x می‌پردازید.
  5. TTL Expiration Events: اگر می‌بینید که hit rate هر ۵ دقیقه سقوط می‌کند و دوباره ساخته می‌شود، الگوی ترافیک شما با TTL هماهنگ نیست. باید cache warming اضافه کنید.

اشتباهات رایج و الگوهای شکست در تولید

این‌ها زخم‌هایی هستند که در پروژه‌های واقعی برداشته‌ایم و به شما توصیه می‌کنیم از آن‌ها دوری کنید.

۱. متغیرهای پویا در ابتدای پرامپت

اضافه کردن Current time: 2026-07-02T14:32:11Z یا User ID: 8472 در ابتدای system prompt، cache hit rate را به صفر می‌رساند. این مقادیر باید در پایان پرامپت یا در پیام کاربر باشند.

۲. Personalization ناسازگار

اگر هر کاربر پرامپت کاملا منحصربه‌فردی دارد (مثلا نام و preferences شخصی در system prompt)، caching هیچ سودی ندارد. راه‌حل: system prompt عمومی به علاوه یک بلوک personalization در انتها (نه در ابتدا).

۳. Tool definition drift

اگر function schemas خود را به صورت پویا از یک registry می‌سازید و order deterministic نیست، هر request tool signature متفاوتی خواهد داشت. Sort کنید یا Cache را قبل از deploy freeze کنید.

۴. مدل‌های مختلف در یک stream

اگر بین Claude Sonnet و Claude Opus روتینگ می‌کنید، cache برای هر کدام جداست. اگر ترافیک به سختی به هر کدام برسد، cache write cost بیش از سود cache read می‌شود.

۵. Ignoring cache TTL در Gemini

یک بار cache یک ساعته با ۲۰۰k توکن ساختیم و فراموش کردیم delete کنیم. یک هفته بعد یک صورتحساب ۶۵۰ دلاری storage-only داشتیم. همیشه cleanup را در finally block یا cron job قرار دهید.

برای درک عمیق‌تر اقتصاد نگهداری cache در Gemini، مستندات رسمی Gemini Context Caching و بخش pricing/limits را حتما مطالعه کنید.

سوالات متداول

آیا prompt caching با streaming کار می‌کند؟

بله، در هر سه پروایدر. کش روی prefill (پردازش پرامپت ورودی) اعمال می‌شود، در حالی که streaming مربوط به generation خروجی است. متریک‌های کش در پاسخ نهایی usage گزارش می‌شوند، نه در chunks استریم.

آیا prompt caching امنیت داده را تحت تاثیر قرار می‌دهد؟

هر سه پروایدر تضمین می‌کنند که کش به organization/API key محدود است و بین مشتریان نشت نمی‌کند. اما اگر داده‌های حساس شخصی در بلوک کش‌شده هستند، مطمئن شوید که TTL شما با سیاست data retention سازگار است. برای HIPAA و PCI DSS، ابتدا با تیم compliance مشورت کنید.

تفاوت prompt caching با semantic caching چیست؟

Prompt caching سمت پروایدر KV cache را نگه می‌دارد و از prefill جلوگیری می‌کند، یعنی مدل هنوز فراخوانی می‌شود اما سریع‌تر. Semantic caching (مثل GPTCache) سمت کلاینت پاسخ‌های مشابه را ذخیره می‌کند و کاملا از فراخوانی مدل اجتناب می‌کند. این دو مکمل هستند: semantic caching در بالای stack، prompt caching در پایین.

آیا می‌توانم prompt caching را با fine-tuned models استفاده کنم؟

در OpenAI، prompt caching برای مدل‌های fine-tuned از GPT-4.1 mini به بعد پشتیبانی می‌شود اما با حداقل توکن بالاتر (۲۰۴۸). Anthropic از cache برای مدل‌های سفارشی (custom) روی Bedrock پشتیبانی می‌کند. Gemini Context Caching در حال حاضر فقط برای مدل‌های پایه در دسترس است، نه برای مدل‌های تیون‌شده.

چگونه cache warming را پیاده‌سازی کنم؟

یک cron job (مثلا هر ۴ دقیقه برای TTL ۵ دقیقه‌ای) با یک درخواست حداقلی به مدل اجرا کنید که system prompt کامل را دارد اما فقط ۱ توکن خروجی می‌خواهد. برای Gemini، cache را explicit ایجاد کنید و آی‌دی را در Redis نگه دارید. هزینه warming معمولا کمتر از ۱٪ کل بار است اما cold start را از بین می‌برد.

Cara Donovan
درباره نویسنده Cara Donovan

AI operations lead at a B2B SaaS. Builds the unglamorous infrastructure that keeps prod LLM apps from melting.