文章目录
在我们的互联网时代,内容审核是显得尤为重要。尤其是在社交媒体和平台上,那么如何有效地管理和过滤敏感词,就成为了我们每个企业和开发者必须面对的事情。
今天,我们将深入探讨敏感词审核的技术细节+敏感词库,帮助你构建一个高效的内容安全系统。🚀
一、背景与需求
随着政策的不断完善,许多平台需要对非积极的词汇进行管制。这不仅是为了维护良好的网络环境,也是为了保护用户的合法权益。因此,敏感词审核的实现变得尤为重要。
二、3个备选方案
在实现敏感词审核时,我们有几个备选方案:
1. 接入第三方审核服务
- 阿里云:提供了强大的内容审核API,能够快速识别敏感词。但是1000万次的费用大约在6750/年。这对于创业企业来说,肯定是一笔不小的开支。
- 腾讯云(天御文本内容安全):同样提供了高效的内容审核解决方案。这里没有找到对等条数参考。但是最近的720万条是14000/年。这个对比与阿里云来说。肯定是贵上不少。
2. 自行开发审核系统
- 通过定义拦截策略,我们构建了属于自己的敏感词审核系统。我们是采用的两层策略审核:它们分别是
包含策略
和全等策略
。
三、审核策略详解
1. 包含策略(严格)
这种策略是非常严格的策略,因为它只要输入词库中包含指定的敏感词,就会被拦截。
这样做的理由:包含就是严格,所以一点都不能出现。
例如:
-
敏感词:
小明
- 输入:
我叫小明,我今年1岁了。
(会被精准拦截)
- 输入:
-
敏感词:
你好吗?
- 输入:
你好吗?
(会被精准拦截)
- 输入:
2. 全等策略(宽松)
这种策略相对宽松,只有完全等于敏感词的内容才会被拦截。
例如:
- 敏感词:
小明
- 输入:
我叫小明,我今年1岁了。
(不会被拦截) - 输入:
我叫 小明 ,我今年1岁了。
(会被拦截)
注意1:小明的前后是有空格
存在的,所以才会被拦截。
注意2:全等策略是比较宽松的拦截,目的就是有一些敏感词,在编写代码中是可以组成词句的。所以在包含策略下,必须要在覆盖一套宽松的策略。避免误审。
如果是注意:是误审核,是误审核的话,那么结果如下:
代码和策略都是很好实现,其实最重要的就是词库。今天小编也一起分享下来:
注意:敏感词库是需要不断完善的,策略词库比较严格请自己筛选一遍。
四、代码实现
在实现敏感词审核时,我们可以使用Aho-Corasick算法来提高匹配效率。以下是具体的代码实现:
1. Maven依赖
我们需要在项目中添加Aho-Corasick算法库的依赖:
<dependency>
<groupId>com.hankcs</groupId>
<artifactId>aho-corasick-double-array-trie</artifactId>
<version>1.2.3</version>
</dependency>
2. 服务实现
然后在实现一个审核服务,使用Aho-Corasick算法来构建敏感词匹配的Trie树。
import com.hankcs.algorithm.AhoCorasickDoubleArrayTrie;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
@Slf4j
@Service
public class PromptAuditService {
@Autowired
private IAuditPromptService auditPromptService; // 注入审计提示服务
private AhoCorasickDoubleArrayTrie<String> containTrie; // 存储包含策略的敏感词Trie树
private AhoCorasickDoubleArrayTrie<String> congruentTrie; // 存储等价策略的敏感词Trie树
@PostConstruct
public void init() {
// 初始化时构建敏感词Trie树
buildContainTrie();
buildCongruentTrie();
// 每2分钟刷新一次敏感词Trie树
Executors.newSingleThreadScheduledExecutor().schedule(this::refreshTries, 2, TimeUnit.MINUTES);
}
// 构建包含策略的敏感词Trie树
private void buildContainTrie() {
List<AuditPrompt> containPrompts = auditPromptService.listWithStrategy(PromptInterceptStrategy.contain);
Map<String, String> containMap = new HashMap<>();
for (AuditPrompt prompt : containPrompts) {
containMap.put(prompt.getContent(), prompt.getContent()); // 将敏感词加入Map
}
containTrie = new AhoCorasickDoubleArrayTrie<>(); // 创建Trie树实例
containTrie.build(containMap); // 构建Trie树
}
// 构建等价策略的敏感词Trie树
private void buildCongruentTrie() {
List<AuditPrompt> congruentPrompts = auditPromptService.listWithStrategy(PromptInterceptStrategy.congruent);
Map<String, String> congruentMap = new HashMap<>();
for (AuditPrompt prompt : congruentPrompts) {
congruentMap.put(prompt.getContent(), prompt.getContent()); // 将敏感词加入Map
}
congruentTrie = new AhoCorasickDoubleArrayTrie<>(); // 创建Trie树实例
congruentTrie.build(congruentMap); // 构建Trie树
}
// 执行审计
public void doAudit(ChatAskInfo chatAskInfo) {
if (chatAskInfo != null && StringUtils.isNotBlank(chatAskInfo.getPrompt())) {
final String prompt = chatAskInfo.getPrompt(); // 获取用户输入的提示
// 检查prompt中是否包含任何一个敏感词
final String badStr = containsForbiddenWords(prompt);
if (StringUtils.isNotBlank(badStr)) {
// 如果包含敏感词,抛出异常并返回敏感词信息
throw new ServiceException(CodeMossErrorCode.PROMPT_ILLEGAL,
String.format("尊敬的用户您好,您的提问违反平台规定;并请您在使用过程中,严格遵守《生成式人工智能服务管理暂行办法》,我们将对您的问题和AI回复进行实时审查。\n\n【敏感词如下:%s】", badStr));
}
}
}
// 使用 Aho-Corasick 算法检查输入中是否包含敏感词
private String containsForbiddenWords(String input) {
if (StringUtils.isBlank(input)) {
return null; // 输入为空时返回null
}
// 检查 'contain' 策略
Collection<AhoCorasickDoubleArrayTrie.Hit<String>> containHits = containTrie.parseText(input);
if (!containHits.isEmpty()) {
// 返回第一个匹配的敏感词
return containHits.iterator().next().value;
}
// 检查 'congruent' 策略
Collection<AhoCorasickDoubleArrayTrie.Hit<String>> congruentHits = congruentTrie.parseText(input);
if (!congruentHits.isEmpty()) {
// 确保是完整单词匹配
for (AhoCorasickDoubleArrayTrie.Hit<String> hit : congruentHits) {
String word = hit.value;
int start = hit.begin;
int end = hit.end;
// 检查匹配的开始和结束边界
boolean isStartBoundary = start == 0 || !Character.isLetterOrDigit(input.charAt(start - 1));
boolean isEndBoundary = end == input.length() || !Character.isLetterOrDigit(input.charAt(end));
if (isStartBoundary && isEndBoundary) {
return word; // 返回完整单词匹配的敏感词
}
}
}
return null; // 如果没有匹配的敏感词,返回null
}
// 动态更新敏感词Trie树
public void refreshTries() {
buildContainTrie(); // 重新构建包含策略的Trie树
buildCongruentTrie(); // 重新构建等价策略的Trie树
}
}
五、总结
通过以上的分析与实现,我们可以看到,敏感词审核不仅是技术问题,更是社会责任。构建一个高效的内容安全系统,不仅能保护平台的健康发展,也能为用户提供更好的使用体验。希望这篇文章能为你在敏感词审核的技术实现上提供一些启发和帮助!💡