搜狐技术产品

高效的文本内容审核系统实现

Image

互联网信息呈指数级增长的当下,每天都有海量的文本数据产生,这些信息不仅污染网络环境,危害用户的身心健康,还可能对社会秩序和安全造成严重威胁。因此,构建高效可靠的文本内容审核系统迫在眉睫,它对于维护网络空间的健康、安全和有序发展具有至关重要的意义。

本文将从新闻客户端文本审核流程、系统实现效果、核心技术具体实现流程以及系统应用拓展四个维度,详细阐述高效文本内容审核系统的设计与实现思路,为相关领域的技术研发和平台应用提供参考。

01

新闻客户端文本审核流程图详解

Image

新闻客户端作为信息传播的重要载体,其文本内容涵盖新闻资讯、用户评论、互动留言等多个板块,审核流程的设计需兼顾效率与精准性,既要实现海量内容的快速筛查,又要尽可能减少漏审、误审情况。目前客户端的文本审核采用****机器审核为主、人工审核为辅****的分层审核机制,整体流程环环相扣、层层筛选,具体执行步骤如下:

1.前置判断:先判定文章是否禁评,禁评则直接终止流程,节省资源。

2.黑白名单校验:支持评论则校验账号、IP,白名单优先 / 快速通过,黑名单直接拦截。

3.正则有效文本判断:过滤乱码、无意义符号等无效内容,减少无效审核。

4.核心机审:识别禁发词与敏感内容,违规直接拦截,合规直接通过,嫌疑内容转人工。

5.人工审核:对嫌疑内容精准判定,合规放行、违规拦截,争议可提交专家组复核。

6.审核结束:任一环节得出通过 / 拦截结果,流程结束并反馈发布状态。

02

系统实现效果与核心算法原理

一、模式匹配算法基础概念

模式匹配是字符串处理领域的经典问题,其核心定义为:给定一个或多个子串(称为****模式串*),在一个待检测的长字符串(称为*目标串*)中找出所有与模式串完全相同的子串位置。根据模式串的数量,可将模式匹配分为单模式匹配和多模式匹配:单模式匹配仅针对一个模式串进行匹配,常用算法有 BF 算法、KMP 算法等;*多模式匹配算法****则可同时对多个模式串进行匹配,适用于文本审核中需同时检测海量敏感词的场景,是本系统的核心算法选型方向。

二、常用多模式匹配算法:AC 自动机算法

在众多多模式匹配算法中,AC 自动机算法是应用最广泛的算法之一,由 Aho 和 Corasick 于 1975 年提出,其本质是在 Trie 树(字典树)的基础上,增加了失败指针(类似 KMP 算法的 next 数组),实现了对目标串的一次遍历即可完成所有模式串的匹配,大幅提升了匹配效率。

(一)AC 自动机算法的核心优势

1.匹配效率极高:对目标串的遍历仅需进行一次,时间复杂度为 O (n)(n 为目标串的长度),模式串的数量和长度几乎不影响匹配效率,非常适合文本审核中****海量敏感词(多模式串)+ 海量待审核文本(目标串)**** 的应用场景。

2.支持批量匹配:可一次性加载所有敏感词模式串,实现对目标串中所有敏感词的同时检测,无需逐个模式串单独匹配,大幅减少计算量。

(二)AC 自动机算法固有缺点

1.内存占用量大:传统 AC 自动机基于普通 Trie 树实现,每个节点需存储字符、子节点指针、失败指针、输出信息等,当模式串数量达到十万、百万级时,节点数量会急剧增加,导致内存占用大幅上升,对服务器的硬件资源要求较高。

2.模式串初始化加载复杂:普通 Trie 树的构建过程繁琐,模式串的增删改查操作需对树结构进行大量调整,且失败指针的构建逻辑复杂,导致模式串初始化加载耗时较长,影响系统的启动效率和敏感词库的更新效率。

3.节点空间利用率低:普通 Trie 树的节点子节点指针多为稀疏分布,大量指针指向空值,造成内存空间的严重浪费。

三、系统优化算法:双数组 Trie 树 AC 自动机算法

针对传统 AC 自动机算法的内存占用问题,本团队在深入研究 AC 自动机算法和 Trie 树优化技术的基础上,调研并实现了****双数组 Trie 树 AC 自动机算法****,通过将普通 Trie 树改造为双数组 Trie 树,对原有 AC 自动机的内存占用进行了大幅优化,同时保留了 AC 自动机算法高匹配效率的核心优势,实现了 “效率与资源占用的双重平衡”。

四、双数组 AC 自动机算法核心原理详解

