The current implementation of the doCreateToolResponseRequest method in the VertexAiGeminiChatModel class does not support multiple function calls. This is a critical issue as it limits the functionality of the model.
Expected Behavior
The doCreateToolResponseRequest method should handle multiple function calls properly, creating and returning a new GeminiRequest with all function responses. Additionally, the role should be set correctly. The modified code should look like this:
public class VertexAiGeminiChatModel {
public enum GeminiMessageType {
USER("user"),
MODEL("model");
FUNCTION("function");
}
@Override
protected GeminiRequest doCreateToolResponseRequest(GeminiRequest previousRequest, Content responseMessage,
List<Content> conversationHistory) {
var parts = responseMessage.getPartsList().stream()
.map(part -> part.getFunctionCall())
.map(functionCall -> {
var functionName = functionCall.getName();
String functionArguments = structToJson(functionCall.getArgs());
if (!this.functionCallbackRegister.containsKey(functionName)) {
throw new IllegalStateException(
"No function callback found for function name: " + functionName
);
}
String functionResponse = this.functionCallbackRegister.get(functionName).call(
functionArguments
);
Part responsePart = Part.newBuilder().setFunctionResponse(
FunctionResponse.newBuilder().setName(functionCall.getName()).setResponse(
jsonToStruct(functionResponse)
).build()
).build();
return responsePart;
})
.toList();
Content contentFnResp = Content.newBuilder()
.setRole(GeminiMessageType.FUNCTION)
.addAllParts(parts)
.build();
conversationHistory.add(contentFnResp);
return new GeminiRequest(conversationHistory, previousRequest.model());
}
}
Current Behavior
Currently, the doCreateToolResponseRequest method does not iterate through all function calls in the responseMessage. This limitation prevents the handling of multiple function calls, which is essential for more complex interactions. The current implementation is as follows:
public class VertexAiGeminiChatModel {
@Override
protected GeminiRequest doCreateToolResponseRequest(GeminiRequest previousRequest, Content responseMessage,
List<Content> conversationHistory) {
FunctionCall functionCall = responseMessage.getPartsList().iterator().next().getFunctionCall();
var functionName = functionCall.getName();
String functionArguments = structToJson(functionCall.getArgs());
if (!this.functionCallbackRegister.containsKey(functionName)) {
throw new IllegalStateException("No function callback found for function name: " + functionName);
}
String functionResponse = this.functionCallbackRegister.get(functionName).call(functionArguments);
Content contentFnResp = Content.newBuilder()
.addParts(Part.newBuilder()
.setFunctionResponse(FunctionResponse.newBuilder()
.setName(functionCall.getName())
.setResponse(jsonToStruct(functionResponse))
.build())
.build())
.build();
conversationHistory.add(contentFnResp);
return new GeminiRequest(conversationHistory, previousRequest.model());
}
}
Context
This issue affects applications using VertexAiGeminiChatModel that require multiple function calls. This limitation restricts the functionality and flexibility of our implementation. We have considered various workarounds but found that modifying the doCreateToolResponseRequest method as proposed is the most effective solution.
Comment From: e1arikawa
FYI https://github.com/spring-projects/spring-ai/issues/843