डेव्हलपर्सना असे आढळले आहे की Claude चे prompt-caching शांतपणे (silently) अयशस्वी होऊ शकते, ज्यामुळे शून्य कॅश्ड टोकन्स (cached tokens) मिळतानाही प्रीमियम दर आकारले जातात. WhatsApp हँडलरवरील आठवडाभराच्या लॉग रनमध्ये एकही कॅशे रीड (cache read) दिसून आला नाही, तरीही API ने कॅशिंग फीचरसाठी बिल आकारले—ज्यामुळे खर्च प्रति महिना $1,890 वरून $406 पर्यंत कमी झाला.
ही समस्या का महत्त्वाची आहे
Prompt caching चा उद्देश प्रॉम्प्टचा एक स्थिर भाग (ज्याला “prefix” म्हणतात) पुन्हा वापरून खर्च कमी करणे आणि प्रतिसाद वेगवान करणे हा आहे. जेव्हा हे व्यवस्थित काम करते, तेव्हा हाय-ट्रॅफिक ॲप्स त्यांच्या मासिक बिलातून शेकडो डॉलर्स वाचवू शकतात. जेव्हा ते काम करत नाही, तेव्हा डेव्हलपर्स अशा फीचरसाठी पैसे देतात ज्याचा ते प्रत्यक्षात कधीच वापर करत नाहीत, आणि ही शांतपणे होणारी चूक (silent failure) समस्येचा संकेत देण्यासाठी कोणताही एरर किंवा वॉर्निंग देत नाही.
ही त्रुटी (bug) कशी दिसून येते
API एक cache-control flag आणि prefix स्वीकारते आणि त्यानंतर कॅशेमधून किती टोकन्स वाचले गेले याचा अहवाल देते. निरीक्षण केलेल्या प्रकरणात, प्रत्येक विनंतीमध्ये (request) कॅशे-रीड काउंट शून्य होता. कॉल यशस्वी झाला, कोणताही अपवाद (exception) उद्भवला नाही आणि बिलिंगमध्ये प्रीमियम कॅशे खर्च दिसून आला. जोपर्यंत तुम्ही स्पष्टपणे रीड काउंट लॉग करत नाही, तोपर्यंत ही त्रुटी दिसून येत नाही.
कॅशे बिघडण्याची सामान्य कारणे
- Prefix खूप लहान असणे – प्रत्येक Claude मॉडेल कॅशे करण्यायोग्य prefix साठी किमान टोकन लांबी निश्चित करते. Haiku 4.5 साठी किमान 4,096 टोकन्स आवश्यक आहेत; Sonnet 4.6 साठी फक्त 1,024 आवश्यक आहेत. लहान prefix पाठवल्याने विनंतीचे स्वरूप (request format) पूर्ण होते, परंतु सेवा कॅशे सूचनांकडे दुर्लक्ष करते.
- अस्थिर बाइटमध्ये बदल होणे – कॅशिंगसाठी बाइट-बाय-बाइट अचूक मॅच आवश्यक असते. सिस्टम प्रॉम्प्टच्या सुरुवातीला टाइमस्टॅम्प,
new Date(), किंवा युजरचा ईमेल यांसारखा डायनॅमिक घटक जोडल्यास बाइट सिक्वेन्स बदलतो, ज्यामुळे प्रत्येक विनंती ही एक नवीन, अनकॅश्ड (uncached) राईट म्हणून मानली जाते. - टूल लिस्टचा क्रम बदलणे – टूल्स प्रॉम्प्टच्या सुरुवातीला जोडले जातात. जर टूल ॲरे (tool array) ऑब्जेक्ट कीजपासून (object keys) तयार केला असेल, तर कॉल्स दरम्यान इटरेशनचा क्रम बदलू शकतो, ज्यामुळे बाइट लेआउट बदलतो आणि कॅशे बिघडतो.
तुम्ही आजच लागू करू शकणारे उपाय
- Prefix लांबीची पडताळणी करा – विनंती पाठवण्यापूर्वी, मॉडेलच्या किमान लांबीच्या तुलनेत prefix च्या टोकन संख्येचा अंदाज घ्या. जर ती कमी असेल, तर prefix नाकारून द्या किंवा त्यात आवश्यकतेनुसार भर घाला (pad).
- प्रत्येक कॉलवर कॅशे रीड्स लॉग करा – “cache read tokens” हे फील्ड रेकॉर्ड करा. सलग शून्य येणे हे कॅशे वापरला जात नाही याचे स्पष्ट लक्षण आहे.
- प्रॉम्प्टचे सुरुवातीचे बाइट्स स्थिर (freeze) ठेवा – डायनॅमिक डेटा कॅश्ड सेगमेंटच्या बाहेर ठेवा. जर तुम्हाला युजर-विशिष्ट माहिती समाविष्ट करणे आवश्यक असेल, तर ती कॅश्ड prefix नंतर ठेवा.
- मॉडेल आयडेंटिफायर्स सिंक्रोनाइझ करा – राउटिंगमध्ये वापरले जाणारे मॉडेल ID तुमच्या कॅशे टेबलमध्ये साठवलेल्या ID शी जुळते याची खात्री करा; विसंगत ID मुळे कॅशे लुकअप (cache lookup) होऊ शकत नाही.
खर्चाचा पैलू
दररोज हजारो कॉल्स करणाऱ्या ॲपसाठी, अनकॅश्डकडून कॅश्डकडे वळल्यामुळे मासिक खर्च मोठ्या प्रमाणात कमी होऊ शकतो—अहवालानुसार हा खर्च अंदाजे $1,890 वरून $406 पर्यंत खाली येऊ शकतो. अगदी कमी ट्रॅफिकमध्येही लक्षणीय बचत दिसून येते आणि मोठा स्थिर प्रॉम्प्ट पुन्हा वापरल्यामुळे मिळणारा परफॉर्मन्स बूस्ट लेटन्सी (latency) कमी करू शकतो.
प्रतिवाद
तथापि, ही त्रुटी शांतपणे (silent) घडत असल्यामुळे, तुम्ही जास्त पैसे भरत नाही आहात याची खात्री करण्याचा एकमेव मार्ग म्हणजे रीड काउंट तपासणे—याकडे अनेकजण दुर्लक्ष करतात.
पुढे काय पाहावे
- मेट्रिक डॅशबोर्ड्स – विनंतीच्या प्रमाणासोबत (request volume) कॅशे-रीड टोकन्ससाठी एक गेज (gauge) जोडा.
- टूल-ऑर्डरिंग स्थिरता – जर तुम्ही डायनॅमिकली तयार केलेल्या टूल लिस्टवर अवलंबून असाल, तर त्यांना प्रॉम्प्टमध्ये समाविष्ट करण्यापूर्वी निश्चित पद्धतीने (deterministically) सॉर्ट करण्याचा विचार करा.
थोडक्यात सांगायचे तर: जेव्हा Claude चे prompt caching तुमच्या विनंतीकडे शांतपणे दुर्लक्ष करते, तेव्हा ते कोणताही एरर देत नाही. रीड टोकन्स लॉग करून कॅशेची परिणामकारकता तपासा, योग्य prefix लांबी सुनिश्चित करा आणि प्रॉम्प्टचे सुरुवातीचे बाइट्स अपरिवर्तनीय (immutable) ठेवा. तरच तुम्हाला वचनित खर्च आणि वेगाचा फायदा मिळेल.
