AI 超级智能体项目——自定义违禁词校验Advisor

SensitiveWordAdvisor.java

java
复制代码
import org.springframework.ai.chat.client.ChatClientRequest; import org.springframework.ai.chat.client.ChatClientResponse; import org.springframework.ai.chat.client.advisor.api.CallAdvisor; import org.springframework.ai.chat.client.advisor.api.CallAdvisorChain; import org.springframework.ai.chat.client.advisor.api.StreamAdvisor; import org.springframework.ai.chat.client.advisor.api.StreamAdvisorChain; import reactor.core.publisher.Flux; import java.util.List; import java.util.Map; public class SensitiveWordAdvisor implements CallAdvisor, StreamAdvisor { // 简单的敏感词列表 private static final List<String> SENSITIVE_WORDS = List.of( "敏感词", "暴力", "色情", "赌博", "毒品" ); @Override public ChatClientResponse adviseCall(ChatClientRequest chatClientRequest, CallAdvisorChain callAdvisorChain) { Boolean hasSensitiveWords = containsSentitiveWords(chatClientRequest.prompt().getUserMessage().getText()); if (hasSensitiveWords){ ChatClientResponse chatClientResponse = ChatClientResponse.builder() .chatResponse(null) .context(Map.of("message","检测到敏感词,请重新输入")) .build(); return chatClientResponse; } else { ChatClientResponse chatClientResponse = callAdvisorChain.nextCall(chatClientRequest); return chatClientResponse; } } @Override public Flux<ChatClientResponse> adviseStream(ChatClientRequest chatClientRequest, StreamAdvisorChain streamAdvisorChain) { Boolean hasSensitiveWords = containsSentitiveWords(chatClientRequest.prompt().getUserMessage().getText()); if (hasSensitiveWords){ ChatClientResponse chatClientResponse = ChatClientResponse.builder() .chatResponse(null) .context(Map.of("message","检测到敏感词,请重新输入")) .build(); return Flux.just(chatClientResponse); }else { return streamAdvisorChain.nextStream(chatClientRequest); } } @Override public String getName() { return this.getClass().getSimpleName(); } @Override public int getOrder() { return 0; } private Boolean containsSentitiveWords(String text) { if (text == null || text.isEmpty()){ return false; } for (String sensitiveWord : SENSITIVE_WORDS) { if (text.contains(sensitiveWord)){ return true; } } return false; } }

实现自定义Advisor的核心就是实现CallAdvisor和StreamAdvisor两个接口,重写adviseStream()和adviseCall()两个方法。

LoveApp.java

java
复制代码
@Component @Slf4j public class LoveApp { private ChatClient chatClient; private static final String SYSTEM_PROMPT = "you are a helpful assistant"; public LoveApp(ChatModel dashscopeChatModel, JdbcChatMemoryRepository chatMemoryRepository){ ChatMemory chatMemory = MessageWindowChatMemory.builder() .chatMemoryRepository(chatMemoryRepository) .maxMessages(10) .build(); ChatClient.Builder builder = ChatClient.builder(dashscopeChatModel); chatClient = builder.defaultSystem(SYSTEM_PROMPT) .defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build(), new SensitiveWordAdvisor(), new MyLoggerAdvisor()) .build(); } public String doChatWithSensitiveWords(String userInput, String chatId){ ChatClientResponse chatClientResponse = chatClient.prompt() .user(userInput) .advisors(advisor -> advisor.param(ChatMemory.CONVERSATION_ID, chatId)) .call() .chatClientResponse(); ChatResponse chatResponse = chatClientResponse.chatResponse(); if (chatResponse == null){ return chatClientResponse.context().get("message").toString(); } else { Object message = chatClientResponse.context().get("message"); return message != null ? message.toString() : "未知错误"; } } }

经过debug发现,如果没有特意设置advisor的order值的话(都是0),那么Spring AI 会按照注册顺序的逆序来处理请求和响应。在该代码中,会先由MyLoggerAdvisor处理请求,再由SensitiveWordAdvisor处理请求,再由SensitiveWordAdvisor处理响应,最后由MyLoggerAdvisor处理响应。 MyLoggerAdvisor应该要放到最后(即最先处理请求,最后处理响应),这样在用户交互时输入违禁词时,同样可以打印出用户输入日志,反之则不行。

0个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
可惜在哪
下载 APP