Prompt caching را درست بچینید؛ یک تغییر کوچک cache را می‌سوزاند

|نویسنده: تیم تحریریه QUASA|7 دقیقه مطالعه| 1
Prompt caching را درست بچینید؛ یک تغییر کوچک cache را می‌سوزاند

برای گرفتن cache hit در APIهای OpenAI و Claude، ابزارها، دستورها و متن تکراری را در ابتدای درخواست ثابت نگه دارید؛ پیام تازهٔ کاربر و داده‌های متغیر را پس از آن بیاورید. مرز کش باید در پایان بخشی قرار بگیرد که در درخواست بعدی دوباره استفاده می‌شود. سپس توکن‌های خوانده‌شده از کش را در usage پاسخ بشمارید؛ فعال‌کردن قابلیت یا دیدن یک cache write به‌تنهایی نشانهٔ صرفه‌جویی نیست.

تطابق از ابتدای ورودی بررسی می‌شود. تغییر زودهنگام در تعریف ابزار، دستور یا تنظیمات سازگار با کش می‌تواند بخش قابل‌بازاستفاده را کوتاه کند یا از بین ببرد، حتی اگر سؤال کاربر همان باشد. برای پیدا کردن miss، طول بخش مشترک، محل مرز، زمان میان درخواست‌ها و شمارنده‌های read و write را کنار دو درخواست پیاپی بررسی کنید.

یک prefix پایدار چگونه ساخته می‌شود؟

الگوی مناسب برای یک دستیار دارای ابزار این است: ابتدا تعریف و ترتیب ثابت ابزارها، سپس دستورهای پایدار و متن مرجعی که بارها به کار می‌رود؛ بعد تاریخچه‌ای که بدون بازنویسی ادامه می‌یابد؛ و در انتها پیام تازه، شناسهٔ سفارش، زمان یا نتیجهٔ ابزار. این یک تصمیم طراحی است: فقط محتوایی را در بخش مشترک بگذارید که انتظار دارید عیناً تکرار شود. ثابت‌ماندن معنای یک دستور برای کش کافی نیست؛ جابه‌جایی بلوک‌ها یا تغییر طرح‌وارهٔ ابزار ورودی مقایسه‌شده را تغییر می‌دهد.

در نمونه‌ای فرضی از پشتیبانی سفارش، سیاست پاسخ‌گویی و تعریف ابزار جست‌وجوی سفارش می‌توانند پیش از مرز باشند. شمارهٔ سفارش و پاسخ جست‌وجو باید پس از آن بیایند. اگر برنامه زمان اجرای هر درخواست را به ابتدای دستورها اضافه کند، نخستین بخش ورودی در هر نوبت متفاوت می‌شود. گذاشتن مرز روی بلوکی که همین زمان را در خود دارد نیز ممکن است هر بار یک ورودی تازه بنویسد، بی‌آنکه درخواست بعدی چیزی از آن بخواند.

برای گفت‌وگوی چندمرحله‌ای، پیام‌های پیشین را در همان ترتیب حفظ کنید و نوبت تازه را به انتها بیفزایید. خلاصه‌سازی تاریخچه یا ویرایش یک پیام قدیمی، prefix ادامهٔ گفت‌وگو را تغییر می‌دهد. اگر چنین کاری بخشی از برنامه است، داشتن یک مرز جداگانه پس از دستورهای ثابت می‌تواند بازاستفاده از همان بخش را حفظ کند. prefix بلندتر تنها وقتی مفید است که واقعاً تکرار شود و خواندن‌های بعدی هزینهٔ نوشتن آن را جبران کنند.

