diff --git a/litellm/utils.py b/litellm/utils.py index e5ce7157e77..467b8602c27 100644 --- a/litellm/utils.py +++ b/litellm/utils.py @@ -6526,21 +6526,10 @@ def acreate(*args, **kwargs): ## Thin client to handle the acreate langchain ca def prompt_token_calculator(model, messages): - # use tiktoken or anthropic's tokenizer depending on the model text: Final = " ".join(message["content"] for message in messages) - num_tokens = 0 if "claude" in model: - try: - import anthropic - except Exception: - Exception("Anthropic import failed please run `pip install anthropic`") - from anthropic import AI_PROMPT, HUMAN_PROMPT, Anthropic - - anthropic_obj: Final = Anthropic() - num_tokens = anthropic_obj.count_tokens(text) - else: - num_tokens = len(_get_default_encoding().encode(text)) - return num_tokens + return token_counter(model=model, text=text) + return len(_get_default_encoding().encode(text)) def valid_model(model): diff --git a/ruff-strict-budget.json b/ruff-strict-budget.json index a990f7c3830..3b3c3e8ae5b 100644 --- a/ruff-strict-budget.json +++ b/ruff-strict-budget.json @@ -57,7 +57,7 @@ "limit": 3 }, "BLE001": { - "limit": 2920 + "limit": 2919 }, "C401": { "limit": 8 @@ -108,7 +108,7 @@ "limit": 3 }, "F401": { - "limit": 17 + "limit": 14 }, "LOG015": { "limit": 5 @@ -152,9 +152,6 @@ "PLW0127": { "limit": 57 }, - "PLW0133": { - "limit": 1 - }, "PLW0602": { "limit": 215 }, diff --git a/ruff.toml b/ruff.toml index 9b90910b355..44bdf9d8125 100644 --- a/ruff.toml +++ b/ruff.toml @@ -5,9 +5,9 @@ lint.ignore = ["F405", "E402", "F403"] lint.extend-select = [ "T20", "PGH004", "RUF008", "RUF009", "RUF100", "B033", "FURB136", "FURB168", "FURB188", "I001", "PERF402", "PIE790", "PIE800", "PLC0208", - "PLR0402", "PLR1711", "PLR1730", "PLR2044", "PYI030", "PYI041", "PYI064", "RET501", "RUF010", - "RUF022", "RUF023", "RUF051", "SIM114", "SIM118", "TC005", "UP006", "UP007", "UP008", "UP012", - "UP018", "UP024", "UP032", "UP034", "UP035", "UP037", "UP045", + "PLR0402", "PLR1711", "PLR1730", "PLR2044", "PLW0133", "PYI030", "PYI041", "PYI064", "RET501", + "RUF010", "RUF022", "RUF023", "RUF051", "SIM114", "SIM118", "TC005", "UP006", "UP007", "UP008", + "UP012", "UP018", "UP024", "UP032", "UP034", "UP035", "UP037", "UP045", ] # RUF100 (unused-noqa) only knows the rules enabled in THIS config, so it would strip # `# noqa` directives that protect rules enforced elsewhere. List those codes as external diff --git a/tests/test_litellm/test_utils.py b/tests/test_litellm/test_utils.py index d655eb96a02..97baf818d7c 100644 --- a/tests/test_litellm/test_utils.py +++ b/tests/test_litellm/test_utils.py @@ -1,6 +1,7 @@ import json import logging import os +import sys from typing import Final from unittest.mock import AsyncMock, MagicMock, patch @@ -41,6 +42,7 @@ from litellm.utils import ( get_prompt_cache_min_tokens, is_cached_message, is_prompt_caching_valid_prompt, + prompt_token_calculator, ) # Adds the parent directory to the system path @@ -4973,3 +4975,19 @@ def test_completion_does_not_leak_rust_flag_into_provider_request_body(): create_kwargs = mock_client.chat.completions.with_raw_response.create.call_args.kwargs assert "rust" not in create_kwargs assert "rust" not in (create_kwargs.get("extra_body") or {}) + + +def test_prompt_token_calculator_counts_claude_without_the_anthropic_sdk(): + """ + The claude branch used to call the anthropic SDK's `count_tokens`, which the SDK + removed, so every claude call raised AttributeError. Counting must work with + `anthropic` unimportable. + """ + messages: Final = [{"role": "user", "content": "the quick brown fox jumps over the lazy dog"}] + + with patch.dict(sys.modules, {"anthropic": None}): + claude_tokens = prompt_token_calculator("claude-sonnet-4-5", messages) + gpt_tokens = prompt_token_calculator("gpt-4o", messages) + + assert claude_tokens == 9 + assert gpt_tokens == 9