مالیات توکن فارسی: متن فارسی در LLM چند برابر توکن مصرف میکند؟
هزینه توکن فارسی در LLM چقدر است؟ روی ۱٬۰۱۲ جمله موازی، فارسی با توکنایزر GPT-4o به ۱٫۵۳ برابر و با توکنایزر GPT-4 به ۳٫۲۶ برابر توکن انگلیسی نیاز داشت. روش، نتایج و راهکارهایی که باید آزمود.
متن فارسی برای رساندن همان محتوا توکن بیشتری از متن انگلیسی مصرف میکند. این اضافهبار همان مالیات توکن فارسی است و اندازهاش بیش از آنکه به خط بستگی داشته باشد، به توکنایزر بستگی دارد. تعداد توکنهای ۱٬۰۱۲ جمله یکسان از بنچمارک FLORES-200 را در نسخههای انگلیسی و فارسیشان شمردم. فارسی با o200k_base، انکودینگی که کتابخانه tiktoken شرکت OpenAI آن را به GPT-4o نسبت میدهد، ۱٫۵۳ برابر انگلیسی توکن لازم داشت و با cl100k_base، که همین کتابخانه به GPT-4 نسبت میدهد، ۳٫۲۶ برابر. این دو عدد دو سر بازه در میان چهار توکنایزری بودند که مدلهای مولد متن به کار میگیرند. در bge-m3، که توکنایزر یک مدل embedding است، این نسبت ۱٫۱۰ برابر بود. Claude و Gemini در این اندازهگیری نیستند: Anthropic توکنایزر Claude را منتشر نمیکند و توکنایزر محلیای را هم که SDK شرکت Google برای Gemini ارائه میدهد نسنجیدهام. هر دو شرکت امکان شمارش توکن مدلهای خود را از راه API در اختیار میگذارند.
این اعداد به تاریخ اندازهگیری وابستهاند: اندازهگیری در ۲۶ شهریور ۱۴۰۵ و با نسخههای ثابت و مشخصی از توکنایزرها انجام شد. توکنایزرها تغییر میکنند و عدد امروز لزوماً عدد فردا نیست.
توکن چیست و چرا متن فارسی توکن بیشتری مصرف میکند؟
توکن واحدی است که مدل زبانی متن را با آن میخواند و تولید میکند: گاهی یک کلمه کامل، گاهی بخشی از کلمه و گاهی فقط یک بایت. هزینه API مدلهای زبانی هم بر همین مبنا محاسبه میشود. Ahia و همکارانش در سال ۲۰۲۳ شواهدی یافتند که «گویشوران شمار زیادی از زبانهای پشتیبانیشده بیش از حد هزینه میپردازند و در همان حال نتیجه ضعیفتری میگیرند». Petrov و همکارانش نشان دادند که یک متن پس از ترجمه به زبانهای مختلف ممکن است طول توکنی بسیار متفاوتی پیدا کند، «در برخی موارد تا ۱۵ برابر». پژوهشی از سال ۲۰۲۵ که بیش از دویست زبان را بررسی کرده است، گزارش میدهد که در زبانهایی که خط غیرلاتین یا ساختواژه پیچیده دارند، نسبت RTC (هزینه نسبی توکنسازی یا Relative Tokenization Cost) «اغلب ۳ تا ۵ برابر» بالاتر است.
مالیات توکن همین است: همان معنا، صورتحساب بزرگتر.
بایتها: نقطه شروع هر توکنایزر بایتمحور
توکنایزر BPE بایتمحور (BPE کوتاهشده byte-pair encoding است)، همان نوعی که GPT-4o و Qwen3 و DeepSeek-V3 به کار میگیرند، کار را از بایتهای متن در کدگذاری UTF-8 شروع میکند و دنبالههای پرتکرار بایت را در هم ادغام میکند تا توکن بسازد. یک حرف لاتین بدون علامت یک بایت است، اما حروف یوروبا که علامت لحن یا نقطه زیرین دارند دو بایت یا بیشتر میگیرند. هر حرف فارسی دو بایت است و نیمفاصلهای که درون کلمههای فارسی میآید سه بایت. در FLORES، فایل فارسی در کدگذاری UTF-8 به ۱٫۶۹ برابر حجم فایل انگلیسی رسید، در حالی که شمار نویسههایش ۰٫۹۴ برابر انگلیسی بود. متن فارسی نویسه بیشتری ندارد؛ کدگذاریاش سنگینتر است.
ادامه کار به ادغامهایی بستگی دارد که توکنایزر از دادههای آموزشیاش آموخته است. گذر از cl100k_base به o200k_base تعداد توکنهای فارسی را ۵۳٫۵٪ کم کرد و تعداد توکنهای انگلیسی را فقط ۱٫۱٪. واژگان جدیدتر وضع فارسی را عوض کرد، نه انگلیسی را.
یوروبا با وجود خط لاتین مالیات بیشتری میپردازد
اگر خط تعیینکننده مالیات توکن بود، زبانهایی که با خط لاتین نوشته میشوند تقریباً از آن معاف میماندند. Roy و Roy و Patel در مقالهای که برای یکی از کارگاههای IJCAI 2026 پذیرفته شده و از مرداد ۱۴۰۵ در arXiv در دسترس است، دریافتند که در ممیزی آنها یوروبا «با وجود استفاده از خط لاتین» بیشترین اضافههزینه توکن را در GPT-4o دارد: ۲٫۳۷ برابر انگلیسی. نویسندگان علامتهای آوایی (diacritics) و میزان پوشش واژگان را عامل احتمالی این پدیده میدانند. یوروبا در آن مقاله فقط نمونهای اکتشافی برای مقایسه است: متنهای یوروبا با ترجمه ماشینی تولید و سپس بهصورت دستی بازبینی شدهاند و موارد اعتبارسنجیشده آن پژوهش، بنگالی و هندیاند.
اندازهگیری من هم همین را نشان میدهد. از پنج توکنایزر، یوروبا در چهار مورد گرانتر از فارسی بود و عربی در چهار مورد ارزانتر از فارسی. در مورد عربی، تنها استثنا bge-m3 است: یک مدل embedding که بر پایه XLM-RoBERTa و واژگان آن ساخته شده است. XLM-R با دادههای صد زبان از پیکره CC-100 آموزش داده شد: ۱۳٬۲۵۹ میلیون توکن فارسی در برابر ۲٬۸۶۹ میلیون توکن عربی؛ یوروبا جزو این صد زبان نبود. این یافته با این فرض سازگار است که سهم هر زبان در دادههای آموزشی از خط آن مهمتر است، اما آن را اثبات نمیکند.
نتایج: فارسی، عربی و یوروبا در برابر انگلیسی
هر خانه جدول، مجموع توکنهای یک زبان تقسیم بر مجموع توکنهای انگلیسی با همان توکنایزر است:
توکنایزر | فارسی (نسبت به انگلیسی) | عربی (نسبت به انگلیسی) | یوروبا (نسبت به انگلیسی) |
|---|---|---|---|
| ۳٫۲۶× | ۳٫۰۳× | ۲٫۹۵× |
Qwen3 | ۲٫۵۸× | ۱٫۶۳× | ۲٫۶۹× |
DeepSeek-V3 | ۱٫۷۹× | ۱٫۶۲× | ۲٫۸۳× |
| ۱٫۵۳× | ۱٫۳۸× | ۲٫۱۷× |
bge-m3 | ۱٫۱۰× | ۱٫۱۷× | ۲٫۲۷× |
مهمترین متغیر خود توکنایزر است. نسبت توکن فارسی به انگلیسی در بدترین توکنایزر (۳٫۲۶ برابر) حدود سه برابر همین نسبت در بهترین توکنایزر (۱٫۱۰ برابر) است و حتی در میان چهار توکنایزر مدلهای مولد هم حدود دو برابر (۳٫۲۶ برابر در برابر ۱٫۵۳ برابر). Qwen3 عربی را بسیار کارآمدتر از فارسی توکنسازی میکند (عربی ۱٫۶۳ برابر انگلیسی، فارسی ۲٫۵۸ برابر)؛ پس یک عدد واحد برای «خط عربی» نماینده هر دو زبان نیست.
نتیجه cl100k_base با شمارشهای منتشرشده پیشین همخوان است. Petrov و همکارانش در دادههایی که روی FLORES-200 منتشر کردهاند بخشهای dev و devtest را یکجا شمردهاند و در آن دادهها نسبت فارسی (گونه ایران) به انگلیسی ۳٫۲۸ برابر است؛ اندازهگیری من، که فقط روی بخش devtest انجام شد، به ۳٫۲۶ برابر رسید.
مجموعهایی که این نسبتها از آنها به دست آمدهاند، همراه با حجم فایل هر زبان پیش از توکنسازی:
شمارش | انگلیسی | فارسی | عربی | یوروبا |
|---|---|---|---|---|
نویسهها | ۱۳۱٬۹۶۶ | ۱۲۳٬۸۳۰ | ۱۱۶٬۳۲۰ | ۱۲۶٬۸۴۸ |
بایتها (UTF-8) | ۱۳۲٬۰۹۶ | ۲۲۳٬۵۰۴ | ۲۱۱٬۲۷۶ | ۱۶۸٬۸۵۷ |
توکنها، | ۲۷٬۱۸۲ | ۸۸٬۵۱۳ | ۸۲٬۲۸۸ | ۸۰٬۲۴۷ |
توکنها، Qwen3 | ۲۷٬۶۲۱ | ۷۱٬۱۸۳ | ۴۴٬۹۹۱ | ۷۴٬۲۲۶ |
توکنها، DeepSeek-V3 | ۲۷٬۰۴۱ | ۴۸٬۳۴۲ | ۴۳٬۷۱۳ | ۷۶٬۵۲۶ |
توکنها، | ۲۶٬۸۷۳ | ۴۱٬۱۱۶ | ۳۷٬۱۱۷ | ۵۸٬۲۳۸ |
توکنها، bge-m3 | ۳۰٬۶۶۱ | ۳۳٬۶۳۱ | ۳۵٬۹۷۹ | ۶۹٬۶۷۲ |
پیکره شما عدد دیگری میدهد
ممیزی Roy و همکاران، o200k_base را روی ۱۲۰ نمونه اشکالزدایی کد Python، ترجمهشده از انگلیسی، سنجیده و نسبت را برای هر نمونه جداگانه محاسبه و سپس میانگین گرفته است. این پژوهش عربی را ۱٫۴۴ برابر و یوروبا را ۲٫۳۷ برابر انگلیسی گزارش میکند و ترجمه هر دو زبان ماشینی بوده است. روی نثر FLORES که مترجمان انسانی ترجمه کردهاند، همان o200k_base برای عربی ۱٫۳۸ برابر و برای یوروبا ۲٫۱۷ برابر به دست داد. توکنایزر یکسان، متن و شیوه ترجمه متفاوت، نتیجه متفاوت. پیش از بودجهبندی، توکنهای پرامپتها، متنهای بازیابیشده و پاسخهای واقعی خودتان را بشمارید.
روش اندازهگیری: توکنهای متن فارسی را چگونه شمردم
یک پیکره واقعاً موازی
تیم NLLB مجموعه FLORES-200 را «بنچمارکی با ترجمه انسانی» توصیف میکند: همان جملهها، به همان ترتیب، در همه زبانها. بخش devtest آن را، که مجوز CC BY-SA 4.0 دارد، از بایگانی رسمی دریافت کردم و هش SHA-256 بایگانی را تطبیق دادم. حاصل ۱٬۰۱۲ جمله از Wikinews و Wikivoyage و Wikibooks است، به چهار زبان انگلیسی، فارسی (گونه ایران)، عربی معیار و یوروبا.
موازی بودن مهمتر از حجم است. ترجمه آزاد، مثل رزومهای که برای دو زبان تنظیم شده، مطلبی را اضافه، حذف یا بازنویسی میکند؛ پس نسبتی که از آن به دست میآید همانقدر که توکنایزر را میسنجد، ویرایش را هم میسنجد. FLORES نیز محدودیتی دارد: متن آن نثر خبری، راهنمای سفر و کتاب آموزشی است، نه گفتوگو، کد یا قرارداد.
توکنایزرهای متنباز با نسخههای تثبیتشده؛ چرا Claude و Gemini در جدول نیستند
پنج توکنایزر به کار رفت و همه را بدون حساب کاربری میتوان دانلود کرد:
کتابخانه tiktoken نسخه 0.14.0:
cl100k_baseوo200k_base. در نگاشت tiktoken، مدلهای GPT-4 و GPT-3.5 Turbo به اولی و مدلهای GPT-4o و o1 و o3 و GPT-4.1 و GPT-5 به دومی نسبت داده شدهاند.مدلهای Qwen3 و DeepSeek-V3 (
Qwen/Qwen3-8Bوdeepseek-ai/DeepSeek-V3)، هر دو از نوع BPE بایتمحور، بارگذاریشده با کتابخانه tokenizers نسخه 0.23.2 از Hugging Face و با revision تثبیتشده در Hub.مدل bge-m3 (
BAAI/bge-m3)، یک مدل embedding که توکنایزرش مدل Unigram از نوع SentencePiece با واژگان XLM-R است، نه BPE بایتمحور. Unigram الگوریتم دیگری است: از میان تقسیمهای ممکن متن با یک واژگان ثابت، محتملترین را انتخاب میکند. این توکنایزر در بازیابی اطلاعات اهمیت دارد، نه در تولید متن.
هر جمله جداگانه و بدون توکنهای ویژه توکنسازی شد و شمارشها با هم جمع شدند. میانه نسبتها در سطح تکجمله هم همان تصویری را نشان میدهد که مجموعها نشان میدهند. بخش اصلی کد چند خط بیشتر نیست:
# after: tar -xzf flores200_dataset.tar.gz
import tiktoken
from huggingface_hub import hf_hub_download
from tokenizers import Tokenizer
def sentences(lang):
with open(f"flores200_dataset/devtest/{lang}.devtest", encoding="utf-8") as f:
return f.read().rstrip("\n").split("\n")
english, persian = sentences("eng_Latn"), sentences("pes_Arab")
o200k = tiktoken.get_encoding("o200k_base")
qwen3 = Tokenizer.from_file(
hf_hub_download(
"Qwen/Qwen3-8B",
"tokenizer.json",
revision="b968826d9c46dd6066d109eabc6255188de91218",
)
)
def o200k_tokens(texts):
return sum(len(o200k.encode_ordinary(t)) for t in texts)
def qwen3_tokens(texts):
return sum(len(qwen3.encode(t, add_special_tokens=False).ids) for t in texts)
print(round(o200k_tokens(persian) / o200k_tokens(english), 2))
print(round(qwen3_tokens(persian) / qwen3_tokens(english), 2))مشخصات اندازهگیری، که برای تکرار دقیق همین اجرا کافی است:
corpus: https://dl.fbaipublicfiles.com/nllb/flores200_dataset.tar.gz
sha256: b8b0b76783024b85797e5cc75064eb83fc5288b41e9654dabc7be6ae944011f6
split: devtest
measured: 2026-09-17
libraries:
tiktoken: 0.14.0
tokenizers: 0.23.2
huggingface_hub: 1.31.0
encodings: [cl100k_base, o200k_base]
hub_revisions:
Qwen/Qwen3-8B: b968826d9c46dd6066d109eabc6255188de91218
deepseek-ai/DeepSeek-V3: e815299b0bcbac849fa540c768ef21845365c9eb
BAAI/bge-m3: 5617a9f61b028005a4858fdac845db406aefb181
method: each sentence encoded on its own, no special tokens, counts summed per languageClaude و Gemini را عمداً کنار گذاشتم. Anthropic توکنایزر Claude را منتشر نمیکند، پس هر نسبتی که برای Claude بدهم حدسی است که رقم اعشار فقط ظاهرش را دقیق میکند. SDK پایتون Google Gen AI یک توکنایزر محلی آزمایشی دارد که فقط متن را میشمارد و برخی مدلهای Gemini را به توکنایزرهای متنباز Gemma نگاشت میکند؛ این توکنایزر را در این اندازهگیری نسنجیدهام. شمارش توکن را میتوان به خود این دو شرکت سپرد. endpoint count_tokens در Anthropic رایگان است اما محدودیت نرخ دارد و مستنداتش نتیجه را «تخمین» مینامد؛ count_tokens در Gemini هم توکنهای ورودی را میشمارد. به گفته مستندات Claude، مدلهای Claude 4.7 و مدلهای پس از آن توکنایزر تازهتری دارند و همان متن ورودی در آنها «تقریباً ۳۰ درصد توکن بیشتر از مدلهای قبلی» تولید میکند. شمار توکن به مدل تعلق دارد، نه به شرکت سازنده.
کرانهایی که برقرارند و کرانی که برقرار نیست
هر چهار توکنایزر BPE بایتمحور این اندازهگیری پیش از ادغام، متن را به پیشتوکنها (pre-tokens) خرد میکنند؛ پیشتوکنها قطعههاییاند که الگوی تقسیم توکنایزر، متن را به آنها تقسیم میکند. در چنین توکنایزرهایی، شمار توکنها میان دو حد قرار میگیرد. شمار توکنها نمیتواند از شمار بایتهای متن در UTF-8، پس از نرمالسازی خود توکنایزر، بیشتر شود، چون هر توکن دستکم یک بایت را میپوشاند. از شمار پیشتوکنهای خود همان توکنایزر هم نمیتواند کمتر شود، چون ادغامها هرگز از مرز یک پیشتوکن عبور نمیکنند. هر دو کران را جملهبهجمله روی چهار توکنایزر BPE بایتمحور و هر چهار زبان آزمودم: در ۱۶٬۱۹۲ آزمون، حتی یک مورد نقض دیده نشد.
زمین بازی توکنایزر در همین سایت هر دو عدد را برای هر متنی که بنویسید، درون مرورگر نشان میدهد: تقسیم پیشتوکن cl100k_base و بایتهای متن در UTF-8. در cl100k_base شمار واقعی توکن میان این دو عدد است؛ توضیح زیر هر قاب هم دقیقاً همین را میگوید.
کران پایین به یک توکنایزر مشخص تعلق دارد. تقسیمبندی cl100k_base کران پایینی برای o200k_base نیست: در ۲۸ جمله انگلیسی، o200k_base به توکن کمتری از تعداد پیشتوکنهای cl100k_base نیاز داشت. هیچیک از دو کران درباره مدل Unigram در bge-m3 صدق نمیکند.
مالیات توکن چه اثری بر هزینه API، تأخیر، پنجره زمینه و محدودیت نرخ دارد؟
هزینه API
ارائهدهندگان API بابت توکنهایی که مدل پردازش و تولید میکند هزینه دریافت میکنند. با قیمت یکسان برای هر توکن، همان محتوا به فارسی با o200k_base حدود یکونیم برابر انگلیسی هزینه دارد و با cl100k_base بیش از سه برابر. وقتی هم پرامپت و هم پاسخ فارسی باشند، این اضافههزینه در هر دو سوی صورتحساب اعمال میشود: هم در هزینه ورودی و هم در هزینه خروجی.
تأخیر پاسخ
سرعت پاسخ را توکنهای خروجی تعیین میکنند. راهنمای بهینهسازی تأخیر OpenAI میگوید «کم کردن ۵۰٪ توکنهای خروجی ممکن است حدود ۵۰٪ از تأخیر بکاهد». کوتاه کردن پرامپت اثر بسیار کمتری دارد: «کوتاه کردن ۵۰٪ پرامپت ممکن است تنها ۱ تا ۵٪ بهبود در تأخیر به همراه داشته باشد». پاسخ فارسیای که توکن بیشتری از معادل انگلیسیاش لازم دارد، هنگام استریم (streaming) دیرتر به پایان میرسد. این نتیجهگیری از اعمال راهنمای OpenAI بر نسبتهایی که پیشتر آمد به دست آمده است؛ تأخیر را خودم اندازه نگرفتهام.
پنجره زمینه (context window)
یک پنجره زمینه با اندازه ثابت، متن فارسی کمتری در خود جا میدهد. اگر ظرفیت پنجره را بر این نسبتها تقسیم کنیم، همان پنجره در این پیکره با cl100k_base فقط ۳۱٪ محتوایی را که به انگلیسی جا میگرفت به فارسی جا میدهد؛ این سهم با Qwen3 به ۳۹٪، با DeepSeek-V3 به ۵۶٪، با o200k_base به ۶۵٪ و با bge-m3 به ۹۱٪ میرسد. ممیزی Roy و همکاران همین نکته را درباره بنگالی نشان میدهد: بنگالی در GPT-4o به ۱٫۵۶ برابر توکن انگلیسی نیاز دارد و همین «پنجره زمینه اسمی ۱۲۸ هزار توکنی را به ظرفیتی مؤثر معادل ۸۲ هزار توکن انگلیسی کاهش میدهد». در یک پرامپت RAG، این یعنی جای کمتر برای متنهای بازیابیشده.
محدودیت نرخ (rate limit)
محدودیت نرخ هم بر حسب توکن شمرده میشود. به گفته مستندات Claude، محدودیتهای API آن «بر حسب درخواست در دقیقه (RPM)، توکن ورودی در دقیقه (ITPM) و توکن خروجی در دقیقه (OTPM)» سنجیده میشوند. زیر سقف توکن در دقیقه، باری که در هر درخواست توکن بیشتری مصرف میکند با تعداد درخواست کمتری به سقف میرسد؛ فارسی در همه توکنایزرهای این اندازهگیری چنین بود. در بیشتر مدلهای Claude، توکنهایی که از کش خوانده میشوند در سقف توکن ورودی حساب نمیشوند.
نیمفاصله و ی و ک عربی: صرفهجویی در توکن یا شکستن جستوجو؟
دو ویژگی نوشتار فارسی در نگاه اول راهی ارزان برای صرفهجویی در توکن به نظر میرسند. هر دو داماند.
نیمفاصله (ZWNJ) نویسه است، نه فاصله
نویسه U+200C با نام ZERO WIDTH NON-JOINER در یونیکد، در رده عمومی Cf قرار دارد؛ یعنی نویسه کنترلی قالببندی است، نه نویسه فاصله (whitespace). این نویسه جلوی اتصال حروف دو طرفش را میگیرد و برای همین «میشود» یک کلمه با گسستی دیداری خوانده میشود. فایل فارسی FLORES این نویسه را ۱٬۷۳۹ بار، در ۷۳۵ جمله از ۱٬۰۱۲ جمله، به کار برده است.
جایگزین کردن همه نیمفاصلهها با فاصله، تعداد توکنهای فارسی را کم کرد: ۱٫۵۹٪ در cl100k_base، ۱٫۸۲٪ در o200k_base، ۱٫۵۷٪ در Qwen3 و ۸٫۰۸٪ در DeepSeek-V3. در bge-m3 هیچ تغییری ایجاد نکرد (۰٫۰۰٪). تعداد توکنهای bge-m3 از آن رو ثابت ماند که نرمالساز این توکنایزر خودش نیمفاصله را به فاصله تبدیل میکند: هر ۷۳۵ جمله تغییریافته دقیقاً همان شناسههای توکن (token ids) را حفظ کردند.
این صرفهجویی در سه توکنایزر ناچیز است و در DeepSeek-V3 بیشتر، اما این جایگزینی متن را تغییر میدهد: یک کلمه دو کلمه میشود و آنچه ذخیره میکنید، نمایش میدهید یا عیناً نقل میکنید دیگر همانی نیست که نویسنده نوشته است. نیمفاصله را در متن ذخیرهشده نگه دارید و جداگانه تصمیم بگیرید که تطبیقدهنده (matcher) چه چیزهایی را یکسان بداند. این سایت دقیقاً همین کار را میکند: فقط یکسانسازیای که درون مقایسهها به کار میرود، نیمفاصله را معادل فاصله میگیرد.
ی و ک عربی در برابر ی و ک فارسی
یای عربی (U+064A) و یای فارسی (U+06CC) دو نویسه متفاوتاند؛ کاف عربی (U+0643) و کاف فارسی (U+06A9) هم. در ابتدا و میانه کلمه یکسان دیده میشوند، اما مقایسه رشتهای آنها را دو نویسه جدا میبیند. حتی FLORES هم آنها را درهم به کار برده است: فایل فارسی آن ۱۱ یای عربی و ۲۲ کاف عربی را کنار ۹٬۵۷۰ یای فارسی و ۲٬۹۵۷ کاف فارسی دارد.
بازنویسی همه یاها و کافهای فارسی این فایل به شکل عربی، تعداد توکنها را افزایش داد: ۲٫۲۰٪ در cl100k_base، ۹٫۴۹٪ در o200k_base، ۱۰٫۳۹٪ در DeepSeek-V3 و ۱۱٫۹۵٪ در bge-m3. فقط در Qwen3 تعداد توکنها ۷٫۴۸٪ کم شد. بازنویسیای که در یک توکنایزر در مصرف توکن صرفهجویی میکند، در چهار توکنایزر دیگر هزینه را بالا میبرد.
مسئله اصلی از دست رفتن نتایج جستوجو (recall) است. اگر متن ذخیرهشده و پرسوجو نقطهکدهای متفاوتی داشته باشند، تطبیق دقیق و واژگانی بیصدا شکست میخورد. این سایت متن فارسی را هنگام ذخیرهسازی یکسانسازی میکند: یای عربی و کاف عربی به شکل فارسیشان برمیگردند و نیمفاصله دستنخورده میماند. عبارت جستوجو هم به همان شیوه یکسانسازی میشود؛ وگرنه عبارتی که با یای عربی تایپ شده باشد، دنبال نویسهای میگردد که در نمایه وجود ندارد و هیچ نتیجهای برنمیگرداند.
قاعده کلی محدودتر از این است: فقط متن فارسی را یکسانسازی کنید، چون در متن عربی، یای عربی و کاف عربی حروف درستاند. بازیاب همین سایت هنوز این تمایز را رعایت نمیکند و تبدیل حروف فارسی را روی محتوا و پرسشهای همه زبانها، از جمله عربی، اجرا میکند. مقاله جستوجوی ترکیبی در RAG فارسی این کاستی را همراه با دیگر جنبههای بازیابی شرح میدهد.
ارقام فارسی و لاتین
نوشتن ارقام ASCII بهصورت ارقام فارسی، تعداد توکنها را ۰٫۴۸٪ تا ۱٫۴۷٪ افزایش داد. این دلیلی برای تغییر آنچه خوانندگان میبینند نیست.
چگونه هزینه توکن فارسی را کم کنیم؟ راهکارها را بیازمایید، فرض نکنید
هر یک از این راهکارها را پیش از تکیه بر آن، روی ترافیک واقعی خودتان بیازمایید.
مدل را با آزمودن روی متن خودتان انتخاب کنید. روی جملههای یکسان، نسبت توکن فارسی به انگلیسی از ۱٫۱۰ تا ۳٫۲۶ برابر متغیر بود.
توکنها را با endpoint شمارش خود ارائهدهنده بشمارید. نسبتهایی که در این اندازهگیری به دست آمد، درباره Claude و Gemini چیزی به شما نمیگوید.
با تغییر مدل، دوباره بشمارید. توکنایزر جدیدتر میتواند همه بودجههایی را که تعیین کردهاید جابهجا کند.
اندازه قطعهها و بودجه زمینه را بر حسب توکن و برای هر زبان جداگانه تعیین کنید. سقفی بر حسب نویسه که برای انگلیسی تنظیم شده، در فارسی توکن بیشتری جا میدهد: از حدود یکششم بیشتر در bge-m3 تا حدود سهونیم برابر در
cl100k_base.طول خروجی را محدود کنید. توکنهای خروجی هم تأخیر را تعیین میکنند و هم هزینه را. Anthropic پیشنهاد میکند بهجای تعداد کلمه، تعداد جمله یا پاراگراف را مشخص کنید.
زمینه تکراری را کش کنید و سپس نرخ اصابت (hit rate) را بسنجید. هر صرفهجویی به این بستگی دارد که پیشوند پرامپت شما واقعاً چند بار تکرار میشود.
پرامپت سیستم انگلیسی را یک فرضیه بدانید. توکن کمتری مصرف میکند، اما هیچ اندازهگیریای ندارم که نشان دهد با پاسخهای فارسی چه میکند.
برای صرفهجویی در توکن، نیمفاصله را حذف نکنید و ی و ک فارسی را به عربی تبدیل نکنید. صرفهجوییاش اندک یا ناپایدار است، اما آسیبش به متن و تطبیق نه اندک است و نه ناپایدار.
بودجه توکن فارسی را چگونه برآورد کنیم؟
قاعده «چند نویسه در هر توکن» برای هر توکنایزر متفاوت است
فارسی از ۱٫۴۰ نویسه (کاراکتر) در هر توکن با cl100k_base تا ۳٫۶۸ با bge-m3 متغیر بود و o200k_base در ۳٫۰۱ قرار داشت. این عدد برای انگلیسی از ۴٫۳۰ تا ۴٫۹۱ بود. مستندات Google برای Gemini میگوید «هر توکن تقریباً معادل ۴ نویسه است» و کنار آن معادلی بر حسب کلمههای انگلیسی میآورد؛ پس این قاعدهای است که برای انگلیسی ساخته شده، نه گزارهای درباره فارسی.
رزرو یک توکن برای هر دو نویسه فارسی سخاوتمندانه به نظر میرسد. همین سایت هم پیشتر بر همین قاعده رزرو میکرد و به همین دلیل آن را روی این جملهها آزمودم: این قاعده برای هر ۱٬۰۱۲ جمله فارسی با cl100k_base و برای ۹۷۶ جمله با Qwen3 کمتر از شمار واقعی توکن برآورد کرد. با o200k_base و bge-m3 کافی بود و با DeepSeek-V3 در ۶ جمله کمتر از شمار واقعی بود. قاعدهای که در یک توکنایزر امن است، ممکن است در توکنایزر بعدی خوشبینانه از آب درآید؛ به همین سبب این سایت دیگر بر پایه چنین قاعدهای رزرو نمیکند.
سقف قطعی: شمار بایتها
برای BPE بایتمحور، شمار بایتهای متن پس از نرمالسازی خود توکنایزر سقفی قطعی است، اما سقفی بسیار بالاتر از مصرف واقعی. اگر شمار پیشتوکنها را صفر و شمار بایتها را یک بگیریم، انگلیسی در این بازه میان ۰٫۰۱۵ و ۰٫۰۱۷ قرار گرفت: تقریباً هر پیشتوکن انگلیسی، که کمابیش یک کلمه است، یک توکن میشود. فارسی با o200k_base در ۰٫۰۷ و با cl100k_base در ۰٫۳۱ قرار گرفت: خردتر شده است، اما هنوز فاصله زیادی تا سطح بایت دارد. پس رزرو بر پایه شمار بایتها بسیار بیش از نیاز است. برای سقفی که هیچ درخواستی نباید از آن بگذرد، این انتخاب درست است و برای پیشبینی هزینه، نادرست. برای Claude و Gemini، پیش از فراخوانی با endpoint شمارش خودشان بشمارید و پس از فراخوانی، مصرفی را که گزارش میکنند ثبت کنید.
پیش از فراخوانی رزرو کنید، پس از آن ثبت کنید
دستیار همین سایت این دو کار را از هم جدا میکند. پیش از فراخوانی مدل زبانی، برآوردی از هزینه درخواست (کران بالای توکنهای پرامپت بهاضافه سقف کامل توکنهای خروجی) را به هزینه ثبتشده ماه اضافه میکند و حاصل را با یک سقف ماهانه میسنجد. اگر شمارنده هزینه خوانده نشود، سامانه بسته عمل میکند (fail closed): درخواست رد میشود و مدل فراخوانی نمیشود. با رسیدن به سقف هم مدل فراخوانی نمیشود و خواننده بهجای خطا یک اطلاعیه میبیند. پس از فراخوانی، مصرفی را که ارائهدهنده گزارش میکند ثبت میکند. برآورد فقط تعیین میکند که درخواست اجازه شروع دارد یا نه؛ جمع جاری از شمار توکنهایی میآید که ارائهدهنده گزارش میکند.
هر دو نیمه این طراحی محدودیتی دارند، اما در دو جهت مخالف. برآورد پیش از فراخوانی، پرامپت را به اندازه شمار بایتهای آن در UTF-8 میشمارد؛ یعنی همان سقفی که بالاتر آمد، نه پیشبینی هزینه. هر مدلی که این دستیار میتواند به آن وصل شود واژگانی از نوع BPE بایتمحور دارد؛ پس این سقف با هر یک از آن مدلها و به هر زبانی که بازدیدکننده بنویسد برقرار میماند. برای فارسی این یعنی چند برابر هزینه واقعی پرامپت رزرو میشود؛ رزروی که فقط تا پایان همان یک درخواست نگه داشته میشود و هرگز بهعنوان هزینه ثبت نمیشود. پیشتر همین برآورد، پرامپت را با همان قاعده ثابت «هر دو نویسه، یک توکن» میشمرد که بالاتر آزمودم و برای هر ۱٬۰۱۲ جمله فارسی با cl100k_base کمتر از شمار واقعی درآمد. رزروی که کمتر از هزینه واقعی باشد، سقف هزینه را در همان جهتی خطا میکند که هرگز نباید خطا کند؛ پس همین اندازهگیری دلیل تغییر آن بود: توضیح خود تابع برآورد در کد سایت به همین اجرای ۱٬۰۱۲ جملهای ارجاع میدهد. جمع ماهانه در هر دو حال از مصرف ثبتشده ساخته میشود، نه از این برآورد.
این ثبت باید با یک سکوت کنار بیاید. OpenAI و Anthropic هر دو شمار توکنهای خروجی را پس از متن تولیدشده گزارش میکنند و مرجع API شرکت OpenAI هشدار میدهد که اگر استریم قطع یا لغو شود، ممکن است «آخرین بخشی که آمار مصرف را در بر دارد» به دستتان نرسد. استریمی که زودتر از موعد قطع شود، مثلاً با توقف یک گاردریل پاسخ استریم یا بسته شدن زبانه مرورگر، پیش از رسیدن این گزارش تمام میشود — و هر نویسهای که تولید شده، روی صورتحساب هست. بنابراین دستیار متن را همانطور که استریم میشود نگه میدارد و هر جا ارائهدهنده چیزی گزارش نکرده باشد، جای خالی را با همان شمار بایت پر میکند؛ یعنی بیشثبت میکند، نه کمثبت. هر جا ارائهدهنده عددی داده باشد، عدد خودش ملاک است: نوبتی که تا انتها اجرا شود دقیقاً همان مقدار اندازهگیریشده را ثبت میکند، نه تقریبی از آن. مقاله جلوگیری از توهم هوش مصنوعی در RAG جایگاه این بررسی را در میان دیگر لایههای دستیار نشان میدهد.
همین اصل در محصول هم صدق میکند. در بوق، که در آن مدیر ارشد فنی هوش مصنوعی هستم، هر کار پیش از اجرا قیمت یا برآورد اولیه خود را نشان میدهد و هزینه کاری که شکست بخورد بهطور خودکار بازگردانده میشود؛ کیساستادی بوق این طراحی را شرح میدهد.
پرسشهای متداول
آیا متن فارسی در مدلهای OpenAI مانند GPT-4o توکن بیشتری از انگلیسی مصرف میکند؟
بله. روی همان جملههای FLORES-200، فارسی با o200k_base (که tiktoken آن را به GPT-4o و GPT-4.1 و GPT-5 نسبت میدهد) ۱٫۵۳ برابر انگلیسی توکن لازم داشت و با cl100k_base، که به GPT-4 نسبت داده میشود، ۳٫۲۶ برابر. نسبت ترافیک خودتان متفاوت خواهد بود، پس توکنهای آن را خودتان بشمارید.
مصرف توکن فارسی در Claude و Gemini چقدر است؟
این اندازهگیری پاسخی برای آن ندارد. Anthropic توکنایزر Claude را منتشر نمیکند و SDK شرکت Google Gen AI برای برخی مدلهای Gemini شمارش محلی آزمایشیای بر پایه توکنایزرهای متنباز Gemma ارائه میدهد که آن را نسنجیدهام. نسبتهای این مقاله به هیچیک از این دو تعمیم نمییابد. روی درخواستهای واقعی از count_tokens در Anthropic یا count_tokens در Gemini استفاده کنید و هر بار که مدل را عوض میکنید، دوباره بشمارید.
آیا عربی ارزانتر از فارسی است؟
از پنج توکنایزر این اندازهگیری، در چهار مورد بله: با o200k_base، عربی ۱٫۳۸ برابر انگلیسی توکن لازم داشت و فارسی ۱٫۵۳ برابر. در bge-m3 وضع برعکس بود (عربی ۱٫۱۷ برابر و فارسی ۱٫۱۰ برابر)، که با سهم بسیار بیشتر فارسی نسبت به عربی در دادههای آموزشی XLM-R سازگار است.
آیا برای صرفهجویی در توکن، نیمفاصله را حذف کنم یا ی و ک عربی به کار ببرم؟
نه. جایگزینی نیمفاصله با فاصله، تعداد توکنها را در توکنایزرهای بایتمحور ۱٫۵۷٪ تا ۸٫۰۸٪ کم کرد، اما کلمهها را تغییر میدهد. تبدیل ی و ک فارسی به یای عربی و کاف عربی فقط در Qwen3 از تعداد توکنها کاست و در بقیه، تعداد توکنها را ۲٫۲۰٪ تا ۱۱٫۹۵٪ افزایش داد. هر دو تغییر تطبیق دقیق را میشکنند، مگر اینکه همه پرسوجوها هم به همان شکل تغییر کنند.
هر توکن فارسی چند کاراکتر است؟
به توکنایزر بستگی دارد: در این اندازهگیری از ۱٫۴۰ با cl100k_base تا ۳٫۶۸ با bge-m3، در برابر ۴٫۳۰ تا ۴٫۹۱ برای انگلیسی. قاعده ثابتی که در یک توکنایزر امن است، ممکن است در توکنایزر دیگر کمتر از واقع بشمارد؛ همین سایت پس از این اندازهگیری قاعده «هر دو نویسه، یک توکن» را کنار گذاشت و اکنون شمار بایتها را رزرو میکند. توصیه کلی هم همین است: بر پایه یک سقف قطعی یا شمارش خود ارائهدهنده رزرو کنید، نه بر پایه یک قاعده سرانگشتی.
منابع
FLORES-200 README، راهنمای FLORES-200 در مخزن facebookresearch/flores
facebookresearch/flores، مخزن FLORES شامل مجوزها و اعلان بایگانی
facebook/flores، کارت مجموعهداده FLORES در Hugging Face
FLORES-200 dataset archive، بایگانی رسمی دادهها
No Language Left Behind: Scaling Human-Centered Machine Translation، مقاله تیم NLLB، سال ۲۰۲۲
Measuring the Tokenization Premium: A Cost Audit for Underserved Language Communities، مقاله Roy و Roy و Patel، پذیرفتهشده در کارگاهی از IJCAI 2026
Language Model Tokenizers Introduce Unfairness Between Languages، مقاله Petrov و همکاران، کنفرانس NeurIPS سال ۲۰۲۳
tokenization_lengths.csv، دادههای طول توکنسازی Petrov و همکاران روی FLORES-200
compute_tokenizations.py، اسکریپت Petrov و همکاران که بخشهای dev و devtest را یکجا میکند
Tokenization Disparities as Infrastructure Bias، مقاله Teklehaymanot و Nejdl، سال ۲۰۲۵
Do All Languages Cost the Same? Tokenization in the Era of Commercial Language Models، مقاله Ahia و همکاران، سال ۲۰۲۳
Unsupervised Cross-lingual Representation Learning at Scale، مقاله Conneau و همکاران درباره XLM-R و پیکره CC-100
M3-Embedding، مقاله Chen و همکاران درباره BGE-M3
BAAI/bge-m3، کارت مدل bge-m3 در Hugging Face
Model card for Qwen3، کارت مدل Qwen3 در Hugging Face
Model card for DeepSeek-V3، کارت مدل DeepSeek-V3 در Hugging Face
openai/tiktoken model.py، نگاشت مدلها به انکودینگها در tiktoken
Token counting، مستندات Claude درباره شمارش توکن
Rate limits، مستندات Claude درباره محدودیت نرخ
Reducing latency، مستندات Claude درباره کاهش تأخیر
Streaming messages، مستندات Claude درباره پاسخ استریم
Latency optimization، مستندات OpenAI API درباره بهینهسازی تأخیر
Chat Completions streaming events، مرجع OpenAI API درباره رویدادهای پاسخ استریم
Understand and count tokens، مستندات Gemini API درباره شمارش توکن
local_tokenizer.py، توکنایزر محلی آزمایشی در SDK پایتون Google Gen AI
_local_tokenizer_loader.py، نگاشت مدلهای Gemini به توکنایزرهای Gemma در همان SDK
UnicodeData.txt، پایگاه داده نویسههای یونیکد
اگر قابلیتی مبتنی بر LLM برای کاربران فارسیزبان طراحی میکنید، از سنجش پروژه شروع کنید.