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 fb51c348e4a..7ca9fced140 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 @@ -51,6 +51,7 @@ * @author Christian Tzolov * @author Mariusz Bernacki * @author Thomas Vitale + * @author Jihoon Kim * @since 1.0.0 */ public class AnthropicApi { @@ -138,8 +139,9 @@ public AnthropicApi(String baseUrl, String anthropicApiKey, String anthropicVers 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 d830980771b..f3f72e3745e 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.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 @@ void chatCompletionStream() { 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\"}}"); + } + }