حداقل طول، مرز و TTL در هر API

  • OpenAI: در راهنمای کش پرامپت OpenAI، حداقل prefix قابل‌ذخیره برای GPT-5.6 و مدل‌های جدیدتر ۱۰۲۴ توکن ورودیِ قابل‌مشاهده است. در این مدل‌ها مرز می‌تواند ضمنی باشد یا با prompt_cache_breakpoint روی یک بلوک پشتیبانی‌شده مشخص شود؛ حالت explicit بدون مرز صریح چیزی در کش نمی‌نویسد. مقدار پیش‌فرض و تنها مقدار پشتیبانی‌شدهٔ prompt_cache_options.ttl برابر ۳۰ دقیقه است. نوشتن با ضریب ۱٫۲۵ و خواندن در بیشتر این مدل‌ها با ضریب ۰٫۱ نرخ عادی ورودی محاسبه می‌شود؛ حداقل طول و کنترل نگهداری در مدل‌های قدیمی‌تر متفاوت است.
  • Claude: در مستندات کش Claude، حداقل طول برای Claude Opus 5.5 برابر ۵۱۲، برای Claude Sonnet 4.6 برابر ۱۰۲۴ و برای Claude Opus 4.6 برابر ۴۰۹۶ توکن آمده است. درخواست کوتاه‌تر بدون خطا اجرا می‌شود، اما کش نمی‌شود. cache_control می‌تواند در سطح درخواست مرز خودکار را روی آخرین بلوک قابل‌کش بگذارد یا روی یک بلوک، مرز صریح بسازد. TTL پیش‌فرض پنج دقیقه است و گزینهٔ یک‌ساعته هزینهٔ نوشتن بیشتری دارد.

در Claude ترتیب محاسبهٔ prefix از tools به system و سپس messages می‌رسد. مرز صریح را روی آخرین بلوک ثابت بگذارید؛ مرز خودکار برای تاریخچه‌ای که با افزودن پیام رشد می‌کند مناسب است، اما در درخواست‌هایی با انتهای متغیر ممکن است همان بخش متغیر را هم برای نوشتن انتخاب کند. در OpenAI نیز اگر مرز ضمنی شامل محتوایی است که در هر درخواست عوض می‌شود، مرز صریح پس از محتوای پایدار کنترل بیشتری بر محل نوشتن می‌دهد.

فاصلهٔ درخواست‌ها را با TTL مقایسه کنید. استفادهٔ دوباره از ورودی کش‌شده عمر آن را تازه می‌کند، اما درخواست بعدی باید زمانی برسد که ورودی هنوز برای بازاستفاده در دسترس است. در Claude زمان عمر از آغاز درخواستِ نوشتن یا خواندن حساب می‌شود؛ تولید پاسخ طولانی بخشی از فرصت درخواست بعدی را مصرف می‌کند. در مدل‌های جدید OpenAI، پنجرهٔ ۳۰ دقیقه‌ای حداقل عمر پس از آخرین نوشتن یا بازاستفاده است و ممکن است ورودی بیشتر هم نگه داشته شود.

hit واقعی را از usage حساب کنید

در پاسخ OpenAI، usage.input_tokens_details.cached_tokens تعداد توکن‌های خوانده‌شده از کش را نشان می‌دهد و cache_write_tokens توکن‌های نوشته‌شده را جدا می‌کند. نرخ hit مبتنی بر توکن را با تقسیم مجموع cached_tokens بر مجموع usage.input_tokens در مجموعه‌ای از درخواست‌های مشابه به دست آورید. میانگین سادهٔ درصد هر درخواست، به درخواست کوچک و بزرگ وزن یکسان می‌دهد و می‌تواند تصویر نادرستی بسازد.

در Claude، cache_read_input_tokens مقدار خوانده‌شده و cache_creation_input_tokens مقدار نوشته‌شده است. برای محاسبهٔ سهم توکن‌های خوانده‌شده از کش، مخرج را از مجموع این دو شمارنده و input_tokens بسازید؛ input_tokens به‌تنهایی کل ورودی را نشان نمی‌دهد. صفر بودن هر دو شمارندهٔ کش می‌تواند از نرسیدن بخش علامت‌گذاری‌شده به حداقل طول یا نبود مرز مؤثر خبر دهد. مثبت‌بودن creation در درخواست‌های پیاپی، همراه با read صفر، نشانه‌ای برای بررسی تغییر prefix یا انقضای ورودی قبلی است.

این نرخ را برای درخواست‌هایی با مدل، مسیر برنامه و الگوی prefix مشابه حساب کنید. یک نرخ کلی می‌تواند missهای مسیر گران‌تر را میان hitهای مسیر دیگر پنهان کند. تأخیر و هزینهٔ کل را نیز کنار شمارنده‌ها ببینید: کش فقط هزینهٔ بخشی از ورودی را تغییر می‌دهد و نرخ hit به‌تنهایی دربارهٔ هزینهٔ خروجی چیزی نمی‌گوید.

