اگر امروز برای مدیریت هزینههای استنتاج خود تنها به تغییر نام فیلدها در دیتابیس تکیه میکنید، احتمالاً بخش بزرگی از حجم ورودیهای خود را بهصورت خاموش از دست میدهید. خطر واقعی در مهاجرت بین ارائهدهندگان، محل ذخیره اعداد نیست، بلکه معنای واقعی این اعداد است. تاریخچه هزینهها به این دلیل تکهتکه نمیشود که دادهها در مکانهای مختلف هستند، بلکه به این دلیل است که دو فیلد با نام یکسان، چیزهای متفاوتی را میشمارند؛ تضادی که یک آداپتور ساده بر پایه تغییر نام (Rename-based adapter) هرگز نمیتواند آن را تشخیص دهد.
بسیاری از توسعهدهندگان تصور میکنند توکن (Token) — مثل برشهای یک کیک طولانی که مدل تکهتکه میخورد — یک مقدار جهانی و ثابت است. اما در واقعیت، OpenAI، Anthropic و Google از ریاضیات کاملاً متفاوتی برای گزارش مصرف استفاده میکنند. این تفاوت باعث ایجاد یک شکاف گزارشدهی میشود که میتواند یک مهاجرت را ارزانتر از آنچه در واقعیت هست جلوه دهد، صرفاً چون توکنهای کششده نادیده گرفته شدهاند. این نوسانات در نحوه مدیریت توکنها، یادآور تغییرات کلیدی در مدلهای کدنویسی این سه شرکت است که مستقیماً بر پنجرههای متنی و هزینههای عملیاتی اثر گذاشت.
تصور کنید پرامپت سیستمی شما یک بلوک متنی عظیم و ثابت است و برای کاهش هزینه از قابلیت کشینگ استفاده میکنید. اگر سیستم ردیابی شما فرض کند همه ارائهدهندگان توکنها را یکسان میشمارند، ممکن است توکنهایی را نادیده بگیرید که ۹۰٪ حجم ترافیک شما را تشکیل میدهند. این همان تله «شامل-در-مقابل-افزایشی» است.
تلهٔ شامل-در-مقابل-افزایشی
برای درک این تله باید به فیلدهای خاص ارائه شده توسط هر فروشنده نگاه کرد. این ارائهدهندگان از سه نام مختلف برای ورودی، سه نام برای خروجی و سه روایت متفاوت برای کش استفاده میکنند:
- OpenAI: در پاسخهای Chat Completions، مقادیر
usage.prompt_tokens،usage.completion_tokensوusage.total_tokensرا ارائه میدهد. جزئیات بیشتر درusage.prompt_tokens_details(شاملcached_tokens) و درusage.completion_tokens_details(شاملreasoning_tokens،accepted_prediction_tokensوrejected_prediction_tokens) قرار دارد. - Anthropic: پاسخهای Messages شامل
usage.input_tokens،usage.output_tokens،usage.cache_creation_input_tokensوusage.cache_read_input_tokensاست. ایجاد کش بر اساس TTL به دو بخشephemeral_5m_input_tokensوephemeral_1h_input_tokensتقسیم میشود. جزئیات خروجی نیز شاملusage.output_tokens_details.thinking_tokensبرای تفکیک توکنهای تفکر است. - Google: در Gemini، بخش
usageMetadataشاملpromptTokenCount،candidatesTokenCount،cachedContentTokenCount،thoughtsTokenCount،toolUsePromptTokenCountوtotalTokenCountاست.
تفاوت در محاسبات ریاضی
مشکل اصلی اینجاست که آیا عدد ورودی نهایی «شامل» (Inclusive) توکنهای کش است یا «افزایشی» (Additive):
- OpenAI و Google (شامل): در OpenAI، مقدار
cached_tokensزیرمجموعهای ازprompt_tokensاست. یعنی توکنهای کششده قبلاً در عدد کلی شمرده شدهاند و حالا فقط برای قیمتگذاری تفکیک میشوند. گوگل نیز همین الگو را دنبال میکند:cachedContentTokenCountتفکیکی ازpromptTokenCountاست، نه مقداری که به آن اضافه شود. - Anthropic (افزایشی): بر اساس مستندات آنتروپیک،
input_tokensفقط توکنهای بعد از آخرین نقطهٔ شکستِ کش (Cache Breakpoint) را نشان میدهد، نه تمام توکنهای ورودی ارسال شده. کل ورودی باید به این صورت بازسازی شود:cache_read_input_tokens+cache_creation_input_tokens+input_tokens. این سه باکت با هم همپوشانی ندارند.
اگر شما هر دو مقدار prompt_tokens (اوپنایآی) و input_tokens (آنتروپیک) را به یک ستون واحد به نام «ورودی» مپ کنید، در واقع تمام توکنهای کششده در گزارشات آنتروپیک را حذف کردهاید. در حجم کاری که دارای یک پرامپت سیستمی بزرگ و ثابت است — که در اکثر سیستمهایی که از کشینگ استفاده میکنند صادق است — این شکاف گزارشدهی بسیار عظیم خواهد بود.
همین تله در بخش خروجی نیز وجود دارد. توکنهای استدلالی (Reasoning) و تفکر (Thinking) در هر سه ارائهدهنده به عنوان خروجی محاسبه شده و در عدد کلی خروجی شمرده میشوند. با این حال، چون اینها اجزایی هستند که احتمال تغییر اندازه آنها در طول مهاجرت بین مدلها بسیار زیاد است، اسکیمایی که آنها را مجزا نگه ندارد، نمیتواند توضیح دهد که چرا مبلغ صورتحساب تغییر کرده است. این چالش در تحلیل استراتژیهای قیمتگذاری مدلهای جدید مانند Nemotron 3 Ultra نیز دیده میشود، جایی که کاهش نرخها بدون تفکیک دقیق توکنها، معنای واقعی صرفهجویی را پنهان میکند.
حل شکاف اسکیمایی
برای جلوگیری از این مشکل، باید رکوردها را بر اساس «باکتهای غیرهمپوشان» مدلسازی کنید. این تنها ساختاری است که اجازه تبدیل بین کنوانسیونهای مختلف را بدون از دست رفتن دادهها میدهد. هر شمارش باید یک مقدار متمایز از توکنها باشد، به طوری که مجموع باکتهای ورودی برابر با حجم واقعی ورودی باشد.
یک رکورد نرمالشده باید از ساختاری مانند NormalizedUsage پیروی کند که شامل موارد زیر باشد:
- provider: رشتهای برای نام ارائهدهنده (مثلاً "openai", "anthropic", "google").
- model: رشته دقیق مدل همانطور که ارسال شده است، نه یک نام دوستانه؛ زیرا نامهای مستعار (Aliases) در طول زمان متفاوت حل میشوند و صورتحسابها بر اساس رشته دقیق مدل صادر میشوند.
- requestId: شناسهی درخواست ارائهدهنده برای تطبیق دادهها (Reconciliation).
- input_fresh: توکنهایی که با نرخ استاندارد ورودی محاسبه شدهاند.
- input_cache_read: توکنهایی که با نرخ خواندن از کش محاسبه شدهاند.
- input_cache_write: توکنهایی که با نرخ نوشتن در کش محاسبه شدهاند.
- output_visible: خروجی نهایی به استثنای توکنهای استدلالی/تفکر.
- output_reasoning: توکنهای استدلالی یا تفکر.
- raw: شیء دستنخورده usage ارائهدهنده. این کار تضمین میکند که اگر ارائهدهنده فیلد جدیدی را اضافه کرد، حتی یک سال بعد هم قابل بازیابی باشد.
منطق پیادهسازی
نوشتن آداپتورها نیازمند ریاضیات متفاوت برای هر ارائهدهنده است تا اطمینان حاصل شود که باکتها مجزا باقی میمانند:
- Anthropic: سه باکت ورودی را مستقیماً بخوانید؛ آنها از پیش غیرهمپوشان هستند.
- OpenAI: ورودی تازه (Fresh input) برابر است با
prompt_tokensمنهایcached_tokens. نوشتن در کش در جاهایی که خانواده مدل برای آن هزینه میگیرد بهطور جداگانه گزارش میشود و در غیر این صورت صفر است. - Google: ورودی تازه برابر است با
promptTokenCountمنهایcachedContentTokenCount. توسعهدهندگان باید آگاهانه تصمیم بگیرند که آیاtoolUsePromptTokenCountباید در مجموع ورودی قرار گیرد یا خیر، زیرا این یک هزینه واقعی است که نادیده گرفتن آن آسان است.
توسعهدهندگان همچنین باید منطق «Clamp and Alarm» را پیاده کنند. اگر یک تفریق منجر به عدد منفی شد، به این معناست که ارائهدهنده معنای فیلدها (Semantics) را تغییر داده است. با استفاده از Math.max(0, value)، گزارشات زنده میمانند، اما باید یک هشدار صادر شود زیرا سیستم متوجه شده است که API تغییر کرده است.
فرآیند اعتبارسنجی
برای تضمین دقت، هر آداپتور باید یک تست ویژگی (Property Test) را پاس کند: برای هر آداپتور، مجموع باکتهای ورودی نرمالشده باید دقیقاً برابر با مفهوم «کل ورودی» خود ارائهدهنده باشد. در آنتروپیک، این مقدار مجموع سه فیلد خام است؛ در اوپنایآی و گوگل، این مقدار همان عدد کلی پرامپت است. دادن پاسخهای ضبطشده (با کش فعال و غیرفعال) به هر آداپتور و بررسی این تساوی، بلافاصله یک آداپتور معیوب مبتنی بر تغییر نام را افشا میکند.
علاوه بر این، اسکیما باید در برابر صورتحساب واقعی سنجیده شود. جمع کردن یک دوره کامل صورتحساب بر اساس ارائهدهنده و قیمتگذاری هر باکت با نرخ خاص خودش باید با مبلغ صورتحساب (با در نظر گرفتن خطاهای گرد کردن) مطابقت داشته باشد. هر شکاف قابل توجهی نشاندهنده سوءبرداشت از تفاوت «شامل-در-مقابل-افزایشی» است. مهاجرت جدول جستجوی قیمتها (Price lookup table)، نیمی دیگر از این تطبیق را مدیریت میکند.
حفاظت از رکورد دادهها
یک تصمیم معماری حیاتی این است که «تعداد توکنها» را ذخیره کنید، نه «مبلغ پول». هزینهها حاصلضرب تعداد توکن در نرخی است که در یک روز خاص جاری بوده است. نرخها تغییر میکنند و تخفیفها اغلب بهصورت عطف (Retroactively) مذاکره میشوند. اگر امروز یک مبلغ دلاری را در یک ردیف بنویسید، نمیتوانید آن را یک سال بعد بدون بازنویسی تاریخچه اصلاح کنید. تعداد توکنها را ذخیره کنید — که حقایقی هستند که هرگز تغییر نمیکنند — و هزینه را در زمان خواندن دادهها از روی یک جدول نرخهای تاریخدار محاسبه کنید. برای سازمانهایی که علاوه بر دقت مالی، با محدودیتهای قانونی مواجهاند، استفاده از دفتر کل (Ledger) برای تفکیک صورتحسابها از دادههای حساس راهکاری جامع برای مدیریت این پیچیدگیهاست.
برخی هزینهها بهسادگی در یک رکوردِ «به ازای هر درخواست» نمیگنجند و باید از مسیر دریافت دادهها (Ingest path) خارج شوند:
- تخفیفهای دستهای (Batch discounts): این تخفیفها به کل یک Job اعمال میشوند، نه یک فراخوانی واحد.
- سطوح سرویس (Service tiers): آنتروپیک
usage.service_tier(استاندارد، اولویت یا دستهای) و جمینایserviceTierرا گزارش میکنند. اینها نرخ را برای درخواستهای مشابه تغییر میدهند، بنابراین سطح سرویس باید یک ستون باشد، نه یک قیمت مفروض. - ظرفیت رزرو شده (Provisioned capacity): این مورد قیمت بهازای هر درخواست ندارد؛ پول در زمان خرید ظرفیت پرداخت شده است. تخصیص این هزینه یک سیاست تخصیصی است که باید در جایی باشد که انسان بتواند درباره آن بحث کند.
دور نگه داشتن این مفروضات از مسیر Ingest تضمین میکند که اسکیما یک رکورد صادقانه از اتفاقات واقعی باقی بماند. استفاده از یک گیتوی مانند Multigrid میتواند این نرمالسازی را متمرکز کرده و از تضاد در منطق ریاضی تیمهای مختلف جلوگیری کند. این رویکرد، تمرکز را از مپینگ ساده API به حسابداری دقیق مالی تغییر میدهد. با در نظر گرفتن فیلدهای مصرف به عنوان سریعترین بخش تغییرات در API، توسعهدهندگان میتوانند از ستون دادههای «raw» برای محافظت از خود در برابر تغییرات اجتنابناپذیر ارائهدهندگان استفاده کنند.
گام بعدی شما
- دیتابیس خود را بررسی کنید و ببینید آیا توکنهای کششده را در یک ستون کلی جمع کردهاید یا در باکتهای مجزا.
- برای هر ارائهدهنده، یک تست تطبیق مجموع توکنها با صورتحساب ماهانه اجرا کنید تا نشت دادهها را شناسایی کنید.
- ذخیرهسازی هزینهها را از حالت «مبلغ ثابت» به «تعداد توکن + جدول نرخ» تغییر دهید.
اما داستان سختافزاری این تحول حتی شگفتانگیزتر است — به تحلیل ما دربارهی تراشههای Blackwell مراجعه کنید.




گفتگو