Prompt caching মানে provider আপনার prompt-এর শুরুর অংশে আগে যে কাজ করে ফেলেছে, সেটা আবার ব্যবহার করে। কোনো request-এ লম্বা system prompt, tool-এর তালিকা বা কথোপকথনের ইতিহাস বারবার এলে, সেই পুনরাবৃত্ত অংশের বিল কম রেটে হয়। coding agent প্রায় একই context প্রতি turn-এ আবার পাঠায়, তাই তার জন্য খরচ কমানোর সবচেয়ে বড় উপায় এটাই।
cache-টা upstream provider-এর। Tokens নিজে কোনো cache চালায় না। Tokens শুধু আপনার request forward করে, provider যে cache count রিপোর্ট করে সেটা পড়ে, আর ওই token-গুলোর বিল করে model-এর জন্য ঠিক করা cache price-এ। এই পেজে দুটো আলাদা করে দেখানো হয়েছে: কোনটা provider-এর নিয়ম, আর Tokens কী করে।
কে কী করে#
| প্রশ্ন | উত্তর |
|---|---|
| request cache hit পাবে কি না, তা কে ঠিক করে? | যে provider request চালায়, সে। Tokens জোর করে hit করাতে পারে না। |
| cache কতক্ষণ থাকবে আর prompt-এর minimum size কত, কে ঠিক করে? | provider, model ধরে ধরে। |
| Tokens কি আমার request-এর cache marker বদলায়? | না, যখন request provider-এর নিজের format-এই যায়। gateway যখন এক format থেকে অন্য format-এ translate করে, তখন cache marker বাদ পড়ে। |
| Tokens কি usage-এর সংখ্যা বদলায়? | না। response-এর usage object provider-এর। gateway format translate করলে cache field-গুলো map করে দেয় (নিচে দেখুন)। |
| cache read আর write-এর দাম কে ঠিক করে? | Tokens, model ধরে ধরে। যে model-এর cache price ঠিক করা নেই, তার বিল স্বাভাবিক input price-এ হয়। |
| কত টাকা গেল, কোথায় দেখব? | Usage-এ প্রতিটা request-এর cached token আর খরচ দেখা যায়। |
দুই রকমের caching#
Automatic caching: আপনাকে কিছুই বদলাতে হয় না। provider নিজেই ধরে ফেলে, আপনার prompt-এর শুরুটা আগের কোনো request-এর সঙ্গে মিলে যাচ্ছে, আর সেটা আবার কাজে লাগায়। OpenAI-র model এভাবে কাজ করে, DeepSeek-ও। provider-দের documentation বলছে, cache চলে prefix ধরে: request তখনই hit পায়, যখন তার শুরুটা আগের কোনো request-এর সঙ্গে হুবহু মেলে। DeepSeek নিজের cache-কে best effort বলে, hit-এর কোনো নিশ্চয়তা দেয় না। provider-এর minimum-এর চেয়ে ছোট prompt cache হয় না; OpenAI তাদের সবচেয়ে নতুন model-এর জন্য 1,024 token লিখেছে।
cache_control দিয়ে explicit caching: Anthropic-এর Messages API-তে যে content cache করতে চান, সেটা একটা cache_control block দিয়ে চিহ্নিত করে দেন। Anthropic-এর নিয়ম, October 2026-এ তাদের prompt caching documentation থেকে checked:
- একটা cache breakpoint তার আগের সবকিছুকে ঢেকে দেয়, এই ক্রমে:
tools,system, তারপরmessages। - প্রতি request-এ সর্বোচ্চ চারটা breakpoint দিতে পারেন। top-level
cache_controlfield দিলে শেষ cache করার মতো block-এ আপনা থেকেই একটা breakpoint বসে যায়। - default মেয়াদ 5 মিনিট, cache করা content প্রতিবার কাজে লাগলে মেয়াদ নতুন করে শুরু হয়।
"ttl": "1h"দিলে এক ঘণ্টা চাওয়া হয়। - model অনুযায়ী prompt-এর একটা minimum দৈর্ঘ্য আছে (Anthropic-এর টেবিলে 512 থেকে 4,096 token)। এর চেয়ে ছোট prompt স্বাভাবিকভাবেই চলে, error ছাড়া, কিন্তু cache হয় না।
- প্রথম response শুরু হওয়ার পরেই কেবল cache entry পাওয়া যায়। তাই একই মুহূর্তে পাঠানো parallel request একে অপরের cache পায় না।
- যেকোনো একটা স্তরে বদল, যেমন একটা tool definition edit করা, ওই স্তর আর তার পরের সবকিছুর cache বাতিল করে দেয়।
এগুলো Anthropic-এর নিজের model-এর নিয়ম। যেসব অন্য provider cache_control নেয়, তাদের নিয়ম আলাদা হতে পারে। আপনি যে model ব্যবহার করছেন, তার provider-এর documentation দেখে নিন।
/v1/messages দিয়ে cache_control ব্যবহার#
cache_control ঠিক সেভাবেই পাঠান, যেভাবে Anthropic-কে পাঠাতেন। যে provider Messages API বোঝে, তার কাছে request body যেমন লিখেছেন তেমনই যায়।
import os
import anthropic
client = anthropic.Anthropic(
base_url="https://tokens.bd",
api_key=os.environ["TOKENS_API_KEY"],
)
# Must be longer than the model's minimum cacheable length.
project_notes = open("project-notes.txt", encoding="utf-8").read()
def ask(question: str) -> None:
message = client.messages.create(
model="deepseek/deepseek-v4.1-flash",
max_tokens=300,
system=[
{
"type": "text",
"text": project_notes,
"cache_control": {"type": "ephemeral"},
}
],
messages=[{"role": "user", "content": question}],
)
usage = message.usage
print(
"input:", usage.input_tokens,
"| cache write:", usage.cache_creation_input_tokens or 0,
"| cache read:", usage.cache_read_input_tokens or 0,
"| output:", usage.output_tokens,
)
ask("Summarize the notes in one sentence.") # first call: expect a cache write
ask("List three risks mentioned in the notes.") # within the TTL: expect a cache readদ্বিতীয় call-এ cache read দেখালে বুঝবেন, marker এমন provider-এর কাছে পৌঁছেছে যে সেটা মানে। দুটো call-এই cache write আর cache read শূন্য এলে এর একটা সত্যি: prompt model-এর minimum-এর চেয়ে ছোট, যে provider চালাচ্ছে সে explicit caching সমর্থন করে না, অথবা request translate হয়ে গেছে (পরের অংশ দেখুন)। কোনো model-এর ক্ষেত্রে একমাত্র নির্ভরযোগ্য পরীক্ষা হলো দুটো একই call পাঠিয়ে দেখা।
কী পৌঁছায় আর কী বাদ পড়ে#
প্রতিটা model এক বা একাধিক upstream provider চালায়, আর প্রতিটা provider OpenAI format, Anthropic format, বা দুটোই বোঝে। provider আপনার format সমর্থন করলে Tokens request আপনার নিজের format-এই পাঠায়। না করলে translate করে।
| আপনি call করেন | provider যে format বোঝে | caching-এর কী হয় |
|---|---|---|
/v1/messages | Anthropic format-এ | body যেমন আছে তেমনই যায়। cache_control provider-এর কাছে পৌঁছায়। usage ফেরত আসে Anthropic-এর field-এ। |
/v1/messages | শুধু OpenAI format-এ | chat completions-এ translate হয়। cache_control marker বাদ পড়ে। provider-এর automatic caching তবুও কাজ করতে পারে। |
/v1/chat/completions | OpenAI format-এ | body যেমন আছে তেমনই যায়। automatic caching চলে। prompt_cache_key-এর মতো field আপনি পাঠালে provider-এর কাছে যায়। |
/v1/chat/completions | শুধু Anthropic format-এ | Messages-এ translate হয়। cache marker যোগও হয় না, বয়েও যায় না। Anthropic provider-এর usage আবার OpenAI-র field-এ map করে দেওয়া হয়। |
কোন provider আপনার request চালাবে, তা আপনি বেছে নিতে পারেন না। provider-দের priority ক্রমে চেষ্টা করা হয়, আর request পরেরটার কাছে যায় তখনই, যখন প্রথমটা fail করে বা সময়মতো সাড়া দেয় না। পরের provider আপনার prefix আগে দেখেনি, তাই ওই request-এ miss ধরে নিন।
Response-এর cache field#
gateway provider-এর usage object থেকে এই field-গুলো পড়ে। response-এর বাকি সবকিছু যেমন আছে তেমনই পৌঁছে দেওয়া হয়।
| Format আর field | মানে | Tokens বিল করে কীভাবে |
|---|---|---|
Chat completions-এ prompt_tokens | সব input token, cached গুলোও ধরে | cached বাদ দিয়ে input |
Chat completions-এ prompt_tokens_details.cached_tokens | cache থেকে আসা input token | cache read |
Chat completions-এ cache_creation_input_tokens (top level) | gateway কোনো Anthropic উত্তর translate করলে থাকে: cache-এ লেখা input token | cache write |
Messages-এ input_tokens | যে input token cache থেকে পড়াও হয়নি, cache-এ লেখাও হয়নি | input |
Messages-এ cache_read_input_tokens | cache থেকে আসা input token | cache read |
Messages-এ cache_creation_input_tokens | cache-এ লেখা input token | cache write |
এর দুটো ফল:
- দুই format আলাদাভাবে গোনে। chat completions-এ
prompt_tokens-এর ভেতরেই cached token ধরা আছে। Messages-এinput_tokens-এ নেই। দাম ধরার আগে Tokens দুটোকেই একই চারটা bucket-এ বদলে নেয়, তাই আপনাকে এই তফাত নিয়ে কিছু সামলাতে হবে না। - যে provider caching শুধু এমন field-এ জানায় যেটা Tokens পড়ে না, যেমন নিজস্ব কোনো hit counter, তার cached token স্বাভাবিক input হিসেবে বিল হয়ে যায়। যে model cache করে বলে আপনি জানেন, তার জন্য usage page-এ কোনো cached token না দেখালে request id-সহ support-কে জানান।
OpenAI-format stream-এ usage chunk আপনার কাছে আসে কেবল stream_options.include_usage দিলে। তবে বিল এর ওপর নির্ভর করে না: gateway দুই ক্ষেত্রেই stream মেপে রাখে। streaming দেখুন।
Cache token-এর বিল কীভাবে হয়#
প্রতিটা request চারটা bucket-এ ভাগ হয়, আর প্রতিটার নিজস্ব দাম আছে, প্রতি মিলিয়ন token হিসেবে:
cost = input x input price
+ cache read x cache-read price
+ cache write x cache-write price
+ output x output priceদাম আসে Tokens catalog-এ model-এর entry থেকে। যে model-এর cache price নেই, তার ওই bucket-এর বিল model-এর input price-এ হয়, তাই ওই model-এ caching কিছুই বাঁচায় না। cache price শূন্য মানে ওই bucket ফ্রি। আপনার plan-এ discount থাকলে সেটা মোটের ওপর বসে।
কাল্পনিক দামের একটা উদাহরণ: প্রতি মিলিয়ন token-এ input $2.00, cache read $0.20, output $8.00। একটা request-এ 10,000 input token, তার 9,880টা এসেছে cache থেকে, আর output হয়েছে 300 token।
| Bucket | Token | প্রতি মিলিয়নের দাম | খরচ |
|---|---|---|---|
| Input | 120 | $2.00 | $0.000240 |
| Cache read | 9,880 | $0.20 | $0.001976 |
| Output | 300 | $8.00 | $0.002400 |
| মোট | $0.004616 |
cache hit না হলে একই request-এর খরচ হতো 10,000 x প্রতি মিলিয়নে $2.00, সঙ্গে একই output, অর্থাৎ $0.0224। প্রতিটা model-এর আসল দাম model catalog আর pricing পেজে আছে, আর প্রতিটা request-এ আসলে কত চার্জ হয়েছে তা usage page-এ দেখা যায়।
কিছু provider cache entry লেখার জন্য বাড়তি নেয় (Anthropic নিজের API-তে 5 মিনিটের write-এ input price-এর 1.25 গুণ আর 1 ঘণ্টার write-এ 2 গুণ নেয়)। সেই বাড়তি আপনার বিলে আসে তখনই, যখন Tokens catalog-এ ওই model-এর cache-write price আছে। না থাকলে write input হিসেবে বিল হয়।
cached request-ও চলার আগে আপনার ব্যালান্সের সঙ্গে মিলিয়ে দেখা হয়। gateway আগে থেকে worst case ধরে টাকা আলাদা করে রাখে: আপনার max_tokens আর input-এর একটা আন্দাজ, স্বাভাবিক input rate-এ। কারণ cache hit হবে কি না, তা আগে থেকে জানা যায় না। তাই খুব বড় cached prefix-ওয়ালা request-এর শেষ খরচ ছোট হলেও কম ব্যালান্সের কারণে সেটা ফিরিয়ে দেওয়া হতে পারে। পরে settlement-এ আসল পরিমাণটাই কাটা হয়। বিস্তারিত chat completions পেজে।
Dashboard-এ cache hit দেখা#
Usage-এর activity table প্রতিটা request-এর token দেখায় input · N cached · output আকারে। cached সংখ্যাটা cache read আর cache write যোগ করে। row-র cost হলো request-টার পুরো চার্জ। provider usage না পাঠানোয় যে request-এর হিসাব আন্দাজে ধরা হয়েছে, তাতে Estimated badge থাকে।
একটা call-এ read আর write আলাদা করে দেখতে চাইলে response-এর usage object-টাই পড়ে log করে রাখুন।
আরও cache hit পাওয়ার উপায়#
এগুলো উপরে বলা provider-দের নিয়মেরই ফল।
- যা বদলায় না, সেটা আগে রাখুন। system prompt, tool definition আর লম্বা reference text শুরুতে থাকুক, request থেকে request-এ একই। যা বদলায়, যেমন নতুন user message, সেটা শেষে।
- prefix byte-এ byte এক রাখুন। system prompt-এর ওপরের দিকে timestamp, request id বা random value থাকলে প্রতি request-এ সেটা বদলে যায়, আর তার পরের সবকিছুর cache নষ্ট হয়। tool definition সব সময় একই ক্রমে রাখুন।
- ইতিহাসে যোগ করুন, আগেরটা নতুন করে লিখবেন না। আগের turn edit বা compact করলে নতুন prefix তৈরি হয়।
- একই model রাখুন। cache model ধরে ধরে আলাদা।
- মেয়াদের মধ্যে থাকুন। 5 মিনিটের মেয়াদে তার চেয়ে বেশি থামলে পরের request-এ আবার write-এর দাম দিতে হয়। ধীর interactive ব্যবহারে Anthropic model-এ
"ttl": "1h"মোটের ওপর কম পড়তে পারে, কারণ 1 ঘণ্টার write 5 মিনিটের write-এর চেয়ে বেশি দামি। - প্রথম request একা পাঠান। একই prefix নিয়ে parallel request ছাড়ার আগে প্রথম response শুরু হওয়া পর্যন্ত অপেক্ষা করুন।
- prompt যথেষ্ট লম্বা করুন। ছোট prompt provider-এর minimum-এর নিচে পড়ে, কখনোই cache হয় না।
সমস্যা হলে#
কখনোই cached token আসে না। উপরের দুই call-এর পরীক্ষাটা চালান। এই ক্রমে দেখুন: model-এর minimum-এর তুলনায় prompt-এর দৈর্ঘ্য, prompt-এর ওপরের দিকে কিছু এক call থেকে আরেক call-এ বদলাচ্ছে কি না, call দুটোর মাঝে কয়েক মিনিটের বেশি ফাঁক আছে কি না, আর আপনি /v1/messages-এ এমন model চালাচ্ছেন কি না যেটা শুধু OpenAI format-এ চলে (marker বাদ পড়ে)। যে model cache করার কথা, তাতে পরীক্ষায় read শূন্য এলে দুটো request id support-কে পাঠান।
cached token দেখা যাচ্ছে, কিন্তু request-এর খরচ প্রায় একই। model-টার সম্ভবত catalog-এ cache-read price নেই, তাই cached token input price-এ বিল হচ্ছে। usage page-এর cost model-এর দামের সঙ্গে মিলিয়ে দেখুন।
cache write token প্রত্যাশার চেয়ে বেশি। prompt-এর শুরুর দিকে প্রতিটা বদল একটা নতুন entry লেখে। এমন content খুঁজুন যা প্রতি request-এ বদলায়, আর এমন tool-এর তালিকা, যা এক turn থেকে আরেক turn-এ বদলে যাচ্ছে।
cache_control দিলে 400 আসে। provider request body ফিরিয়ে দিয়েছে। Anthropic error দেয়, যদি একটা request-এ automatic caching আর চারটা explicit breakpoint একসাথে থাকে। provider-এর সীমা দেখুন, তারপর errors পেজে যান।
coding agent-এর খরচ ভাবনার চেয়ে বেশি। prompt-এ কী যাবে আর কোথায় যাবে, তা ঠিক করে agent। সে আগের turn compact বা নতুন করে লিখলে prefix বদলে যায়, আর পরের request cache miss করে। আপনার agent-এর compaction-এর setting দেখুন, আর coding agents-এর অধীনে তার পেজ পড়ুন।