لم يوفر لي تفعيل تخزين المطالبات (prompt caching) أي شيء - بل في الواقع، ارتفعت فاتورة OpenAI-API الخاصة بي بنحو الربع. وكان السبب سطراً واحداً يتغير مع كل طلب: طابع زمني (timestamp) مدمج في مطالبة النظام (system prompt).

يتيح مزودو نماذج اللغة الكبيرة (LLM) للمطورين تخزين أجزاء من المطالبات مؤقتاً لتقليل تكاليف معالجة الرموز (tokens). تكلفة القراءة من التخزين المؤقت (حالة "hit") ضئيلة جداً، حيث تعادل عُشر السعر العادي، بينما تكلفة الكتابة في التخزين المؤقت (حالة "miss") تبلغ حوالي 1.25 ضعف السعر الطبيعي. إذا تمت عملية كتابة ولكن لم يتم قراءة الجزء المخزن أبداً، فإن رسوم الـ 25% الإضافية تذهب سدى. وهذا بالضبط ما حدث عندما منع الطابع الزمني المطالبة من مطابقة أي إدخال موجود في التخزين المؤقت.

لماذا يمكن أن يؤدي التخزين المؤقت إلى نتائج عكسية

يعمل تخزين المطالبات مؤقتاً عن طريق مطابقة تسلسل البايتات (byte sequence) الدقيق للجزء المخزن. يقوم المزود بعمل هاش (hash) للمدخلات؛ فإذا تطابق الهاش مع إدخال مخزن، يعيد النظام استخدام الحسابات السابقة ويطبق سعر القراءة الرخيص. أي اختلاف - حتى لو كان حرفاً واحداً - يكسر المطابقة ويجبر النظام على إجراء عملية حسابية جديدة، يتم فوترتها بسعر الكتابة الأعلى.

في حالتي، بدأت مطالبة النظام بـ:

Current session started: 2026-07-14T09:41:07Z

نظرًا لأن الطابع الزمني كان يتحدث مع كل استدعاء لـ API، فإن البايتات القليلة الأولى من الطلب لم تكن متطابقة أبداً. تعامل المزود مع كل استدعاء كإدخال جديد في التخزين المؤقت، وفرض رسوم الكتابة الإضافية، ولم يسجل أي عملية قراءة. وكانت النتيجة ارتفاعاً مستمراً في cache_creation_input_tokens بينما ظل cache_read_input_tokens عند الصفر، وهي علامة واضحة على أن التخزين المؤقت لم يتم استخدامه أبداً.

كيف تكتشف التخزين المؤقت المعطل

توفر سجلات الاستخدام التي يوفرها الـ API عدادين رئيسيين:

  • cache_creation_input_tokens – الرموز (tokens) التي تسببت في عملية كتابة.
  • cache_read_input_tokens – الرموز التي استفادت من عملية قراءة.

عندما يرتفع الأول ويبقى الثاني ثابتاً، فهذا يعني أن التخزين المؤقت لا يُعاد استخدامه. اختبار سريع للتأكد هو تكرار نفس الطلب تماماً مرتين؛ يجب أن يظهر الاستدعاء الثاني ارتفاعاً في رموز القراءة إذا كان التخزين المؤقت يعمل بشكل صحيح.

إصلاح المشكلة

الحل بسيط: تأكد من أن المنطقة المخزنة مؤقتاً ثابتة عبر الاستدعاءات. اتبع هاتين القاعدتين:

  1. ضع المحتوى غير القابل للتغيير أولاً. يجب أن تشغل مطالبات النظام، أو تعريفات الأدوات، أو أي تعليمات لا تتغير أبداً، البايتات الأولى من الطلب.
  2. ألحق المحتوى القابل للتغيير في النهاية. يجب أن تأتي الطوابع الزمنية، أو النصوص التي ينشئها المستخدم، أو معرفات الطلبات (request IDs)، أو أي بيانات تتغير مع كل استدعاء بعد الجزء المخزن مؤقتاً.

إذا تغير حرف واحد فقط، سيتغير الهاش ويستمر فشل التخزين المؤقت (cache miss). إعادة ترتيب المطالبة بحيث يوضع الطابع الزمني في النهاية يعيد معدل نجاح التخزين المؤقت (cache hit rate) ويخفض الفاتورة مرة أخرى إلى مستوى التكلفة المنخفضة المتوقع.

متى يساعد التخزين المؤقت فعلياً

