المستوى: متوسط — يفترض إنك بعتت request لـ Claude API قبل كده، وعارف الفرق بين system و messages، وفاهم إن كل token له تكلفة.
Prompt Caching في Claude: ادفع 10% فقط على الـ Tokens المتكررة
لو فاتورتك على Claude API طلعت $1,400 الشهر اللي فات، وأنت بتبعت نفس system prompt طويل (كتالوج منتجات، توثيق داخلي، 12 مثال few-shot) في كل request، أنت بتدفع تقريبًا 90% أكتر من اللازم. Prompt Caching ميزة رسمية من Anthropic بتنزّل تكلفة الـ tokens المتكررة من $3 لـ $0.30 لكل مليون token على Claude Sonnet 4.6، بدون تغيير في جودة الإجابة.
المشكلة باختصار
تطبيقات RAG و الـ AI agents بترسل نفس الـ context طول الوقت: تعليمات النظام، أمثلة few-shot، PDF كتالوج منتج، schema بقواعد عمل. كل request جديد بيعيد إرسال الـ tokens دي ويدفع عليها سعر input كامل. الطبيعي إن السيرفر يحتفظ بالنسخة المعالجة من الـ KV state، ويعيد استخدامها لو الـ prefix جا تاني نفسه بايت ببايت. ده بالظبط اللي بيعمله Prompt Caching.
المفهوم بمثال بسيط
تخيّل إنك بتروح كافيه كل يوم الصبح، وبتطلب نفس الطلب بالظبط: "قهوة turkish بسكر قليل، ومعها كرواسون شوكولاتة سادة". في أول مرة الباريستا بيسمع الطلب كامل، يفكر، يجهز كل حاجة من الأول. الباريستا الغبي بيعمل نفس العملية الذهنية كل يوم حتى لو أنت زبون يومي معروف.
الباريستا الذكي بيحفظ الطلب: في اليوم التالت بيبصلك ويقول "أحمد، الـ usual؟"، تقول أيوه، يعمله في 30 ثانية. ده Prompt Caching بالظبط: الـ system prompt الطويل بيتخزّن في صورة معالجة، والـ request الجديد بياخد جزء بسيط من المعالجة لإنه بيبني فوق نتيجة محفوظة.
تقنيًا، الـ Transformer بيحوّل كل token لمصفوفتين Key و Value داخل كل layer من الـ attention. الـ tensors دي تكلفتها الحوسبية هي المسؤولة عن غالبية فاتورة الـ input. Prompt Caching بيحفظ المصفوفات دي بعد أول request مباشرة على نفس الـ GPU لمدة 5 دقايق افتراضيًا (قابلة للتمديد لساعة كاملة عبر extended-cache-ttl beta header)، وبيعيد استخدامها بدل ما يعيد حسابها.
الكود الفعلي
أربع خطوات بس: تحط cache_control على آخر block في الـ system prompt اللي عايز تخزّنه، تبعت request، تبص على حقول usage في الرد علشان تتأكد إن الـ cache اشتغل.
from anthropic import Anthropic
client = Anthropic()
# 18,400 token — كتالوج منتج + 12 مثال few-shot
LONG_SYSTEM = open("docs/product_catalog.txt").read()
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=512,
system=[
{"type": "text", "text": "أنت مساعد دعم فني عربي."},
{
"type": "text",
"text": LONG_SYSTEM,
"cache_control": {"type": "ephemeral"}
}
],
messages=[
{"role": "user", "content": "هل المنتج 4781 يدعم العربية؟"}
]
)
usage = response.usage
print(f"cache_creation_input_tokens: {usage.cache_creation_input_tokens}")
print(f"cache_read_input_tokens: {usage.cache_read_input_tokens}")
print(f"input_tokens (uncached): {usage.input_tokens}")