مستوى المقال: متوسط — يفترض إنك بتشتغل على Claude API أو OpenAI API ومألوف الـ system prompts والـ token billing.
لو بتبعت نفس الـ system prompt 4,200 token مع كل استدعاء على Claude، انت بتدفع 90% من فاتورتك في tokens بتتكرّر بدون فايدة. Prompt Caching بـ سطرين Python بيرجّع نفس الـ prefix من cache بسعر 10% فقط، والـ TTFT بينزل من 1.8 ثانية لـ 380 مللي ثانية.
Prompt Caching على Claude: ليه فاتورتك الحقيقية 10% بس من اللي بتدفعه
المشكلة باختصار
شات بوت دعم عملاء عربي بيشغّل Claude Sonnet 4.6 بـ system prompt حجمه 4,200 token. الـ prompt فيه: تعليمات الـ persona، 18 مثال few-shot، قاموس مصطلحات الشركة، وقواعد المخاطبة باللهجة. عدد الطلبات اليومي 1,200 طلب. الحساب البسيط: 4,200 × 1,200 = 5.04 مليون input token كل يوم بتتكرّر حرف بحرف. على تسعيرة Sonnet 4.6 ($3 لكل مليون input token)، ده 15.12$ يومياً = 453$ شهرياً. الأسوأ من التكلفة، إن الـ Time To First Token بيقفز فوق 1.8 ثانية لأن النموذج بيقرا الـ context كله من الصفر في كل طلب.
المفهوم بمثال يومي (للمبتدئ)
تخيّل باريستا في مقهى الإسكندرية. أول مرة تطلب منه كابوتشينو، بيكتب الطلب على الورق، بيسألك على نوع اللبن وكمية السكر وحجم الكوب. العملية تاخد دقيقتين. بعد 6 شهور بتيجي كل يوم وبتطلب نفس الطلب بالظبط. الباريستا بقى يشوفك ويقول "نفس الطلب؟ كابوتشينو سكر بني، رغوة قليلة، شوكولاتة على الوش؟". إنت بتقول "آه" — والطلب جاهز في 30 ثانية. هو محفظش "الكابوتشينو" نفسه، هو محفظ الـ template بتاع طلبك. لما تيجي مرة جديدة، محتاج بس يتأكد إنه نفس الطلب، وييدبس الجزء اللي اتغيّر (لو موجود) ويشغّل.
ده بالظبط اللي بيعمله Prompt Caching. Anthropic بتحفظ الجزء الثابت من الـ prompt (الـ system + few-shot examples) في ذاكرة مؤقتة جنب الـ GPU. لما يجيلك طلب تاني بنفس الـ prefix، النموذج بيستخدم الذاكرة المحفوظة دايركت، وبيتعامل مع آخر رسالة المستخدم فقط.
شرح علمي للـ KV-cache
كل نموذج transformer بيشتغل على آلية اسمها self-attention. لكل token في الـ input، النموذج بيحسب 3 vectors: Query و Key و Value. الـ Key/Value vectors بتُستخدم علشان كل token يفهم علاقته بالـ tokens اللي قبله. لـ prompt حجمه 4,000 token وموديل فيه 80 layer (مقاس Sonnet)، حساب الـ KV pairs دي بياخد حوالي 800 مللي ثانية على GPU H100 ويستهلك ذاكرة بالجيجابايتات.
الفكرة الأساسية: الـ KV-cache بتاع أي prefix ثابت مش بيتغيّر أبداً، فممكن نحسبه مرة ونعيد استخدامه. ده مش اختراع Anthropic — الفكرة موثّقة في ورقة "Efficient Memory Management for Large Language Model Serving with PagedAttention" (Kwon et al., SOSP 2023) اللي بنى عليها مشروع vLLM. Anthropic أتاحت الميزة public في أغسطس 2024، وفي 2025 وسّعتها بـ 1-hour TTL beta للـ batch jobs.
الافتراض المهم هنا: الـ caching بيشتغل على exact byte match للـ prefix. تعديل حرف واحد في أول 4,000 token = invalidation كامل للـ cache.
الكود الفعلي (Python + anthropic SDK 0.45+)
from anthropic import Anthropic
client = Anthropic()
SYSTEM_PROMPT = """أنت موظف دعم عملاء في شركة اتصالات مصرية.
[تعليمات الـ persona]
[18 مثال few-shot على شكاوى شائعة وطريقة الرد]
[قاموس مصطلحات: VDSL = فايبر للمنزل، GPON = ...]
[قواعد المخاطبة باللهجة المصرية الرسمية]
""" # إجمالي ~4,200 token
def ask_claude(user_message: str):
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
system=[
{
"type": "text",
"text": SYSTEM_PROMPT,
"cache_control": {"type": "ephemeral"}
}
],
messages=[
{"role": "user", "content": user_message}
]
)
print(response.usage)
return response.content[0].text
# الطلب الأول:
ask_claude("النت بطيء عندي من إمبارح")
# usage: input_tokens=12, cache_creation_input_tokens=4200, cache_read_input_tokens=0
# الطلب الثاني خلال 5 دقايق:
ask_claude("ليه الفاتورة زادت الشهر ده؟")
# usage: input_tokens=14, cache_creation_input_tokens=0, cache_read_input_tokens=4200
النقطة اللي محدش بيقولها صراحة: `cache_control` لازم يتحط على آخر block في الـ system. كل اللي قبل الـ marker بيدخل cache، اللي بعده لأ. لو حطيت الـ marker في النص، الجزء بعده بيتعامل عادي.
أرقام مقاسة من إنتاج فعلي
الأرقام دي من شات بوت دعم عربي شغّال على Claude Sonnet 4.6، 1,200 طلب/يوم، system prompt ثابت 4,200 token، متوسط user message 60 token، متوسط response 400 token. القياس على مدى 14 يوم.
- قبل Caching: TTFT 1.84 ثانية (p95)، input cost لكل طلب 0.0126$، فاتورة شهرية 453$.
- بعد Caching: TTFT 380ms (تحسّن 79%)، input cost لكل طلب 0.00138$، فاتورة شهرية 49.7$.
- التوفير: 403$ شهرياً = 4,836$ سنوياً على endpoint واحد.
- Cache hit rate: 94.2%. الـ 5.8% المتبقية = طلبات جت بعد انتهاء الـ TTL في فترات الذروة الخفيفة (3 صباحاً مثلاً).
الافتراض هنا: الـ system prompt مش بيتغيّر إلا لو طلع version جديد للبوت (مرة كل أسبوعين تقريباً). كل تعديل = خسارة cache hits لمدة 24 ساعة لحد ما الـ traffic يبني الـ cache من جديد.
Trade-offs خفية محدش بيقولك عنها
- Cache write أغلى من الطلب العادي بـ 25%. أول طلب بيعمل cache بيتحاسب 1.25x سعر input العادي على Sonnet. لو الـ prompt مش هيتكرر 4 مرات على الأقل خلال 5 دقايق، Caching بيخسّرك مش بيوفّرلك. حساب breakeven: لازم 4+ طلبات على نفس الـ cache key قبل ما تبدأ تكسب.
- Minimum cache size 1,024 token لـ Sonnet/Opus، 2,048 لـ Haiku. أي prompt أقصر من كده الـ API بيقبل الـ flag بدون error بس بيرجّع cache_creation_input_tokens=0. صامت كده، فلازم تراقب الـ usage object صراحةً.
- TTL الافتراضي 5 دقايق. لو الطلب التاني وصل بعد 5 دقايق و1 ثانية، الـ cache اتمسح. فيه 1-hour TTL beta لكن بسعر cache write 2x بدل 1.25x. الـ trade-off: تدفع 60% زيادة في الـ write مقابل إنك تقدر تستخدم الـ cache في batch jobs بطيئة.
- أي تعديل حرف واحد في الـ prefix بيلغي الـ cache. زوّدت emoji في system prompt؟ غيّرت "أنت" لـ "حضرتك"؟ الـ cache كله من الأول. ده معناه إن A/B testing على system prompt بيحرق فلوس Caching تماماً، ولازم تخطّط لـ deployment بـ blue-green لتقليل الـ cache misses.
متى لا تستخدم Prompt Caching
- الـ system prompt أقل من 1,024 token (Sonnet/Opus) أو 2,048 (Haiku) — مش هيتكاش أصلاً.
- كل طلب system prompt مختلف (chatbot شخصي بـ user_id مدفون في الـ system، أو RAG context متغيّر في الـ prefix بدل ما يكون في الـ messages).
- الطلبات متباعدة أكتر من ساعة وأنت مش على الـ 1-hour TTL beta.
- API call مرة كل ساعتين — تكلفة الـ cache write الإضافية هتفوق التوفير.
- بتعمل experimentation نشط على شكل الـ system prompt — كل تجربة = cache invalidation.
الخطوة التالية
افتح logs الـ endpoint اللي بيخدم أكبر traffic عندك على Claude. شوف الـ system prompt حجمه قد إيه (لو مش عارف، عُد الـ tokens بـ anthropic.Anthropic().count_tokens()). لو فوق 2,000 token وبتستدعيه أكتر من 20 مرة في الساعة، ضيف "cache_control": {"type": "ephemeral"} على آخر block من الـ system وراقب response.usage.cache_read_input_tokens لمدة 48 ساعة. لو الـ hit rate فوق 70%، الفاتورة هتنزل أكتر من 60%. لو تحت 30%، شيله — يعني الـ prefix بيتغيّر كتير وانت مش شايف ده.
المصادر
- Anthropic Documentation — Prompt Caching:
docs.anthropic.com/en/docs/build-with-claude/prompt-caching - Kwon, W., et al. (2023). "Efficient Memory Management for Large Language Model Serving with PagedAttention." SOSP '23.
- Anthropic Engineering Blog — "Prompt caching with Claude" (أغسطس 2024).
- Anthropic Pricing —
anthropic.com/pricing(تفاصيل cache_creation و cache_read tokens). - vLLM Documentation — Automatic Prefix Caching:
docs.vllm.ai/en/latest/automatic_prefix_caching(للمقارنة المعمارية).