fix(openai): prevent incorrect ToolCall merging caused by empty id and name strings

Empty tool call id and name strings causing improper ToolCall merging during OpenAI stream
processing, resulting in incorrect function calling responses. This fix ensures both null
and empty strings are properly validated before merging operations.

Fixes GH-2417 (https://github.com/spring-projects/spring-ai/issues/2417)
Fixes GH-2423 (https://github.com/spring-projects/spring-ai/issues/2423)

Signed-off-by: Wenhao Ma <296232679@qq.com>
This commit is contained in:
mawenhao
2025-03-29 14:30:54 +08:00
committed by Ilayaperumal Gopinathan
parent 77e87ccb39
commit e888895a4e

View File

@@ -31,6 +31,7 @@ import org.springframework.ai.openai.api.OpenAiApi.ChatCompletionMessage.ToolCal
import org.springframework.ai.openai.api.OpenAiApi.LogProbs;
import org.springframework.ai.openai.api.OpenAiApi.Usage;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
/**
* Helper class to support Streaming function calling.
@@ -111,7 +112,7 @@ public class OpenAiStreamFunctionCallingHelper {
throw new IllegalStateException("Currently only one tool call is supported per message!");
}
var currentToolCall = current.toolCalls().iterator().next();
if (currentToolCall.id() != null) {
if (StringUtils.hasText(currentToolCall.id())) {
if (lastPreviousTooCall != null) {
toolCalls.add(lastPreviousTooCall);
}
@@ -133,7 +134,7 @@ public class OpenAiStreamFunctionCallingHelper {
if (previous == null) {
return current;
}
String id = (current.id() != null ? current.id() : previous.id());
String id = (StringUtils.hasText(current.id()) ? current.id() : previous.id());
String type = (current.type() != null ? current.type() : previous.type());
ChatCompletionFunction function = merge(previous.function(), current.function());
return new ToolCall(id, type, function);
@@ -143,7 +144,7 @@ public class OpenAiStreamFunctionCallingHelper {
if (previous == null) {
return current;
}
String name = (current.name() != null ? current.name() : previous.name());
String name = (StringUtils.hasText(current.name()) ? current.name() : previous.name());
StringBuilder arguments = new StringBuilder();
if (previous.arguments() != null) {
arguments.append(previous.arguments());