要理解双数组 Trie 树 AC 自动机算法,首先需掌握传统 AC 自动机算法的实现原理,其核心构建过程分为****构建 Trie 树*、*构建失败指针*、*模式串匹配*三个步骤,以下以多模式串*he、she、hers、his****为例,详细解析各步骤的实现逻辑。

(一)构建 Trie 树:基于前缀共用的树形结构

Trie 树是一种树形数据结构,核心特征为****节点共用公共前缀****,有效减少字符的重复存储,提升空间利用率。构建过程以根节点为起点,依次将每个模式串的字符逐个插入树中,每个节点仅存储一个字符,具体步骤如下:

1.初始化一个空的根节点,根节点不存储任何字符,作为所有模式串的起始入口。

2.插入第一个模式串****he*:从根节点出发,创建子节点存储字符*h*,再以*h*节点为父节点,创建子节点存储字符*e*,*e*节点为*he****的结束节点,标记模式串结束。

3.插入第二个模式串****she*:从根节点出发,创建子节点存储字符*s*,以*s*为父节点创建子节点*h*,再以*s-h*为父节点创建子节点*e*,*e*节点为*she*的结束节点;此过程中,*she*的*h-e*与*he*的*h-e****为不同分支,无公共前缀,故单独创建节点。

4.插入第三个模式串****hers*:在*she*的结束节点*e*后,依次创建子节点*r*、*s*,*s*节点为*hers*的结束节点,实现与*she****的前缀共用。

5.插入第四个模式串****his*:从根节点的*h*节点出发,创建子节点*i*,再以*h-i*为父节点创建子节点*s*,*s*节点为*his*的结束节点,实现与*he*的前缀*h****共用。

最终构建的 Trie 树中,每个节点包含****字符信息*、*子节点指针*、*失败指针*、*模式串结果长度*四大核心信息,其中*模式串结果长度****是结束节点的关键标记,用于后续匹配时快速定位模式串。

最终结构如图所示:
Image

(二)构建失败指针:AC 自动机的核心关键

失败指针是 AC 自动机实现高效匹配的核心,其作用是:当在 Trie 树中遍历目标串时,若当前节点的子节点无法匹配目标串的下一个字符,则通过失败指针跳转到另一个节点,继续进行匹配,无需回退目标串的遍历指针,实现一次遍历完成所有匹配。失败指针的构建遵循****广度优先遍历(BFS)**** 原则,从根节点的第一层子节点开始,逐层为每个节点设置失败指针,具体规则如下:

1.*根节点的失败指针为 null*,根节点的所有直接子节点(如示例中的****h*、*s*节点)的失败指针*均指向根节点****。

2. 对于其他非根节点子节点,假设当前节点为****cur*,其父节点为*parent*,*parent*的失败指针指向*p_fail****:

3. 检查****p_fail*是否存在与*cur*存储相同字符的子节点*p_fail_child****;

(1)若存在,则****cur*的失败指针直接指向*p_fail_child****;

(2)若不存在,则继续向上追溯****p_fail*的失败指针,直至追溯到根节点;若根节点仍无对应字符的子节点,则*cur****的失败指针指向根节点。

4. 所有结束节点的失败指针构建完成后,需将失败指针指向节点的输出信息与当前节点的输出信息进行合并,确保匹配时能捕获所有相关模式串。

以示例中的****she*的*e*节点为例,其父节点为*h*(*s*的子节点),*h*的失败指针指向根节点的*h*节点,根节点的*h*节点存在子节点*e*,因此*she*的*e*节点的失败指针指向*he*的*e****节点,实现匹配时的快速跳转。

(三)模式串匹配:一次遍历完成全量检测

完成 Trie 树和失败指针的构建后,即可进行目标串的匹配,匹配过程为对目标串的一次正向遍历,具体步骤如下:

1. 从根节点开始,将目标串的字符逐个与 Trie 树的节点进行匹配。

2. 若当前节点存在与目标串字符匹配的子节点,则跳转到该子节点,继续匹配下一个字符;若匹配到结束节点,则根据节点的****模式串结果长度****,从当前位置往回截取对应长度的字符,即为匹配到的模式串。

3. 若当前节点无匹配的子节点,则通过失败指针跳转到对应节点,继续匹配;若跳转到根节点仍无匹配,则继续遍历目标串的下一个字符,根节点保持不变。

4. 遍历完目标串的所有字符后,输出所有匹配到的模式串及位置信息。

例如,若目标串为****shers*,遍历过程中将依次匹配到*she*、*hers****两个模式串,实现一次遍历完成多模式串的精准匹配。

