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 6f7913efd04..f32fe5d3c5a 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.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 @@ else if (message.getMessageType() == MessageType.TOOL) { 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 ee6743681a8..036a6aa1a3c 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 String getValue() { /** * 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 FunctionTool(Function function) { 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 enum Type { */ @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 e2ee4fb061d..dcb91c547a0 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 void promptOptionsTools() { 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 void defaultOptionsTools() { 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 void defaultOptionsTools() { 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 2dad6668d44..86c337a58e4 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.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 void toolFunctionCall() { 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 39e03852255..33ce9cad636 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 String getValue() { /** * 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 FunctionTool(Function function) { 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 enum Type { /** * 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 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-openai/pom.xml b/models/spring-ai-openai/pom.xml index 869708c6a38..aa52d0521fc 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 905071bf90b..4171af43ae2 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,8 +37,8 @@ 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; +import org.springframework.util.StringUtils; /** * @author Christian Tzolov @@ -133,7 +133,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 @@ -314,6 +314,14 @@ public ResponseFormat getResponseFormat() { } public void setResponseFormat(ResponseFormat responseFormat) { + if (responseFormat != null) { + ResponseFormat.JsonSchema jsonSchema = StringUtils.hasText(responseFormat.getSchema()) + ? new ResponseFormat.JsonSchema(responseFormat.getName(), responseFormat.getSchema(), + responseFormat.getStrict()) + : null; + + responseFormat.setJsonSchema(jsonSchema); + } this.responseFormat = responseFormat; } @@ -370,11 +378,11 @@ public void setTopP(Double topP) { 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 +601,7 @@ public Builder withTopP(Double topP) { 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 a6754ab4c3c..e4982d4f913 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 @@ -18,6 +18,7 @@ import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; import java.util.function.Predicate; @@ -532,14 +533,35 @@ public String getValue() { /** * 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 +571,73 @@ public FunctionTool(Function function) { 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 +645,45 @@ public record Function( 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. @@ -771,16 +868,62 @@ public static Object FUNCTION(String functionName) { } } - /** - * An object specifying the format that the model must output. - * @param type Must be one of 'text' or 'json_object'. - * @param jsonSchema JSON schema object that describes the format of the JSON object. - * Only applicable when type is 'json_schema'. - */ - @JsonInclude(Include.NON_NULL) - public record ResponseFormat( - @JsonProperty("type") Type type, - @JsonProperty("json_schema") JsonSchema jsonSchema) { + @JsonInclude(JsonInclude.Include.NON_NULL) + public static class ResponseFormat { + + @JsonProperty("type") + private Type type; + + private String name; + + private String schema; + + private Boolean strict; + + @JsonProperty("json_schema") + private JsonSchema jsonSchema; + + @JsonProperty("type") + public Type getType() { + return this.type; + } + + @JsonProperty("json_schema") + public JsonSchema getJsonSchema() { + return StringUtils.hasText(this.schema) ? new JsonSchema(this.name, this.schema, this.strict) : null; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public String getSchema() { + return this.schema; + } + + public void setSchema(String schema) { + this.schema = schema; + } + + public Boolean getStrict() { + return this.strict; + } + + public void setStrict(Boolean strict) { + this.strict = strict; + } + + private ResponseFormat() { + } + + public ResponseFormat(Type type, JsonSchema jsonSchema) { + this.type = type; + this.jsonSchema = jsonSchema; + } public ResponseFormat(Type type) { this(type, (JsonSchema) null); @@ -794,6 +937,40 @@ public ResponseFormat(Type type, String name, String schema, Boolean strict) { this(type, StringUtils.hasText(schema) ? new JsonSchema(name, schema, strict) : null); } + public void setType(Type type) { + this.type = type; + } + + public void setJsonSchema(JsonSchema jsonSchema) { + this.jsonSchema = jsonSchema; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ResponseFormat that = (ResponseFormat) o; + return Objects.equals(this.type, that.type) && + Objects.equals(this.jsonSchema, that.jsonSchema); + } + + @Override + public int hashCode() { + return Objects.hash(this.type, this.jsonSchema); + } + + @Override + public String toString() { + return "ResponseFormat{" + + "type=" + this.type + + ", jsonSchema=" + this.jsonSchema + + '}'; + } + public enum Type { /** * Generates a text response. (default) @@ -823,11 +1000,11 @@ public enum Type { * @param schema The JSON schema object that describes the format of the JSON object. * @param strict If true, the model will only generate outputs that match the schema. */ - @JsonInclude(Include.NON_NULL) + @JsonInclude(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 1bd7236319c..d948080cbae 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 void promptOptionsTools() { 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 void defaultOptionsTools() { 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 void defaultOptionsTools() { 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 6a511e8fd68..a7b1cb48aa9 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.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 void toolFunctionCall() { 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 9694f2961fa..7da150c62e7 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.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 @@ private ChatOptions buildRequestOptions(ZhiPuAiApi.ChatCompletionRequest request .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 e37ab4465ab..ec2216f50c1 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.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 void setTopP(Double topP) { 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 Builder withTopP(Double topP) { 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 d6d92d0eed4..c5f9abe28f5 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 String getValue() { } } + 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 FunctionTool(Function function) { 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 enum Type { /** * 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 record Function( 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 a4f2c08f717..f548ea011d7 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 void promptOptionsTools() { 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 void defaultOptionsTools() { 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 void defaultOptionsTools() { 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 4817580acc0..c45b8b0171b 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.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 void toolFunctionCall() { 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 47131bedc32..4140f029b4b 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 void chatOptionsTest() { 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 e69a711ffa0..46c814bc380 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 @@ 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 void embeddingProperties() { }); } + @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 3ba07792bef..a14ca15fe70 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.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 void chatOptionsTest() { 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 481488d0a30..b33f714cb67 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.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 void addAndSearchWithFilters() { @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 c8d620d0823..98f4def3e32 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 @@ 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 2cc2c9b21e5..ac6e743e53f 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 void chatOptionsTest() { 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(); }); }