2017 年 5 月

第 32 卷,第 5 期

认知服务 - 使用 Microsoft 内容审查器保护 Web 应用

作者 Maarten Van De Bospoort | 2017 年 5 月

每天有数十亿的用户在社交媒体上分享所拍摄的照片和视频。任何处理 Internet 上用户生成内容的人员都知道,网络匿名未必会让文明的人类行为显现出来。 

另一非常重要的最新趋势就是聊天机器人的激增。每天都有一套新的机器人诞生,它们可以执行各方面的任务,包括预订旅行、协调会议和网上银行。这些机器人的实用性是毋庸置疑的,但杀手级聊天机器人(所有信息平台为了实现每天十亿活跃用户的目标都需要使用的一类机器人)仍遥不可及。

现在,假设你创造出了这样的机器人: Butterfly(即所有人都觉得有必要与其进行交互的机器人)。用户可以与机器人共享媒体,机器人可以通过秘密机器学习算法预测用户在未来 24 小时内的行为。经过一年的努力工作,你发布了自己的机器人。而在一夜之间,Butterfly 感染了病毒。遗憾的是,你的创业梦想很快就变成了一个公关噩梦。用户在提交挑逗性的成人内容,这些内容随后被共享并公开给其他机器人用户。其中一些内容很糟糕。非常糟糕。用户在起诉你,电话在响个不停,你还收到自己的 Web 服务将被关闭的威胁。你需要使用一个功能强大的解决方案,帮助你检测不当内容,并阻止向其他用户显示这些内容。并且需要立刻就用上。

在这种情况下,Microsoft 内容审查器就派上用场了!

本文将介绍内容审查器可以帮助你完成哪些事项。首先,我们会使用 Microsoft Bot Framework 创建一个聊天机器人。不过,请注意,相关信息同样适用于所有 Web 或客户端应用程序。Butterfly 会允许最终用户共享文本、图像和视频,并且会在发布前使用内容审查器筛选掉不当内容。在此过程中,你将了解如何配置自定义内容审查器工作流,并调整内容分类器阀值。我们还将介绍可以在工作流中使用的不同连接器,如“文本”和“儿童剥削”。首先,让我们来了解一下内容审查概述。

内容审查

一直以来,Microsoft 在打击数字犯罪方面具有良好的过往表现。Microsoft 反数字犯罪部致力于移除僵尸网络、限制技术支持欺诈、挫败钓鱼计划等。此部门有一个活跃工作领域不太引人注意,就是协助世界各地的执法机构遏制儿童剥削。自 2009 年起,Microsoft 就开始提供 PhotoDNA 免费服务。如今,同一团队还在内容审查领域表现活跃。

内容审查是计算机可以为人类提供许多帮助的计算机学习领域。用户生成数据量实在是太多了,因此无法通过极具成本效益的方式进行快速人工评审。更重要的是,内容审查这项活动令审阅者感到不舒服。若要大概了解一些背景信息,请访问 tcrn.ch/2n1d9M0

内容审查 API 属于 Azure 中运行的一组不断扩充的 Microsoft 认知服务 API。这些 API 全都是机器学习模型的具体实现代码。也就是说,Microsoft 使用了大量数据来定型这些模型。作为开发者,无论是为了执行计算机视觉、说话人识别还是语言理解(此外还有很多,我们不一一赘述),只需调用其中一个 API 即可获得结果。内容审查器图像 API 利用图像识别,这是近年来取得了很大进展的机器学习领域。

图 1 展示了如何设置内容审查器管道。你可以根据需要,调用不同的内容审查 API,包括审查、评审和提高自定义程度的作业。例如,调用工作流 API,可以编程方式修改用于作业的工作流。接下来,可以看到图像、文本和视频以及 儿童性侵内容 (CSAM) 的不同分类器。PhotoDNA 是有助于组织遏制这些图像传播的技术。CSAM“分类器”的工作原理与我先前提到的分类器略有不同: PhotoDNA 运用哈希和匹配技术与已知图像的数据库进行比较。在内容审查器中,可以设置连接多个筛选器的工作流(例如,首先检查是否有 CSAM,然后检查图像中是否有成人/挑逗性内容)。工作流还可以邀请审阅者进行评审。最后,内容审查器管道非常灵活,未来可能还会包含其他 API。

