प्रॉम्प्ट कॅशिंग सुरू केल्यामुळे माझे काहीही वाचले नाही—खरं तर, माझा OpenAI-API इनव्हॉइस सुमारे २५% वाढला. याचे मुख्य कारण एकच ओळ होती जी प्रत्येक विनंतीसोबत बदलत होती: सिस्टम प्रॉम्प्टमध्ये समाविष्ट असलेला एक टाइमस्टॅम्प.
LLM प्रोव्हायडर्स टोकन-प्रोसेसिंग खर्च कमी करण्यासाठी डेव्हलपर्सना प्रॉम्प्टचे तुकडे (fragments) कॅश करण्याची परवानगी देतात. कॅश रीड (एक “hit”) नियमित दराच्या केवळ एक दशांश इतका स्वस्त असतो, तर कॅश राईट (एक “miss”) साधारणपणे नियमित किमतीच्या १.२५ पट असतो. जर राईट झाले पण कॅश केलेला तुकडा कधीही वाचला गेला नाही, तर तो अतिरिक्त २५% खर्च वाया जातो. नेमके हेच घडले जेव्हा टाइमस्टॅम्पमुळे प्रॉम्प्ट कोणत्याही अस्तित्वात असलेल्या कॅश एंट्रीशी जुळू शकला नाही.
कॅशिंग उलट लागू का शकते
प्रॉम्प्ट कॅशिंग हे कॅश केलेल्या भागाचा अचूक (exact) बाइट सिक्वेन्स मॅच करून काम करते. प्रोव्हायडर इनपुटचा हॅश (hash) तयार करतो; जर तो हॅश स्टोअर केलेल्या एंट्रीशी जुळला, तर सिस्टम मागील गणना (computation) पुन्हा वापरते आणि स्वस्त रीड रेट लागू करते. कोणताही बदल—अगदी एक अक्षरही—मॅच तोडतो आणि नवीन गणना करण्यास भाग पाडतो, ज्यासाठी जास्त राईट रेट आकारला जातो.
माझ्या बाबतीत सिस्टम प्रॉम्प्टची सुरुवात अशी होती:
Current session started: 2026-07-14T09:41:07Z
प्रत्येक API कॉलसाठी टाइमस्टॅम्प अपडेट होत असल्यामुळे, विनंतीचे पहिले काही बाइट्स कधीही सारखे नव्हते. प्रोव्हायडरने प्रत्येक कॉलला एक नवीन कॅश एंट्री मानले, राईट प्रीमियम आकारला आणि कधीही रीड रेकॉर्ड केला नाही. परिणामी cache_creation_input_tokens मध्ये सतत वाढ होत होती, तर cache_read_input_tokens शून्यच राहिले होते, जे कॅश कधीही हिट होत नसल्याचे स्पष्ट लक्षण होते.
बिघडलेले कॅश कसे ओळखावे
API द्वारे पुरवलेले युसेज लॉग्स दोन महत्त्वाचे काउंटर्स देतात:
- cache_creation_input_tokens – ज्या टोकन्समुळे राईट (write) ट्रिगर झाले.
- cache_read_input_tokens – ज्या टोकन्सचा रीड (read) मुळे फायदा झाला.
जेव्हा पहिले वाढते आणि दुसरे स्थिर राहते, तेव्हा कॅशचा पुनर्वापर होत नाही. एक सोपी तपासणी म्हणजे अगदी तीच विनंती दोनदा करणे; जर कॅश व्यवस्थित काम करत असेल, तर दुसऱ्या कॉलमध्ये रीड टोकन्समध्ये वाढ दिसली पाहिजे.
समस्या कशी सुधारावी
उपाय सोपा आहे: कॅश केलेला भाग कॉल दरम्यान स्थिर (static) असल्याची खात्री करा. या दोन नियमांचे पालन करा:
- अपरिवर्तनीय (immutable) मजकूर आधी ठेवा. सिस्टम प्रॉम्प्ट्स, टूल डेफिनिशन्स किंवा कोणतीही सूचना जी कधीही बदलत नाही, ती विनंतीच्या सुरुवातीच्या बाइट्समध्ये असावी.
- परिवर्तनीय (mutable) मजकूर शेवटी जोडा. टाइमस्टॅम्प्स, युजर-जनरेटेड टेक्स्ट, रिक्वेस्ट आयडी किंवा कोणताही डेटा जो प्रत्येक कॉलनुसार बदलतो, तो कॅश केलेल्या भागाच्या नंतर आला पाहिजे.
जर एक अक्षरही बदलले, तर हॅश बदलतो आणि कॅश मिस (cache miss) कायम राहतो. प्रॉम्प्टची मांडणी अशी करा की टाइमस्टॅम्प शेवटी येईल, ज्यामुळे कॅश हिट रेट पुन्हा पूर्ववत होईल आणि बिल अपेक्षित कमी खर्चाच्या पातळीवर येईल.
कॅशिंग खरोखर कधी उपयुक्त ठरते
प्रॉम्प्ट कॅशिंग अशा परिस्थितींमध्ये उत्तम काम करते जिथे एकच सूचना संच (instruction set) अनेक वेळा वापरला जातो:
- एजंट लूप्स (Agent loops) जिथे AI वारंवार ठराविक टूल्सना कॉल करते.
- चॅट सेशन्स (Chat sessions) जे एका मोठ्या, स्थिर दस्तऐवजाचा संदर्भ देतात, जिथे फक्त वापरकर्त्याचा नवीनतम प्रश्न बदलतो.
- बल्क डेटा एक्सट्रॅक्शन (Bulk data extraction) जिथे अनेक रेकॉर्ड्ससाठी तोच पार्सिंग प्रॉम्प्ट वापरला जातो.
ज्या सिंगल-शॉट कॉल्समध्ये प्रत्येक वेळी नवीन कॉन्टेक्स्ट असतो—जसे की युनिक प्रिएम्बलसह विचारलेला एक प्रश्न—तिथे कॅशिंगचा कोणताही फायदा होत नाही आणि जर विनंतीमुळे अनवधानाने राईट ट्रिगर झाला, तर खर्च देखील वाढू शकतो.
लपलेले धोके
जरी प्रॉम्प्ट स्वतः स्थिर असला तरी, विनंती (request) पुढील प्रक्रियेत बदलली जाऊ शकते:
- प्रॉक्सिस किंवा अॅग्रिगेटर्स (Proxies or aggregators) जे क्रम बदलतात किंवा व्हाईटस्पेस (whitespace) समाविष्ट करतात, ते बाइट-बाय-बाइट मॅच तोडू शकतात.
- गेटवे सर्व्हिसेस (Gateway services) जे ऑथेंटिकेशन हेडर्स जोडतात किंवा JSON फॉरमॅटिंगमध्ये बदल करतात, ते नकळत कॅश केलेला भाग बदलू शकतात.
गेटवेद्वारे दोनदा एकसारखी विनंती पाठवून आणि रीड काउंटर्स तपासून कॅशिंग पाथ सुरक्षित आहे की नाही याची पडताळणी करणे उपयुक्त ठरते.
खर्चाचे व्यापक चित्र
राईट्सवरील २५% अतिरिक्त शुल्क हे कॅशिंग वापरल्याबद्दलचे दंड नाही; ते भविष्यातील वापरासाठी तुकडा स्टोअर करण्यासाठी लागणाऱ्या अतिरिक्त कम्प्युटचे प्रतिबिंब आहे. जेव्हा कॅश हिट होते, तेव्हा खर्च लक्षणीयरीत्या कमी होतो—अनेकदा नियमित दराच्या काही अंशांपर्यंत. मुख्य गोष्ट म्हणजे सिस्टमला प्रत्यक्षात कॅश हिट करू देणे. अन्यथा, तुम्ही कोणत्याही बचतीशिवाय प्रीमियम भरत राहता.
प्रतिवाद: कॅशिंग संपलेले नाही
काही डेव्हलपर्स असा युक्तिवाद करतात की स्टॅटिक विरुद्ध डायनॅमिक प्रॉम्प्ट भागांचे व्यवस्थापन करण्याची गुंतागुंत ही होणाऱ्या बचतीपेक्षा जास्त आहे. हा दृष्टिकोन या तथ्याकडे दुर्लक्ष करतो की अनेक प्रोडक्शन पाईपलाईन्समध्ये कॉन्फिगरेशन (स्टॅटिक) आणि युजर डेटा (डायनॅमिक) आधीच वेगळे केले जातात. प्रॉम्प्ट्सना त्यानुसार स्ट्रक्चर करून, API च्या मूळ डेव्हलपर्सना ज्या कॅशिंग मेकॅनिझममुळे फायदा झाला होता, त्याचाच वापर अतिरिक्त प्रयत्नांशिवाय करता येतो. ही तडजोड प्रॉम्प्ट डिझाइनमधील थोड्या शिस्तीची आहे, तंत्रज्ञानातील मूलभूत त्रुटी नाही.
पुढे काय पाहावे
- तुमच्या वापराच्या डॅशबोर्डमधील दोन कॅश काउंटर्सचे (cache counters) आठवड्याला निरीक्षण करा.
- कोणताही व्हेरिएबल घटक कॅश केलेल्या ब्लॉकच्या नंतर आहे याची खात्री करण्यासाठी प्रॉम्प्ट कन्स्ट्रक्शनचे ऑडिट करा.
- प्रत्यक्ष बचत मोजण्यासाठी, प्रतिनिधी वर्कलोडवर कॅशिंगसह आणि कॅशिंगशिवाय A/B टेस्ट्स चालवा.
- कोणत्याही प्रॉक्सीपूर्वी आणि नंतरच्या रॉ रिक्वेस्ट पेलोड्सची (raw request payloads) तुलना करून गेटवेची पडताळणी करा.
मुख्य निष्कर्ष
प्रॉम्प्ट कॅशिंगमुळे LLM API खर्च लक्षणीयरीत्या कमी होऊ शकतो, परंतु ते तेव्हाच शक्य आहे जेव्हा कॅश केलेला भाग सर्व कॉल्समध्ये तंतोतंत सारखा असेल. प्रॉम्प्टच्या सुरुवातीला एखादा विखुरलेला टाइमस्टॅम्प किंवा इतर कोणताही डायनॅमिक टोकन असल्यास, प्रत्येक वेळी खर्चिक 'राईट' (write) प्रक्रिया करावी लागते, ज्यामुळे बिल वाढते. स्थिर सूचना सुरुवातीला देऊन आणि बदलणारा डेटा शेवटी ठेवून, तुम्ही कॅशला त्याचे काम करू देता आणि तुमचा खर्च नियंत्रणात ठेवता.
