پرش به محتوای اصلی
پرش به محتوای مقاله

تضاد در شمارش توکن‌ها؛ عامل پنهان نشت هزینه‌ها در مهاجرت بین مدل‌های AI

·۲۴ مرداد ۱۴۰۵۶ دقیقه مطالعه۱ بازدید
راهنما
ردیابی یکپارچه هزینه‌ها به جای تخصیص مبتنی بر ارائه‌دهنده
ردیابی یکپارچه هزینه‌ها به جای تخصیص مبتنی بر ارائه‌دهنده
اشتراک‌گذاری
واقعاً چه چیز جدید است؟

افشای تضاد ساختاری در نحوه گزارش توکن‌های ورودی بین سه ارائه‌دهنده اصلی؛ در حالی که OpenAI و گوگل توکن‌های کش را بخشی از کل می‌بینند، آنتروپیک آن‌ها را جداگانه می‌شمارد.

اگر امروز برای مدیریت هزینه‌های استنتاج خود تنها به تغییر نام فیلدها در دیتابیس تکیه می‌کنید، احتمالاً بخش بزرگی از حجم ورودی‌های خود را به‌صورت خاموش از دست می‌دهید. خطر واقعی در مهاجرت بین ارائه‌دهندگان، محل ذخیره اعداد نیست، بلکه معنای واقعی این اعداد است. تاریخچه هزینه‌ها به این دلیل تکه‌تکه نمی‌شود که داده‌ها در مکان‌های مختلف هستند، بلکه به این دلیل است که دو فیلد با نام یکسان، چیزهای متفاوتی را می‌شمارند؛ تضادی که یک آداپتور ساده بر پایه تغییر نام (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 مراجعه کنید.

چرا این موضوع مهم است؟

این موضوع بر اساس تجربه عملی در مقیاس بالا نشان می‌دهد که خطاهای کوچک در اسکیمای داده‌ها می‌تواند منجر به اختلاف‌های مالی کلان در صورت‌حساب‌های سازمانی شود. اعتبار گزارشات مالی AI به تفکیک دقیق توکن‌های کش و استدلالی وابسته است.

تأثیر برای ایران

برای توسعه‌دهندگان ایرانی که به‌دلیل محدودیت‌ها از چندین واسط API یا مدل‌های مختلف استفاده می‌کنند، پیاده‌سازی این تفکیک برای کنترل هزینه‌های ارزی حیاتی است.

·نگاه ما
تحریریه دات‌هوش

بسیاری از تیم‌های مهندسی به اشتباه تصور می‌کنند لایه‌ی ردیابی هزینه (Cost Tracking) یک مسئله ساده‌ی مپینگ داده است، در حالی که این یک مسئله‌ی حسابداری است. تله‌ی «شامل-در-مقابل-افزایشی» نشان می‌دهد که حتی در سطح API، استانداردی برای گزارش مصرف وجود ندارد و هر ارائه‌دهنده تعریف خود را از «ورودی» دارد. انتقال به مدل باکت‌های غیرهم‌پوشان، تنها راهی است که اجازه می‌دهد تحلیل‌های تاریخی (Historical Analysis) پس از مهاجرت بین مدل‌ها معتبر باقی بمانند.

منابع

این گزارش با خط‌لولهٔ خودکار دات‌هوش از منابع معتبر جهانی تدوین و زیر نظر تحریریه منتشر شده است. روش کار ما

گفتگو

پنج‌شنبه‌های هوش‌محور

بسته‌ی هفتگی دات‌هوش

۵ خبر، ۲ ابزار، ۱ پرامپت در هر شماره. به‌زودی راه‌اندازی می‌شود — هر پنج‌شنبه صبح.

خبر کلیدی
ابزار کاربردی
پرامپت حرفه‌ای
تحلیل پژوهش
به‌زودی
زاویه‌ی ایرانی
به‌زودی
تمرین این هفته
به‌زودی

راهنماهای دات‌هوش

راهنماهای کاربردیِ دات‌هوش برای کار با هوش مصنوعی — از همین‌جا شروع کنید:

دات‌هوش

راهنمای فارسی هوش مصنوعی — با نگاه به ایران

اخبار روزانه، معرفی ابزارها و مدل‌ها، و آموزشِ کار با هوش مصنوعی؛ همیشه با این پرسش که از ایران چه چیزی کار می‌کند و چه چیزی نه.