fix(proxy_server.py): fix setting router redis cache, if cache enable… (#8859)

* fix(proxy_server.py): fix setting router redis cache, if cache enabled on litellm_settings

enables configurations like namespace to just work

* fix(redis_cache.py): fix key for async increment, to use the set namespace

prevents collisions if redis instance shared across environments

* fix load tests on litellm release notes

* fix caching on main branch (#8858)

* fix(streaming_handler.py): fix is delta empty check to handle empty str

* fix(streaming_handler.py): fix delta chunk on final response

* [Bug]: Deepseek error on proxy after upgrading to 1.61.13-stable (#8860)

* fix deepseek error

* test_deepseek_provider_async_completion

* fix get_complete_url

* bump: version 1.61.17 → 1.61.18

* bump: version 1.61.18 → 1.61.19

* vertex ai anthropic thinking param support (#8853)

* fix(vertex_llm_base.py): handle credentials passed in as dictionary

* fix(router.py): support vertex credentials as json dict

* test(test_vertex.py): allows easier testing

mock anthropic thinking response for vertex ai

* test(vertex_ai_partner_models/): don't remove "@" from model

breaks anthropic cost calculation

* test: move testing

* fix: fix linting error

* fix: fix linting error

* fix(vertex_ai_partner_models/main.py): split @ for codestral model

* test: fix test

* fix: fix stripping "@" on mistral models

* fix: fix test

* test: fix test

---------

Co-authored-by: Ishaan Jaff <ishaanjaffer0324@gmail.com>
This commit is contained in:
Krish Dholakia 2025-03-02 08:39:06 -08:00 committed by GitHub
parent 4ee4719a4f
commit ed65dee59f
4 changed files with 50 additions and 4 deletions

View file

@ -543,6 +543,7 @@ class RedisCache(BaseCache):
_redis_client: Redis = self.init_async_client() # type: ignore _redis_client: Redis = self.init_async_client() # type: ignore
start_time = time.time() start_time = time.time()
_used_ttl = self.get_ttl(ttl=ttl) _used_ttl = self.get_ttl(ttl=ttl)
key = self.check_and_fix_namespace(key=key)
try: try:
result = await _redis_client.incrbyfloat(name=key, amount=value) result = await _redis_client.incrbyfloat(name=key, amount=value)
if _used_ttl is not None: if _used_ttl is not None:

View file

@ -27,3 +27,8 @@ model_list:
litellm_params: litellm_params:
model: openai/gpt-4o model: openai/gpt-4o
litellm_settings:
cache: true
cache_params: # set cache params for redis
type: redis
namespace: "litellm.caching"

View file

@ -1653,10 +1653,6 @@ class ProxyConfig:
## INIT PROXY REDIS USAGE CLIENT ## ## INIT PROXY REDIS USAGE CLIENT ##
redis_usage_cache = litellm.cache.cache redis_usage_cache = litellm.cache.cache
## INIT ROUTER REDIS CACHE ##
if llm_router is not None:
llm_router._update_redis_cache(cache=redis_usage_cache)
async def get_config(self, config_file_path: Optional[str] = None) -> dict: async def get_config(self, config_file_path: Optional[str] = None) -> dict:
""" """
Load config file Load config file
@ -2183,6 +2179,9 @@ class ProxyConfig:
), ),
) # type:ignore ) # type:ignore
if redis_usage_cache is not None and router.cache.redis_cache is None:
router._update_redis_cache(cache=redis_usage_cache)
# Guardrail settings # Guardrail settings
guardrails_v2: Optional[List[Dict]] = None guardrails_v2: Optional[List[Dict]] = None

View file

@ -0,0 +1,41 @@
import json
import os
import sys
from unittest.mock import MagicMock, patch
import pytest
from fastapi.testclient import TestClient
sys.path.insert(
0, os.path.abspath("../../..")
) # Adds the parent directory to the system path
from unittest.mock import AsyncMock
from litellm.caching.redis_cache import RedisCache
@pytest.mark.parametrize("namespace", [None, "test"])
@pytest.mark.asyncio
async def test_redis_cache_async_increment(namespace):
redis_cache = RedisCache(namespace=namespace)
# Create an AsyncMock for the Redis client
mock_redis_instance = AsyncMock()
# Make sure the mock can be used as an async context manager
mock_redis_instance.__aenter__.return_value = mock_redis_instance
mock_redis_instance.__aexit__.return_value = None
assert redis_cache is not None
expected_key = "test:test" if namespace else "test"
with patch.object(
redis_cache, "init_async_client", return_value=mock_redis_instance
):
# Call async_set_cache
await redis_cache.async_increment(key=expected_key, value=1)
# Verify that the set method was called on the mock Redis instance
mock_redis_instance.incrbyfloat.assert_called_once_with(
name=expected_key, amount=1
)