fix(cache): Prevent "multiple values" error in get_cache_key (#20261)
## Problem
When `get_cache_key(**kwargs)` is called with kwargs that already
contains `preset_cache_key` (which can happen when cache key is
recomputed in certain code paths), the call to
`_set_preset_cache_key_in_kwargs()` fails with:
```
TypeError: _set_preset_cache_key_in_kwargs() got multiple values
for keyword argument 'preset_cache_key'
```
This is because `preset_cache_key` is passed both explicitly:
```python
self._set_preset_cache_key_in_kwargs(
preset_cache_key=hashed_cache_key, **kwargs
)
```
And implicitly via `**kwargs` unpacking when `kwargs["preset_cache_key"]`
exists.
## Solution
Filter out `preset_cache_key` from kwargs before passing to
`_set_preset_cache_key_in_kwargs()`:
```python
kwargs_for_preset = {k: v for k, v in kwargs.items() if k != "preset_cache_key"}
self._set_preset_cache_key_in_kwargs(
preset_cache_key=hashed_cache_key, **kwargs_for_preset
)
```
## Testing
Added unit tests covering:
- kwargs with existing preset_cache_key (the bug case)
- kwargs without preset_cache_key (regression test)
- Verification that preset_cache_key is correctly set in litellm_params
This commit is contained in:
parent
d6351a3966
commit
e68cfaae0c
@ -312,8 +312,11 @@ class Cache:
|
||||
verbose_logger.debug("\nCreated cache key: %s", cache_key)
|
||||
hashed_cache_key = Cache._get_hashed_cache_key(cache_key)
|
||||
hashed_cache_key = self._add_namespace_to_cache_key(hashed_cache_key, **kwargs)
|
||||
# Remove preset_cache_key from kwargs to avoid "got multiple values" TypeError
|
||||
# when kwargs already contains preset_cache_key from upstream callers
|
||||
kwargs_for_preset = {k: v for k, v in kwargs.items() if k != "preset_cache_key"}
|
||||
self._set_preset_cache_key_in_kwargs(
|
||||
preset_cache_key=hashed_cache_key, **kwargs
|
||||
preset_cache_key=hashed_cache_key, **kwargs_for_preset
|
||||
)
|
||||
return hashed_cache_key
|
||||
|
||||
|
||||
87
tests/local_testing/test_cache_preset_key.py
Normal file
87
tests/local_testing/test_cache_preset_key.py
Normal file
@ -0,0 +1,87 @@
|
||||
"""
|
||||
Test for preset_cache_key multiple values bug fix.
|
||||
|
||||
This test verifies that get_cache_key doesn't raise TypeError when kwargs
|
||||
already contains preset_cache_key.
|
||||
|
||||
Issue: When get_cache_key(**kwargs) is called with kwargs containing
|
||||
preset_cache_key, the call to _set_preset_cache_key_in_kwargs() would fail with:
|
||||
TypeError: got multiple values for keyword argument 'preset_cache_key'
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
|
||||
class TestPresetCacheKeyFix:
|
||||
"""Tests for the preset_cache_key multiple values fix."""
|
||||
|
||||
def test_get_cache_key_with_preset_cache_key_in_kwargs(self):
|
||||
"""
|
||||
Test that get_cache_key handles kwargs that already contain preset_cache_key.
|
||||
|
||||
This was causing:
|
||||
TypeError: _set_preset_cache_key_in_kwargs() got multiple values
|
||||
for keyword argument 'preset_cache_key'
|
||||
"""
|
||||
from litellm.caching.caching import Cache
|
||||
|
||||
cache = Cache()
|
||||
|
||||
# Simulate kwargs that already has preset_cache_key (as can happen
|
||||
# when the cache key is recomputed in certain code paths)
|
||||
kwargs_with_preset = {
|
||||
"model": "gpt-4",
|
||||
"messages": [{"role": "user", "content": "Hello"}],
|
||||
"preset_cache_key": "existing_key_12345", # This caused the bug
|
||||
"litellm_params": {},
|
||||
}
|
||||
|
||||
# This should NOT raise TypeError
|
||||
try:
|
||||
result = cache.get_cache_key(**kwargs_with_preset)
|
||||
assert result is not None
|
||||
assert isinstance(result, str)
|
||||
except TypeError as e:
|
||||
if "multiple values for keyword argument" in str(e):
|
||||
pytest.fail(f"Bug not fixed: {e}")
|
||||
raise
|
||||
|
||||
def test_get_cache_key_without_preset_cache_key(self):
|
||||
"""Test normal case without preset_cache_key in kwargs still works."""
|
||||
from litellm.caching.caching import Cache
|
||||
|
||||
cache = Cache()
|
||||
|
||||
kwargs_normal = {
|
||||
"model": "gpt-4",
|
||||
"messages": [{"role": "user", "content": "Hello"}],
|
||||
"litellm_params": {},
|
||||
}
|
||||
|
||||
result = cache.get_cache_key(**kwargs_normal)
|
||||
assert result is not None
|
||||
assert isinstance(result, str)
|
||||
|
||||
def test_preset_cache_key_is_set_in_litellm_params(self):
|
||||
"""Verify that preset_cache_key is correctly set in litellm_params."""
|
||||
from litellm.caching.caching import Cache
|
||||
|
||||
cache = Cache()
|
||||
|
||||
litellm_params = {}
|
||||
kwargs = {
|
||||
"model": "gpt-4",
|
||||
"messages": [{"role": "user", "content": "Hello"}],
|
||||
"litellm_params": litellm_params,
|
||||
}
|
||||
|
||||
result = cache.get_cache_key(**kwargs)
|
||||
|
||||
# The method should set preset_cache_key in litellm_params
|
||||
assert "preset_cache_key" in litellm_params
|
||||
assert litellm_params["preset_cache_key"] == result
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pytest.main([__file__, "-v"])
|
||||
Loading…
Reference in New Issue
Block a user