صرفه‌جویی در یک مثال فرضی چقدر است؟

فرض کنید سه درخواست، هرکدام ۲۰۰۰ توکن prefix یکسان و ۱۰۰ توکن بخش متغیر دارند. درخواست نخست prefix را می‌نویسد و دو درخواست بعدی پیش از پایان عمر کش آن را کامل می‌خوانند. بدون کش، ۶۳۰۰ توکن ورودی با نرخ عادی محاسبه می‌شود. با ضریب نوشتن ۱٫۲۵ و خواندن ۰٫۱، هزینهٔ ورودی برحسب «توکن با نرخ عادی» برابر ۲۰۰۰×۱٫۲۵ + ۱۰۰ + ۲×(۲۰۰۰×۰٫۱ + ۱۰۰)، یعنی ۳۲۰۰ واحد است.

اختلاف این دو حالت در همین فرض ۳۱۰۰ واحد است، نه قیمت دلاری یا نتیجهٔ آزمون یک برنامه. اگر درخواست دوم به‌جای خواندن دوباره بنویسد، فاصلهٔ زمانی زیاد شود یا تعرفهٔ مدل فرق کند، پاسخ حساب نیز تغییر می‌کند. همین محاسبه دلیل احتیاط در بلندکردن مصنوعی prefix را روشن می‌کند: توکن‌های افزوده ابتدا هزینه دارند و باید به دفعات کافی دوباره خوانده شوند.

برای پیدا کردن cache miss چه چیزهایی را مقایسه کنید؟

از دو پاسخ پیاپی که انتظار داشتید prefix مشترکی داشته باشند شروع کنید. در مدل‌های پشتیبانی‌شدهٔ Responses API، راهنمای عیب‌یابی OpenAI استفاده از prompt_cache_options.comparison_response_id را برای مقایسه با شناسهٔ پاسخ مبنا توضیح می‌دهد. نتیجهٔ prompt_cache_diagnostics می‌تواند دلیل تشخیص‌داده‌شدهٔ miss را نشان دهد؛ مقدار واقعی بازاستفاده را همچنان از cached_tokens پاسخ جاری بخوانید.

  1. طول را تا مرز کش بشمارید، نه تا پایان کل درخواست. پیام متغیر پس از مرز، کمبود طول prefix قابل‌ذخیره را جبران نمی‌کند.
  2. نام، ترتیب، توضیح و طرح‌وارهٔ ابزارها را مقایسه کنید. اگر فقط دسترسی به ابزار باید عوض شود، ثابت نگه‌داشتن تعریف ابزارها و تغییر انتخاب ابزار در OpenAI می‌تواند prefix مشترک را حفظ کند.
  3. دستورها، ترتیب پیام‌ها و تنظیمات را کنار هم بگذارید. در Claude تغییر پارامترهای thinking کش پیام‌ها را بی‌اعتبار می‌کند و بسته به مدل ممکن است بر کش system و tools نیز اثر بگذارد.
  4. زمان میان درخواست‌ها را با TTL انتخابی بسنجید. برای درخواست‌های هم‌زمان Claude نیز ورودی نوشته‌شده پس از شروع پاسخ نخست در دسترس قرار می‌گیرد؛ درخواست بعدی که زودتر برسد الزاماً hit نمی‌گیرد.

پس از اصلاح علت miss، read، write و هزینهٔ ورودی را در همان مسیر کاری دوباره مقایسه کنید. نتیجهٔ مطلوب prefix ثابتی است که در ترافیک واقعی بارها خوانده می‌شود؛ اگر فقط شمارندهٔ نوشتن بالا می‌رود، جای مرز یا محتوای پیش از آن هنوز با الگوی درخواست‌ها سازگار نیست.

بیشتر بخوانید:

اشتراک‌گذاری:

عضویت در خبرنامه

تازه‌ترین اخبار Web3، هوش مصنوعی و رمزارز را مستقیم در صندوق ایمیل خود دریافت کنید.

0