mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-14 09:03:16 +00:00
perf(caching): skip cache bookkeeping when caching is disabled
Return before copying kwargs or inspecting signatures when caching is disabled, and cache bounded positional parameter-name lookups for enabled-cache calls. Preserve positional-argument behavior with focused regression coverage, including empty and surplus positional arguments. Co-Authored-By: Aiden <aiden@weco.ai>
This commit is contained in:
parent
d7e4b1bdd0
commit
b8282f095b
2 changed files with 49 additions and 16 deletions
|
|
@ -19,6 +19,7 @@ import datetime
|
|||
import inspect
|
||||
import time
|
||||
from collections.abc import AsyncGenerator, AsyncIterator, Callable, Generator, Mapping
|
||||
from functools import lru_cache
|
||||
from typing import TYPE_CHECKING, Any, Final, Optional, TypeVar
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
|
@ -1033,6 +1034,9 @@ class LLMCachingHandler:
|
|||
Sync internal method to add the result to the cache
|
||||
"""
|
||||
|
||||
if litellm.cache is None:
|
||||
return
|
||||
|
||||
new_kwargs: Final = kwargs.copy()
|
||||
new_kwargs.update(
|
||||
convert_args_to_kwargs(
|
||||
|
|
@ -1040,8 +1044,6 @@ class LLMCachingHandler:
|
|||
args,
|
||||
)
|
||||
)
|
||||
if litellm.cache is None:
|
||||
return
|
||||
|
||||
if self._should_store_result_in_cache(original_function=self.original_function, kwargs=new_kwargs):
|
||||
litellm.cache.add_cache(result, **new_kwargs)
|
||||
|
|
@ -1215,22 +1217,16 @@ class LLMCachingHandler:
|
|||
)
|
||||
|
||||
|
||||
@lru_cache(maxsize=1024)
|
||||
def _positional_param_names(original_function: Callable) -> tuple[str, ...]:
|
||||
return tuple(inspect.signature(original_function).parameters)
|
||||
|
||||
|
||||
def convert_args_to_kwargs(
|
||||
original_function: Callable,
|
||||
args: tuple[object, ...] | None = None,
|
||||
) -> dict[str, object]:
|
||||
# Get the signature of the original function
|
||||
signature: Final = inspect.signature(original_function)
|
||||
if not args:
|
||||
return {}
|
||||
|
||||
# Get parameter names in the order they appear in the original function
|
||||
param_names: Final = list(signature.parameters.keys())
|
||||
|
||||
# Create a mapping of positional arguments to parameter names
|
||||
args_to_kwargs: Final = {}
|
||||
if args:
|
||||
for index, arg in enumerate(args):
|
||||
if index < len(param_names):
|
||||
param_name = param_names[index]
|
||||
args_to_kwargs[param_name] = arg
|
||||
|
||||
return args_to_kwargs
|
||||
return dict(zip(_positional_param_names(original_function), args))
|
||||
|
|
|
|||
|
|
@ -622,3 +622,40 @@ def test_request_kwargs_does_not_retain_logging_obj():
|
|||
assert "litellm_logging_obj" not in handler.request_kwargs
|
||||
assert handler.request_kwargs["messages"] == kwargs["messages"]
|
||||
assert handler.request_kwargs["model"] == "gpt-4o"
|
||||
|
||||
|
||||
def test_convert_args_to_kwargs_maps_positional_args_on_decorated_functions():
|
||||
"""
|
||||
convert_args_to_kwargs must resolve positional arguments against the
|
||||
signature litellm's public entry points actually expose, not against the
|
||||
`client` decorator's `(*args, **kwargs)` wrapper.
|
||||
|
||||
litellm.completion is decorated, so wrapper.__code__.co_argcount is 0 and
|
||||
reading __code__ directly yields no parameter names at all. Those names are
|
||||
what turns a positional call into cache-key material, so losing them makes
|
||||
distinct requests collide on one key instead of raising.
|
||||
"""
|
||||
import litellm
|
||||
from litellm.caching.caching_handler import convert_args_to_kwargs
|
||||
|
||||
messages = [{"role": "user", "content": "hello"}]
|
||||
|
||||
mapped = convert_args_to_kwargs(litellm.completion, ("gpt-4o", messages))
|
||||
|
||||
assert mapped["model"] == "gpt-4o"
|
||||
assert mapped["messages"] == messages
|
||||
|
||||
assert convert_args_to_kwargs(litellm.completion, ()) == {}
|
||||
assert convert_args_to_kwargs(litellm.completion, None) == {}
|
||||
|
||||
|
||||
def test_convert_args_to_kwargs_truncates_extra_positional_args():
|
||||
"""More positional args than parameters must not raise or invent names."""
|
||||
from litellm.caching.caching_handler import convert_args_to_kwargs
|
||||
|
||||
def sample(model, messages, temperature=None):
|
||||
return None
|
||||
|
||||
mapped = convert_args_to_kwargs(sample, ("gpt-4o", [], 0.5, "extra", "extra2"))
|
||||
|
||||
assert mapped == {"model": "gpt-4o", "messages": [], "temperature": 0.5}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue