diff --git a/models/spring-ai-minimax/src/main/java/org/springframework/ai/minimax/MiniMaxChatOptions.java b/models/spring-ai-minimax/src/main/java/org/springframework/ai/minimax/MiniMaxChatOptions.java index b924c0084..f1bf80773 100644 --- a/models/spring-ai-minimax/src/main/java/org/springframework/ai/minimax/MiniMaxChatOptions.java +++ b/models/spring-ai-minimax/src/main/java/org/springframework/ai/minimax/MiniMaxChatOptions.java @@ -99,6 +99,12 @@ public class MiniMaxChatOptions implements FunctionCallingOptions, ChatOptions { * probability mass are considered. We generally recommend altering this or temperature but not both. */ private @JsonProperty("top_p") Float topP; + /** + * Mask the text information in the output that is easy to involve privacy issues, + * including but not limited to email, domain name, link, ID number, home address, etc. + * The default is true, which means enabling masking. + */ + private @JsonProperty("mask_sensitive_info") Boolean maskSensitiveInfo; /** * 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. @@ -204,6 +210,11 @@ public class MiniMaxChatOptions implements FunctionCallingOptions, ChatOptions { return this; } + public Builder withMaskSensitiveInfo(Boolean maskSensitiveInfo) { + this.options.maskSensitiveInfo = maskSensitiveInfo; + return this; + } + public Builder withTools(List tools) { this.options.tools = tools; return this; @@ -334,6 +345,14 @@ public class MiniMaxChatOptions implements FunctionCallingOptions, ChatOptions { this.topP = topP; } + public Boolean getMaskSensitiveInfo() { + return maskSensitiveInfo; + } + + public void setMaskSensitiveInfo(Boolean maskSensitiveInfo) { + this.maskSensitiveInfo = maskSensitiveInfo; + } + public List getTools() { return this.tools; } @@ -389,6 +408,7 @@ public class MiniMaxChatOptions implements FunctionCallingOptions, ChatOptions { result = prime * result + ((stop == null) ? 0 : stop.hashCode()); result = prime * result + ((temperature == null) ? 0 : temperature.hashCode()); result = prime * result + ((topP == null) ? 0 : topP.hashCode()); + result = prime * result + ((maskSensitiveInfo == null) ? 0 : maskSensitiveInfo.hashCode()); result = prime * result + ((tools == null) ? 0 : tools.hashCode()); result = prime * result + ((toolChoice == null) ? 0 : toolChoice.hashCode()); return result; @@ -463,6 +483,12 @@ public class MiniMaxChatOptions implements FunctionCallingOptions, ChatOptions { } else if (!topP.equals(other.topP)) return false; + if (this.maskSensitiveInfo == null) { + if (other.maskSensitiveInfo != null) + return false; + } + else if (!maskSensitiveInfo.equals(other.maskSensitiveInfo)) + return false; if (this.tools == null) { if (other.tools != null) return false; @@ -494,6 +520,7 @@ public class MiniMaxChatOptions implements FunctionCallingOptions, ChatOptions { .withStop(fromOptions.getStop()) .withTemperature(fromOptions.getTemperature()) .withTopP(fromOptions.getTopP()) + .withMaskSensitiveInfo(fromOptions.getMaskSensitiveInfo()) .withTools(fromOptions.getTools()) .withToolChoice(fromOptions.getToolChoice()) .withFunctionCallbacks(fromOptions.getFunctionCallbacks()) 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 aedaed9d4..eb4923464 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 @@ -227,6 +227,9 @@ public class MiniMaxApi { * @param topP An alternative to sampling with temperature, called nucleus sampling, where the model considers the * results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% * probability mass are considered. We generally recommend altering this or temperature but not both. + * @param maskSensitiveInfo Mask the text information in the output that is easy to involve privacy issues, + * including but not limited to email, domain name, link, ID number, home address, etc. The default is true, + * which means enabling masking. * @param tools 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. * @param toolChoice Controls which (if any) function is called by the model. none means the model will not call a @@ -249,6 +252,7 @@ public class MiniMaxApi { @JsonProperty("stream") Boolean stream, @JsonProperty("temperature") Float temperature, @JsonProperty("top_p") Float topP, + @JsonProperty("mask_sensitive_info") Boolean maskSensitiveInfo, @JsonProperty("tools") List tools, @JsonProperty("tool_choice") Object toolChoice) { @@ -261,7 +265,7 @@ public class MiniMaxApi { */ public ChatCompletionRequest(List messages, String model, Float temperature) { this(messages, model, null, null, null, null, - null, null, null, false, temperature, null, + null, null, null, false, temperature, null,null, null, null); } @@ -276,7 +280,7 @@ public class MiniMaxApi { */ public ChatCompletionRequest(List messages, String model, Float temperature, boolean stream) { this(messages, model, null, null, null, null, - null, null, null, stream, temperature, null, + null, null, null, stream, temperature, null,null, null, null); } @@ -292,7 +296,7 @@ public class MiniMaxApi { public ChatCompletionRequest(List messages, String model, List tools, Object toolChoice) { this(messages, model, null, null, null, null, - null, null, null, false, 0.8f, null, + null, null, null, false, 0.8f, null,null, tools, toolChoice); } @@ -306,7 +310,7 @@ public class MiniMaxApi { */ public ChatCompletionRequest(List messages, Boolean stream) { this(messages, null, null, null, null, null, - null, null, null, stream, null, null, + null, null, null, stream, null, null,null, null, null); } diff --git a/models/spring-ai-minimax/src/test/java/org/springframework/ai/minimax/chat/MiniMaxChatOptionsTests.java b/models/spring-ai-minimax/src/test/java/org/springframework/ai/minimax/chat/MiniMaxChatOptionsTests.java new file mode 100644 index 000000000..35326fa6e --- /dev/null +++ b/models/spring-ai-minimax/src/test/java/org/springframework/ai/minimax/chat/MiniMaxChatOptionsTests.java @@ -0,0 +1,49 @@ +package org.springframework.ai.minimax.chat; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; +import org.springframework.ai.chat.messages.Message; +import org.springframework.ai.chat.messages.UserMessage; +import org.springframework.ai.chat.model.ChatResponse; +import org.springframework.ai.chat.prompt.Prompt; +import org.springframework.ai.minimax.MiniMaxChatModel; +import org.springframework.ai.minimax.MiniMaxChatOptions; +import org.springframework.ai.minimax.api.MiniMaxApi; + +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Geng Rong + */ +@EnabledIfEnvironmentVariable(named = "MINIMAX_API_KEY", matches = ".+") +public class MiniMaxChatOptionsTests { + + private final MiniMaxChatModel chatModel = new MiniMaxChatModel(new MiniMaxApi(System.getenv("MINIMAX_API_KEY"))); + + @Test + void testMarkSensitiveInfo() { + + UserMessage userMessage = new UserMessage( + "Please extract the phone number, the content: My name is Bob, and my phone number is 133-12345678"); + + List messages = new ArrayList<>(List.of(userMessage)); + + // markSensitiveInfo is enabled by default + ChatResponse response = chatModel.call(new Prompt(messages)); + String responseContent = response.getResult().getOutput().getContent(); + + assertThat(responseContent).contains("133-**"); + assertThat(responseContent).doesNotContain("133-12345678"); + + var chatOptions = MiniMaxChatOptions.builder().withMaskSensitiveInfo(false).build(); + + ChatResponse unmaskResponse = chatModel.call(new Prompt(messages, chatOptions)); + String unmaskResponseContent = unmaskResponse.getResult().getOutput().getContent(); + + assertThat(unmaskResponseContent).contains("133-12345678"); + } + +}