feat(openai): add litellm.acount_tokens() public API + OpenAI token counting support - #22809
Merged
Chesars merged 15 commits intoMar 5, 2026
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
Greptile SummaryThis PR adds OpenAI token counting support via the Responses API
Confidence Score: 4/5
|
| Filename | Overview |
|---|---|
| litellm/llms/openai/responses/count_tokens/transformation.py | New transformation logic for OpenAI Responses API token counting. Handles chat-to-Responses format conversion including system/developer→instructions extraction, tool_calls→function_call mapping, and multimodal content extraction. Well-structured with good coverage of edge cases. |
| litellm/llms/openai/responses/count_tokens/handler.py | Async HTTP handler for OpenAI token counting endpoint. Uses shared httpx client, proper error handling with OpenAIError wrapping, and follows the existing Anthropic handler pattern closely. |
| litellm/llms/openai/responses/count_tokens/token_counter.py | BaseTokenCounter implementation for OpenAI. Handles API key resolution, message conversion, and graceful fallback to None when API is unavailable. Follows existing patterns from Anthropic token counter. |
| litellm/main.py | Adds acount_tokens() public async API with provider auto-detection, token counting delegation, and local tiktoken fallback. Error handling improved from earlier revisions — now logs and falls back gracefully. |
| litellm/proxy/response_api_endpoints/endpoints.py | Adds /v1/responses/input_tokens proxy endpoint with Responses API→chat format conversion. Handles function_call and function_call_output items correctly. ProxyException handling follows existing Anthropic endpoint pattern. |
| litellm/llms/openai/chat/gpt_transformation.py | Minimal change — adds get_token_counter() factory method to OpenAIGPTConfig, wiring OpenAI into the existing provider token counter infrastructure. |
| tests/test_litellm/llms/openai/responses/test_openai_count_tokens_transformation.py | 15 unit tests for transformation logic covering basic requests, instructions, tools, message conversion, validation, and endpoint URL generation. All use mocks — no real network calls. |
| tests/test_litellm/test_count_tokens_public_api.py | 7 tests for the public acount_tokens() API covering routing, fallback, tools passthrough, system messages, and error recovery. All provider API calls are properly mocked. |
Sequence Diagram
sequenceDiagram
participant User
participant SDK as acount_tokens
participant Router as ProviderConfigManager
participant Counter as OpenAITokenCounter
participant Transform as CountTokensConfig
participant Handler as CountTokensHandler
participant OpenAI as OpenAI Endpoint
participant Fallback as Local Tiktoken
User->>SDK: model, messages, tools, system
SDK->>Router: get_provider_model_info(model)
Router-->>SDK: OpenAIGPTConfig
SDK->>Counter: count_tokens(messages, tools, system)
Counter->>Transform: messages_to_responses_input(messages)
Transform-->>Counter: (input_items, instructions)
Counter->>Handler: handle_count_tokens_request(input, tools)
Handler->>OpenAI: POST /responses/input_tokens
OpenAI-->>Handler: input_tokens count
Handler-->>Counter: response
Counter-->>SDK: TokenCountResponse
SDK-->>User: TokenCountResponse
Note over SDK,Fallback: On failure or unsupported provider
SDK->>Fallback: token_counter(model, messages, tools)
Fallback-->>SDK: count (int)
SDK-->>User: TokenCountResponse(local_tokenizer)
Last reviewed commit: abc381c
…m.acount_tokens() - Add OpenAITokenCounter using POST /v1/responses/input_tokens endpoint - Add litellm.acount_tokens() public async API that auto-routes to provider APIs - Add proxy endpoint POST /v1/responses/input_tokens for OpenAI-compatible counting - Transform chat tools format to Responses API format for correct token counting - Fall back to local tiktoken when provider API unavailable Fixes BerriAI#22302
- Log provider token counting failures instead of silently swallowing - Fall back to local tokenizer when provider returns error response - Map assistant tool_calls to Responses API function_call items - Concatenate multiple system messages instead of overwriting - Hide internal error details from proxy API responses - Narrow exception catch in handler to network/JSON errors only - Update test to match new fallback behavior
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
…te instructions and elif
Chesars
force-pushed
the
worktree-count-tokens-api
branch
from
March 4, 2026 22:32
73d031c to
c185652
Compare
Match the error handling pattern used in the Anthropic count_tokens endpoint: catch ProxyException separately to surface its status code and message, and include error details in the generic 500 fallback.
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
…cs format, system-only fallback - Fix F821: add BaseTokenCounter TYPE_CHECKING import in gpt_transformation.py - Remove duplicate auth invocation in count_response_input_tokens endpoint - Preserve `strict` field during chat→Responses API tool conversion - Fix docs tools example to use chat completions format (not Responses API format) - Return None early for system-only messages to avoid noisy error logs
Chesars
merged commit Mar 5, 2026
6693723
into
BerriAI:litellm_oss_staging_03_04_2026
4 of 5 checks passed
fzowl
pushed a commit
to fzowl/litellm
that referenced
this pull request
Jun 24, 2026
feat(openai): add litellm.acount_tokens() public API + OpenAI token counting support
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Relevant issues
Fixes #22302
Pre-Submission checklist
Please complete all items before asking a LiteLLM maintainer to review your PR
tests/test_litellm/directory, Adding at least 1 test is a hard requirement - see detailsmake test-unit@greptileaiand received a Confidence Score of at least 4/5 before requesting a maintainer reviewCI (LiteLLM team)
Branch creation CI run
Link:
CI run for the last commit
Link:
Merge / cherry-pick CI run
Links:
Type
🆕 New Feature
Changes
1. OpenAI Token Counting Provider (
litellm/llms/openai/responses/count_tokens/)Adds
OpenAITokenCounterthat calls OpenAI'sPOST /v1/responses/input_tokensendpoint for exact token counts. Follows the same pattern as existing Anthropic, Bedrock, and Gemini token counters.transformation.py— Request/response transformation, including chat tools → Responses API tools format conversionhandler.py— Async HTTP handler using httpxtoken_counter.py—BaseTokenCounterimplementation that auto-detects OpenAI provider2. Public SDK Method (
litellm/main.py)Adds
litellm.acount_tokens()— an async public method that:openai/gpt-4o,anthropic/claude-3-5-sonnet)TokenCountResponsewith exact token count3. Proxy Endpoint (
litellm/proxy/response_api_endpoints/endpoints.py)Adds
POST /v1/responses/input_tokens(+/responses/input_tokens,/openai/v1/responses/input_tokens) that:input,instructions,tools)call_endpoint=True{"input_tokens": N}4. Wiring (
litellm/llms/openai/chat/gpt_transformation.py)Adds
get_token_counter()toOpenAIGPTConfigso the existing proxy routing (_get_provider_token_counter) automatically picks up OpenAI.Provider Support Status
POST /v1/responses/input_tokensPOST /v1/messages/count_tokensTests
tests/test_litellm/llms/openai/responses/test_openai_count_tokens_transformation.py— 15 tests for transformation logictests/test_litellm/test_count_tokens_public_api.py— 7 tests for public API routing + fallback