litellm/tests/test_litellm/proxy/spend_tracking
devin-ai-integration[bot] 359b7a8489
feat(rust): count tiktoken cl100k_base admission tokens in Rust (#40777)
* feat(rust): count tiktoken cl100k_base admission tokens in Rust

The Rust admission token counter only had the Anthropic tokenizer, so every
other model (OpenAI gpt-4 family, Azure, Gemini, Bedrock non-Claude, Mistral)
tokenized with tiktoken on the Python inference worker.

Add an exact cl100k_base counter to litellm-token-counter: the vendored rank
file (base64 token / rank lines, the bytes Python's tiktoken uses) is parsed
into a byte-level BPE model and the cl100k split pattern is a handwritten
scanner over the shared Unicode classes, so no regex engine runs per request.
Both tokenizers share the message, tool and reply-priming accounting.

The PyO3 TokenCounter gains a from_cl100k_ranks constructor; Python reads the
rank file and passes it in, the way claude_json_str already works. The bridge
selects the counter through the same predicates litellm.token_counter uses
(huggingface_tokenizer_kind, openai_tokenizer_encoding), declines o200k_base,
downloaded HuggingFace and custom tokenizers to Python, and budget reservation
counts once per distinct tokenizer a request names.

The legacy gpt-3.5-turbo-0301 message accounting (4 per message, -1 per name)
stays in Python: the selector declines it through the predicate token_counter
itself uses.

* feat(rust): count tiktoken o200k_base admission tokens in Rust (#40794)

Add a handwritten o200k_base split scanner and TokenCounter::from_o200k_ranks
next to the cl100k_base counter, sharing MergeRanks and the request
accounting. The Python bridge selects it when openai_tokenizer_encoding
names o200k_base, so gpt-4o, gpt-4.1, gpt-5, o1/o3/o4 and chatgpt-4o
requests stop tokenizing on the Python worker under LITELLM_RUST=true

Co-authored-by: yassin <yassin@berri.ai>

---------

Co-authored-by: yassin <yassin@berri.ai>
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-11 23:47:05 +00:00
..
test_budget_reservation.py feat(rust): count tiktoken cl100k_base admission tokens in Rust (#40777) 2026-09-11 23:47:05 +00:00
test_budget_reservation_redis_failure.py perf(proxy): pipeline spend counter increments into one Redis call per request (#40371) 2026-09-09 10:35:50 -07:00
test_cloudzero_endpoints.py test: drop the cwd-relative sys.path.insert calls from the test suite (#37802) 2026-08-22 09:25:58 -07:00
test_compression_savings.py feat(spend): track prompt compression saved tokens in daily spend aggregates (#33810) 2026-07-18 17:47:54 -07:00
test_key_metadata_recovery.py fix(spend-tracking): bound the spend-log scan with a statement timeout and name only unanimous alias, team, and owner 2026-09-08 17:24:22 -07:00
test_ptu_feature_flag.py feat(ptu): gate PTU flat-cost attribution behind an opt-in env var (#36138) 2026-08-10 12:23:20 -07:00
test_ptu_flat_cost_rollup.py test(ptu): drop the assertion on the flag removed upstream 2026-08-23 10:02:41 +00:00
test_savings.py fix(spend): compare auto-router targets by deployment identity (#40206) 2026-09-07 23:29:42 -07:00
test_spend_event.py feat(proxy): offload spend tracking to a pod-local collector sidecar (#40545) 2026-09-10 17:14:13 -07:00
test_spend_event_producer.py feat(proxy): offload spend tracking to a pod-local collector sidecar (#40545) 2026-09-10 17:14:13 -07:00
test_spend_log_error_logger.py feat(spend-logs): opt-in suppression of stack traces in spend-tracking error logs 2026-05-02 00:44:34 +00:00
test_spend_management_endpoints.py fix(proxy): count when a grouped log page starts past the last one 2026-09-11 14:59:18 -07:00
test_spend_query_optimization.py perf(proxy): total a short grouped log page from the page itself 2026-09-11 14:51:05 -07:00
test_spend_tracking_utils.py fix(proxy): keep call_type and request start time on failed-request spend logs (#40558) 2026-09-11 12:22:18 -07:00