(四)接下来简单讲解双数组Trie基于普通Trie树的压缩过程

Image

核心压缩逻辑在fetch()和insert()方法中

fetch()方法目的是是获取兄弟节点

压缩过程按层顺序:

先处理 root 的所有子节点 (h, s, i)

再处理第二层节点 (e, h, s)

依此类推...

Image

Insert()方法用于双数组插入

Image
Characterhseir
code值
104
115
101
105
114

最终生成双数组结构为

压缩关键流程:

查找连续空闲位置存放兄弟节点

check[begin + sibling.getKey()] = begin 建立父子关系

叶子节点:base[pos] = -valueId - 1(负值表示终点)

characerroothe(he)h(she)i(his)ss(his)e(she)s(hers)r(hers)
index
0
106
107
108
111
117
118
119
120
224
base值
1
5
109
17
2
3
121
122
123
4
check值
0
1
5
3
5
1
2
17
4
109

(五)双数组Trie树匹配过程

Image

根据输入字符串,按顺序校验单个字符转移状态

Image

从根节点开始,根据等式next = base[current] + char + 1,计算下一节点的跳转,然后通过下一节点的check值进行校验,匹配成功则根据节点对应的emit值进行结果输出。

(六)内存优化对比

普通 Trie 树内存占用:
Image

双数组结构:

Image

内存对比:

Image

性能对比:

Image

03

系统核心技术具体实现流程

Image
一.初始化流程主要分为四步

第一步从数据库中读取对应的敏感词数据,因为客户端的文敏感词分为联合敏感词和单敏感词,先会将联合敏感词通过空格分隔,转成单敏感词+附带敏感词结构,最后统一加载到内存Map中。

第二步构建二分Trie树。

第三步将二分Trie树节点压缩成双数组Trie树。

第四步构建failure表及output表。

对应代码如下图

Image

该代码的核心逻辑为 “数据加载→树形构建→结构压缩→辅助表构建→资源释放”,通过一站式方法实现初始化流程的自动化执行,同时在最后通过loseWeight方法释放无用的中间资源,进一步降低内存占用。

二、敏感词查找过程:目标串的遍历与匹配

查找过程是系统实现敏感词检测的核心环节,核心作用是对用户提交的待审核文本(目标串)进行遍历,基于内存中构建完成的****AhoCorasickDoubleArrayTrie*结构,实现敏感词的精准匹配,并记录命中敏感词的关键信息。整个查找过程为对目标串的*一次正向遍历****,时间复杂度为 O (n),确保海量文本的快速处理,具体实现逻辑和核心代码如下:

Image
Image

(一)查找过程核心逻辑

1. 初始化遍历指针:从双数组 Trie 树的根节点(base [0])开始,目标串的遍历指针从第一个字符开始。

2. 逐字符匹配:将目标串的当前字符转换为编码值,结合当前节点的 base 值,计算子节点的下标,通过 check 数组验证子节点的合法性:

(1)若子节点合法,则跳转到该子节点,继续匹配下一个字符;

(2)若子节点不合法,则通过 failure 表跳转到失败指针指向的节点,重复上述验证过程,直至跳转到根节点。

3. 命中结果记录:若当前节点为结束节点(output 表中存在有效信息),则触发****storeEmits****方法,记录命中敏感词的关键信息,包括起始下标、结束下标、敏感词附属信息等。

4. 遍历结束:当目标串的所有字符遍历完成后,输出所有命中的敏感词信息,查找过程结束。

(二)命中结果记录核心代码解析

****storeEmits*方法是记录命中结果的核心方法,该方法接收当前匹配位置、当前节点、命中结果集合作为入参,从 output 表中读取当前节点的敏感词信息,封装为*Hit 对象****并添加到结果集合中,核心代码如下:

从代码中可清晰看出,****Hit 对象****是存储命中结果的核心数据结构,其包含三大关键信息:

1.*begin*:命中模式串在目标串中的****起始下标****,通过 “当前匹配位置 - 模式串长度” 计算得出;

2.*position*:命中模式串在目标串中的****结束下标****,即当前匹配位置;

3.*v[hit]*:命中敏感词在数据库中的****附属信息****,如敏感词等级、所属分类等。

Hit 对象的设计实现了对命中敏感词位置和属性的精准记录,为后续的结果过滤和审核判定提供了完整的数据支撑。

三、命中结果过滤:单敏感词与联合敏感词双重校验

由于本系统支持****单敏感词过滤*和*联合敏感词过滤*两类规则,因此在查找过程得到命中模式串后,还需对命中结果进行针对性过滤,确保审核结果符合平台的审核规则,避免因单独命中联合敏感词的组成部分而造成误判。过滤过程分为*两步执行****,依次完成单敏感词和联合敏感词的校验,具体逻辑如下:

