Skip to content

敏感词过滤

Turms不支持且未来也不会支持图片、视频与语音的反垃圾检测功能,下文所有内容仅在文本检测范围内进行说明。

功能特性对比

结合现实情况,商用敏感词过滤功能的最大优点是:词库丰富,更新及时,支持多语言。最主要缺点是:按检测次数收费、每次检测都需要发送网络请求;turms-plugin-antispam的最大优点是:免费、本地极速检测,只需遍历一遍目标串。最主要缺点是:不提供词库。具体而言:

特别一提的是:由于黑产的客观存在,“按检测次数收费”的实际开销可能会比您预期的开销大。

商业反垃圾服务(含敏感词过滤)turms-plugin-antispam
免费否。按检测次数收费
开源否。完全闭源是。完全开源
匹配速度需要发送网络请求,比turms-plugin-antispam的匹配速度慢了几个数量级本地极速匹配(基于双数组Trie的AC自动机算法实现)。您可以忽略匹配时带来的性能开销。
在NORMALIZATION模式下,匹配的时间复杂度为O(n),n为输入字符串长度。
在NORMALIZATION_TRANSLITERATION模式下,音译的时间复杂度为O(n),n为输入字符串长度。匹配音译结果的时间复杂度为O(m),m为音译结果字符串长度。
补充:汉字音译指将汉字转换成拼音
文本去噪(如去标点符号、字母与数字标准化)部分支持部分支持
形近字匹配(如火星文)部分支持TODO(1.1支持)
拆字匹配部分支持TODO(1.2支持)
音近字精确匹配支持支持
音近字模糊匹配支持TODO(1.1支持)
多音字匹配支持TODO(1.1支持)
词库闭源,但是词库丰富,更新及时不提供。具体原因见下文
多语言/方言支持支持多种语言与方言需要用户自行采集词库。另外,也有项目通过调用“翻译API”,将源语言翻译成某特定语言再进行匹配,但turms-plugin-antispam不提供该类实现
生僻字支持部分支持部分支持。turms-plugin-antispam能够识别Unicode基本多语言平面(BMP)内的code points,支持识别两万多个汉字(《新华字典》最新版仅收录一万多个汉字)。
由于大部分IM应用都不要求一定要能显示特别生僻的字(如“𤳵”字),建议您的UI前端应用直接用如“?”的占位符对BMP之外的cope points进行替换。
turms-plugin-antispam没有计划支持BMP以外的code points
组合敏感词支持TODO(1.1支持)
文字竖排检测不支持不支持
查询词库附加信息附加信息丰富。如敏感词类别(涉黄、涉政、暴恐、违禁、谩骂、灌水、广告、广告法、涉价值观等)TODO(1.0)。另外,虽然Turms之后会支持该功能,但Turms依旧不提供敏感词库
白名单支持TODO(1.1支持)
地区差异化服务部分支持不支持
人工审核系统部分支持不支持

敏感词检测的复杂性

  • 并不是什么文本都能检测的。以字符串“Turms是一个优秀的IM开源项目”为例,如果我们采用常规的竖排明文显示。那么如果敏感词检测系统不支持特征提取,那么该系统就无法检测该类文本:

    text
    ╔═╤═╤═╤═╤═╗
    ║┊│项│的│是│T║
    ║┊│目│I│一│u║
    ║┊│┊│M│个│r║
    ║┊│┊│开│优│m║
    ║┊│┊│源│秀│s║
    ╚═╧═╧═╧═╧═╝

    甚至也可以先用加密算法对消息进行加密后再发送(比如您的应用支持Web端,那黑客甚至可以给您的Web端,写个浏览器插件,让每条消息在发送前都进行加密,在收到时进行解密)。因此敏感词过滤只能提高发出敏感词行为的成本,没法根除发送敏感词这一行为。

  • 大部分系统都不支持检测语义,尤其是正话反说,明褒暗贬。同样一句话,放在不同的上下文,可以有着完全不同的含义。

  • 存在误封。对一些正常词汇又存在着误封,如很多商业服务将“水乳交融”认为是“具有极高可信度的色情词汇”,结果造成了正常用户的流失。补充:为了避免这种误封情况,需要将这些词语录入“白名单”中(turms-plugin-antispam目前暂不提供)。

  • 实现可以非常灵活(turms-plugin-antispam暂无计划提供相关实现)。具体而言包括:根据不同区域的用户提供不同的敏感词过滤服务;相比私聊消息,对群消息实行更为严格检测;有些词具有时效性,在某些时候是敏感词,在某些时候就不是敏感词。

