From 0f453cc59d928b85ef7223c8bd92c63be9c0b9b8 Mon Sep 17 00:00:00 2001 From: Sameer Kankute Date: Tue, 14 Apr 2026 10:00:27 +0530 Subject: [PATCH] Fic code qa --- litellm/llms/custom_httpx/llm_http_handler.py | 139 ++++++++++-------- 1 file changed, 79 insertions(+), 60 deletions(-) diff --git a/litellm/llms/custom_httpx/llm_http_handler.py b/litellm/llms/custom_httpx/llm_http_handler.py index 06f030fc2ce..9155fbb4aca 100644 --- a/litellm/llms/custom_httpx/llm_http_handler.py +++ b/litellm/llms/custom_httpx/llm_http_handler.py @@ -1816,6 +1816,73 @@ class BaseLLMHTTPHandler: logging_obj=logging_obj, ) + async def _async_post_anthropic_messages_with_http_error_retry( + self, + async_httpx_client: AsyncHTTPHandler, + request_url: str, + headers: dict, + signed_json_body: Optional[bytes], + request_body: dict, + stream: bool, + logging_obj: LiteLLMLoggingObj, + provider_config: BaseAnthropicMessagesConfig, + litellm_params: GenericLiteLLMParams, + api_key: Optional[str], + model: str, + ) -> httpx.Response: + max_attempts = max(provider_config.max_retry_on_anthropic_messages_http_error, 1) + litellm_params_dict = dict(litellm_params) + optional_params_dict = dict(litellm_params) + response: Optional[httpx.Response] = None + for attempt_idx in range(max_attempts): + try: + response = await async_httpx_client.post( + url=request_url, + headers=headers, + data=signed_json_body or json.dumps(request_body), + stream=stream or False, + logging_obj=logging_obj, + ) + response.raise_for_status() + except httpx.HTTPStatusError as e: + hit_max_attempt = attempt_idx + 1 == max_attempts + should_retry = provider_config.should_retry_anthropic_messages_on_http_error( + e=e, litellm_params=litellm_params_dict + ) + if should_retry and not hit_max_attempt: + verbose_logger.debug( + "Anthropic /v1/messages: invalid thinking signature; " + "stripping thinking blocks and retrying (attempt %s/%s).", + attempt_idx + 2, + max_attempts, + ) + provider_config.transform_anthropic_messages_request_on_http_error( + e=e, request_data=request_body + ) + headers, signed_json_body = provider_config.sign_request( + headers=headers, + optional_params=optional_params_dict, + request_data=request_body, + api_base=request_url, + api_key=api_key, + stream=stream, + fake_stream=False, + model=model, + ) + logging_obj.model_call_details.update(request_body) + continue + raise self._handle_error(e=e, provider_config=provider_config) + except Exception as e: + raise self._handle_error(e=e, provider_config=provider_config) + break + + if response is None: + raise self._handle_error( + e=ValueError("No response from Anthropic /v1/messages"), + provider_config=provider_config, + ) + return response + async def async_anthropic_messages_handler( self, model: str, @@ -1955,67 +2022,19 @@ class BaseLLMHTTPHandler: }, ) - max_anthropic_messages_http_attempts = max( - anthropic_messages_provider_config.max_retry_on_anthropic_messages_http_error, - 1, + response = await self._async_post_anthropic_messages_with_http_error_retry( + async_httpx_client=async_httpx_client, + request_url=request_url, + headers=headers, + signed_json_body=signed_json_body, + request_body=request_body, + stream=stream or False, + logging_obj=logging_obj, + provider_config=anthropic_messages_provider_config, + litellm_params=litellm_params, + api_key=api_key, + model=model, ) - response: Optional[httpx.Response] = None - litellm_params_dict = dict(litellm_params) - for attempt_idx in range(max_anthropic_messages_http_attempts): - try: - response = await async_httpx_client.post( - url=request_url, - headers=headers, - data=signed_json_body or json.dumps(request_body), - stream=stream or False, - logging_obj=logging_obj, - ) - response.raise_for_status() - except httpx.HTTPStatusError as e: - hit_max_attempt = ( - attempt_idx + 1 == max_anthropic_messages_http_attempts - ) - should_retry = anthropic_messages_provider_config.should_retry_anthropic_messages_on_http_error( - e=e, litellm_params=litellm_params_dict - ) - if should_retry and not hit_max_attempt: - verbose_logger.debug( - "Retrying on HTTPStatusError (attempt %s/%s).", - attempt_idx + 2, - max_anthropic_messages_http_attempts, - ) - - request_body = anthropic_messages_provider_config.transform_anthropic_messages_request_on_http_error( - e=e, request_data=request_body - ) - headers, signed_json_body = ( - anthropic_messages_provider_config.sign_request( - headers=headers, - optional_params=dict(litellm_params), - request_data=request_body, - api_base=request_url, - api_key=api_key, - stream=stream, - fake_stream=False, - model=model, - ) - ) - logging_obj.model_call_details.update(request_body) - continue - raise self._handle_error( - e=e, provider_config=anthropic_messages_provider_config - ) - except Exception as e: - raise self._handle_error( - e=e, provider_config=anthropic_messages_provider_config - ) - break - - if response is None: - raise self._handle_error( - e=ValueError("No response from Anthropic /v1/messages"), - provider_config=anthropic_messages_provider_config, - ) # used for logging + cost tracking logging_obj.model_call_details["httpx_response"] = response