用户内容流经内容审查器,其中机器学习模型与审阅者协作,共同筛选掉不当内容
图 1:用户内容流经内容审查器,其中机器学习模型与审阅者协作,共同筛选掉不当内容

审查用户内容

至此,你已对审查技术有了一定的了解,现在让我们将此类技术应用到 Butterfly 机器人中。我们将使用 Microsoft Bot Framework 生成机器人,对 Butterfly 使用 Node.js 版本的 Bot Framework。由于所有这些 API 都只是 REST API 调用,因此可以轻松执行内容审查(就像通过 C# 进行审查一样轻松);实际上,此操作可以说是更容易了,因为有内容审查器 .NET SDK (bit.ly/2mXQqQV)。 

本杂志已有好几篇文章对机器人进行了精彩概述。强烈建议在尚未生成机器人的情况下参阅以下文章:

或者,请参阅 dev.botframework.com 上的快速入门,它可以让你快速上手。

在本文中,我们将使用适用于 Node.js 的简单入门解决方案。我们使用 Node.js 框架提供的对话模型,将对话划分到单独的对话中。在图 2 所示的对话代码中,机器人要求用户提供第一个函数中图片的 URL。然后,控件会回传给用户。当用户发送一些文本时,对话流会将用户输入传递给第二个函数。然后,机器人会转发用户输入,以供在 moderate.js 中进行评估。在第一次尝试中,我们调用的是简单的审查器 API(而不是更为复杂的评审和作业 API)。

图 2:对话代码

bot.dialog('/moderateImage', [
  function (session, args) {
    builder.Prompts.text(session, 'Give me a picture URL to moderate, please.');
  },
  function (session, results){
    var input = session.message.text;
    var cm = require('./moderate.js');
    cm( 'ImageUrl', input, function(err, body) {
      if (err) {
        session.send('Oops. Something went wrong.');
        return;
      }
      var output = JSON.stringify(body);
      session.endDialog(output);
    });
  }
]);

必须提供凭据,才能调用内容审查器 API。可以从内容审查器网站或 Azure 获取凭据。在本文中,我们将采取后一种获取方法。在 Azure 门户 (portal.azure.com) 中,单击绿色加号,然后指定“认知服务”,从而新建一个认知服务帐户。单击“创建”后,指定“内容审查器”作为 API 类型(见图 3)。使用 F0 层,因为它是免费的,并且允许每秒调用一次,这对于目前的使用来说应该已经足够了。创建帐户后,在“资源管理”中的“密钥”下方找到帐户名和密钥。请注意,稍后将使用其中一个密钥和资源 ID 字符串(在“属性”中),将内容审查器 API 连接到内容审查器评审门户。

从认知服务列表中选择内容审查器
图 3:从认知服务列表中选择内容审查器

Azure 门户还会显示终结点 https://westus.api.cognitive.microsoft.com/contentmoderator。虽然这是正确的基本地址,但有点太短了。有关完整的终结点,请参阅内容审查器文档。

图 4 所示,我们指定“URL”作为 DataRepresentation 来发送图片 URL,但也可以轻松发送 blob 中的图像。调用审查器 API 后,返回的结果正文包含带图像得分的 JSON。得分范围介于 0.0(正常)到 1.0(非常成人/极具挑逗性)之间。

图 4:向内容审查器发送图片 URL

var unirest = require("unirest");
var url = "https://westus.api.cognitive.microsoft.com/contentmoderator/
  moderate/v1.0/ProcessImage/Evaluate";
module.exports = function(input, cb) {
  unirest.post(url)
    .type("json")
    .headers({
      "content-type": "application/json",
      "Ocp-Apim-Subscription-Key":<Key from the Azure portal>,
    })
    .send({
      "DataRepresentation": "URL",
      "Value": input
    })
    .end(function (res) {
      return cb(res.error, res.body );
    });
};

可以看到,结果(如图 5 所示)包含成人和挑逗性预测得分,以及有关是否达到分类标志中设定阈值的结论。让人高兴万分的是,只需在机器人中插入这几行代码,就可以拦截所有挑逗性或成人内容。将新版本的机器人部署到 Azure 中,用户再次蜂拥而至来咨询你的 Oracle 机器人。大功告成。你和你的团队对结果非常满意,围着生啤保鲜机,喝着生啤进行庆祝。

图 5:图像的成人和挑逗性分类分数

"AdultClassificationScore":0.0324602909386158,
"IsImageAdultClassified":false,
"RacyClassificationScore":0.06506475061178207,
"IsImageRacyClassified":false,
"AdvancedInfo":[],
"Result":false,
"Status":{
  "Code":3000,
  "Description":"OK",
  "Exception":null},
"TrackingId":"WU_ibiza_4470e022-4110-48bb-b4e8-7656b1f6703f_
  ContentModerator.F0_3e598d6c-5678-4e24-b7c6-62c40ef42028"

才刚刚尝了两口微酿的 IPA 啤酒,手机便开始不断振动显示 Tweet 消息。一大批愤怒的客户如潮水般涌来: “为什么要拦截我的正常图片?“我哥哥的更加裸露的图片都可以通过。必须解决这个问题!”

图像分类本身没有问题,但没有一个放之四海而皆准的衡量标准。我们刚刚使用的内容审查器 API 显然可以协助审阅者做出明智的决定,但它们并非完美无瑕。我们已做出的一项改进是,使用原始分数,而不是判断是否属于成人和挑逗性内容分类来优化审查。此外,用户似乎往往还会重复使用相同的图像。幸运的是,内容审查器提供了列表 API,用于管理一组已经过筛选的自定义图像或文本。审查器 API 会对图像进行一定的模糊匹配,以防用户通过稍作修改或重设大小轻易蒙混过关。这很好地改进了第一种方法,但仍无法排除支持人员需要处理的误报。和以往一样,在处理更为棘手的难题时将人工和计算机相结合将会得出最佳解决方案。计算机视觉可有助于检测图像明显是/不是挑逗性或成人内容的极端情况。对于介于中间的边缘情况,我们人类可以针对具体场景确定内容的分类。这便是内容审查器评审工具和 API 的优势所在。让我们来看看如何使用它来改进我们的解决方案。

调用审查器评审 API

到目前为止,方法一直都非常简单: 发送一张图片,然后根据内容审查器标签来确定是否拦截它。现在,我们将扩展解决方案。我们的想法是设置如图 6 所示的流。

与内容审查器工作流协同工作的 Butterfly 机器人
图 6:与内容审查器工作流协同工作的 Butterfly 机器人

在这种情况下,用户会先向 Butterfly 机器人发送一张图像。在第 2 步中,机器人的 Web 服务会使用评审 API 的作业操作(需要使用工作流 ID 参数)将图片发送给内容审查器。我们将在评审工具中设置此工作流。我们的具体工作流(第 3 步)是立即允许得分低于特定成人/挑逗性分数(例如,0.7)的所有图片通过,并标记得分超过特定限制(如 0.9)的其他图片。我们的机器人会允许得分低的内容通过,并拦截明显极具挑逗性或非常成人的内容。对于介于两者之间的边缘情况,我们希望将内容转给评审工具以供审查人员检查(第 4 步)。然后,我们的审阅者团队就可以决定如何处理这些内容。评审结束后,内容审查器会回叫我们的机器人应用服务,从而共享结果。此时,机器人可以移除标记为攻击性内容的内容。请注意这样做带来的灵活性。可以在工作流中调整分数,而且审阅者可以决定对于特定应用而言什么是适当内容。

首先,需要在 bit.ly/2n8XUB6 上注册内容审查器评审工具。可以使用 Microsoft 帐户或创建一个本地帐户进行注册。接下来,网站会要求你创建一个评审团队,负责评审属于边缘情况的内容。可以创建多个子团队,并创建将评审作业分配给不同子团队的工作流。在门户“设置”页的“凭据”选项卡中,可以将内容审查器设置与之前创建的 Azure 认知服务资源关联起来。只需将密钥和资源 ID 从 Azure 门户复制到审查器 UI 中的“订阅密钥和资源 ID”设置中即可。首次创建帐户时,你会获得一个自动配置的“默认”工作流。正如在评审 UI 中所见,此工作流会在发现成人图像时创建人工评审。让我们从在评审 API 的作业操作中使用此工作流入手。

若要调用评审作业 API,请使用图 7 中所示的代码。

图 7:调用评审作业 API

var url = 'https://westus.api.cognitive.microsoft.com/contentmoderator/
  review/v1.0/teams/butterfly/jobs';
var req = unirest.post(url)
  .type("application/json")
  .query({
    ContentType: 'Image',
    ContentId: '67c21785-fb0a-4676-acf6-ccba82776f9a',
    WorkflowName: 'default',
    CallBackEndpoint: 'http://butterfly.azure.com/review'
  })
  .headers({
    "Ocp-Apim-Subscription-Key": <ocp_key>
  })
  .send({
    "ContentValue": pictureUrl
  })
  .end(function (res) {
    return callback(res.error, res.body );
});

请注意,URL 包含团队名称 Butterfly 和后缀 job。在 CallBackEndpoint 中,我们指定了内容审查器为了通知评审结果而需要调用的 REST 终结点。此外,我们还指定了唯一 Contentid,因此我们可以在内容审查器回叫时关联图像,并发送 ContentValue 中的实际图像 URL。调用成功时,结果正文不包含任何内容审查器结果。相反,结果中返回 JobId:

{"JobId":"2017035c6c5f19bfa543f09ddfca927366dfb7"}

将通过在 CallBackEndpoint 中指定的回叫获得结果。此结果同样包含 JobId(可能还包含 ReviewId)和 Contentid,以便你可以进行交叉引用。对于默认工作流,如果认为图像不是成人内容,内容审查器会立即回叫(结果包含在元数据中)。实际 JSON 如图 8 中所示。

图 8:默认工作流结果

{
  "JobId": "2017035c6c5f19bfa543f09ddfca927366dfb7",
  "ReviewId": "",
  "WorkFlowId": "default",
  "Status": "Complete",
  "ContentType": "Image",
  "CallBackType": "Job",
  "ContentId": "67c21785-fb0a-4676-acf6-ccba82776f9a",
  "Metadata": {
    "adultscore": "0.465",
    "isadult": "False",
    "racyscore": "0.854",
    "isracy": "True"
  }
}

此作业的状态设置为“完成”,并且 CallbackType 为作业。不过,如果认为图像是成人内容,内容审查器会创建评审作业,并使用标识符填充 ReviewId 字段。最后,图像会出现在评审 UI 中,以供评审团队审查(见图 9)。

包含图片和未选中标记的内容审查器评审工具
图 9:包含图片和未选中标记的内容审查器评审工具

如果能够对评审工具及其用途加以解释,将会有所帮助。评审工具专为处理大量图像而设计。审阅者会先在一个屏幕上审查所有图片,标记不符合要求的图片,然后转到下一个屏幕。评审工具为审阅者留出了几秒钟的返回修改时间,以免出现误判。在这几秒钟过后,内容审查器会保存包含最终标记的图像,并调用我们再次指定的回叫函数(现在是用于最终判断)。此时,我们可以采取相应行动(移除或发布内容,具体视我们的业务需求而定)。第二次回叫如图 10 中所示。

图 10:评审回叫结果

{
  "ReviewId": "201703367f430472074c1fb18651a04750448c",
  "ModifiedOn": "2017-03-07T18:34:17.9436621Z",
  "ModifiedBy": "Bob",
  "CallBackType": "Review",
  "ContentId": "67c21785-fb0a-4676-acf6-ccba82776f9a",
  "ContentType": "Image",
  "Metadata": {
    "adultscore": "0.465",
    "isadult": "False",
    "racyscore": "0.854",
    "isracy": "True"
  },
  "ReviewerResultTags": {
    "a": "True",
    "r": "True",
    "pt": "False"
  }
}

CallBackType 现在是评审(而不是作业),可以看到添加的 ReviewerResultTag,同时 ContentId 和 ReviewId 与第一次回叫中的结果一致。

自定义工作流

至此,我们已充分了解默认工作流,现在可以开始调整一些设置。对于 Butterfly,我们希望允许挑逗性得分低于 0.7 的所有内容通过,但拦截挑逗性得分高于 0.9 的所有内容。对于介于两者之间的任何内容,我们希望评审团队再次进行审查。因此,在工作流编辑器中,我们将新建一个工作流。

你会发现下拉菜单中有很多用于连接的选项。使用这些选项,可以构建高级工作流。例如,图像和人脸检测 API 中的光学字符识别 (OCR ) 文本。使用此工具,还可以声明评审的回叫终结点。如果在 CallBackEndpoint 中指定回叫作业 API,并在工作流中指定回叫,工作流中的回叫终结点会覆盖 CallBackEndpoint。

现在,调用评审作业 API 并指定此工作流会返回 JobId,就像调用默认工作流时一样。根据图片的挑逗性得分(在此示例中,介于 0.7 到 0.9 之间),内容审查器会再次创建评审作业,这些图像也会显示在内容审查器评审 UI 中。

最后,关于工作流有两个注意事项。第一,如果图片不符合初始作业回叫中的评审条件,我们仍必须确定图片的得分是否很高(需要拦截),或者得分是否很低(可以允许通过)。为此,必须略微重复逻辑。也就是说,操作可能会不同步。幸运的是,评审工具将工作流公开为 JSON。更棒的是,可以使用工作流 REST API 将工作流提交给内容审查器 API。稍微探究一下,便可以发现能够使用同一 JSON 让机器人逻辑和评审 UI 工具保持同步。

关于工作流的第二个注意事项与其扩展性相关。团队关注的焦点是让评审工具成为各种 API 的共同目标。转到评审 UI 中的“连接器”选项卡时,可以看到当前可用的连接器。可以通过输入相应的订阅密钥来激活这些连接器。对于 PhotoDNA,执行起来很简单。如果你的产品接收任意类型的用户内容,不妨确保不会共享儿童剥削图像。注册服务后,就可以将此轻松连接到现有工作流。一定可以避免单独调用 REST API。截至本文撰写之时,文本分析 API 和人脸检测 API 可作为连接器使用。对于这些连接器,可以转到 Azure 门户,创建认知服务(就像我们之前所做),并在内容审查器 UI 中输入订阅密钥。

总结

限于篇幅,我们无法深入探究其他高级功能。例如,可以在“设置”下创建自己的标记,以便在工作流中使用。我们创建了“pt”标记来标记文本中存在的猥亵内容。我们将在所设置的文本内容审查工作流中使用此标记。此外,工作流还可以通过备用输入来处理输入格式与限定符不一致的情况。例如,当需要通过 OCR 检测图像中是否存在文本猥亵内容时。可以注册视频审查(目前为非公开预览版)。最后,门户中预计将会显示更多连接器,以便你可以用来构建和扩展工作流。

使用内容审查器,可以对所有媒体格式的大量内容进行内容审查。内容审查器是一个平台,其中包含专为内容审查行业构建的 API 和解决方案。借助它,可以开始接触其他媒体格式,并开始使用新推出的内容审查功能。内容审查器使用基于最佳机器学习的分类器,以及每时每刻都在不断完善的其他技术。分类器改进将会自动优化结果。 


Maarten van de Bospoort 是位于雷德蒙德市的 Microsoft 开发者体验部的首席软件开发工程师。他与来自大型使用者 ISV 的开发者和架构师协同工作,共同推动 Microsoft 技术(如机器人、认知服务以及不定期推出的通用 Windows 平台应用)的采用。

Sanjeev Jagtap 是位于雷德蒙德市的 Microsoft 内容审查器团队的高级产品经理。他热衷的领域包括客户、Microsoft 技术和编程马拉松。

衷心感谢以下 Microsoft 技术专家对本文的审阅: Christopher Harrison 和 Sudipto Rakshit