mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-14 04:09:09 +00:00
fix(anthropic): propagate api_base to count_tokens endpoint
When a deployment configures a custom api_base, /v1/messages/count_tokens was silently routing to api.anthropic.com instead. The token counter read api_base from litellm_params but never passed it to the handler; the handler had the parameter but used it as a raw URL without appending the path. Fixes: propagate api_base (and ANTHROPIC_API_BASE env fallback) from AnthropicTokenCounter.count_tokens into the handler, and add _build_count_tokens_url to AnthropicCountTokensConfig to correctly append /v1/messages/count_tokens to any base variant.
This commit is contained in:
parent
6003187165
commit
f8eaf7f8bd
4 changed files with 69 additions and 9 deletions
|
|
@ -68,8 +68,8 @@ class AnthropicCountTokensHandler(AnthropicCountTokensConfig):
|
|||
|
||||
verbose_logger.debug(f"Transformed request: {request_body}")
|
||||
|
||||
# Get endpoint URL
|
||||
endpoint_url = api_base or self.get_anthropic_count_tokens_endpoint()
|
||||
# Get endpoint URL; append the count_tokens path when a custom base is given
|
||||
endpoint_url = self._build_count_tokens_url(api_base)
|
||||
|
||||
verbose_logger.debug(f"Making request to: {endpoint_url}")
|
||||
|
||||
|
|
|
|||
|
|
@ -63,11 +63,16 @@ class AnthropicTokenCounter(BaseTokenCounter):
|
|||
verbose_logger.warning("No Anthropic API key found for token counting")
|
||||
return None
|
||||
|
||||
api_base: Optional[str] = litellm_params.get("api_base") or os.getenv(
|
||||
"ANTHROPIC_API_BASE"
|
||||
)
|
||||
|
||||
try:
|
||||
result = await anthropic_count_tokens_handler.handle_count_tokens_request(
|
||||
model=model_to_use,
|
||||
messages=messages,
|
||||
api_key=api_key,
|
||||
api_base=api_base,
|
||||
tools=tools,
|
||||
system=system,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -19,14 +19,22 @@ class AnthropicCountTokensConfig:
|
|||
- Response: {"input_tokens": <number>}
|
||||
"""
|
||||
|
||||
def get_anthropic_count_tokens_endpoint(self) -> str:
|
||||
"""
|
||||
Get the Anthropic CountTokens API endpoint.
|
||||
_COUNT_TOKENS_PATH: str = "/v1/messages/count_tokens"
|
||||
_DEFAULT_ENDPOINT: str = f"https://api.anthropic.com{_COUNT_TOKENS_PATH}"
|
||||
|
||||
Returns:
|
||||
The endpoint URL for the CountTokens API
|
||||
"""
|
||||
return "https://api.anthropic.com/v1/messages/count_tokens"
|
||||
def get_anthropic_count_tokens_endpoint(self) -> str:
|
||||
return self._DEFAULT_ENDPOINT
|
||||
|
||||
def _build_count_tokens_url(self, api_base: Optional[str]) -> str:
|
||||
"""Return the full count_tokens URL, appending the path when a custom base is provided."""
|
||||
if not api_base:
|
||||
return self._DEFAULT_ENDPOINT
|
||||
base = api_base.rstrip("/")
|
||||
if base.endswith(self._COUNT_TOKENS_PATH):
|
||||
return base
|
||||
if base.endswith("/v1/messages"):
|
||||
return f"{base}/count_tokens"
|
||||
return f"{base}{self._COUNT_TOKENS_PATH}"
|
||||
|
||||
def transform_request_to_count_tokens(
|
||||
self,
|
||||
|
|
|
|||
|
|
@ -93,3 +93,50 @@ def test_transform_no_system_no_tools():
|
|||
|
||||
assert "system" not in result
|
||||
assert "tools" not in result
|
||||
|
||||
|
||||
def test_build_count_tokens_url_no_base():
|
||||
"""No custom base -> default Anthropic endpoint."""
|
||||
config = AnthropicCountTokensConfig()
|
||||
assert (
|
||||
config._build_count_tokens_url(None)
|
||||
== "https://api.anthropic.com/v1/messages/count_tokens"
|
||||
)
|
||||
|
||||
|
||||
def test_build_count_tokens_url_bare_base():
|
||||
"""Plain domain base gets full path appended."""
|
||||
config = AnthropicCountTokensConfig()
|
||||
assert (
|
||||
config._build_count_tokens_url("https://my-proxy.example.com")
|
||||
== "https://my-proxy.example.com/v1/messages/count_tokens"
|
||||
)
|
||||
|
||||
|
||||
def test_build_count_tokens_url_base_with_v1_messages():
|
||||
"""Base already ending in /v1/messages gets only /count_tokens."""
|
||||
config = AnthropicCountTokensConfig()
|
||||
assert (
|
||||
config._build_count_tokens_url("https://my-proxy.example.com/v1/messages")
|
||||
== "https://my-proxy.example.com/v1/messages/count_tokens"
|
||||
)
|
||||
|
||||
|
||||
def test_build_count_tokens_url_already_full():
|
||||
"""Base already containing the full path is returned as-is."""
|
||||
config = AnthropicCountTokensConfig()
|
||||
assert (
|
||||
config._build_count_tokens_url(
|
||||
"https://my-proxy.example.com/v1/messages/count_tokens"
|
||||
)
|
||||
== "https://my-proxy.example.com/v1/messages/count_tokens"
|
||||
)
|
||||
|
||||
|
||||
def test_build_count_tokens_url_trailing_slash_stripped():
|
||||
"""Trailing slash on the base is ignored."""
|
||||
config = AnthropicCountTokensConfig()
|
||||
assert (
|
||||
config._build_count_tokens_url("https://my-proxy.example.com/")
|
||||
== "https://my-proxy.example.com/v1/messages/count_tokens"
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue