SafeGuardAdvisor 类是一个关键内容安全审查组件,用于在 AI 生成内容(如聊天回复、文本生成)时进行实时风险检测(如暴力、仇恨言论、隐私泄露等),确保输出符合安全策略。
SafeGuardAdvisor 类的核心功能如下:
敏敏感词校验
SafeGuardAdvisor 可精准识别并拦截含敏感词的用户输入,有效规避因信息处理不当导致的系统风险。敏感词库支持按需定制与动态更新,确保对各类敏感信息的识别与处理始终精准高效。
请求拦截
当用户提交的内容触发敏感词机制时,SafeGuardAdvisor 会即时拦截该请求,终止后续大模型调用流程。这一机制既能减少不必要的计算资源消耗,也能从源头防范因处理敏感信息引发的潜在安全隐患。
合规性保障
通过敏感词校验与请求拦截的协同作用,SafeGuardAdvisor 助力系统在用户信息处理环节严格遵循相关法律法规及行业标准,显著提升系统合规水平,降低因违规操作导致的法律风险。
SafeGuardAdvisor 类的工作原理如下:
(1)请求拦截
当用户向系统提交请求时,SafeGuardAdvisor 类会首先对该请求进行拦截。对请求中的文本内容进行敏感词校验,以判断是否存在敏感信息。
(2)敏感词识别
SafeGuardAdvisor 类使用预定义的敏感词库对请求中的文本进行匹配。如果发现文本中包含敏感词,则触发敏感词机制。
(3)请求处理
如果请求被识别为包含敏感信息,SafeGuardAdvisor 类会立即对该请求进行拦截,并返回相应的错误信息或提示。如果请求不包含敏感信息,则允许其继续传递至后续的 Advisor 组件或聊天模型进行处理。
SafeGuardAdvisor 和其他 Advisor 不同,提供了两个公开的构造方法,如下:
public SafeGuardAdvisor(List<String> sensitiveWords) { this(sensitiveWords, DEFAULT_FAILURE_RESPONSE, DEFAULT_ORDER); } public SafeGuardAdvisor(List<String> sensitiveWords, String failureResponse, int order) { Assert.notNull(sensitiveWords, "Sensitive words must not be null!"); Assert.notNull(failureResponse, "Failure response must not be null!"); this.sensitiveWords = sensitiveWords; this.failureResponse = failureResponse; this.order = order; }
参数说明:
sensitiveWords 敏感词列表,用于内容审查。在 SafeGuardAdvisor 的后续处理中,系统会检查输入内容是否包含这些敏感词,若包含则触发安全机制。
failureResponse 当检测到敏感词时返回的失败响应信息。当用户输入包含敏感词时,系统会直接返回此消息,而非继续处理请求。默认值为:
private static final String DEFAULT_FAILURE_RESPONSE = "I'm unable to respond to that due to sensitive content. Could we rephrase or discuss something else?";
order 设置该 Advisor 的执行顺序。在多个 Advisor 共存的场景中,order 值越小,优先级越高。例如,若有多个拦截器,order 决定了它们的执行顺序。默认为 0,如下:
private static final int DEFAULT_ORDER = 0;
注意,除了使用上述公开构造方法创建 SafeGuardAdvisor 外,还可以使用静态方法 builder() 来创建:
public static Builder builder() { return new Builder(); }
builder() 方法将返回 SafeGuardAdvisor.Builder 对象,SafeGuardAdvisor.Builder 定义如下:
public static final class Builder { // 敏感词 private List<String> sensitiveWords; // 错误返回信息 private String failureResponse = DEFAULT_FAILURE_RESPONSE; // 执行顺序 private int order = DEFAULT_ORDER; private Builder() { } //... }
下面示例,将通过 SafeGuardAdvisor 类的 sensitiveWords() 方法,将“账号”、“密码”和“电话号码”关键字作为敏感词。当我们输入中涉及这些敏感词,服务将终止请求大模型,而是直接返回错误提示信息。
在 resources 目录下创建名为 application.yml 的配置文件,如下:
spring: application: name: springai_demo1 # AI配置 ai: # openai相关配置 openai: # 基础地址 base-url: https://api.xty.app # AI KEY api-key: sk-vHTHX8D3wNZBfRya8***********2BeB8A23e48AbB600 # 聊天模型配置 chat: options: model: gpt-3.5-turbo # 图片模型配置 image: options: # 需要高级接口 model: dall-e-3 chat: memory: # 会话历史持久化 repository: jdbc: # 启动时不自动执行初始化SQL脚本,手动创建数据表 initialize-schema: never client: # true 开启,自动注入 ChatClient,false 关闭,需要手动创建 ChatClient enabled: true # 日志配置 logging: charset: console: UTF-8 level: root: info org.springframework.ai: debug
使用 @Configuration 注解创建名为 AiConfig 的配置类,用来配置 SafeGuardAdvisor,以及设置敏感词。如下:
package com.hxstrive.springai.springai_openai.advisor_SafeGuardAdvisor.config; import org.springframework.ai.chat.client.advisor.SafeGuardAdvisor; import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.List; /** * AI配置 * @author Administrator */ @Configuration public class AiConfig { @Bean public SafeGuardAdvisor safeGuardAdvisor() { return SafeGuardAdvisor.builder() // 设置铭感词,避免敏感词被记录到聊天历史中 .sensitiveWords(List.of("账号", "密码", "电话号码")).build(); } @Bean public SimpleLoggerAdvisor simpleLoggerAdvisor() { return new SimpleLoggerAdvisor(); // 默认配置 } }
注意,你可以尝试将敏感词存放到配置文件、数据库等中。
创建名为 AIController 的 Controller,将上面创建的 SafeGuardAdvisor 注入进来,然后通过 ChatClient 的 defaultAdvisors() 方法添加到 Advisor 链中。如下:
package com.hxstrive.springai.springai_openai.advisor_SafeGuardAdvisor.controller; import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.chat.client.advisor.SafeGuardAdvisor; import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor; import org.springframework.ai.chat.memory.ChatMemory; import org.springframework.ai.chat.model.ChatModel; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController public class AIController { @Autowired private ChatModel chatModel; @Autowired private SimpleLoggerAdvisor simpleLoggerAdvisor; @Autowired private SafeGuardAdvisor safeGuardAdvisor; @GetMapping("/ai/simple") public String completion(@RequestParam("userText") String userText) { // 构建 RAG advisor 时需要完成 vectorStore 初始化 ChatClient chatClient = ChatClient.builder(chatModel) .defaultSystem("使用中文进行回复") .defaultAdvisors( simpleLoggerAdvisor, safeGuardAdvisor ) .build(); // conversationId 区分不同对话,定位对应的历史记录 String conversationId = "sessionId-20250708204548"; return chatClient.prompt() // 运行时设置会话ID参数 .advisors(advisor -> { advisor.param(ChatMemory.CONVERSATION_ID, conversationId); }) .user(userText) .call() .content(); } }
启动应用程序,浏览器访问 http://localhost:8080/ai/simple 接口,问“张三的银行卡密码”,如下:
由于提的问题涉及了“密码”敏感词,后端直接返回如下信息:
I'm unable to respond to that due to sensitive content. Could we rephrase or discuss something else? 由于内容敏感,我无法回应这个问题。我们可以换一种说法,或者讨论其他事情吗?
如果将问题改为“张三”,回复如下:
上图正常回复了内容,因为没有涉及敏感关键字。
当然,我们可以通过 failureResponse() 自定义设置触发敏感词响应的内容,如下:
@Bean public SafeGuardAdvisor safeGuardAdvisor() { return SafeGuardAdvisor.builder() // 设置铭感词,避免敏感词被记录到聊天历史中 .sensitiveWords(List.of("账号", "密码", "电话号码")) // 设置触发敏感关键词响应的内容 .failureResponse("由于内容敏感,我无法回应这个问题。我们可以换一种说法,或者讨论其他事情吗?") .build(); }
再次运行程序,问“张三的银行卡密码”,效果如下图:
上图成功返回了自定义的提示信息。