Skip to content

Commit 9d04572

Browse files
committed
feat: Fixed GH-3586, Optimize SafeGuardAdvisor to output the matched sensitive words in debug log level when a sensitive word is hit.
Signed-off-by: Sun Yuhan <[email protected]>
1 parent 17c1156 commit 9d04572

File tree

1 file changed

+20
-8
lines changed

1 file changed

+20
-8
lines changed

spring-ai-client-chat/src/main/java/org/springframework/ai/chat/client/advisor/SafeGuardAdvisor.java

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@
1818

1919
import java.util.List;
2020
import java.util.Map;
21+
import java.util.Set;
22+
import java.util.stream.Collectors;
2123

24+
import org.slf4j.Logger;
25+
import org.slf4j.LoggerFactory;
2226
import reactor.core.publisher.Flux;
2327

2428
import org.springframework.ai.chat.client.ChatClientRequest;
@@ -44,6 +48,8 @@
4448
*/
4549
public class SafeGuardAdvisor implements CallAdvisor, StreamAdvisor {
4650

51+
private static final Logger log = LoggerFactory.getLogger(SafeGuardAdvisor.class);
52+
4753
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?";
4854

4955
private static final int DEFAULT_ORDER = 0;
@@ -76,22 +82,28 @@ public String getName() {
7682

7783
@Override
7884
public ChatClientResponse adviseCall(ChatClientRequest chatClientRequest, CallAdvisorChain callAdvisorChain) {
79-
if (!CollectionUtils.isEmpty(this.sensitiveWords)
80-
&& this.sensitiveWords.stream().anyMatch(w -> chatClientRequest.prompt().getContents().contains(w))) {
81-
return createFailureResponse(chatClientRequest);
85+
if (!CollectionUtils.isEmpty(this.sensitiveWords)) {
86+
String content = chatClientRequest.prompt().getContents();
87+
Set<String> hitWords = this.sensitiveWords.stream().filter(content::contains).collect(Collectors.toSet());
88+
if (!hitWords.isEmpty()) {
89+
log.debug("sensitive words found: {}", hitWords);
90+
return createFailureResponse(chatClientRequest);
91+
}
8292
}
83-
8493
return callAdvisorChain.nextCall(chatClientRequest);
8594
}
8695

8796
@Override
8897
public Flux<ChatClientResponse> adviseStream(ChatClientRequest chatClientRequest,
8998
StreamAdvisorChain streamAdvisorChain) {
90-
if (!CollectionUtils.isEmpty(this.sensitiveWords)
91-
&& this.sensitiveWords.stream().anyMatch(w -> chatClientRequest.prompt().getContents().contains(w))) {
92-
return Flux.just(createFailureResponse(chatClientRequest));
99+
if (!CollectionUtils.isEmpty(this.sensitiveWords)) {
100+
String contents = chatClientRequest.prompt().getContents();
101+
Set<String> hitWords = this.sensitiveWords.stream().filter(contents::contains).collect(Collectors.toSet());
102+
if (!hitWords.isEmpty()) {
103+
log.debug("sensitive words found: {}", hitWords);
104+
return Flux.just(createFailureResponse(chatClientRequest));
105+
}
93106
}
94-
95107
return streamAdvisorChain.nextStream(chatClientRequest);
96108
}
97109

0 commit comments

Comments
 (0)