-
-
Notifications
You must be signed in to change notification settings - Fork 11.7k
fix: python 3.10 typing compatibility in compact editor and claude 3 cache pricing (#38076, #38056) #38189
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
fix: python 3.10 typing compatibility in compact editor and claude 3 cache pricing (#38076, #38056) #38189
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| """ | ||
| Unit tests for Python 3.10+ typing compatibility in context management compact editor. | ||
|
|
||
| Fixes Issue #38076: | ||
| - Verifies that NotRequired is correctly imported either from typing (>= 3.11) or typing_extensions (< 3.11). | ||
| - Verifies that _SummaryCallKwargs TypedDict definition is valid across Python versions. | ||
| """ | ||
|
|
||
| import importlib | ||
| import sys | ||
|
|
||
|
|
||
| def test_compact_editor_not_required_import(): | ||
| """Verify that compact.py imports NotRequired correctly based on sys.version_info.""" | ||
| import litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact as compact_module | ||
|
|
||
| assert hasattr(compact_module, "NotRequired") | ||
| if sys.version_info >= (3, 11): | ||
| import typing | ||
|
|
||
| assert compact_module.NotRequired is typing.NotRequired | ||
| else: | ||
| import typing_extensions | ||
|
|
||
| assert compact_module.NotRequired is typing_extensions.NotRequired | ||
|
|
||
|
|
||
| def test_compact_editor_summary_call_kwargs_definition(): | ||
| """Verify that _SummaryCallKwargs TypedDict is properly constructed.""" | ||
| from litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact import ( | ||
| _SummaryCallKwargs, | ||
| ) | ||
|
|
||
| annotations = _SummaryCallKwargs.__annotations__ | ||
| assert "model" in annotations | ||
| assert "messages" in annotations | ||
| assert "max_tokens" in annotations | ||
| assert "timeout" in annotations | ||
| assert "litellm_metadata" in annotations | ||
| assert "user" in annotations | ||
| assert "allowed_model_region" in annotations | ||
|
|
||
|
|
||
| def test_compact_module_can_be_imported(): | ||
| """Ensure litellm compact module imports without error on the current runtime.""" | ||
| compact_module = importlib.import_module( | ||
| "litellm.llms.anthropic.experimental_pass_through.context_management.editors.compact" | ||
| ) | ||
| assert compact_module is not None | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| """ | ||
| Unit tests for Claude 3 cache creation pricing above 1 hour in model prices map. | ||
|
|
||
| Fixes Issue #38056: | ||
| - claude-3-haiku-20240307 cache_creation_input_token_cost_above_1hr should be 5e-07 (2x input cost of 2.5e-07) | ||
| - claude-3-opus-20240229 cache_creation_input_token_cost_above_1hr should be 3e-05 (2x input cost of 1.5e-05) | ||
| """ | ||
|
|
||
| import json | ||
| from pathlib import Path | ||
|
|
||
| import pytest | ||
|
|
||
| REPO_ROOT = Path(__file__).parents[2] | ||
| MAIN_PATH = REPO_ROOT / "model_prices_and_context_window.json" | ||
| BACKUP_PATH = REPO_ROOT / "litellm" / "model_prices_and_context_window_backup.json" | ||
|
|
||
|
|
||
| def _load_prices(path: Path) -> dict: | ||
| with open(path) as f: | ||
| return json.load(f) | ||
|
|
||
|
|
||
| @pytest.mark.parametrize("path", [MAIN_PATH, BACKUP_PATH], ids=["main", "backup"]) | ||
| def test_claude_3_haiku_cache_creation_cost_above_1hr(path: Path): | ||
| prices = _load_prices(path) | ||
| model = "claude-3-haiku-20240307" | ||
| assert model in prices, f"{model} not found in {path}" | ||
| model_info = prices[model] | ||
|
|
||
| input_cost = model_info["input_cost_per_token"] | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment and the equivalent Opus comment merely restate the immediately following Context Used: CLAUDE.md (source) Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time! |
||
| assert input_cost == 2.5e-07 | ||
|
|
||
| # Cache creation cost above 1hr is 2x standard input cost (5e-07) | ||
| expected_cache_creation_above_1hr = input_cost * 2 | ||
| assert model_info["cache_creation_input_token_cost_above_1hr"] == expected_cache_creation_above_1hr | ||
| assert model_info["cache_creation_input_token_cost_above_1hr"] == 5e-07 | ||
|
|
||
|
|
||
| @pytest.mark.parametrize("path", [MAIN_PATH, BACKUP_PATH], ids=["main", "backup"]) | ||
| def test_claude_3_opus_cache_creation_cost_above_1hr(path: Path): | ||
| prices = _load_prices(path) | ||
| model = "claude-3-opus-20240229" | ||
| assert model in prices, f"{model} not found in {path}" | ||
| model_info = prices[model] | ||
|
|
||
| input_cost = model_info["input_cost_per_token"] | ||
| assert input_cost == 1.5e-05 | ||
|
|
||
| # Cache creation cost above 1hr is 2x standard input cost (3e-05) | ||
| expected_cache_creation_above_1hr = input_cost * 2 | ||
| assert model_info["cache_creation_input_token_cost_above_1hr"] == expected_cache_creation_above_1hr | ||
| assert model_info["cache_creation_input_token_cost_above_1hr"] == 3e-05 | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test selects its assertion from the interpreter running pytest, while the standard unit workflow uses Python 3.12. As a result, the newly added
typing_extensions.NotRequiredfallback is not exercised there, so a Python 3.10 compatibility regression would not be caught by this test.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!