鉴于上述敏感词检测的复杂性,turms-plugin-antispam所需做的就是:结合边际效应,综合考虑敏感词的广泛度、敏感词的识别难度、识别时所需的系统资源开销。只要求能够识别大多数敏感词与常见伪装方式,不要求能够识别相对少见的伪装形式。

敏感词词库

由于敏感词的特殊性,turms-plugin-antispam不提供敏感词词库,需要用户自行采集。

来源

网络采集、运营采集、逆向工程、相关部门提供、人工举报

作用

  • 为turms-plugin-antispam提供敏感词词库,以进行后续的敏感词检测。除word字段以外,其他字段目前暂时对敏感词检测没有实际作用

  • (TODO)为运营人员提供Admin API接口,来查询与全量更新敏感词词库

    短期内,我们并没有计划支持从数据库中导入原始数据,以及敏感词词库的运营功能。您需要自行管理敏感词词库,turms-plugin-antispam目前只是作为一个纯粹的数据使用方

格式

turms-plugin-antispam目前支持两种导入词库的格式:1. 原始的CSV格式数据;2. 已经解析好的bin数据。

由于通过解析好的bin数据导入,turms-plugin-antispam就无需进行词库的解析操作,只是单纯地读取文件的字节流数据,因此强烈推荐您通过im.turms.plugin.antispam.ac.AhoCorasickCodec#main自行将原始的CSV格式数据解析成bin数据,再通过dictParsing.binFilePath让turms-plugin-antispam直接导入bin数据(TODO:即将支持通过Admin API导入数据)

CSV格式

spreadsheet
敏感词,词ID,过滤等级,类别,词源,收录时间,失效时间,生效时间,更新时间,注释
word,id,level,category,source,create_time,disable_time,enable_time,update_time,comment
  • 要特别注意导入的文件格式,非常推荐统一采用UTF-8编码
  • ,\t这两种分隔符都会被自动识别,不需要用户手动指定
  • 上述所有列中,除了word列必须存在之外,其他所有列都可以不存在
  • 如果在解析到与列格式不符的数据格式,则拒绝继续解析,并抛出异常

考虑到上述列已经可以满足大部分场景,暂不计划支持自定义列特性。

举例而言:

spreadsheet
你好,123,1,打招呼的敬语,网络采集,1970-01-01T00:00:00.000Z,1970-01-01T00:00:00.000Z,1970-01-01T00:00:00.000Z,,汉语中打招呼的敬语常用词语
Hello,,2,,

안녕하세요,,,,,,,,,,,,,,,,,,,,,,,,,,,
こんにちは

配置讲解

配置类:im.turms.plugin.antispam.property.AntiSpamProperties

配置前缀:turms.plugin.antispam

配置项

