From fd8cac57bb6fb42a76f5bb367a208168944f2ad1 Mon Sep 17 00:00:00 2001 From: Christian Tzolov Date: Tue, 5 Nov 2024 11:52:41 +0100 Subject: [PATCH] Revert "Revert "Convert API records to POJOs and fix failing autconfig tests"" This reverts commit 3e9a3fd3b0bb508a07ee7aff5526f35e841b077c. --- .../ai/minimax/MiniMaxChatModel.java | 9 +- .../ai/minimax/api/MiniMaxApi.java | 150 +++++++++++++++--- .../minimax/ChatCompletionRequestTests.java | 6 +- .../api/MiniMaxApiToolFunctionCallIT.java | 51 +++--- .../ai/mistralai/api/MistralAiApi.java | 115 ++++++++++++-- models/spring-ai-openai/pom.xml | 3 +- .../ai/openai/OpenAiChatOptions.java | 9 +- .../ai/openai/api/OpenAiApi.java | 142 ++++++++++++++--- .../ai/openai/ChatCompletionRequestTests.java | 6 +- .../api/tool/OpenAiApiToolFunctionCallIT.java | 3 +- .../ai/zhipuai/ZhiPuAiChatModel.java | 9 +- .../ai/zhipuai/ZhiPuAiChatOptions.java | 12 +- .../ai/zhipuai/api/ZhiPuAiApi.java | 144 ++++++++++++++--- .../zhipuai/ChatCompletionRequestTests.java | 6 +- .../api/ZhiPuAiApiToolFunctionCallIT.java | 3 +- .../minimax/MiniMaxPropertiesTests.java | 10 +- .../mistralai/MistralAiPropertiesTests.java | 49 ++++++ .../openai/OpenAiPropertiesTests.java | 12 +- .../ChromaVectorStoreAutoConfigurationIT.java | 8 +- ...naCloudVectorStoreAutoConfigurationIT.java | 2 +- .../zhipuai/ZhiPuAiPropertiesTests.java | 10 +- 21 files changed, 602 insertions(+), 157 deletions(-) diff --git a/models/spring-ai-minimax/src/main/java/org/springframework/ai/minimax/MiniMaxChatModel.java b/models/spring-ai-minimax/src/main/java/org/springframework/ai/minimax/MiniMaxChatModel.java index 6f7913efd..f32fe5d3c 100644 --- a/models/spring-ai-minimax/src/main/java/org/springframework/ai/minimax/MiniMaxChatModel.java +++ b/models/spring-ai-minimax/src/main/java/org/springframework/ai/minimax/MiniMaxChatModel.java @@ -60,7 +60,6 @@ import org.springframework.ai.minimax.api.MiniMaxApi.ChatCompletionMessage.ChatC import org.springframework.ai.minimax.api.MiniMaxApi.ChatCompletionMessage.Role; import org.springframework.ai.minimax.api.MiniMaxApi.ChatCompletionMessage.ToolCall; import org.springframework.ai.minimax.api.MiniMaxApi.ChatCompletionRequest; -import org.springframework.ai.minimax.api.MiniMaxApi.FunctionTool; import org.springframework.ai.minimax.api.MiniMaxApiConstants; import org.springframework.ai.minimax.metadata.MiniMaxUsage; import org.springframework.ai.model.ModelOptionsUtils; @@ -508,11 +507,11 @@ public class MiniMaxChatModel extends AbstractToolCallSupport implements ChatMod return request; } - private List getFunctionTools(Set functionNames) { + private List getFunctionTools(Set functionNames) { return this.resolveFunctionCallbacks(functionNames).stream().map(functionCallback -> { - var function = new FunctionTool.Function(functionCallback.getDescription(), functionCallback.getName(), - functionCallback.getInputTypeSchema()); - return new FunctionTool(function); + var function = new MiniMaxApi.FunctionTool.Function(functionCallback.getDescription(), + functionCallback.getName(), functionCallback.getInputTypeSchema()); + return new MiniMaxApi.FunctionTool(function); }).toList(); } diff --git a/models/spring-ai-minimax/src/main/java/org/springframework/ai/minimax/api/MiniMaxApi.java b/models/spring-ai-minimax/src/main/java/org/springframework/ai/minimax/api/MiniMaxApi.java index ee6743681..036a6aa1a 100644 --- a/models/spring-ai-minimax/src/main/java/org/springframework/ai/minimax/api/MiniMaxApi.java +++ b/models/spring-ai-minimax/src/main/java/org/springframework/ai/minimax/api/MiniMaxApi.java @@ -331,14 +331,35 @@ public class MiniMaxApi { /** * Represents a tool the model may call. Currently, only functions are supported as a tool. - * - * @param type The type of the tool. Currently, only 'function' is supported. - * @param function The function definition. */ - @JsonInclude(Include.NON_NULL) - public record FunctionTool( - @JsonProperty("type") Type type, - @JsonProperty("function") Function function) { + @JsonInclude(JsonInclude.Include.NON_NULL) + public static class FunctionTool { + + /** + * The type of the tool. Currently, only 'function' is supported. + */ + private Type type = Type.FUNCTION; + + /** + * The function definition. + */ + private Function function; + + public FunctionTool() { + + } + + /** + * Create a tool of type 'function' and the given function definition. + * @param type the tool type + * @param function function definition + */ + public FunctionTool( + @JsonProperty("type") Type type, + @JsonProperty("function") Function function) { + this.type = type; + this.function = function; + } /** * Create a tool of type 'function' and the given function definition. @@ -348,8 +369,22 @@ public class MiniMaxApi { this(Type.FUNCTION, function); } - public static FunctionTool webSearchFunctionTool() { - return new FunctionTool(Type.WEB_SEARCH, null); + @JsonProperty("type") + public Type getType() { + return this.type; + } + + @JsonProperty("function") + public Function getFunction() { + return this.function; + } + + public void setType(Type type) { + this.type = type; + } + + public void setFunction(Function function) { + this.function = function; } /** @@ -361,35 +396,104 @@ public class MiniMaxApi { */ @JsonProperty("function") FUNCTION, + @JsonProperty("web_search") WEB_SEARCH } + public static FunctionTool webSearchFunctionTool() { + return new FunctionTool(FunctionTool.Type.WEB_SEARCH, null); + } + + /** * Function definition. - * - * @param description A description of what the function does, used by the model to choose when and how to call - * the function. - * @param name The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and dashes, - * with a maximum length of 64. - * @param parameters The parameters the functions accepts, described as a JSON Schema object. To describe a - * function that accepts no parameters, provide the value {"type": "object", "properties": {}}. */ - public record Function( - @JsonProperty("description") String description, - @JsonProperty("name") String name, - @JsonProperty("parameters") String parameters) { + public static class Function { + + @JsonProperty("description") + private String description; + + @JsonProperty("name") + private String name; + + @JsonProperty("parameters") + private Map parameters; + + private String jsonSchema; + + private Function() { + + } + + /** + * Create tool function definition. + * + * @param description A description of what the function does, used by the model to choose when and how to call + * the function. + * @param name The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and dashes, + * with a maximum length of 64. + * @param parameters The parameters the functions accepts, described as a JSON Schema object. To describe a + * function that accepts no parameters, provide the value {"type": "object", "properties": {}}. + */ + public Function( + String description, + String name, + Map parameters) { + this.description = description; + this.name = name; + this.parameters = parameters; + } /** * Create tool function definition. * * @param description tool function description. * @param name tool function name. - * @param parameters tool function schema. + * @param jsonSchema tool function schema as json. */ - public Function(String description, String name, Map parameters) { - this(description, name, ModelOptionsUtils.toJsonString(parameters)); + public Function(String description, String name, String jsonSchema) { + this(description, name, ModelOptionsUtils.jsonToMap(jsonSchema)); } + + @JsonProperty("description") + public String getDescription() { + return this.description; + } + + @JsonProperty("name") + public String getName() { + return this.name; + } + + @JsonProperty("parameters") + public Map getParameters() { + return this.parameters; + } + + public void setDescription(String description) { + this.description = description; + } + + public void setName(String name) { + this.name = name; + } + + public void setParameters(Map parameters) { + this.parameters = parameters; + } + + public String getJsonSchema() { + return this.jsonSchema; + } + + public void setJsonSchema(String jsonSchema) { + this.jsonSchema = jsonSchema; + if (jsonSchema != null) { + this.parameters = ModelOptionsUtils.jsonToMap(jsonSchema); + } + } + } } diff --git a/models/spring-ai-minimax/src/test/java/org/springframework/ai/minimax/ChatCompletionRequestTests.java b/models/spring-ai-minimax/src/test/java/org/springframework/ai/minimax/ChatCompletionRequestTests.java index e2ee4fb06..dcb91c547 100644 --- a/models/spring-ai-minimax/src/test/java/org/springframework/ai/minimax/ChatCompletionRequestTests.java +++ b/models/spring-ai-minimax/src/test/java/org/springframework/ai/minimax/ChatCompletionRequestTests.java @@ -83,7 +83,7 @@ public class ChatCompletionRequestTests { assertThat(request.model()).isEqualTo("PROMPT_MODEL"); assertThat(request.tools()).hasSize(1); - assertThat(request.tools().get(0).function().name()).isEqualTo(TOOL_FUNCTION_NAME); + assertThat(request.tools().get(0).getFunction().getName()).isEqualTo(TOOL_FUNCTION_NAME); } @Test @@ -120,7 +120,7 @@ public class ChatCompletionRequestTests { MiniMaxChatOptions.builder().withFunction(TOOL_FUNCTION_NAME).build()), false); assertThat(request.tools()).hasSize(1); - assertThat(request.tools().get(0).function().name()).as("Explicitly enabled function") + assertThat(request.tools().get(0).getFunction().getName()).as("Explicitly enabled function") .isEqualTo(TOOL_FUNCTION_NAME); // Override the default options function with one from the prompt @@ -134,7 +134,7 @@ public class ChatCompletionRequestTests { false); assertThat(request.tools()).hasSize(1); - assertThat(request.tools().get(0).function().name()).as("Explicitly enabled function") + assertThat(request.tools().get(0).getFunction().getName()).as("Explicitly enabled function") .isEqualTo(TOOL_FUNCTION_NAME); assertThat(client.getFunctionCallbackRegister()).hasSize(1); diff --git a/models/spring-ai-minimax/src/test/java/org/springframework/ai/minimax/api/MiniMaxApiToolFunctionCallIT.java b/models/spring-ai-minimax/src/test/java/org/springframework/ai/minimax/api/MiniMaxApiToolFunctionCallIT.java index 2dad6668d..86c337a58 100644 --- a/models/spring-ai-minimax/src/test/java/org/springframework/ai/minimax/api/MiniMaxApiToolFunctionCallIT.java +++ b/models/spring-ai-minimax/src/test/java/org/springframework/ai/minimax/api/MiniMaxApiToolFunctionCallIT.java @@ -33,7 +33,6 @@ import org.springframework.ai.minimax.api.MiniMaxApi.ChatCompletionMessage.Role; import org.springframework.ai.minimax.api.MiniMaxApi.ChatCompletionMessage.ToolCall; import org.springframework.ai.minimax.api.MiniMaxApi.ChatCompletionRequest; import org.springframework.ai.minimax.api.MiniMaxApi.ChatCompletionRequest.ToolChoiceBuilder; -import org.springframework.ai.minimax.api.MiniMaxApi.FunctionTool.Type; import org.springframework.http.ResponseEntity; import static org.assertj.core.api.Assertions.assertThat; @@ -67,31 +66,33 @@ public class MiniMaxApiToolFunctionCallIT { var message = new ChatCompletionMessage( "What's the weather like in San Francisco? Return the temperature in Celsius.", Role.USER); - var functionTool = new MiniMaxApi.FunctionTool(Type.FUNCTION, new MiniMaxApi.FunctionTool.Function( - "Get the weather in location. Return temperature in 30°F or 30°C format.", "getCurrentWeather", """ - { - "type": "object", - "properties": { - "location": { - "type": "string", - "description": "The city and state e.g. San Francisco, CA" - }, - "lat": { - "type": "number", - "description": "The city latitude" - }, - "lon": { - "type": "number", - "description": "The city longitude" - }, - "unit": { - "type": "string", - "enum": ["C", "F"] + var functionTool = new MiniMaxApi.FunctionTool(MiniMaxApi.FunctionTool.Type.FUNCTION, + new MiniMaxApi.FunctionTool.Function( + "Get the weather in location. Return temperature in 30°F or 30°C format.", "getCurrentWeather", + """ + { + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "The city and state e.g. San Francisco, CA" + }, + "lat": { + "type": "number", + "description": "The city latitude" + }, + "lon": { + "type": "number", + "description": "The city longitude" + }, + "unit": { + "type": "string", + "enum": ["C", "F"] + } + }, + "required": ["location", "lat", "lon", "unit"] } - }, - "required": ["location", "lat", "lon", "unit"] - } - """)); + """)); List messages = new ArrayList<>(List.of(message)); diff --git a/models/spring-ai-mistral-ai/src/main/java/org/springframework/ai/mistralai/api/MistralAiApi.java b/models/spring-ai-mistral-ai/src/main/java/org/springframework/ai/mistralai/api/MistralAiApi.java index 39e038522..33ce9cad6 100644 --- a/models/spring-ai-mistral-ai/src/main/java/org/springframework/ai/mistralai/api/MistralAiApi.java +++ b/models/spring-ai-mistral-ai/src/main/java/org/springframework/ai/mistralai/api/MistralAiApi.java @@ -318,12 +318,21 @@ public class MistralAiApi { /** * Represents a tool the model may call. Currently, only functions are supported as a * tool. - * - * @param type The type of the tool. Currently, only 'function' is supported. - * @param function The function definition. */ @JsonInclude(Include.NON_NULL) - public record FunctionTool(@JsonProperty("type") Type type, @JsonProperty("function") Function function) { + public static class FunctionTool { + + // The type of the tool. Currently, only 'function' is supported. + @JsonProperty("type") + Type type = Type.FUNCTION; + + // The function definition. + @JsonProperty("function") + Function function; + + public FunctionTool() { + + } /** * Create a tool of type 'function' and the given function definition. @@ -333,6 +342,27 @@ public class MistralAiApi { this(Type.FUNCTION, function); } + public FunctionTool(Type type, Function function) { + this.type = type; + this.function = function; + } + + public Type getType() { + return this.type; + } + + public Function getFunction() { + return this.function; + } + + public void setType(Type type) { + this.type = type; + } + + public void setFunction(Function function) { + this.function = function; + } + /** * Create a tool of type 'function' and the given function definition. */ @@ -348,17 +378,39 @@ public class MistralAiApi { /** * Function definition. - * - * @param description A description of what the function does, used by the model - * to choose when and how to call the function. - * @param name The name of the function to be called. Must be a-z, A-Z, 0-9, or - * contain underscores and dashes, with a maximum length of 64. - * @param parameters The parameters the functions accepts, described as a JSON - * Schema object. To describe a function that accepts no parameters, provide the - * value {"type": "object", "properties": {}}. */ - public record Function(@JsonProperty("description") String description, @JsonProperty("name") String name, - @JsonProperty("parameters") Map parameters) { + public static class Function { + + @JsonProperty("description") + private String description; + + @JsonProperty("name") + private String name; + + @JsonProperty("parameters") + private Map parameters; + + private String jsonSchema; + + private Function() { + + } + + /** + * Create tool function definition. + * @param description A description of what the function does, used by the + * model to choose when and how to call the function. + * @param name The name of the function to be called. Must be a-z, A-Z, 0-9, + * or contain underscores and dashes, with a maximum length of 64. + * @param parameters The parameters the functions accepts, described as a JSON + * Schema object. To describe a function that accepts no parameters, provide + * the value {"type": "object", "properties": {}}. + */ + public Function(String description, String name, Map parameters) { + this.description = description; + this.name = name; + this.parameters = parameters; + } /** * Create tool function definition. @@ -370,6 +422,41 @@ public class MistralAiApi { this(description, name, ModelOptionsUtils.jsonToMap(jsonSchema)); } + public String getDescription() { + return this.description; + } + + public String getName() { + return this.name; + } + + public Map getParameters() { + return this.parameters; + } + + public void setDescription(String description) { + this.description = description; + } + + public void setName(String name) { + this.name = name; + } + + public void setParameters(Map parameters) { + this.parameters = parameters; + } + + public String getJsonSchema() { + return this.jsonSchema; + } + + public void setJsonSchema(String jsonSchema) { + this.jsonSchema = jsonSchema; + if (jsonSchema != null) { + this.parameters = ModelOptionsUtils.jsonToMap(jsonSchema); + } + } + } } diff --git a/models/spring-ai-openai/pom.xml b/models/spring-ai-openai/pom.xml index 869708c6a..aa52d0521 100644 --- a/models/spring-ai-openai/pom.xml +++ b/models/spring-ai-openai/pom.xml @@ -131,7 +131,8 @@ ollama test - + + diff --git a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiChatOptions.java b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiChatOptions.java index 905071bf9..0ada1f33b 100644 --- a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiChatOptions.java +++ b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiChatOptions.java @@ -37,7 +37,6 @@ import org.springframework.ai.openai.api.OpenAiApi; import org.springframework.ai.openai.api.OpenAiApi.ChatCompletionRequest.ResponseFormat; import org.springframework.ai.openai.api.OpenAiApi.ChatCompletionRequest.StreamOptions; import org.springframework.ai.openai.api.OpenAiApi.ChatCompletionRequest.ToolChoiceBuilder; -import org.springframework.ai.openai.api.OpenAiApi.FunctionTool; import org.springframework.util.Assert; /** @@ -133,7 +132,7 @@ public class OpenAiChatOptions implements FunctionCallingOptions, ChatOptions { * A list of tools the model may call. Currently, only functions are supported as a tool. Use this to * provide a list of functions the model may generate JSON inputs for. */ - private @JsonProperty("tools") List tools; + private @JsonProperty("tools") List tools; /** * Controls which (if any) function is called by the model. none means the model will not call a * function and instead generates a message. auto means the model can pick between generating a message or calling a @@ -370,11 +369,11 @@ public class OpenAiChatOptions implements FunctionCallingOptions, ChatOptions { this.topP = topP; } - public List getTools() { + public List getTools() { return this.tools; } - public void setTools(List tools) { + public void setTools(List tools) { this.tools = tools; } @@ -593,7 +592,7 @@ public class OpenAiChatOptions implements FunctionCallingOptions, ChatOptions { return this; } - public Builder withTools(List tools) { + public Builder withTools(List tools) { this.options.tools = tools; return this; } 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 76a5a2c45..173fbf866 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 @@ -532,14 +532,35 @@ public class OpenAiApi { /** * Represents a tool the model may call. Currently, only functions are supported as a * tool. - * - * @param type The type of the tool. Currently, only 'function' is supported. - * @param function The function definition. */ - @JsonInclude(Include.NON_NULL) - public record FunctionTool(// @formatter:off - @JsonProperty("type") Type type, - @JsonProperty("function") Function function) { + @JsonInclude(JsonInclude.Include.NON_NULL) + public static class FunctionTool { + + /** + * The type of the tool. Currently, only 'function' is supported. + */ + @JsonProperty("type") + private Type type = Type.FUNCTION; + + /** + * The function definition. + */ + @JsonProperty("function") + private Function function; + + public FunctionTool() { + + } + + /** + * Create a tool of type 'function' and the given function definition. + * @param type the tool type + * @param function function definition + */ + public FunctionTool(Type type, Function function) { + this.type = type; + this.function = function; + } /** * Create a tool of type 'function' and the given function definition. @@ -549,35 +570,73 @@ public class OpenAiApi { this(Type.FUNCTION, function); } + public Type getType() { + return this.type; + } + + public Function getFunction() { + return this.function; + } + + public void setType(Type type) { + this.type = type; + } + + public void setFunction(Function function) { + this.function = function; + } + /** * Create a tool of type 'function' and the given function definition. */ public enum Type { + /** * Function tool type. */ @JsonProperty("function") FUNCTION + } /** * Function definition. - * - * @param description A description of what the function does, used by the model to choose when and how to call - * the function. - * @param name The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and dashes, - * with a maximum length of 64. - * @param parameters The parameters the functions accepts, described as a JSON Schema object. To describe a - * function that accepts no parameters, provide the value {"type": "object", "properties": {}}. */ - public record Function( - @JsonProperty("description") String description, - @JsonProperty("name") String name, - @JsonProperty("parameters") Map parameters) { + public static class Function { + + @JsonProperty("description") + private String description; + + @JsonProperty("name") + private String name; + + @JsonProperty("parameters") + private Map parameters; + + private String jsonSchema; + + private Function() { + + } + + /** + * Create tool function definition. + * @param description A description of what the function does, used by the + * model to choose when and how to call the function. + * @param name The name of the function to be called. Must be a-z, A-Z, 0-9, + * or contain underscores and dashes, with a maximum length of 64. + * @param parameters The parameters the functions accepts, described as a JSON + * Schema object. To describe a function that accepts no parameters, provide + * the value {"type": "object", "properties": {}}. + */ + public Function(String description, String name, Map parameters) { + this.description = description; + this.name = name; + this.parameters = parameters; + } /** * Create tool function definition. - * * @param description tool function description. * @param name tool function name. * @param jsonSchema tool function schema as json. @@ -585,8 +644,45 @@ public class OpenAiApi { public Function(String description, String name, String jsonSchema) { this(description, name, ModelOptionsUtils.jsonToMap(jsonSchema)); } + + public String getDescription() { + return this.description; + } + + public String getName() { + return this.name; + } + + public Map getParameters() { + return this.parameters; + } + + public void setDescription(String description) { + this.description = description; + } + + public void setName(String name) { + this.name = name; + } + + public void setParameters(Map parameters) { + this.parameters = parameters; + } + + public String getJsonSchema() { + return this.jsonSchema; + } + + public void setJsonSchema(String jsonSchema) { + this.jsonSchema = jsonSchema; + if (jsonSchema != null) { + this.parameters = ModelOptionsUtils.jsonToMap(jsonSchema); + } + } + } - } // @formatter:on + + } /** * Creates a model response for the given chat conversation. @@ -825,9 +921,9 @@ public class OpenAiApi { */ @JsonInclude(Include.NON_NULL) public record JsonSchema( - @JsonProperty("name") String name, - @JsonProperty("schema") Map schema, - @JsonProperty("strict") Boolean strict) { + @JsonProperty("name") String name, + @JsonProperty("schema") Map schema, + @JsonProperty("strict") Boolean strict) { public JsonSchema(String name, String schema) { this(name, ModelOptionsUtils.jsonToMap(schema), true); diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/ChatCompletionRequestTests.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/ChatCompletionRequestTests.java index 1bd723631..d948080cb 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/ChatCompletionRequestTests.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/ChatCompletionRequestTests.java @@ -83,7 +83,7 @@ public class ChatCompletionRequestTests { assertThat(request.model()).isEqualTo("PROMPT_MODEL"); assertThat(request.tools()).hasSize(1); - assertThat(request.tools().get(0).function().name()).isEqualTo(TOOL_FUNCTION_NAME); + assertThat(request.tools().get(0).getFunction().getName()).isEqualTo(TOOL_FUNCTION_NAME); } @Test @@ -120,7 +120,7 @@ public class ChatCompletionRequestTests { OpenAiChatOptions.builder().withFunction(TOOL_FUNCTION_NAME).build()), false); assertThat(request.tools()).hasSize(1); - assertThat(request.tools().get(0).function().name()).as("Explicitly enabled function") + assertThat(request.tools().get(0).getFunction().getName()).as("Explicitly enabled function") .isEqualTo(TOOL_FUNCTION_NAME); // Override the default options function with one from the prompt @@ -134,7 +134,7 @@ public class ChatCompletionRequestTests { false); assertThat(request.tools()).hasSize(1); - assertThat(request.tools().get(0).function().name()).as("Explicitly enabled function") + assertThat(request.tools().get(0).getFunction().getName()).as("Explicitly enabled function") .isEqualTo(TOOL_FUNCTION_NAME); assertThat(client.getFunctionCallbackRegister()).hasSize(1); 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 6a511e8fd..a7b1cb48a 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 @@ -34,7 +34,6 @@ 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; import org.springframework.ai.openai.api.OpenAiApi.ChatCompletionRequest.ToolChoiceBuilder; -import org.springframework.ai.openai.api.OpenAiApi.FunctionTool.Type; import org.springframework.http.ResponseEntity; import static org.assertj.core.api.Assertions.assertThat; @@ -71,7 +70,7 @@ public class OpenAiApiToolFunctionCallIT { var message = new ChatCompletionMessage("What's the weather like in San Francisco, Tokyo, and Paris?", Role.USER); - var functionTool = new OpenAiApi.FunctionTool(Type.FUNCTION, + var functionTool = new OpenAiApi.FunctionTool(OpenAiApi.FunctionTool.Type.FUNCTION, new OpenAiApi.FunctionTool.Function("Get the weather in location. Return temperature in Celsius.", "getCurrentWeather", ModelOptionsUtils.jsonToMap(""" { diff --git a/models/spring-ai-zhipuai/src/main/java/org/springframework/ai/zhipuai/ZhiPuAiChatModel.java b/models/spring-ai-zhipuai/src/main/java/org/springframework/ai/zhipuai/ZhiPuAiChatModel.java index 9694f2961..7da150c62 100644 --- a/models/spring-ai-zhipuai/src/main/java/org/springframework/ai/zhipuai/ZhiPuAiChatModel.java +++ b/models/spring-ai-zhipuai/src/main/java/org/springframework/ai/zhipuai/ZhiPuAiChatModel.java @@ -68,7 +68,6 @@ import org.springframework.ai.zhipuai.api.ZhiPuAiApi.ChatCompletionMessage.Media import org.springframework.ai.zhipuai.api.ZhiPuAiApi.ChatCompletionMessage.Role; import org.springframework.ai.zhipuai.api.ZhiPuAiApi.ChatCompletionMessage.ToolCall; import org.springframework.ai.zhipuai.api.ZhiPuAiApi.ChatCompletionRequest; -import org.springframework.ai.zhipuai.api.ZhiPuAiApi.FunctionTool; import org.springframework.ai.zhipuai.api.ZhiPuApiConstants; import org.springframework.ai.zhipuai.metadata.ZhiPuAiUsage; import org.springframework.http.ResponseEntity; @@ -470,11 +469,11 @@ public class ZhiPuAiChatModel extends AbstractToolCallSupport implements ChatMod .build(); } - private List getFunctionTools(Set functionNames) { + private List getFunctionTools(Set functionNames) { return this.resolveFunctionCallbacks(functionNames).stream().map(functionCallback -> { - var function = new FunctionTool.Function(functionCallback.getDescription(), functionCallback.getName(), - functionCallback.getInputTypeSchema()); - return new FunctionTool(function); + var function = new ZhiPuAiApi.FunctionTool.Function(functionCallback.getDescription(), + functionCallback.getName(), functionCallback.getInputTypeSchema()); + return new ZhiPuAiApi.FunctionTool(function); }).toList(); } diff --git a/models/spring-ai-zhipuai/src/main/java/org/springframework/ai/zhipuai/ZhiPuAiChatOptions.java b/models/spring-ai-zhipuai/src/main/java/org/springframework/ai/zhipuai/ZhiPuAiChatOptions.java index e37ab4465..ec2216f50 100644 --- a/models/spring-ai-zhipuai/src/main/java/org/springframework/ai/zhipuai/ZhiPuAiChatOptions.java +++ b/models/spring-ai-zhipuai/src/main/java/org/springframework/ai/zhipuai/ZhiPuAiChatOptions.java @@ -31,7 +31,6 @@ import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.model.function.FunctionCallback; import org.springframework.ai.model.function.FunctionCallingOptions; import org.springframework.ai.zhipuai.api.ZhiPuAiApi; -import org.springframework.ai.zhipuai.api.ZhiPuAiApi.FunctionTool; import org.springframework.util.Assert; /** @@ -74,7 +73,10 @@ public class ZhiPuAiChatOptions implements FunctionCallingOptions, ChatOptions { * A list of tools the model may call. Currently, only functions are supported as a tool. Use this to * provide a list of functions the model may generate JSON inputs for. */ - private @JsonProperty("tools") List tools; + private @JsonProperty("tools") List tools; + + private @JsonProperty("tools1") List foos; + /** * Controls which (if any) function is called by the model. none means the model will not call a * function and instead generates a message. auto means the model can pick between generating a message or calling a @@ -207,11 +209,11 @@ public class ZhiPuAiChatOptions implements FunctionCallingOptions, ChatOptions { this.topP = topP; } - public List getTools() { + public List getTools() { return this.tools; } - public void setTools(List tools) { + public void setTools(List tools) { this.tools = tools; } @@ -473,7 +475,7 @@ public class ZhiPuAiChatOptions implements FunctionCallingOptions, ChatOptions { return this; } - public Builder withTools(List tools) { + public Builder withTools(List tools) { this.options.tools = tools; return this; } diff --git a/models/spring-ai-zhipuai/src/main/java/org/springframework/ai/zhipuai/api/ZhiPuAiApi.java b/models/spring-ai-zhipuai/src/main/java/org/springframework/ai/zhipuai/api/ZhiPuAiApi.java index d6d92d0ee..c5f9abe28 100644 --- a/models/spring-ai-zhipuai/src/main/java/org/springframework/ai/zhipuai/api/ZhiPuAiApi.java +++ b/models/spring-ai-zhipuai/src/main/java/org/springframework/ai/zhipuai/api/ZhiPuAiApi.java @@ -312,16 +312,48 @@ public class ZhiPuAiApi { } } + public class Foo { + + String foo; + + public Foo() { + + } + public Foo(String foo) { + this.foo = foo; + } + } + + /** * Represents a tool the model may call. Currently, only functions are supported as a tool. - * - * @param type The type of the tool. Currently, only 'function' is supported. - * @param function The function definition. */ - @JsonInclude(Include.NON_NULL) - public record FunctionTool( - @JsonProperty("type") Type type, - @JsonProperty("function") Function function) { + @JsonInclude(JsonInclude.Include.NON_NULL) + public static class FunctionTool { + + // The type of the tool. Currently, only 'function' is supported. + @JsonProperty("type") + private Function function; + + // The function definition. + @JsonProperty("function") + private Type type = Type.FUNCTION; + + public FunctionTool() { + + } + + /** + * Create a tool of type 'function' and the given function definition. + * @param type the tool type + * @param function function definition + */ + public FunctionTool( + Type type, + Function function) { + this.type = type; + this.function = function; + } /** * Create a tool of type 'function' and the given function definition. @@ -331,6 +363,22 @@ public class ZhiPuAiApi { this(Type.FUNCTION, function); } + public Type getType() { + return this.type; + } + + public Function getFunction() { + return this.function; + } + + public void setType(Type type) { + this.type = type; + } + + public void setFunction(Function function) { + this.function = function; + } + /** * Create a tool of type 'function' and the given function definition. */ @@ -344,18 +392,42 @@ public class ZhiPuAiApi { /** * Function definition. - * - * @param description A description of what the function does, used by the model to choose when and how to call - * the function. - * @param name The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and dashes, - * with a maximum length of 64. - * @param parameters The parameters the functions accepts, described as a JSON Schema object. To describe a - * function that accepts no parameters, provide the value {"type": "object", "properties": {}}. */ - public record Function( - @JsonProperty("description") String description, - @JsonProperty("name") String name, - @JsonProperty("parameters") Map parameters) { + public static class Function { + + @JsonProperty("description") + private String description; + + @JsonProperty("name") + private String name; + + @JsonProperty("parameters") + private Map parameters; + + private String jsonSchema; + + private Function() { + + } + + /** + * Create tool function definition. + * + * @param description A description of what the function does, used by the model to choose when and how to call + * the function. + * @param name The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and dashes, + * with a maximum length of 64. + * @param parameters The parameters the functions accepts, described as a JSON Schema object. To describe a + * function that accepts no parameters, provide the value {"type": "object", "properties": {}}. + */ + public Function( + String description, + String name, + Map parameters) { + this.description = description; + this.name = name; + this.parameters = parameters; + } /** * Create tool function definition. @@ -367,6 +439,42 @@ public class ZhiPuAiApi { public Function(String description, String name, String jsonSchema) { this(description, name, ModelOptionsUtils.jsonToMap(jsonSchema)); } + + public String getDescription() { + return this.description; + } + + public String getName() { + return this.name; + } + + public Map getParameters() { + return this.parameters; + } + + public void setDescription(String description) { + this.description = description; + } + + public void setName(String name) { + this.name = name; + } + + public void setParameters(Map parameters) { + this.parameters = parameters; + } + + public String getJsonSchema() { + return this.jsonSchema; + } + + public void setJsonSchema(String jsonSchema) { + this.jsonSchema = jsonSchema; + if (jsonSchema != null) { + this.parameters = ModelOptionsUtils.jsonToMap(jsonSchema); + } + } + } } diff --git a/models/spring-ai-zhipuai/src/test/java/org/springframework/ai/zhipuai/ChatCompletionRequestTests.java b/models/spring-ai-zhipuai/src/test/java/org/springframework/ai/zhipuai/ChatCompletionRequestTests.java index a4f2c08f7..f548ea011 100644 --- a/models/spring-ai-zhipuai/src/test/java/org/springframework/ai/zhipuai/ChatCompletionRequestTests.java +++ b/models/spring-ai-zhipuai/src/test/java/org/springframework/ai/zhipuai/ChatCompletionRequestTests.java @@ -83,7 +83,7 @@ public class ChatCompletionRequestTests { assertThat(request.model()).isEqualTo("PROMPT_MODEL"); assertThat(request.tools()).hasSize(1); - assertThat(request.tools().get(0).function().name()).isEqualTo(TOOL_FUNCTION_NAME); + assertThat(request.tools().get(0).getFunction().getName()).isEqualTo(TOOL_FUNCTION_NAME); } @Test @@ -120,7 +120,7 @@ public class ChatCompletionRequestTests { ZhiPuAiChatOptions.builder().withFunction(TOOL_FUNCTION_NAME).build()), false); assertThat(request.tools()).hasSize(1); - assertThat(request.tools().get(0).function().name()).as("Explicitly enabled function") + assertThat(request.tools().get(0).getFunction().getName()).as("Explicitly enabled function") .isEqualTo(TOOL_FUNCTION_NAME); // Override the default options function with one from the prompt @@ -134,7 +134,7 @@ public class ChatCompletionRequestTests { false); assertThat(request.tools()).hasSize(1); - assertThat(request.tools().get(0).function().name()).as("Explicitly enabled function") + assertThat(request.tools().get(0).getFunction().getName()).as("Explicitly enabled function") .isEqualTo(TOOL_FUNCTION_NAME); assertThat(client.getFunctionCallbackRegister()).hasSize(1); diff --git a/models/spring-ai-zhipuai/src/test/java/org/springframework/ai/zhipuai/api/ZhiPuAiApiToolFunctionCallIT.java b/models/spring-ai-zhipuai/src/test/java/org/springframework/ai/zhipuai/api/ZhiPuAiApiToolFunctionCallIT.java index 4817580ac..c45b8b017 100644 --- a/models/spring-ai-zhipuai/src/test/java/org/springframework/ai/zhipuai/api/ZhiPuAiApiToolFunctionCallIT.java +++ b/models/spring-ai-zhipuai/src/test/java/org/springframework/ai/zhipuai/api/ZhiPuAiApiToolFunctionCallIT.java @@ -34,7 +34,6 @@ import org.springframework.ai.zhipuai.api.ZhiPuAiApi.ChatCompletionMessage.Role; import org.springframework.ai.zhipuai.api.ZhiPuAiApi.ChatCompletionMessage.ToolCall; import org.springframework.ai.zhipuai.api.ZhiPuAiApi.ChatCompletionRequest; import org.springframework.ai.zhipuai.api.ZhiPuAiApi.ChatCompletionRequest.ToolChoiceBuilder; -import org.springframework.ai.zhipuai.api.ZhiPuAiApi.FunctionTool.Type; import org.springframework.http.ResponseEntity; import static org.assertj.core.api.Assertions.assertThat; @@ -68,7 +67,7 @@ public class ZhiPuAiApiToolFunctionCallIT { var message = new ChatCompletionMessage( "What's the weather like in San Francisco? Return the temperature in Celsius.", Role.USER); - var functionTool = new ZhiPuAiApi.FunctionTool(Type.FUNCTION, + var functionTool = new ZhiPuAiApi.FunctionTool(ZhiPuAiApi.FunctionTool.Type.FUNCTION, new ZhiPuAiApi.FunctionTool.Function( "Get the weather in location. Return temperature in 30°F or 30°C format.", "getCurrentWeather", ModelOptionsUtils.jsonToMap(""" diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/minimax/MiniMaxPropertiesTests.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/minimax/MiniMaxPropertiesTests.java index 47131bedc..4140f029b 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/minimax/MiniMaxPropertiesTests.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/minimax/MiniMaxPropertiesTests.java @@ -229,11 +229,11 @@ public class MiniMaxPropertiesTests { assertThat(chatProperties.getOptions().getTools()).hasSize(1); var tool = chatProperties.getOptions().getTools().get(0); - assertThat(tool.type()).isEqualTo(MiniMaxApi.FunctionTool.Type.FUNCTION); - var function = tool.function(); - assertThat(function.name()).isEqualTo("myFunction1"); - assertThat(function.description()).isEqualTo("function description"); - assertThat(function.parameters()).isNotEmpty(); + assertThat(tool.getType()).isEqualTo(MiniMaxApi.FunctionTool.Type.FUNCTION); + var function = tool.getFunction(); + assertThat(function.getName()).isEqualTo("myFunction1"); + assertThat(function.getDescription()).isEqualTo("function description"); + assertThat(function.getParameters()).isNotEmpty(); }); } diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/mistralai/MistralAiPropertiesTests.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/mistralai/MistralAiPropertiesTests.java index e69a711ff..46c814bc3 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/mistralai/MistralAiPropertiesTests.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/mistralai/MistralAiPropertiesTests.java @@ -19,6 +19,7 @@ package org.springframework.ai.autoconfigure.mistralai; import org.junit.jupiter.api.Test; import org.springframework.ai.autoconfigure.retry.SpringAiRetryAutoConfiguration; +import org.springframework.ai.mistralai.api.MistralAiApi; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -52,6 +53,54 @@ public class MistralAiPropertiesTests { }); } + @Test + public void chatOptionsTest() { + + new ApplicationContextRunner().withPropertyValues("spring.ai.mistralai.base-url=TEST_BASE_URL", + "spring.ai.mistralai.chat.options.tools[0].function.name=myFunction1", + "spring.ai.mistralai.chat.options.tools[0].function.description=function description", + "spring.ai.mistralai.chat.options.tools[0].function.jsonSchema=" + """ + { + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "The city and state e.g. San Francisco, CA" + }, + "lat": { + "type": "number", + "description": "The city latitude" + }, + "lon": { + "type": "number", + "description": "The city longitude" + }, + "unit": { + "type": "string", + "enum": ["c", "f"] + } + }, + "required": ["location", "lat", "lon", "unit"] + } + """, + + "spring.ai.mistralai.api-key=abc123", "spring.ai.mistralai.embedding.base-url=TEST_BASE_URL2", + "spring.ai.mistralai.embedding.api-key=456", "spring.ai.mistralai.embedding.options.model=MODEL_XYZ") + .withConfiguration(AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, + RestClientAutoConfiguration.class, MistralAiAutoConfiguration.class)) + .run(context -> { + + var chatProperties = context.getBean(MistralAiChatProperties.class); + + var tool = chatProperties.getOptions().getTools().get(0); + assertThat(tool.getType()).isEqualTo(MistralAiApi.FunctionTool.Type.FUNCTION); + var function = tool.getFunction(); + assertThat(function.getName()).isEqualTo("myFunction1"); + assertThat(function.getDescription()).isEqualTo("function description"); + assertThat(function.getParameters()).isNotEmpty(); + }); + } + @Test public void embeddingOverrideConnectionProperties() { diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/openai/OpenAiPropertiesTests.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/openai/OpenAiPropertiesTests.java index 3ba07792b..a14ca15fe 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/openai/OpenAiPropertiesTests.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/openai/OpenAiPropertiesTests.java @@ -26,8 +26,8 @@ import org.springframework.ai.openai.OpenAiAudioTranscriptionModel; import org.springframework.ai.openai.OpenAiChatModel; import org.springframework.ai.openai.OpenAiEmbeddingModel; import org.springframework.ai.openai.OpenAiImageModel; +import org.springframework.ai.openai.api.OpenAiApi; import org.springframework.ai.openai.api.OpenAiApi.ChatCompletionRequest.ToolChoiceBuilder; -import org.springframework.ai.openai.api.OpenAiApi.FunctionTool.Type; import org.springframework.ai.openai.api.OpenAiAudioApi; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -426,11 +426,11 @@ public class OpenAiPropertiesTests { assertThat(chatProperties.getOptions().getTools()).hasSize(1); var tool = chatProperties.getOptions().getTools().get(0); - assertThat(tool.type()).isEqualTo(Type.FUNCTION); - var function = tool.function(); - assertThat(function.name()).isEqualTo("myFunction1"); - assertThat(function.description()).isEqualTo("function description"); - assertThat(function.parameters()).isNotEmpty(); + assertThat(tool.getType()).isEqualTo(OpenAiApi.FunctionTool.Type.FUNCTION); + var function = tool.getFunction(); + assertThat(function.getName()).isEqualTo("myFunction1"); + assertThat(function.getDescription()).isEqualTo("function description"); + assertThat(function.getParameters()).isNotEmpty(); }); } diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/chroma/ChromaVectorStoreAutoConfigurationIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/chroma/ChromaVectorStoreAutoConfigurationIT.java index 481488d0a..b33f714cb 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/chroma/ChromaVectorStoreAutoConfigurationIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/chroma/ChromaVectorStoreAutoConfigurationIT.java @@ -36,6 +36,7 @@ import org.springframework.ai.vectorstore.VectorStore; import org.springframework.ai.vectorstore.observation.DefaultVectorStoreObservationConvention; import org.springframework.ai.vectorstore.observation.VectorStoreObservationContext; import org.springframework.ai.vectorstore.observation.VectorStoreObservationDocumentation.HighCardinalityKeyNames; +import org.springframework.beans.factory.BeanCreationException; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; @@ -127,11 +128,12 @@ public class ChromaVectorStoreAutoConfigurationIT { @Test public void throwExceptionOnMissingCollectionAndDisabledInitializedSchema() { - this.contextRunner.withPropertyValues("spring.ai.vectorstore.chroma.initializeSchema=false") .run(context -> assertThatThrownBy(() -> context.getBean(VectorStore.class)) - .isInstanceOf(RuntimeException.class) - .hasMessage( + .isInstanceOf(IllegalStateException.class) + .hasCauseInstanceOf(BeanCreationException.class) + .hasRootCauseExactlyInstanceOf(RuntimeException.class) + .hasRootCauseMessage( "Collection TestCollection doesn't exist and won't be created as the initializeSchema is set to false.")); } diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/hanadb/HanaCloudVectorStoreAutoConfigurationIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/hanadb/HanaCloudVectorStoreAutoConfigurationIT.java index c8d620d08..98f4def3e 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/hanadb/HanaCloudVectorStoreAutoConfigurationIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/hanadb/HanaCloudVectorStoreAutoConfigurationIT.java @@ -18,9 +18,9 @@ package org.springframework.ai.autoconfigure.vectorstore.hanadb; import java.util.List; -import org.junit.Test; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration; diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/zhipuai/ZhiPuAiPropertiesTests.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/zhipuai/ZhiPuAiPropertiesTests.java index 2cc2c9b21..ac6e743e5 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/zhipuai/ZhiPuAiPropertiesTests.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/zhipuai/ZhiPuAiPropertiesTests.java @@ -273,11 +273,11 @@ public class ZhiPuAiPropertiesTests { assertThat(chatProperties.getOptions().getTools()).hasSize(1); var tool = chatProperties.getOptions().getTools().get(0); - assertThat(tool.type()).isEqualTo(ZhiPuAiApi.FunctionTool.Type.FUNCTION); - var function = tool.function(); - assertThat(function.name()).isEqualTo("myFunction1"); - assertThat(function.description()).isEqualTo("function description"); - assertThat(function.parameters()).isNotEmpty(); + assertThat(tool.getType()).isEqualTo(ZhiPuAiApi.FunctionTool.Type.FUNCTION); + var function = tool.getFunction(); + assertThat(function.getName()).isEqualTo("myFunction1"); + assertThat(function.getDescription()).isEqualTo("function description"); + assertThat(function.getParameters()).isNotEmpty(); }); }