From 1196ef2f71a8f036c9f5fd3b1cdc364eafd67ea1 Mon Sep 17 00:00:00 2001 From: Christian Tzolov Date: Sun, 7 Apr 2024 00:01:32 +0200 Subject: [PATCH] Fix OpenAI API Tool Choice configuraiton options - Related to the https://platform.openai.com/docs/api-reference/chat/create#chat-create-tool_choice - It seems that when a cuntion type is set explicitely: {"type": "function", "function": {"name": "my_function"}} the parallel calling is not working anymore! Resolves #551 --- .../springframework/ai/openai/api/OpenAiApi.java | 8 ++++---- .../api/tool/OpenAiApiToolFunctionCallIT.java | 13 +++---------- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/api/OpenAiApi.java b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/api/OpenAiApi.java index 5bc83eade..605697906 100644 --- a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/api/OpenAiApi.java +++ b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/api/OpenAiApi.java @@ -319,7 +319,7 @@ public class OpenAiApi { @JsonProperty("temperature") Float temperature, @JsonProperty("top_p") Float topP, @JsonProperty("tools") List tools, - @JsonProperty("tool_choice") String toolChoice, + @JsonProperty("tool_choice") Object toolChoice, @JsonProperty("user") String user) { /** @@ -360,7 +360,7 @@ public class OpenAiApi { * @param toolChoice Controls which (if any) function is called by the model. */ public ChatCompletionRequest(List messages, String model, - List tools, String toolChoice) { + List tools, Object toolChoice) { this(messages, model, null, null, null, null, null, null, null, null, null, null, false, 0.8f, null, tools, toolChoice, null); @@ -396,8 +396,8 @@ public class OpenAiApi { /** * Specifying a particular function forces the model to call that function. */ - public static String FUNCTION(String functionName) { - return ModelOptionsUtils.toJsonString(Map.of("type", "function", "function", Map.of("name", functionName))); + public static Object FUNCTION(String functionName) { + return Map.of("type", "function", "function", Map.of("name", functionName)); } } diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/api/tool/OpenAiApiToolFunctionCallIT.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/api/tool/OpenAiApiToolFunctionCallIT.java index 4138a24a9..c13f7196f 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/api/tool/OpenAiApiToolFunctionCallIT.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/api/tool/OpenAiApiToolFunctionCallIT.java @@ -32,6 +32,7 @@ import org.springframework.ai.openai.api.OpenAiApi.ChatCompletion; import org.springframework.ai.openai.api.OpenAiApi.ChatCompletionMessage; import org.springframework.ai.openai.api.OpenAiApi.ChatCompletionMessage.Role; import org.springframework.ai.openai.api.OpenAiApi.ChatCompletionMessage.ToolCall; +import org.springframework.ai.openai.api.OpenAiApi.ChatCompletionRequest.ToolChoiceBuilder; import org.springframework.ai.openai.api.OpenAiApi.ChatCompletionRequest; import org.springframework.ai.openai.api.OpenAiApi.FunctionTool.Type; import org.springframework.http.ResponseEntity; @@ -89,19 +90,11 @@ public class OpenAiApiToolFunctionCallIT { } """))); - // Or you can use the - // ModelOptionsUtils.getJsonSchema(FakeWeatherService.Request.class))) to - // auto-generate the JSON schema like: - // var functionTool = new OpenAiApi.FunctionTool(Type.FUNCTION, new - // OpenAiApi.FunctionTool.Function( - // "Get the weather in location. Return temperature in 30°F or 30°C format.", - // "getCurrentWeather", - // ModelOptionsUtils.getJsonSchema(FakeWeatherService.Request.class))); - List messages = new ArrayList<>(List.of(message)); ChatCompletionRequest chatCompletionRequest = new ChatCompletionRequest(messages, "gpt-4-turbo-preview", - List.of(functionTool), null); + List.of(functionTool), ToolChoiceBuilder.AUTO); + // List.of(functionTool), ToolChoiceBuilder.FUNCTION("getCurrentWeather")); ResponseEntity chatCompletion = completionApi.chatCompletionEntity(chatCompletionRequest);