配置名默认值作用
enabledtrue是否启动反垃圾功能
dictParsing.binFilePathnull词库的二进制文件路径。该文件保存了词库文本解析后的数据,用于避免每次服务端启动时都从头解析词库文本。如果用户配置了“textFilePath”与“binFilePath”,则会优先使用“binFilePath”
dictParsing.textFilePathnull词库的文本文件路径
dictParsing.textFileCharset"UTF-8"词库编码格式。推荐统一使用“UTF-8”编码
dictParsing.skipInvalidCharactertrue解析词库文本时,是否自动跳过非法字符。
如果false且在解析过程中遇到非法字符,则会抛出异常
dictParsing.extendedWords.enabledtrue是否需要支持拓展词库功能。如果为true,则解析并使用词库中的所有数据。如果为false,则仅仅解析与使用word字段数据,以大幅度减少内存开销
textParsingStrategyNORMALIZATION_TRANSLITERATION词典文本与用户输入文本的解析策略:
NORMALIZATION:对输入文本进行标准化。如:⑩HELLO(你{}好./ -> 10hello你好
NORMALIZATION_TRANSLITERATION:对输入文本进行标准化并音译。如:⑩HELLO(你{}好./ -> 10hellonihao
unwantedWordHandleStrategyREJECT_REQUEST非法文本处理策略:
REJECT_REQUEST:向客户端返回“MESSAGE_IS_ILLEGAL”错误状态码
MASK_TEXT:替换非法字符,并继续正常处理请求
mask'*'当“unwantedWordHandleStrategy”为“MASK_TEXT”时,所采用的掩码
maxNumberOfUnwantedWordsToReturn0当处理策略为REJECT_REQUEST且该值大于0时,被检测为非法文本的字符串,将以ASCII0x1E(Record Separator)字符作为分隔符,通过异常的描述字符串来表示。该异常文本最终会被客户端接收
textTypes所有其他用户可见的文本配置哪些请求的哪些文本字段需要进行检测
silentIllegalTextTypes配置当检测到这些请求的这些文本字段包含非法字符时,服务端会“OK”状态码响应客户端,但服务端实际并没有继续处理该请求。
在实际业务场景中,该值除了通常为空外,还通常为CREATE_MESSAGE_REQUEST_TEXT,用于静默拒绝发送用户消息

Admin API

TODO

不使用其他开源实现的原因

在全球开源圈子内,目前可找到的开源实现的质量都非常之低,主要体现在:代码质量低(高空间复杂度与时间复杂度)、很多匹配功能都不支持、作者不具备工程设计能力,甚至还有收费的半开源IM项目通过遍历词库来进行匹配的。暂未有像turms-plugin-antispam这样的算法与代码质量都优秀的实现,且传统反垃圾方案(不涉及机器学习)的总体实现难度不大,因此Turms选择自研,也为后期众多拓展做足准备。具体而言:

  • 会算法的不会工程设计,会工程设计的不会算法。一方面,实现基于双数组Trie的AC自动机算法的难度较高,且Java的数据结构设计的都比较保守,如StringStringBuilder为了保证内部数据与外部数据隔离,很多函数都会涉及内存拷贝工作,能够在算法实现中避开各种Java的“坑”就需要工程师有基本的优化意识。另一方面,Turms里的反垃圾设计与算法实现的逻辑都是统一的,都是为了Turms这个IM项目设计的,为实际IM需求服务的。因此能保证“能想到的功能就能做到,不需要的功能就不需要提供,以免不必要的时间与空间开销”。
  • 自研可以根据项目需求,定制算法实现与算法的上下游代码,以保证绝对的高效(把空间复杂度压到O(1),时间复杂度压到O(n),保证遍历一边字符串即可完成敏感词匹配)。举个例子,在AC自动机标准算法实现中,并没有涉及到“跳过某字符进行匹配”的逻辑。那么如果我们想要实现“只检测BMP内的code points”,就需要在把原始char[]传递给标准AC算法实现之前,先自行过滤并拷贝一个新的char[],再传递给AC自动机进行匹配。这频繁的内存拷贝工作无疑是非常低效且不必要的,尤其是“用户文本消息”本身就是所有用户请求中最占内存也是出现最频繁的数据。而采用定制实现的话,我们只需在AC自动机进行匹配时,加一个if判断条件直接跳过该字符即可。既实现简单清晰,又无需开辟新的内存空间,空间效率高。