From fb2e7528d0b74ae4adcb4aa6e18436bff2e808e5 Mon Sep 17 00:00:00 2001 From: jitokim Date: Sun, 10 Nov 2024 02:43:16 +0900 Subject: [PATCH] Fix Anthropic issue using unsubscribed response body in exception message Signed-off-by: jitokim --- .../ai/anthropic/api/AnthropicApi.java | 6 ++++-- .../ai/anthropic/api/AnthropicApiIT.java | 20 ++++++++++++++++++- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/api/AnthropicApi.java b/models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/api/AnthropicApi.java index 665e0879f..76d0844c1 100644 --- a/models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/api/AnthropicApi.java +++ b/models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/api/AnthropicApi.java @@ -53,6 +53,7 @@ import org.springframework.web.reactive.function.client.WebClient; * @author Christian Tzolov * @author Mariusz Bernacki * @author Thomas Vitale + * @author Jihoon Kim * @since 1.0.0 */ public class AnthropicApi { @@ -143,8 +144,9 @@ public class AnthropicApi { this.webClient = webClientBuilder.baseUrl(baseUrl) .defaultHeaders(jsonContentHeaders) .defaultStatusHandler(HttpStatusCode::isError, - resp -> Mono.just(new RuntimeException("Response exception, Status: [" + resp.statusCode() - + "], Body:[" + resp.bodyToMono(java.lang.String.class) + "]"))) + resp -> resp.bodyToMono(String.class) + .flatMap(it -> Mono.error(new RuntimeException( + "Response exception, Status: [" + resp.statusCode() + "], Body:[" + it + "]")))) .build(); } diff --git a/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/api/AnthropicApiIT.java b/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/api/AnthropicApiIT.java index d83098077..f3f72e374 100644 --- a/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/api/AnthropicApiIT.java +++ b/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/api/AnthropicApiIT.java @@ -28,11 +28,12 @@ import org.springframework.ai.anthropic.api.AnthropicApi.ChatCompletionResponse; import org.springframework.ai.anthropic.api.AnthropicApi.ContentBlock; import org.springframework.ai.anthropic.api.AnthropicApi.Role; import org.springframework.http.ResponseEntity; - +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.assertThat; /** * @author Christian Tzolov + * @author Jihoon Kim */ @EnabledIfEnvironmentVariable(named = "ANTHROPIC_API_KEY", matches = ".+") public class AnthropicApiIT { @@ -70,4 +71,21 @@ public class AnthropicApiIT { bla.stream().forEach(r -> System.out.println(r)); } + @Test + void chatCompletionStreamError() { + AnthropicMessage chatCompletionMessage = new AnthropicMessage(List.of(new ContentBlock("Tell me a Joke?")), + Role.USER); + AnthropicApi api = new AnthropicApi("FAKE_KEY_FOR_ERROR_RESPONSE"); + + Flux response = api.chatCompletionStream(new ChatCompletionRequest( + AnthropicApi.ChatModel.CLAUDE_3_OPUS.getValue(), List.of(chatCompletionMessage), null, 100, 0.8, true)); + + assertThat(response).isNotNull(); + + assertThatThrownBy(() -> response.collectList().block()).isInstanceOf(RuntimeException.class) + .hasMessageStartingWith("Response exception, Status: [") + .hasMessageContaining( + "{\"type\":\"error\",\"error\":{\"type\":\"authentication_error\",\"message\":\"invalid x-api-key\"}}"); + } + }