perf(caching): memoize _get_all_llm_api_params, rebuilt per request (#31430)

ModelParamHelper._get_all_llm_api_params() introspects six sets of supported
kwargs from static OpenAI type annotations and fixed sets and unions them. The
result is constant for the process lifetime, but it was recomputed on every
request through both Cache.get_cache_key (caching path) and
_get_relevant_args_to_use_for_logging -> get_standard_logging_model_parameters
(spend-logging / callback path). Memoize it with lru_cache(maxsize=1); the
function takes no arguments, its result is process-static, and both callers
treat it as read-only. ~4.7 us/call to ~0.02 us/call.
This commit is contained in:
Yassin Kortam 2026-06-26 19:46:18 +03:00 committed by GitHub
parent 0e1a3babf0
commit aa49568059
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 36 additions and 1 deletions

View file

@ -1,3 +1,4 @@
from functools import lru_cache
from typing import Set
from openai.types.chat.completion_create_params import (
@ -54,9 +55,17 @@ class ModelParamHelper:
return combined_kwargs
@staticmethod
@lru_cache(maxsize=1)
def _get_all_llm_api_params() -> Set[str]:
"""
Gets the supported kwargs for each call type and combines them
Gets the supported kwargs for each call type and combines them.
The result is derived from static type annotations and fixed sets, so it
is constant for the process lifetime. It is computed once and cached
because it is rebuilt on every request through both the cache-key path
(``Cache.get_cache_key``) and the spend-logging path
(``_get_relevant_args_to_use_for_logging``). Callers treat the result as
read-only.
"""
chat_completion_kwargs = (
ModelParamHelper._get_litellm_supported_chat_completion_kwargs()

View file

@ -0,0 +1,26 @@
import os
import sys
sys.path.insert(
0, os.path.abspath("../../..")
) # Adds the parent directory to the system path
from litellm.litellm_core_utils.model_param_helper import ModelParamHelper
def test_get_all_llm_api_params_is_correct():
"""The cached result must equal a fresh, uncached computation."""
cached = ModelParamHelper._get_all_llm_api_params()
uncached = ModelParamHelper._get_all_llm_api_params.__wrapped__()
assert cached == uncached
assert {"model", "temperature", "stream"} <= cached
assert "metadata" not in cached # excluded via _get_exclude_kwargs
def test_get_all_llm_api_params_is_memoized():
"""Regression: the param set is static and is rebuilt on every request via
the cache-key and spend-logging paths, so it must be memoized. Without the
cache each call returns a freshly built set (a different object)."""
first = ModelParamHelper._get_all_llm_api_params()
second = ModelParamHelper._get_all_llm_api_params()
assert first is second