Skip to content

Commit c0cc32c

Browse files
tzolovilayaperumalg
authored andcommitted
Handle malformed OpenAI API responses
Signed-off-by: Christian Tzolov <[email protected]>
1 parent bd544fe commit c0cc32c

File tree

6 files changed

+15
-10
lines changed

6 files changed

+15
-10
lines changed

models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiChatModel.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ private Generation buildGeneration(Choice choice, Map<String, Object> metadata,
428428
List<Media> media = new ArrayList<>();
429429
String textContent = choice.message().content();
430430
var audioOutput = choice.message().audioOutput();
431-
if (audioOutput != null) {
431+
if (audioOutput != null && StringUtils.hasText(audioOutput.data()) && request.audioParameters() != null) {
432432
String mimeType = String.format("audio/%s", request.audioParameters().format().name().toLowerCase());
433433
byte[] audioData = Base64.getDecoder().decode(audioOutput.data());
434434
Resource resource = new ByteArrayResource(audioData);

models/spring-ai-openai/src/main/java/org/springframework/ai/openai/api/OpenAiApi.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,11 @@ public String getName() {
758758
*/
759759
public enum ChatCompletionFinishReason {
760760

761+
/**
762+
* Handles, empty, NULL and unknown values
763+
*/
764+
@JsonProperty("")
765+
UNKNOWN,
761766
/**
762767
* The model hit a natural stop point or a provided stop sequence.
763768
*/

models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiCompatibleChatModelIT.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ static Stream<ChatModel> openAiCompatibleApis() {
6666
.baseUrl("https://api.groq.com/openai")
6767
.apiKey(System.getenv("GROQ_API_KEY"))
6868
.build())
69-
.defaultOptions(forModelName("llama3-8b-8192"))
69+
.defaultOptions(forModelName("meta-llama/llama-4-scout-17b-16e-instruct"))
7070
.build());
7171
}
7272

models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiStreamingFinishReasonTests.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,7 @@ void testJsonDeserializationWithEmptyStringFinishReason() throws JsonProcessingE
143143
assertThat(choice.index()).isEqualTo(0);
144144
assertThat(choice.delta().content()).isEmpty();
145145

146-
// The key test: what happens with empty string finish_reason?
147-
// This might be null if Jackson handles empty string -> enum conversion
148-
// gracefully
149-
assertThat(choice.finishReason()).isNull();
146+
assertThat(choice.finishReason()).isEqualTo(ChatCompletionFinishReason.UNKNOWN);
150147
}
151148

152149
@Test
@@ -245,7 +242,7 @@ void testModelOptionsUtilsJsonToObjectWithEmptyFinishReason() {
245242

246243
var choice = chunk.choices().get(0);
247244
// The critical test: how does ModelOptionsUtils handle empty string -> enum?
248-
assertThat(choice.finishReason()).isNull();
245+
assertThat(choice.finishReason()).isEqualTo(ChatCompletionFinishReason.UNKNOWN);
249246
}
250247

251248
private void setupChatModel() {

models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/proxy/GroqWithOpenAiChatModelIT.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ class GroqWithOpenAiChatModelIT {
7373

7474
private static final String GROQ_BASE_URL = "https://api.groq.com/openai";
7575

76-
private static final String DEFAULT_GROQ_MODEL = "llama3-70b-8192";
76+
private static final String DEFAULT_GROQ_MODEL = "llama-3.1-8b-instant";
7777

7878
@Value("classpath:/prompts/system-message.st")
7979
private Resource systemResource;
@@ -373,7 +373,7 @@ void streamingMultiModalityImageUrl() throws IOException {
373373
}
374374

375375
@ParameterizedTest(name = "{0} : {displayName} ")
376-
@ValueSource(strings = { "llama3-8b-8192", "llama3-70b-8192", "mixtral-8x7b-32768", "gemma-7b-it" })
376+
@ValueSource(strings = { "meta-llama/llama-4-scout-17b-16e-instruct" })
377377
void validateCallResponseMetadata(String model) {
378378
// @formatter:off
379379
ChatResponse response = ChatClient.create(this.chatModel).prompt()

models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/proxy/MultiOpenAiClientIT.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,10 @@ void multiClientFlow() {
6464
// Derive a new OpenAiChatModel for Groq
6565
OpenAiChatModel groqModel = this.baseChatModel.mutate()
6666
.openAiApi(groqApi)
67-
.defaultOptions(OpenAiChatOptions.builder().model("llama3-70b-8192").temperature(0.5).build())
67+
.defaultOptions(OpenAiChatOptions.builder()
68+
.model("meta-llama/llama-4-scout-17b-16e-instruct")
69+
.temperature(0.5)
70+
.build())
6871
.build();
6972

7073
// Derive a new OpenAiChatModel for GPT-4

0 commit comments

Comments
 (0)