做AI原生应用的同学,这两年应该都躲不开一个话题:多模态内容过滤。我在某个智能助手项目里负责安全链路时,最大的感受是——过去的文本关键词黑名单根本扛不住现在的输入形态。用户上传一张图、一段录音,或者模型自己生成一份带图回答,任何一个环节没拦住,都可能让产品陷入被动。这篇文章就把我落地多模态内容处理方案的完整思路和实操经验拆开讲,包括为什么传统文本过滤会失灵、多模态过滤管线怎么设计、阈值怎么调、成本怎么压,以及上线后踩过的那些坑,希望对正在做同类产品的同学有帮助。
这套方案适合谁?凡是AI聊天、AI绘画、智能客服、内容社区UGC上传这类涉及大模型输入输出的项目,都会遇到同样的审核需求。如果你是负责算法、后端的工程师,或者分管内容安全的同学,这篇文章的思路和配置参数可以直接拿去作参考。整体不依赖特定平台,核心逻辑在本地或者云端私有化部署都能跑。
1. 为什么AI原生应用绕不开多模态内容过滤
1.1 文本关键词过滤为什么先失灵
大多数业务最早上线的内容过滤都是从关键词黑名单开始的。敏感词表一拉,用户输入的时候匹配一下,命中就拦截。这套方案在传统UGC时代确实能用,但到了AI原生应用阶段,问题会暴露得非常明显。
第一,用户很容易绕过字面匹配。同音字、拼音、拆字、谐音、繁体简体混用,甚至把词藏在一串乱码里,静态词表很难全覆盖。我在线上见过最离谱的输入是一段正常的古诗词,每个字的声母连起来是一句违规内容,纯文本规则完全无感。
第二,我们要过滤的不只是用户输入,还有模型输出。大模型的生成结果具有不确定性,同一个安全的问题可能得到一段包含风险内容的回答,甚至触发提示注入后带着系统指令往外吐。这种情况下,关键词过滤几乎没有防御能力,因为生成内容无法提前枚举。
第三,用户输入和模型输出之间还存在“语义上下文”问题。一句“给我看一张恐怖图片”本身是正常关键词,但如果用户在对话里要求模型生成某种特定风格的图片,单看文本和单看图片都可能安全,合在一起却出问题。传统文本过滤没有能力理解这种跨模态组合语义。
1.2 多模态语境让判断变得更复杂
AI原生应用的内容形态已经远远不止文字。输入侧有图片、音频、视频、文件;输出侧有AI生成的图片、语音、甚至短视频。每种形态都需要对应的理解能力,但更要命的是跨模态的组合判断。
举一个实际场景:某AI绘画产品里,用户输入“一只猫在窗台上晒太阳”,配了一张参考图。单独看这句提示词完全正常,参考图看起来也只是一张普通照片,但通过图片隐含的拍摄地点、画面里的地标文字,可能会被识别出来,最后生成的图片就带有不该出现的信息。文本过滤无法理解图像里的内容,图像模型又不知道当前对话的语境,这就是多模态过滤要解决的核心问题。
另一个常见难点是“哪些内容需要被过滤”本身就是一个动态策略,不同行业、不同产品阶段、不同用户群体,判定标准都不一样。比如医疗健康类助手和亲子教育类应用,面对同一个词的处理方式完全不同。这意味着过滤系统不能是一堆规则写死,而应该是一套可配置的决策引擎。
1.3 多模态过滤到底解决什么
一句话概括:把文本、图像、音频、视频等多路内容统一变成“机器能判定的风险信号”,再结合业务策略输出“拦截、放行、转人工”的结论。它解决的不仅是单条内容有没有问题,还包括内容组合之后的风险、模型输出过程中的风险,以及对抗性输入的绕过风险。
我自己的经验是,多模态内容过滤不是一个模型能搞定的,而是一条链路。链路里既有快速判断的规则,也有需要调度的理解模型,还有最后的策略引擎。三者配合,才能在保证安全的同时不把正常用户体验伤害得太狠。
2. 整体架构:把文本、图像、音频、视频揉进同一条过滤链路
2.1 审核对象与决策粒度要提前定清楚
开始搭建之前,建议先把四个问题想明白,否则后面返工成本很高。
第一,审核对象是什么。用户输入、模型输出、检索到的外部资料、模型中间的推理信息,这四类要分别对待。用户输入通常要前置过滤,模型输出要后置过滤,而RAG类应用还要检查向量库里被召回的内容。
第二,审核粒度是什么。是一句话、一张图,还是一个对话回合、一组图文组合?粒度越细,定位越准,但开销也越大。我的经验是,AI原生应用至少要支持到“单轮消息”和“单张图片”这两个级别,同时保留“组合检查”的能力。
第三,决策方式是什么。不是只有“拦”和“放”两种选择。实际业务里还有“打码”“替换成安全文本”“提示用户修改”“转人工审核”“仅记录不展示”等更细的操作,决策引擎要能输出这些动作,而不是只给一个布尔值。
第四,架构模式是什么。内容过滤往往有同步和异步两条路。用户发消息时走同步过滤,响应要在几百毫秒内出结果;图片视频这类非实时内容可以走异步队列,后台慢慢审。两条路线共用一套策略引擎,但延迟预算完全不同,设计时要分开。
2.2 一条标准的多模态内容过滤链路
我最终收敛下来的标准链路分为四层:接入层、理解层、决策层、处置层。
接入层负责接收各种格式的原始内容,统一转成内部结构。比如图片转成压缩后的图像张量,音频转成固定时长的波形,视频抽帧成若干张画面,文本做统一编码。这一层还会去掉多余元信息,避免利用文件属性做对抗。
理解层是核心,不同模态分别过各自的模型。文本用分类模型加语义相似度;图像用OCR加图像理解;音频先转写再走文本通道;视频则拆成帧和音频轨道,合并判断。理解层输出的是结构化风险信号,比如“文字内容命中某类风险”“画面包含某类元素”“语义与某画像相似”。
决策层拿到这些信号后,结合业务配置的风险等级、用户类型、上下文状态,输出最终动作。这里用到的不是单一阈值,而是一套策略规则表,比如命中A类风险直接拦截,命中B类风险且用户等级低则提示修改,命中C类风险只记录日志。
处置层负责执行动作:拦截请求、替换内容、追加警示文案、打码处理,或者进入人工审核队列。
这四层拆开之后,每一层都可以单独升级。比如换更强的图像模型,只需要在理解层替换,不需要动决策规则。这是整个链路可持续迭代的关键。
2.3 不要在“每个模态单独建模”上浪费资源
一开始我犯过比较明显的错误:音频做一个专用分类模型,图像做一个专用模型,视频又单独跑一遍,结果每个模型都要维护、都要调优,效果还一般。后来想明白一个道理——多模态过滤的大部分信息是冗余的。
图像里出现违规文字,走OCR后得到的文本,完全可以直接复用文本过滤通道;音频里说了什么敏感词,转成文字后也可以走同一个文本通道;视频就是图像加音频的组合,本质上是多个模态特征的叠加。所以真正核心的两个能力是:跨模态特征抽取和语义匹配。我最终只保留了一个多模态Embedding模型,用来把图像和文本映射到同一个向量空间,再加上一个OCR模型和一个语音转写模型。剩下的判断逻辑,全部收敛到文本语义和图像语义两个维度上。
这样做的好处非常直接:模型数量少了,推理成本降了,维护负担轻了,策略也可以统一描述,不用每个模态单独写规则。
3. 实操指南:从零搭建一套多模态内容过滤服务
3.1 先在请求链路里确定两个过滤端点
我强烈建议在系统设计阶段就把“输入前过滤”和“输出后过滤”两个端点都做上。
输入前过滤的作用是拦截恶意请求,降低模型被注入和消耗算力的风险。用户提交消息后、进入大模型推理之前,过一道文本和图像检查;命中高风险就中止请求。这里的关键是速度要快,因为大模型推理本身已经很慢,不能因为审核再把首字延迟拉高。
输出后过滤的作用是兜底,因为模型生成内容无法完全预测。大模型返回结果之后,在把内容推给用户之前再跑一次检查。生成的长文本要分句检查,AI绘画生成的图片要单独过图像审核,语音输出则先转写再判定。
两个端点的过滤逻辑可以共用,但阈值可以不一样。比如输入侧容忍度低,稍微可疑就拦截;输出侧可以稍微放宽,优先保证正常用户不被卡太狠,但对确定有问题的硬性拦截。
3.2 文本与图像预处理的具体手法
文本预处理是过滤链路的基石,做得好能省掉后面很多无效计算。我实际采用的流程是:统一转小写,繁体转简体,全角转半角,去掉零宽字符和不可见控制字符,对URL做脱敏,把连续标点和换行压缩成一个。对乱序或者拆字的情况,用分词后的单字再组合成N-gram,交给语义模型判断。
这一层的重点是“归一化”而不是“穷举关键词”。关键词表永远补不完,但把文本变成模型更容易理解的形态之后,语义模型能覆盖大部分变体。
图像预处理相对简单但容易忽略。图片上传后先统一做缩略图,长边压到1024像素以内,保持宽高比;格式统一转成RGB,去掉EXIF信息,避免恶意附加数据。如果要做OCR,用放大低分辨率区域的技巧提高识别率。对视频抽帧时,不是均匀抽帧,而是根据场景切换点抽关键帧,否则一个长时间不动的画面会抽出一堆重复帧,浪费算力。
3.3 多模态特征抽取与风险判定怎么做
理解层最核心的是特征抽取。我用一个图文双塔模型把文本和图像都映射到同一个向量空间,这样“一张图片”和“一段描述”能够直接算相似度。做法是:上线前准备一批风险画像样本,比如危险动作、违规物品、争议场景等,每个画像生成对应的文本描述和图片示例,统一过模型得到基准向量。
线上请求进来后,把用户内容也过一遍模型拿到向量,再和基准向量做余弦相似度。相似度越高,风险越大。再配合一组分类器,比如“是否包含敏感文字”“是否包含OCR识别出的风险词”“整体视觉风险分”,综合得出风险分数。
风险分数不能只看一个值。最稳的做法是给每个风险类别单独算分,再按当前业务策略加权。比如一个内容社区对视觉风险更敏感,那图像分类权重就高一些;一个语音助手对音频转写文本更敏感,那文本通道权重就高一些。
3.4 策略配置示例与阈值选择
我习惯把策略做成可热更新的JSON配置,而不是写死在代码里。下面是一个简化示例,可以直接参考:
{ "risk_classes": [ {"name": "violence", "enabled": true, "threshold": 0.72}, {"name": "text_policy", "enabled": true, "threshold": 0.80, "min_length": 5}, {"name": "visual_adult", "enabled": true, "threshold": 0.68} ], "actions": { "high": "block", "medium": "mask", "low": "pass" }, "filters": { "input": { "enabled": true, "high_threshold": 0.75, "block_when_any": ["violence", "visual_adult"] }, "output": { "enabled": true, "high_threshold": 0.80, "block_when_any": ["violence"] } } }这里的阈值选择是实践出来的,不是拍脑袋。我的经验是,新业务刚开始可以把阈值调低一些,宁可多拦一点,保证安全不出事;然后连续跑一周,看误杀率,如果“用户投诉被拦截”的比例太高,再逐步把阈值往上提0.02到0.05。一次不要调太多,否则漏检风险飙升。
另外一个很重要的细节:输入侧和输出侧的阈值必须分开。输入侧可以更严格,因为用户被拦住后可以换个说法重新输入;输出侧如果大量拦截,会严重挫伤用户体验,所以要谨慎。
4. 性能与成本:怎么让过滤服务不拖垮主业务
4.1 用“级联过滤”控制推理次数
多模态模型推理是很贵的,如果所有内容都上完整链路,成本直接爆炸。我的解决思路是做一个判断漏斗,从便宜到昂贵逐级过滤。
第一级是低成本的硬规则,比如URL黑名单、文件类型拦截、关键词快速匹配,这些操作毫秒级完成,能挡住很大一部分明显违规的输入。第二级是轻量模型,比如文本分类小模型、OCR模型,成本可控,能识别出大部分常规风险。第三级才是跨模态向量比对,只有在前两级都拿不准的情况下才调用。
我测算过,大部分线上请求其实在第一级就已经有了结论,真正需要跑大模型的只有一小部分。这样整体平均延迟能控制在几十毫秒以内,不会给用户明显感知。
4.2 缓存、批量与异步的实战经验
内容过滤有很多重复计算可以省掉。文本和图片都做特征缓存,同一个用户反复提交类似内容时直接命中缓存,不需要重新推理。图片以内容哈希作为缓存键,但要小心对抗性扰动会改变像素级哈希,所以我会同时存一个感知哈希,对压缩、调色更鲁棒。
对于视频这类耗时较长的内容,走异步队列比较合适。用户上传后先返回“审核中”,后台任务去抽帧、转写、打分。等到结果出来再决定是公开还是仅自己可见。这样避免用户被长时间卡在等待结果上,同时后端也能用批量推理提升GPU利用率。
4.3 过滤质量与用户体验的平衡
安全和体验之间的冲突,最终一定是靠策略配置和产品交互共同消化。我见过很多项目一上线就把阈值拉到很严,结果用户正常输入也被拦截,社区瞬间涌现大量投诉。
比较好的做法是给用户留出“申诉”和“修改”的路径:当一条内容被拦截时,返回的结果不是冷冰冰的“内容违规”,而是告诉用户哪一类内容触发了限制,并引导用户修改。这样即使过滤出现误判,用户也能理解是规则问题,而不是产品故障。
另外,对“疑似但不确定”的内容,与其硬拦截,不如走“仅自己可见”或“异步审核”的中间态。等人工审核确认后再对外展示,既保证安全,又不打断用户创作流程。
5. 常见问题与排查技巧实录
5.1 图像内容命中低、误杀高怎么办
图像误杀最常见的原因是OCR把画面中的正常文字识别成了风险词,比如商标上的文字、海报上的标语。我踩过这个坑之后,处理办法是把OCR结果和图像语义分开判断:OCR只负责提供文字来源,风险判断要考虑这个文字是不是画面主体。如果OCR识别出的词只是背景里很小的一个元素,权重就要调低。
另一个问题是图像缩略图导致细节丢失,比如很小的一行字在压缩后根本看不清。解决方案是分级压缩,先跑一遍低清检测,命中可疑区域后,在原图上裁剪对应区域做高分辨率OCR。
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| 正常图片被拦截 | OCR把背景文字误判 | 查看OCR置信度和文字占比 |
| 违规图片漏检 | 压缩后细节丢失 | 改用原图局部再检测 |
| 反复出现不同图片但同风险 | 特征向量未覆盖 | 补充对应风险画像样本 |
5.2 对抗性输入与伪装的图片怎么防
对抗样本是内容过滤绕不开的难题。用户会尝试在图片上添加轻微噪声,让模型看不出风险;也会把文字藏在很复杂的背景纹理里,让OCR失效。面对这些情况,我的经验是不要指望单点模型完美,而是靠多层信号互相印证。
图片人眼看着可疑,但OCR完全识别不出,这时候就要靠图像分类模型的直接视觉判断兜底。反过来,如果图像分类模型分数不高,但OCR识别出了大量风险词,也要提高风险等级。两者都不高,但文本Prompt里出现了明确要求“绕过检测”的指令,更要直接拦截。
对抗样本的防御也依赖持续运营。我会定期从线上被绕过或者被举报的内容里抽取样本,加入训练集并重新生成风险画像向量,这样才能跟上对抗节奏。
5.3 模型输出内容漏检怎么办
模型输出漏检是AI原生应用里最隐蔽的问题。因为生成内容不是固定的,今天这个词安全,明天模型可能换个说法生成相似内容,纯静态规则根本追不上。
我最后采取的是“生成内容分路审核”的方案:长文本按段落拆开,每段独立打分,任何一个分段命中高危就拦截全文;图片生成结果必须过图像通道,同时把用户原始PrompT和生成图片做一次跨模态相似度检查。如果Prompt本身正常但生成图片异常,说明模型已经被诱导,要立即对会话上下文做更严格处理。
5.4 日志、监控与可观测性怎么补
过滤服务上线之后,最难的不是开发,而是怎么判断它到底有没有在正常工作。建议至少从四个维度埋点:决策分布、拦截率、误杀率、模型耗时。
拦截率突然升高,先看是不是新策略误伤了正常内容;模型耗时异常升高,看是不是输入图片过大或者GPU负载过高;误杀率则需要每天抽看人工复核标记的样本。我习惯给每条审核请求打一个traceId,串起原始内容、中间特征、规则命中、最终动作、人工复核结果,排查问题的时候效率会高很多。
6. 写在最后:个人实操中的几点体会
6.1 上线前先做红队测试
我在某个项目上线第一版过滤服务的时候,内部自己先组了个“红队”,专门尝试用各种方式绕过系统。结果第一天就发现了十多个漏洞:图片里藏字、文本拆成多段、语音里夹杂方言……这些问题如果等到线上被用户发现,会很被动。红队测试不一定需要很复杂的工具,几个同事用手机、电脑、常见软件就能模拟很大一部分攻击路径。关键是测试要贴近真实用户习惯,而不是只在标准样例上验证。
6.2 安全不是一道过滤接口,而是一条持续运营的链路
内容过滤这个事,很多人以为接一个审核API就完了,实际上真正的工作量在持续调优。用户对抗手段在变,模型生成模式在变,业务策略也在变。我一般会保留一个日报,每天看拦截数据、误杀数据、转人工数据,每周更新一次风险画像样本,每两周微调一次阈值和规则。没有持续运营的过滤系统,上线一个月之后基本就会开始失效。
最后一个小技巧:如果条件允许,把“误杀后用户申诉成功”和“漏检后被用户举报”这两类样本单独存好,这是过滤系统长期迭代最宝贵的训练素材。做安全链路没有一劳永逸的方案,但把这套数据闭环跑起来,至少能保证系统会越用越准。