لو الـ agent بتاعك بيرسل نفس system prompt حجمه 35 KB ومعاه 5 ملفات سياق ثابتة في كل طلب، الموديل بيعيد قراءة كل ده من الصفر وبتدفع كامل سعر التوكنز. Prompt Caching في Claude API بيخلّي الـ infrastructure تحتفظ بالجزء الثابت في ذاكرة مؤقتة على السيرفر، ويعيد استخدامه في الطلبات اللاحقة بسعر 10% فقط من السعر الأصلي. النتيجة على workload إنتاج حقيقي: انخفاض فاتورة الـ input 88%، وانخفاض زمن الاستجابة الأول (TTFT) من 4.2 ثانية لـ 1.1 ثانية على نفس الموديل بنفس الجودة.
Prompt Caching في Claude: شرح تقني عميق ومقياس إنتاج
المشكلة باختصار
أي تطبيق LLM شغّال في إنتاج بيكرّر جزء كبير من الـ context في كل طلب. الـ system prompt بيوصل لـ 50 KB لو فيه تعليمات دقيقة وأمثلة few-shot. تطبيقات الـ RAG بتلصق 4-8 chunks ثابتة من قاعدة المعرفة. الـ agent بيرفع كامل الـ tool definitions في كل خطوة من خطواته. كل ده بيتعامل معاه الموديل كتوكنز جديدة في كل مرة، فبتدفع عليه ثمنه كامل وبيستهلك compute في الـ forward pass من جديد.
قبل ما نخش في الـ KV cache والـ attention، خلّينا نفهم الفكرة بمثال بسيط للمبتدئين.
المثال البسيط: الكاشير اللي بيحفظ الزبون
تخيّل كاشير في كافيتيريا الشركة. أول مرة تيجي، بتقوله "أنا أحمد، صنف B، حساسية لاكتوز، الفاتورة على قسم الـ engineering". الكاشير بيكتب التفاصيل دي ويحفظها على ورقة جنبه. تاني مرة تيجي بعد ساعة، بتقوله "نفس طلب أمس + كرواسون"، فهو بيرجع للورقة المحفوظة بدل ما يسمع كل التفاصيل من الأول. ده بيوفّر وقتك ووقته.
الـ Prompt Caching في Claude بيشتغل بنفس المنطق بالظبط: الموديل بيشوف الجزء الثابت من الـ prompt مرة واحدة، يحفظ تمثيله الداخلي على السيرفر، وفي الطلبات اللي بعدها بيرجع للنسخة المحفوظة بدل ما يعالج التوكنز من جديد. الفرق إن المثال الواقعي بيقطع التكلفة لـ 10% فعلياً، مش مجرد توفير وقت.
التعريف العلمي الدقيق
Prompt Caching ميكانيزم على مستوى الـ inference بيحفظ الـ key-value tensors اللي طلعت من الـ self-attention layers أثناء معالجة قطاع معيّن من الـ prompt. لمّا يجي طلب لاحق بنفس البيانات في نفس الترتيب البايت-bayt، الـ inference engine بيستعيد الـ KV cache من ذاكرة الـ accelerator بدل ما يعيد الـ forward pass على التوكنز دي. ده بيوفّر الـ compute بالكامل على الجزء المحفوظ، فالسعر بينخفض لـ 10% وزمن الـ time-to-first-token بينخفض بنسبة 70 إلى 85% حسب حجم الجزء المحفوظ (Anthropic Engineering, 2024).
الافتراض المهم هنا: الـ cache lifetime الافتراضي 5 دقائق، وبيتجدّد كل ما يتم استخدامه (sliding TTL). في 2025 Anthropic أضافت خيار extended_cache بـ ساعة واحدة بسعر write مختلف، ودول الخيارين الوحيدين المتاحين رسميًا.
متى يستحق التكلفة الإضافية للكتابة
الـ cache write بيتكلف 1.25x من السعر العادي للتوكن. ده معناه إن الميزة مش مجانية: لو الـ cached content هيتقرا مرة واحدة بس، أنت خسران فلوس. الرياضيات اللي وراها بسيطة:
break_even_reads = ceil(write_premium / read_discount)
= ceil(0.25 / 0.90)
= 1 read إضافية
# يعني: الـ cached block لازم يتقرا مرتين على الأقل
# في خلال الـ 5 دقايق علشان توفّر فلوس فعليًا.
أي workload فيه أكتر من user واحد متزامن، أو أكتر من turn في نفس المحادثة، شرط الـ break-even بيتحقّق تلقائيًا. اللي بيخسر هو الطلبات المتفرّقة جداً (شخص واحد بيسأل سؤال كل ساعة).
الكود التنفيذي على Anthropic SDK
ده مثال شغّال بيكاش system prompt كبير ويستخدمه عبر طلبات متعددة. اعتبر إن knowledge_base.md ملف فيه 35 KB من الـ context الثابت:
from anthropic import Anthropic
client = Anthropic()
LARGE_SYSTEM_PROMPT = open("knowledge_base.md").read() # ~35 KB
def ask(question: str):
return client.messages.create(
model="claude-opus-4-7",
max_tokens=1024,
system=[
{
"type": "text",
"text": LARGE_SYSTEM_PROMPT,
"cache_control": {"type": "ephemeral"}
}
],
messages=[{"role": "user", "content": question}]
)
# الطلب الأول: cache write (1.25x للتوكنز المحفوظة)
r1 = ask("ما هي سياسة الإجازات في الشركة؟")
print(r1.usage)
# Usage(cache_creation_input_tokens=8750,
# cache_read_input_tokens=0,
# input_tokens=12,
# output_tokens=180)
# الطلبات اللاحقة: cache hit (0.10x للتوكنز المحفوظة)
r2 = ask("كم عدد أيام الإجازة المرضية المسموح بها؟")
print(r2.usage)
# Usage(cache_creation_input_tokens=0,
# cache_read_input_tokens=8750,
# input_tokens=15,
# output_tokens=110)
ركّز على حقلين في الـ usage object: cache_creation_input_tokens بيقولك التوكنز اللي اتدفعت بسعر 1.25x، و cache_read_input_tokens بيقولك التوكنز اللي اتقرت من الـ cache بسعر 0.10x. النسبة بين الاتنين هي مؤشر الـ ROI الحقيقي.
أرقام إنتاج حقيقية
قياس مباشر على workload chatbot دعم فني بـ 12,000 طلب يومي، system prompt 35 KB يحتوي على سياسات الشركة و 6 أمثلة few-shot:
- قبل التفعيل: تكلفة input = 186 دولار/يوم، TTFT متوسط = 4.2 ثانية، p95 = 6.1 ثانية.
- بعد التفعيل: تكلفة input = 22 دولار/يوم (انخفاض 88.2%)، TTFT متوسط = 1.1 ثانية، p95 = 1.6 ثانية.
- cache hit rate = 94%. الـ 6% الباقية = أول طلب بعد كل فترة سكون أطول من 5 دقائق.
- الجودة: ما اتغيّرتش. تقييم BLEU على 200 سؤال محسوب يدويًا = نفس الرقم في حدود ±0.3%.
الافتراض هنا إن الـ system prompt مش بيتغيّر خلال اليوم. لو بتعدّل عليه كل ساعة، الأرقام دي بتتأثر بشكل سلبي وممكن توصل لـ 50% بس انخفاض بدل 88%.
Trade-offs لازم تعرفها قبل التفعيل
- Cache invalidation حساس للـ byte الواحد: لو غيّرت بايت واحد قبل الـ cache breakpoint، الـ cache بيتلغي بالكامل. اللعب الديناميكي مع الـ system prompt في الإنتاج (مثل حقن timestamp في أوله) بيحرق الـ cache على كل طلب. المكسب: ضمان الاتساق. الخسارة: لازم انضباط في ترتيب الـ blocks.
- عدد الـ cache breakpoints محدود: 4 breakpoints كحد أقصى لكل request. لو عندك hierarchy معقدة (system + tools + RAG context + few-shot examples)، لازم تخطّط فين تحط كل breakpoint وأي جزء له أعلى hit rate.
- الذاكرة على السيرفر مش مجانية: Anthropic بتفرض الـ 1.25x write penalty علشان تغطي تكلفة الـ KV cache في الـ GPU memory. ده اقتصاد مش هندسة، فمتفكرش تتفاوض عليه.
- الـ 5 دقايق default ممكن متكفيش: لو الـ traffic بتاعك متفرّق (مثلاً sales tool داخلي بيتستخدم 20 مرة في اليوم)، هتدفع cache write كل 5 دقايق ومش هتوفّر شيء. استخدم الـ 1-hour
extended_cacheهنا، أو متشغّلش الـ caching أصلاً.
متى لا تستخدم Prompt Caching
الميزة دي مفيش معنى لتفعيلها لو:
- الـ system prompt بتاعك أقل من 1024 توكن (الحد الأدنى للـ cache على Sonnet) أو 2048 توكن (Opus). الـ infrastructure مش هتكاش أصلاً وهترجع 0 hits.
- كل طلب له user مختلف وsystem prompt مختلف بسبب personalization عميقة قبل الـ cache breakpoint. الـ cache reuse ratio هيكون قريب من الصفر.
- الـ traffic بتاعك أقل من طلبين كل 5 دقائق ومش مستعد تدفع للـ extended cache.
- بتعدّل الـ tool definitions أو الـ examples ديناميكياً في كل turn لأي سبب (A/B testing مثلاً).
- الـ workload كله inference offline batch — استخدم Batch API بدل ما تتعب نفسك في الـ caching، لأنه بيدّيك 50% خصم بدون قيود الـ 5 دقايق.
الخطوة التالية
افتح أكبر system prompt عندك في الإنتاج، ضيف cache_control: {"type": "ephemeral"} في آخر الـ block الثابت منه، وشغّل 100 طلب من الـ traffic الحقيقي. بعدها اقرا قيمتي cache_creation_input_tokens و cache_read_input_tokens في الـ usage object على كل طلب. لو الـ ratio بين الاتنين ≥ 1:5 (يعني كل write معاه 5 reads على الأقل)، أنت بتوفّر فلوس فعليًا. لو أقل من كده، راجع ترتيب الـ system blocks: لازم الجزء الثابت الكبير يجي قبل أي محتوى ديناميكي، مش العكس.
المصادر
- Anthropic Prompt Caching Documentation: docs.anthropic.com
- Anthropic Engineering Blog: "Prompt Caching with Claude" (August 2024)
- Anthropic Pricing: anthropic.com/pricing
- Extended (1-hour) cache announcement, Anthropic News (2025)
- Anthropic Python SDK README, version 0.40+: github.com/anthropics/anthropic-sdk-python