اكتشف المطورون أن ميزة التخزين المؤقت للمطالبات (prompt-caching) في Claude يمكن أن تفشل بصمت، حيث يتم فرض أسعار مميزة (premium rates) بينما تعيد صفرًا من الرموز (tokens) المخزنة مؤقتًا. أظهر تشغيل سجل (log) لمدة أسبوع على معالج WhatsApp عدم وجود أي قراءات من التخزين المؤقت على الإطلاق، ومع ذلك قامت واجهة برمجة التطبيقات (API) بفرض رسوم ميزة التخزين المؤقت — مما أدى إلى انخفاض التكاليف من 1,890 دولارًا إلى 406 دولارات شهريًا.
لماذا تهم هذه المشكلة
يهدف التخزين المؤقت للمطالبات إلى خفض التكاليف وتسريع الاستجابات عن طريق إعادة استخدام جزء ثابت من المطالبة (البادئة أو "prefix"). عندما تعمل هذه الميزة، يمكن للتطبيقات ذات الحركة المرورية العالية توفير مئات الدولارات من فواتيرها الشهرية. وعندما لا تعمل، يدفع المطورون مقابل ميزة لا يستخدمونها فعليًا، كما أن الفشل الصامت لا يعطي أي خطأ أو تحذير للإشارة إلى المشكلة.
كيف يظهر هذا الخلل
تقبل واجهة برمجة التطبيقات (API) علامة cache-control وبادئة (prefix)، ثم تبلغ عن عدد الرموز (tokens) التي تمت قراءتها من التخزين المؤقت. في الحالة التي تمت ملاحظتها، أعاد كل طلب عدد قراءات من التخزين المؤقت يساوي صفرًا. نجح الاستدعاء، ولم يتم إطلاق أي استثناء (exception)، وعكست الفاتورة تكلفة التخزين المؤقت المميزة. الفشل غير مرئي ما لم تقم بتسجيل عدد القراءات بشكل صريح.
الطرق الشائعة لتعطل التخزين المؤقت
- البادئة قصيرة جدًا – يحدد كل نموذج من نماذج Claude حدًا أدنى لطول الرموز (tokens) للبادئة القابلة للتخزين المؤقت. يحتاج Haiku 4.5 إلى 4,096 رمزًا على الأقل؛ بينما يحتاج Sonnet 4.6 إلى 1,024 فقط. إرسال بادئة أقصر يستوفي تنسيق الطلب ولكن الخدمة تتجاهل تعليمات التخزين المؤقت.
- تحرك بايت متغير – يتطلب التخزين المؤقت تطابقًا تامًا بايت ببايت. إضافة عنصر ديناميكي مثل طابع زمني، أو
new Date()، أو بريد إلكتروني للمستخدم في مقدمة مطالبة النظام (system prompt) يغير تسلسل البايتات، مما يؤدي إلى معاملة كل طلب كعملية كتابة جديدة غير مخزنة مؤقتًا. - تغير ترتيب قائمة الأدوات – يتم إدراج الأدوات في مقدمة المطالبة. إذا تم بناء مصفوفة الأدوات من مفاتيح الكائنات (object keys)، فقد يختلف ترتيب التكرار بين الاستدعاءات، مما يؤدي إلى تغيير تخطيط البايتات وكسر التخزين المؤقت.
إصلاحات يمكنك تطبيقها اليوم
- التحقق من طول البادئة – قبل إرسال الطلب، قم بتقدير عدد الرموز (tokens) للبادئة مقابل الحد الأدنى للنموذج. ارفض البادئة أو قم بحشوها (pad) إذا كانت أقل من المطلوب.
- تسجيل قراءات التخزين المؤقت في كل استدعاء – قم بتسجيل حقل "cache read tokens". إن تتابع الأصفار هو علامة واضحة على عدم استخدام التخزين المؤقت.
- تجميد البايتات الأولى للمطالبة – ابقِ البيانات الديناميكية بعيدًا عن الجزء المخزن مؤقتًا. إذا كان لابد من تضمين معلومات خاصة بالمستخدم، فضعها بعد البادئة المخزنة مؤقتًا.
- مزامنة معرفات النماذج – تأكد من أن معرف النموذج (model ID) المستخدم في التوجيه يتطابق مع المعرف المخزن في جدول التخزين المؤقت الخاص بك؛ حيث تمنع المعرفات غير المتطابقة عملية البحث في التخزين المؤقت.
زاوية التكلفة
بالنسبة لتطبيق يقوم بآلاف الاستدعاءات يوميًا، فإن الانتقال من عدم استخدام التخزين المؤقت إلى استخدامه يمكن أن يخفض النفقات الشهرية بشكل كبير — من حوالي 1,890 دولارًا إلى 406 دولارات في الحالة المذكورة. حتى حركة المرور المتواضعة تشهد توفيرًا ملحوظًا، كما أن تعزيز الأداء الناتج عن إعادة استخدام مطالبة ثابتة كبيرة يمكن أن يقلل من زمن الاستجابة (latency).
وجهة نظر مقابلة
ومع ذلك، فإن الطبيعة الصامتة للفشل تعني أن الطريقة الوحيدة للتأكد من أنك لا تدفع أكثر من اللازم هي التحقق من عدد القراءات — وهو أمر يتجاهله الكثيرون.
ما يجب مراقبته لاحقًا
- لوحات قياس المقاييس – أضف مقياسًا لرموز قراءة التخزين المؤقت (cache-read tokens) إلى جانب حجم الطلبات.
- استقرار ترتيب الأدوات – إذا كنت تعتمد على قوائم أدوات يتم إنشاؤها ديناميكيًا، ففكر في فرزها بشكل حتمي (deterministically) قبل تضمينها في المطالبة.
الخلاصة: لا يظهر التخزين المؤقت للمطالبات في Claude خطأً عندما يتجاهل طلبك بصمت. تحقق من فعالية التخزين المؤقت عن طريق تسجيل الرموز المقروءة (read tokens)، وافرض طولًا مناسبًا للبادئة، وحافظ على ثبات البايتات الأولى للمطالبة. عندها فقط ستجني فوائد التكلفة والسرعة الموعودة.
