المستوى المطلوب: متوسط — تحتاج تعرف Anthropic SDK وأساسيات الـ messages API.
Prompt Caching: ليه فاتورة Claude بتاعتك أعلى 10x من اللازم
لو تطبيقك بيرسل 200 صفحة وثيقة قانونية لـ Claude في كل سؤال جديد، إنت بتدفع ثمن نفس الـ tokens مرة ورا التانية، رغم إنها ما اتغيرتش ولا حرف واحد. Prompt Caching بيحفظ الجزء الثابت من الـ prompt على سيرفرات Anthropic لمدة 5 دقايق، وبيحاسبك بـ 10% بس من السعر الأصلي على كل قراءة بعد كده.
المشكلة باختصار
افتراض إنك بتبني chatbot لشركة قانون مصرية. عندك dataset 50,000 token من العقود والقوانين، وكل مستخدم بيسأل سؤال جديد على نفس الـ dataset. لو بتبعت الـ dataset كامل في كل request بدون caching، الفاتورة بتكبر بشكل غير منطقي:
- 50,000 token × 500 سؤال يومي × 3$/مليون = 75$ يوميًا = 2,250$ شهريًا.
- الفعلي اللي محتاج تدفعه مع caching مفعّل: أقل من 230$ شهريًا.
- الباقي (2,020$) ضايع لأن Claude بيعيد قراءة نفس الوثائق 500 مرة كل يوم من الصفر.
الافتراض هنا إن كل الطلبات الـ 500 بتيجي على فترات أقل من 5 دقايق بين كل واحدة والتانية. لو في فجوات أطول، الأرقام بتختلف وهنرجع لها بعد شوية.
تخيّل المكتبة (شرح بسيط للمبتدئ)
تخيّل أمين مكتبة بيقرا نفس الكتاب من أول صفحة كل ما حد يسأله سؤال عن صفحة معينة. هياخد ساعة عشان يوصل للجزء المطلوب. لو خلّى الكتاب مفتوح على المكتب وحفظ في دماغه فهرس الموضوعات لمدة شوية، أي سؤال جاي هيرد عليه في ثواني، لأن الجهد الكبير اتعمل مرة واحدة في الأول.
Prompt Caching هو نفس الفكرة بالظبط. Anthropic بتحفظ نسخة جاهزة من الجزء المتكرر من الـ prompt بتاعك على السيرفرات بتاعتها لمدة 5 دقايق default، أو ساعة كاملة لو طلبت extended cache. أي طلب جاي في الفترة دي بيقرأ من الـ cache مباشرة، بدل ما الموديل يعيد معالجة كل token من الصفر.
التعريف العلمي الدقيق
الـ cache مش حفظ نص خام في key-value store. هو حفظ للـ KV-cache (Key-Value Cache) اللي الـ transformer بيبنيه أثناء الـ forward pass على كل layer من attention layers. يعني الموديل بيخزّن النتيجة الوسيطة (الـ keys والـ values المحسوبة لكل token) وبيستخدمها مباشرة في الطلبات اللي بعد كده، بدل ما يعيد الحساب الثقيل.
على مستوى الـ API، إنت بتحدد cache breakpoint عبر إضافة cache_control: {"type": "ephemeral"} على آخر block في الـ prompt اللي إنت عايز يتعمله cache. كل اللي قبله بيتخزّن، واللي بعده بيتعامل عادي. عندك حد أقصى 4 breakpoints في الـ request الواحد، فممكن تعمل caching متدرّج (system prompt + tool definitions + few-shot examples).
الحد الأدنى لتفعيل الـ cache
مش أي حاجة بتتخزّن. لازم الـ block يكون 1,024 token على الأقل لـ Sonnet و Opus، و2,048 token لـ Haiku. تحت الحد ده الطلب بيشتغل عادي بدون caching ومش هيرجعلك خطأ، بس الـ cache_control هيتجاهل بصمت. ده سبب شائع لمشكلة "الـ cache مش شغّال" عند المبتدئين.
كود شغّال على Anthropic SDK
الكود ده بيستخدم anthropic SDK 0.45+ على Python 3.10+. غيّر اسم الموديل لو شغّال على Opus 4.7.
import anthropic
client = anthropic.Anthropic()
LEGAL_CONTEXT = open("egyptian_civil_code.txt").read() # حوالي 50K token
def ask_legal_question(question: str):
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
system=[
{
"type": "text",
"text": "أنت مساعد قانوني متخصص في القانون المدني المصري."
},
{
"type": "text",
"text": LEGAL_CONTEXT,
"cache_control": {"type": "ephemeral"}
}
],
messages=[{"role": "user", "content": question}]
)
usage = response.usage
print(f"cache_creation: {usage.cache_creation_input_tokens}")
print(f"cache_read: {usage.cache_read_input_tokens}")
print(f"input (new): {usage.input_tokens}")
return response.content[0].text
# أول طلب: cache_creation_input_tokens = 50000، الباقي بيكتب الـ cache
ask_legal_question("ما هي شروط صحة العقد في القانون المصري؟")
# تاني طلب خلال 5 دقايق: cache_read_input_tokens = 50000
ask_legal_question("ما الفرق بين العقد والاتفاق؟")
السطر الحاسم في الكود ده هو cache_control: {"type": "ephemeral"}. ده اللي بيحوّل الفاتورة من 2,250$ لـ 230$. كل الباقي boilerplate موجود أصلًا في أي تطبيق Anthropic.
الأرقام الحقيقية: قبل وبعد
الأرقام دي مقاسة على 500 سؤال مختلف على نفس الـ legal context (50,000 token) باستخدام Sonnet 4.6 وأسعار Anthropic Pricing مايو 2026:
- بدون caching: 500 × 50,000 × 3$/مليون = 75$ في اليوم الواحد فقط على الـ input.
- مع caching 5 دقايق:
- أول طلب (cache write): 50,000 × 3.75$/مليون = 0.1875$.
- 499 طلب (cache read): 499 × 50,000 × 0.30$/مليون = 7.485$.
- الإجمالي اليومي للـ input: 7.67$.
- التوفير: 89.7% على تكلفة الـ input. التكلفة الشهرية بتنزل من 2,250$ لـ 230$ تقريبًا.
مهم تنتبه: الأرقام دي مبنية على فرضية إن كل الـ 500 طلب بتيجي خلال نوافذ 5 دقايق متتالية. لو في فجوات أكبر بين كل مجموعة طلبات، الـ cache بيتمسح وبتدفع write مرة تانية. الحل في الحالة دي: استخدم الـ "type": "ephemeral_1h" اللي TTL بتاعه ساعة كاملة، مع العلم إن الـ write بيكلّف 100% extra بدل 25%، وده break-even point مختلف.
الـ trade-offs اللي محدش بيقولك عليها
- Cache writes أغلى 25% من السعر العادي. لو ما حصلش read واحد بعد write، إنت بتخسر فلوس. الـ break-even = استخدام واحد على الأقل في خلال 5 دقايق.
- الترتيب مهم جدًا. لو غيّرت ترتيب الـ blocks في الـ system prompt، الـ cache بيتلغي بالكامل ويتعمل من جديد. القاعدة: الجزء الثابت لازم يكون أول حاجة دايمًا، والمتغيّر بعده.
- Cache مش shareable بين users. كل API key له cache منفصل. لو عندك multi-tenancy بـ key واحد، كل اللي شغالين على نفس الـ context هياستفيدوا. لو عندك key لكل tenant، كل واحد هيدفع write الأول بنفسه.
- Latency أحسن، مش revolutionary. الفرق بين cache hit و cache miss بيوصل لحوالي 30-40% أسرع في TTFT (time-to-first-token) على contexts كبيرة. لو متوقّع 10x، إنت بتتوقّع غلط.
كيف تعرف إن الـ cache شغّال فعلًا
كل response من Claude API بيرجع usage object فيه أربعة حقول مهمة لازم تراقبهم:
input_tokens: الـ tokens الجديدة (مش متخزّنة).cache_creation_input_tokens: الـ tokens اللي اتعملها cache في الطلب ده (الـ write).cache_read_input_tokens: الـ tokens اللي اتقرت من cache موجود (الـ read الرخيص).output_tokens: مخرجات الموديل.
لو cache_read_input_tokens = 0 دايمًا حتى في الطلبات اللي بعد الأولى، يبقى في مشكلة في الترتيب أو الفترة الزمنية بين الطلبات أو الـ block أقل من الحد الأدنى. ابدأ من النقاط دي بالترتيب.
متى Prompt Caching مش الحل أصلاً
القاعدة الذهبية: لو معدل الطلبات على نفس الـ context أقل من واحد كل 5 دقايق، الـ caching هيكلّفك أكتر من اللي بيوفّره. لأن كل cache write بيكون 25% أغلى من السعر العادي. لو بتدفع write كل مرة بدون reads بعدها، إنت بتدفع زيادة بدل ما توفّر.
كمان مش مناسب للحالات دي:
- الـ system prompt قصير (أقل من 1,024 token).
- كل سؤال له context مختلف تمامًا (RAG على diverse documents بدون مكون ثابت).
- تطبيق batch بـ 10 طلبات شهريًا — استخدم Message Batches API بدل ذلك للحصول على خصم 50%.
- لو الـ context بيتغيّر كل request (timestamps أو IDs ديناميكية في المتن — احذفها من الـ cached part).
الخطوة التالية
افتح أكبر system prompt عندك دلوقتي. لو طوله أكتر من 1,024 token وبتبعته في كل request، ضيف cache_control: {"type": "ephemeral"} عليه واعمل deploy. شغّل 10 طلبات وراقب cache_read_input_tokens في الـ usage. لو ظهرت بقيمة موجبة من الطلب الثاني فما فوق، إنت توفّر فلوس بشكل فوري ومقاس.
مصادر
- توثيق Prompt Caching الرسمي من Anthropic:
docs.anthropic.com/en/docs/build-with-claude/prompt-caching. - إعلان Prompt Caching على مدونة Anthropic، أغسطس 2024:
anthropic.com/news/prompt-caching. - صفحة الأسعار الرسمية مع تفاصيل cache write/read multipliers:
docs.anthropic.com/en/docs/about-claude/pricing. - ورقة Pope et al. 2022 — "Efficiently Scaling Transformer Inference" — لشرح KV-cache في الـ transformer.
- Anthropic Cookbook، أمثلة عملية لـ prompt caching:
github.com/anthropics/anthropic-cookbook.