refactor(caching): tighten anthropic messages cache types and drop comments

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
shivam 2026-07-25 00:15:55 +00:00
parent ab997e04eb
commit d2a5de2e04
3 changed files with 3 additions and 43 deletions

View file

@ -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,

View file

@ -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]:

View file

@ -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(