يتألق تخزين المطالبات مؤقتاً في السيناريوهات التي يُعاد فيها استخدام نفس مجموعة التعليمات عدة مرات:

  • حلقات الوكيل (Agent loops) حيث يقوم الذكاء الاصطناعي باستدعاء مجموعة ثابتة من الأدوات بشكل متكرر.
  • جلسات الدردشة التي تشير إلى مستند طويل وثابت بينما يتغير استعلام المستخدم الأخير فقط.
  • استخراج البيانات الضخمة حيث يتم تطبيق نفس مطالبة التحليل (parsing prompt) على العديد من السجلات.

بالنسبة للاستدعاءات لمرة واحدة (single-shot calls) التي تتضمن سياقاً جديداً في كل مرة - مثل سؤال لمرة واحدة مع مقدمة فريدة - لا يوفر التخزين المؤقت أي فائدة، بل قد يضيف تكلفة إذا تسبب الطلب عن غير قصد في عملية كتابة.

عثرات خفية

حتى لو كانت المطالبة نفسها ثابتة، يمكن تغيير الطلب في المراحل اللاحقة:

  • الوكلاء (Proxies) أو المجمّعات (aggregators) التي تعيد ترتيب البيانات أو تحقن مسافات بيضاء يمكن أن تكسر مطابقة البايتات.
  • خدمات البوابة (Gateway services) التي تسبق رؤوس المصادقة (authentication headers) أو تعدل تنسيق JSON قد تغير الجزء المخزن مؤقتاً عن غير قصد.

يساعد الاختبار من خلال البوابة عن طريق إرسال طلب متطابق مرتين والتحقق من عدادات القراءة في التأكد من أن مسار التخزين المؤقت لا يزال سليماً.

الصورة الأوسع للتكلفة

الرسوم الإضافية بنسبة 25% على عمليات الكتابة ليست عقوبة على استخدام التخزين المؤقت؛ بل هي تعكس الحوسبة الإضافية اللازمة لتخزين الجزء لإعادة استخدامه مستقبلاً. عندما تحدث حالة "cache hit"، تنخفض التكلفة بشكل كبير - غالباً إلى جزء بسيط من السعر العادي. المفتاح هو السماح للنظام بالوصول فعلياً إلى التخزين المؤقت، وإلا فستدفع الرسوم الإضافية دون أي توفير.

الحجة المضادة: التخزين المؤقت لم يمت

يجادل بعض المطورين بأن تعقيد إدارة أجزاء المطالبة الثابتة مقابل الديناميكية يفوق التوفير المحقق. وتتجاهل هذه الرؤية حقيقة أن العديد من مسارات الإنتاج تفصل بالفعل بين الإعدادات (الثابتة) وبيانات المستخدم (الديناميكية). ومن خلال هيكلة المطالبات وفقاً لذلك، يمكن الاستفادة من نفس آلية التخزين المؤقت التي أنقذت المطورين الأصليين لواجهة برمجة التطبيقات (API) دون بذل مجهود إضافي. إن المقايضة هنا هي مجرد انضباط بسيط في تصميم المطالبات، وليست عيباً جوهرياً في التكنولوجيا.

ما يجب مراقبته لاحقاً

  • راقب عدادي التخزين المؤقت في لوحة تحكم الاستخدام الخاصة بك أسبوعياً.
  • راجع بناء المطالبة للتأكد من أن أي عنصر متغير يقع بعد الكتلة المخزنة مؤقتاً.
  • أجرِ اختبارات A/B مع وبدون التخزين المؤقت على عبء عمل ممثل لقياس التوفير الفعلي.
  • تحقق من صحة البوابة (gateway) من خلال مقارنة حمولات الطلبات الخام قبل وبعد أي وكيل (proxy).

الخلاصة

يمكن لتخزين المطالبات مؤقتاً أن يقلص تكاليف واجهة برمجة تطبيقات LLM بشكل كبير، ولكن فقط إذا كان الجزء المخزن مؤقتاً متطابقاً تماماً عبر جميع الاستدعاءات. إن وجود طابع زمني عابر أو أي رمز ديناميكي آخر في بداية المطالبة يفرض عملية كتابة مكلفة في كل مرة، مما يؤدي إلى تضخم الفاتورة. ومن خلال وضع التعليمات الثابتة في البداية وتأجيل البيانات المتغيرة إلى النهاية، فإنك تترك التخزين المؤقت يقوم بعمله وتحافظ على نفقاتك تحت السيطرة.