1.单敏感词过滤

系统首先对命中的模式串进行筛选,分离出单敏感词和联合敏感词的组成部分。对于****无联合敏感词关联*的模式串,直接判定为*命中单敏感词****,将其相关信息(下标、附属信息、敏感词内容)存储到最终的审核结果集中,作为违规判定的依据。

2.联合敏感词过滤

对于命中的****联合敏感词组成部分*,系统将其单独存储在一个临时 Map 集合中,该 Map 的键为联合敏感词的标识,值为其组成部分的命中位置和信息。随后,系统遍历该临时 Map 集合,按照联合敏感词的预设规则(如词汇组合、位置关系、逻辑关系等),校验是否存在*完整匹配的联合敏感词****:

若存在完整匹配的联合敏感词,则将其信息存储到最终的审核结果集中;

若仅命中联合敏感词的单个组成部分,未形成完整的违规组合,则判定为未命中,不加入结果集。

通过上述两步过滤,系统实现了对单敏感词和联合敏感词的精准判定,有效避免了联合敏感词的误判问题,提升了审核结果的准确性。

四、审核结果返回:标准化数据格式输出
Image

可以输出命中的敏感词集合,敏感词等级,敏感词在输入字符串中的起始下标,结束下标。

五、系统线上运行核心指标

本系统经过算法优化和工程实现后,在实际线上运行中表现出优异的性能,核心运行指标如下,完全满足新闻客户端海量文本的高效审核需求:

1.敏感词量级:支持 20 万级敏感词库的稳定加载和匹配,可根据业务需求灵活扩展至百万级;

2.单机内存占用:20 万级敏感词库在单机上的内存占用仅为 80M,相较于传统 AC 自动机算法,内存占用降低 70% 以上;

3.审核接口耗时:审核接口的 P99 耗时仅为 3ms(即 99% 的审核请求响应时间在 3ms 以内),实现了海量文本的毫秒级审核;

4.日均处理量:单台服务器可支持日均亿级文本的审核处理,满足新闻客户端高并发的内容发布需求。

04

系统应用拓展

本系统基于双数组 Trie 树 AC 自动机算法实现的高效文本内容审核功能,不仅在新闻客户端的文本审核场景中实现了优异的效果,还凭借****高匹配效率、低内存占用、易扩展、易部署****的技术优势,实现了多场景、多领域的应用拓展。同时,双数组 Trie 树 AC 自动机作为一种高效的多模式匹配算法,其技术价值不仅局限于文本审核,还可在其他字符串处理场景中发挥重要作用,为相关领域的技术研发提供新的思路。本节将详细介绍系统的应用场景拓展和算法的技术延伸方向。

一、文本审核系统的多场景应用

目前,本客户端文本审核系统已成功部署并应用于互联网平台的****多个文本处理场景****,实现了全场景、全链路的内容审核覆盖,为平台的内容治理提供了一体化的解决方案,具体应用场景如下:

1.用户评论审核.

2.活动文案过滤

3.AI 模型输出校验

4.直播弹幕审核

5.私信 / 聊天内容审核

6.文章 / 资讯发布审核

二、双数组 Trie 树 AC 自动机算法的技术延伸应用

双数组 Trie 树 AC 自动机算法作为一种高效的多模式匹配算法,其核心优势是****一次遍历、多模式匹配、低内存占用、高匹配效率*,除了文本审核场景外,还可广泛应用于*各类字符串处理和数据检索场景****,为相关场景的性能优化提供技术支撑,具体延伸应用方向如下:

低成本高效搜索场景,垃圾邮件拦截场景,网络入侵检测场景输入法智能联想场景。

三.双数组 Trie 树 AC 自动机算法**与大模型实现适用场景对比

✅ 适用双数组 Trie 的场景

·明确关键词匹配(敏感词过滤、违禁词检测)

·高性能要求(QPS > 10000,响应 < 10ms)

·资源受限环境(内存 < 1GB,无 GPU)

·规则明确的场景(白名单/黑名单系统)

·实时流式处理(Kafka 消息过滤)

✅ 适用大模型的场景

·语义理解(情感分析、意图识别)

·上下文推理(对话系统、问答系统)

·模糊匹配(同义词、隐喻、暗示)

·生成任务(文本生成、摘要、翻译)

·复杂决策(内容质量评估、风险综合判断)

后续可以在现有审核系统基础上加上离线大模型分析,实现高效且多维度的审核系统。