<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Abdul Rauf Ghulam Nabi</title>
    <description>The latest articles on DEV Community by Abdul Rauf Ghulam Nabi (@abdul_raufghulamnabi_65).</description>
    <link>https://dev.to/abdul_raufghulamnabi_65</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4227182%2F2e69c570-8403-4853-804a-39ca360fd853.png</url>
      <title>DEV Community: Abdul Rauf Ghulam Nabi</title>
      <link>https://dev.to/abdul_raufghulamnabi_65</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/abdul_raufghulamnabi_65"/>
    <language>en</language>
    <item>
      <title>What an Urdu sentence costs in tokens</title>
      <dc:creator>Abdul Rauf Ghulam Nabi</dc:creator>
      <pubDate>Wed, 04 Nov 2026 21:16:46 +0000</pubDate>
      <link>https://dev.to/abdul_raufghulamnabi_65/what-an-urdu-sentence-costs-in-tokens-1mk6</link>
      <guid>https://dev.to/abdul_raufghulamnabi_65/what-an-urdu-sentence-costs-in-tokens-1mk6</guid>
      <description>&lt;p&gt;Here are two sentences that mean exactly the same thing:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The government announced a new policy on electricity prices yesterday.&lt;/p&gt;

&lt;p&gt;حکومت نے کل بجلی کی قیمتوں سے متعلق نئی پالیسی کا اعلان کیا۔&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ten words in English, thirteen in Urdu. If you're paying for an LLM, you'd expect them to cost roughly the same.&lt;/p&gt;

&lt;p&gt;Measured across 30 pairs like this one, the same meanings cost &lt;strong&gt;320 tokens in English and 1,999 in Urdu&lt;/strong&gt; on GPT-2.&lt;/p&gt;

&lt;p&gt;That's not a rounding error. That's the price of writing in a different script.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why tokens are the wrong unit to ignore
&lt;/h2&gt;

&lt;p&gt;Every LLM interaction is measured in tokens — you're billed in them, and your context window is counted in them. Words and characters are irrelevant to the meter.&lt;/p&gt;

&lt;p&gt;Tokenizers are trained on whatever text their creators had, and that text is overwhelmingly English. When a tokenizer meets a script it barely saw during training, it falls back to breaking text into small pieces — sometimes into raw bytes.&lt;/p&gt;

&lt;p&gt;The result is that "one page" of Urdu is not one page of tokens. It's five pages' worth.&lt;/p&gt;

&lt;p&gt;I wanted a real number instead of a vibe, so I built a small benchmark to measure it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The method
&lt;/h2&gt;

&lt;p&gt;The measurement is called &lt;strong&gt;fertility&lt;/strong&gt;: tokens divided by words. Compare the same content in two languages, and the ratio tells you how much more you pay.&lt;/p&gt;

&lt;p&gt;The key requirement is that the two texts must mean the same thing — otherwise you're measuring content, not encoding. So I wrote a parallel corpus: 30 sentences, each written in both English and Urdu, spanning 17 everyday domains (news, medical, legal, technical, agriculture, and so on).&lt;/p&gt;

&lt;p&gt;I couldn't use FLORES+, the standard benchmark for this work. Its access gate explicitly forbids re-hosting it anywhere web crawlers can reach, and a public Space or dataset would violate that. So the corpus is original, released CC-BY-4.0, and freely re-hostable: &lt;a href="https://huggingface.co/datasets/abdulrauf5121/urdu-english-parallel" rel="noopener noreferrer"&gt;urdu-english-parallel&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Corpus shape: 30 pairs, 283 English words / 1,711 characters vs 328 Urdu words / 2,680 characters. All strings verified NFC, with no zero-width joiners and no Arabic presentation forms — those inflate token counts for reasons that have nothing to do with vocabulary, and they are easy to overlook.&lt;/p&gt;

&lt;h2&gt;
  
  
  The results
&lt;/h2&gt;

&lt;p&gt;Three tokenizers, spanning a wide range of vocabulary sizes:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tokenizer&lt;/th&gt;
&lt;th&gt;Vocab&lt;/th&gt;
&lt;th&gt;English tokens&lt;/th&gt;
&lt;th&gt;Urdu tokens&lt;/th&gt;
&lt;th&gt;Urdu inflation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GPT-2&lt;/td&gt;
&lt;td&gt;~50k&lt;/td&gt;
&lt;td&gt;320&lt;/td&gt;
&lt;td&gt;1,999&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;5.39×&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mistral v0.3&lt;/td&gt;
&lt;td&gt;~32k&lt;/td&gt;
&lt;td&gt;359&lt;/td&gt;
&lt;td&gt;1,554&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3.73×&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Qwen2.5&lt;/td&gt;
&lt;td&gt;~151k&lt;/td&gt;
&lt;td&gt;318&lt;/td&gt;
&lt;td&gt;1,002&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;2.72×&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Same 30 sentences, same meanings, in every row.&lt;/p&gt;

&lt;p&gt;Inflation is Urdu fertility ÷ English fertility. A value of 5.39× means the same meaning costs you more than five times as many tokens.&lt;/p&gt;

&lt;h2&gt;
  
  
  The number that actually made me stop
&lt;/h2&gt;

