Overview
The estimate_prompt_tokens function uses a simplistic character-count heuristic (len(content) // 4) to estimate token counts. While this provides a rough approximation for English prose, it fails significantly for code (heavy punctuation), multi-byte Unicode strings (CJK, emojis), and whitespace-padded content, compromising context-window clamping accuracy and routing metrics.
Location
File:router/main.py — estimate_prompt_tokens(), Lines 68–85
Current Code
defestimate_prompt_tokens(body: dict) ->int:
"""Estimate prompt tokens by counting characters in message contents (1 token ~= 4 chars) to avoid inflating metrics with large tool/schema declarations. """tokens=0formsginbody.get("messages", []):
ifnotisinstance(msg, dict):
continuecontent=msg.get("content") or""ifisinstance(content, str):
tokens+=len(content) //4elifisinstance(content, list):
forblockincontent:
ifisinstance(block, dict) andblock.get("type") =="text":
tokens+=len(block.get("text") or"") //4tokens+=50returnmax(1, tokens)Problems
| Content Type | Actual Tokens | len//4 Estimate | Error |
|---|
| English prose | ~100 | ~100 | ✅ ~0% |
| Python code | ~100 | ~60 | ❌ -40% (punctuation is individually tokenized) |
| CJK text (Chinese/Japanese) | ~50 | ~75 | ❌ +50% (multi-byte chars inflate len()) |
| Whitespace-padded JSON | ~100 | ~200 | ❌ +100% (spaces count as chars but not tokens) |
| System emojis | ~10 | ~40 | ❌ +300% (4-byte chars) |
Impact
- Severity: 🟡 Medium (Accuracy)
- Under-estimation for code prompts → context window overflows not caught by the router
- Over-estimation for CJK → unnecessarily routing to larger models
- Metrics dashboard shows inaccurate token counts, misleading cost analysis
Recommendations
Option A: Word-count baseline (Zero dependency, better accuracy)
A word-count heuristic provides tighter tracking than character division for mixed content:
defestimate_prompt_tokens(body: dict) ->int:
"""Estimate prompt tokens using word-count heuristic. Average English: ~1.3 tokens/word. Code: ~1.5 tokens/word. We use 1.3 as a conservative multiplier. """tokens=0formsginbody.get("messages", []):
ifnotisinstance(msg, dict):
continuecontent=msg.get("content") or""ifisinstance(content, str):
words=len(content.split())
tokens+=int(words*1.3)
elifisinstance(content, list):
forblockincontent:
ifisinstance(block, dict) andblock.get("type") =="text":
text=block.get("text") or""tokens+=int(len(text.split()) *1.3)
tokens+=50# metadata overheadreturnmax(1, tokens)Option B: Hybrid heuristic (Best accuracy without dependencies)
Combine character and word counting for a more robust estimate:
defestimate_prompt_tokens(body: dict) ->int:
tokens=0formsginbody.get("messages", []):
ifnotisinstance(msg, dict):
continuecontent=msg.get("content") or""ifisinstance(content, str):
# Average of char-based and word-based estimateschar_est=len(content) //4word_est=int(len(content.split()) *1.3)
tokens+= (char_est+word_est) //2elifisinstance(content, list):
forblockincontent:
ifisinstance(block, dict) andblock.get("type") =="text":
text=block.get("text") or""char_est=len(text) //4word_est=int(len(text.split()) *1.3)
tokens+= (char_est+word_est) //2tokens+=50returnmax(1, tokens)Option C: tiktoken (Most accurate, adds dependency)
For production-grade accuracy, use OpenAI's tiktoken library:
importtiktoken_enc=tiktoken.get_encoding("cl100k_base") # GPT-4 / Claude compatibledefestimate_prompt_tokens(body: dict) ->int:
tokens=0formsginbody.get("messages", []):
content=msg.get("content") or""ifisinstance(content, str):
tokens+=len(_enc.encode(content))
tokens+=50returnmax(1, tokens)Note: tiktoken adds a dependency but provides exact tokenizer-aligned counts. Consider the tradeoff vs. zero-dependency heuristics.
Acceptance Criteria
Overview
The
estimate_prompt_tokensfunction uses a simplistic character-count heuristic (len(content) // 4) to estimate token counts. While this provides a rough approximation for English prose, it fails significantly for code (heavy punctuation), multi-byte Unicode strings (CJK, emojis), and whitespace-padded content, compromising context-window clamping accuracy and routing metrics.Location
File:
router/main.py—estimate_prompt_tokens(), Lines 68–85Current Code
Problems
len//4Estimatelen())Impact
Recommendations
Option A: Word-count baseline (Zero dependency, better accuracy)
A word-count heuristic provides tighter tracking than character division for mixed content:
Option B: Hybrid heuristic (Best accuracy without dependencies)
Combine character and word counting for a more robust estimate:
Option C:
tiktoken(Most accurate, adds dependency)For production-grade accuracy, use OpenAI's
tiktokenlibrary:Acceptance Criteria