From d2a5de2e04d10042060c1e68c157857bdacfb165 Mon Sep 17 00:00:00 2001 From: shivam Date: Sat, 25 Jul 2026 00:15:55 +0000 Subject: [PATCH] refactor(caching): tighten anthropic messages cache types and drop comments Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- litellm/caching/caching_handler.py | 11 ++------ .../litellm_core_utils/model_param_helper.py | 7 +---- .../messages/response_cache.py | 28 ------------------- 3 files changed, 3 insertions(+), 43 deletions(-) diff --git a/litellm/caching/caching_handler.py b/litellm/caching/caching_handler.py index 8b2d033f24a..70a2e3fd1b2 100644 --- a/litellm/caching/caching_handler.py +++ b/litellm/caching/caching_handler.py @@ -18,6 +18,7 @@ import asyncio import datetime import inspect import time +from collections.abc import AsyncIterator from typing import ( TYPE_CHECKING, Any, @@ -1058,14 +1059,6 @@ class LLMCachingHandler: ) def wrap_streaming_result_for_cache(self, result: Any, call_type: str) -> Any: - """ - Tee a streaming result so it still reaches the cache. - - Streaming responses are returned to the caller before ``async_set_cache`` - runs. Chat/text completion streams are teed inside ``CustomStreamWrapper`` - and Responses API streams inside their own iterator; Anthropic Messages - streams have no such hook, so they are wrapped here. - """ if call_type not in ( CallTypes.anthropic_messages.value, CallTypes.aanthropic_messages.value, @@ -1075,7 +1068,7 @@ class LLMCachingHandler: original_function=self.original_function, kwargs=self.request_kwargs ): return result - if not hasattr(result, "__anext__"): + if not isinstance(result, AsyncIterator): return result from litellm.llms.anthropic.experimental_pass_through.messages.response_cache import ( AnthropicMessagesStreamCacheWriter, diff --git a/litellm/litellm_core_utils/model_param_helper.py b/litellm/litellm_core_utils/model_param_helper.py index cf4eba933b8..7e99e5fc5b2 100644 --- a/litellm/litellm_core_utils/model_param_helper.py +++ b/litellm/litellm_core_utils/model_param_helper.py @@ -174,13 +174,8 @@ class ModelParamHelper: def _get_litellm_supported_anthropic_messages_kwargs() -> set[str]: """ Get the litellm supported Anthropic /v1/messages kwargs - - This follows the Anthropic Messages API spec. `system`, `top_k` and - `stop_sequences` have no OpenAI equivalent, so without them the cache key - for a /v1/messages request ignores them and collides across requests that - differ only by system prompt. """ - return set(getattr(AnthropicMessagesRequest, "__annotations__", {}).keys()) + return set(AnthropicMessagesRequest.__annotations__.keys()) @staticmethod def _get_exclude_kwargs() -> Set[str]: diff --git a/litellm/llms/anthropic/experimental_pass_through/messages/response_cache.py b/litellm/llms/anthropic/experimental_pass_through/messages/response_cache.py index e94d8f6bbaf..4873b1fdb96 100644 --- a/litellm/llms/anthropic/experimental_pass_through/messages/response_cache.py +++ b/litellm/llms/anthropic/experimental_pass_through/messages/response_cache.py @@ -1,13 +1,3 @@ -""" -Response caching for Anthropic Messages (`/v1/messages`) requests. - -Non-streaming responses are plain dicts and are stored by the generic caching -handler. Streaming responses are returned to the caller before -``LLMCachingHandler.async_set_cache`` runs, so they are teed here instead: the -SSE events are buffered while they are forwarded and persisted verbatim once the -stream completes, and a hit replays exactly what the provider sent. -""" - from collections.abc import AsyncIterator from typing import TYPE_CHECKING, Any, cast @@ -38,14 +28,6 @@ def _decode(chunk: bytes | str) -> str: class AnthropicMessagesStreamCacheWriter: - """ - Forwards a `/v1/messages` SSE stream unchanged while buffering it, then - writes the collected events to the response cache on normal completion. - - Only a stream that ran to a ``message_stop`` without a provider ``error`` - event is written, so partial or failed responses cannot be replayed. - """ - def __init__( self, stream: AsyncIterator[bytes | str], @@ -105,11 +87,6 @@ class AnthropicMessagesStreamCacheWriter: class CachedAnthropicMessagesStreamIterator(BaseAnthropicMessagesStreamingIterator): - """ - Replays cached `/v1/messages` SSE events and logs the request as a cache hit - once the replay finishes, mirroring what the live stream logs at end of stream. - """ - def __init__( self, events: list[str], @@ -146,11 +123,6 @@ def convert_cached_anthropic_messages_result( logging_obj: LiteLLMLoggingObj, kwargs: dict[str, Any], ) -> AnthropicMessagesResponse | CachedAnthropicMessagesStreamIterator: - """ - Turn a cached `/v1/messages` entry back into what the caller expects: an - SSE replay iterator for a streamed entry, otherwise the response itself - (``AnthropicMessagesResponse`` is a TypedDict, i.e. a dict at runtime). - """ events = get_cached_stream_events(cached_result) if events is not None: return CachedAnthropicMessagesStreamIterator(