&lt;p&gt;Fertility is abstract. Here it is per character:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Characters per token&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;English (GPT-2)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;5.35&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Urdu (GPT-2)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.34&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;English gets more than five characters packed into every token. Urdu gets &lt;strong&gt;one and a third&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That is close to character-level: on this tokenizer, Urdu is being encoded nearly one letter at a time rather than one word at a time. A thousand-character Urdu page costs about &lt;strong&gt;746 tokens&lt;/strong&gt; on GPT-2; the same number of characters in English costs about &lt;strong&gt;187&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this does to your context window
&lt;/h2&gt;

&lt;p&gt;A 128,000-token context sounds enormous. Here's what it holds:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tokenizer&lt;/th&gt;
&lt;th&gt;Words of English&lt;/th&gt;
&lt;th&gt;Words of Urdu&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GPT-2&lt;/td&gt;
&lt;td&gt;~113,000&lt;/td&gt;
&lt;td&gt;~21,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Qwen2.5&lt;/td&gt;
&lt;td&gt;~114,000&lt;/td&gt;
&lt;td&gt;~41,900&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;(English capacity differs slightly per row because English fertility differs slightly — 1.13 vs 1.12.)&lt;/p&gt;

&lt;p&gt;On the English-trained tokenizer, a "128k" model holds &lt;strong&gt;roughly a fifth&lt;/strong&gt; of the Urdu it holds of English. Put a 200-page Urdu document in front of it and you're truncating most of it. In a RAG pipeline, the same chunk costs five times as much, so you retrieve far less for the same budget.&lt;/p&gt;

&lt;p&gt;And the billing follows the context window: at any per-token price, Urdu documents cost 2.7–5.4× more to process than English ones of the same substance.&lt;/p&gt;

&lt;h2&gt;
  
  
  A surprise: bigger vocabulary isn't the whole story
&lt;/h2&gt;

&lt;p&gt;I expected this to be a pure vocabulary-size story. It isn't.&lt;/p&gt;

&lt;p&gt;GPT-2 has &lt;strong&gt;50k&lt;/strong&gt; vocabulary and 5.39× inflation. Mistral has only &lt;strong&gt;32k&lt;/strong&gt; and still does better at 3.73×. Qwen2.5 with 151k is best at 2.72×.&lt;/p&gt;

&lt;p&gt;So vocabulary size helps, but &lt;em&gt;what the tokenizer was trained on&lt;/em&gt; appears to matter at least as much. My reading is that Mistral's tokenizer saw far more non-English text than GPT-2's, and that diversity outweighs an 18k-vocabulary deficit. Either way the conclusion holds: you cannot fix script fairness by scaling the vocabulary alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd actually do about it
&lt;/h2&gt;

&lt;p&gt;If you're building for Urdu users today:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Normalize your text first — and decide what you are normalizing.&lt;/strong&gt; Apply NFKC and remove Arabic presentation forms. Be deliberate about zero-width joiners: they are orthographically meaningful in Urdu (they block ligatures), so they are not simply noise. Measure both ways and document which you chose.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Measure your own corpus.&lt;/strong&gt; Fertility varies by domain and register. My formal corpus is not your conversational data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pick the tokenizer deliberately.&lt;/strong&gt; If your app is Urdu-first, the tokenizer choice can cut your bill by half — that's a real product decision, not a detail.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Budget context accordingly.&lt;/strong&gt; If you assume 128k tokens ≈ 128k tokens of Urdu, you'll silently truncate.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Caveats, honestly
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;30 sentences is a pilot.&lt;/strong&gt; It supports the direction of the effect; it does not pin down a precise multiplier. Treat 5.39× as "roughly five", not a decimal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Formal register only.&lt;/strong&gt; These sentences lean administrative and technical. Conversational Urdu — and Roman Urdu, which tokenizes completely differently — is not represented.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;One translator, no inter-annotator measurement.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Each sentence was encoded independently.&lt;/strong&gt; Where a tokenizer adds per-sentence special tokens, they are added equally to both languages, so ratios are essentially unaffected — though absolute counts may differ slightly from a one-pass measurement.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it yourself
&lt;/h2&gt;

&lt;p&gt;Everything runs in your browser — no server, no API key, your text never leaves the page:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Space:&lt;/strong&gt; &lt;a href="https://huggingface.co/spaces/abdulrauf5121/urdu-token-fairness" rel="noopener noreferrer"&gt;urdu-token-fairness&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Corpus:&lt;/strong&gt; &lt;a href="https://huggingface.co/datasets/abdulrauf5121/urdu-english-parallel" rel="noopener noreferrer"&gt;urdu-english-parallel&lt;/a&gt; (CC-BY-4.0)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Space shows the actual subword pieces. Some are pink: those are single Urdu characters split across two tokens. That visual is the whole argument in one glance.&lt;/p&gt;

&lt;h2&gt;
  
  
  The general point
&lt;/h2&gt;

&lt;p&gt;This isn't only about Urdu. Every language outside the tokenizer's training distribution pays a tax — in money, in context, in latency, in what fits in a prompt. The tax is invisible unless you measure it, and it compounds for exactly the users who already have less compute directed at their language.&lt;/p&gt;

&lt;p&gt;If you speak a language that isn't well represented in tokenizers, the most useful thing you can do is measure it. The corpus format is 30 sentences and a JSON file. Add your language, run the Space, publish the number.&lt;/p&gt;

&lt;p&gt;The tax is real. It should at least be visible.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>nlp</category>
      <category>tokenization</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
