我做了一个深度学习驱动的表情符号Slackbot

2020-07-24 04:10:05

当我在加州大学伯克利分校(UC Berkeley)完成计算机系统博士论文时,我经常想知道人工智能世界的生活是什么样子。我的人工智能朋友们不断吹嘘深度学习将如何彻底改变从医学到网购的一切-他们的论文一发布就获得了100个引文(见鬼!)。但我一直在想,他们实际上是如何使用人工智能来解决真正的问题的。

与此同时,我最近注意到,我把大部分时间都花在回应Slake的对话上。受到最近一篇博客文章的启发(我经历了很多论文写作的冷漠),我决定建造并部署一个深度学习驱动的Slackbot,用最合适的表情符号自动添加对Slake帖子的反应。😃👍。

在这篇文章中,我讲述了我建造这个由DeepMoji驱动的Slackbot的经历。我最终使用两个不同的框架(AWS SageMaker和Algmia)部署DeepMoji。在这里,我将比较我使用这两个系统的经验,强调预测服务系统的一些优点、局限性和改进机会。这篇文章是相当高层次的,但是这个资源库有详细说明和代码的链接,可以重现我的Slackbot。

就我个人而言,我在过去的几年里一直在研究可伸缩的云系统。我特别兴奋能投入到这项任务中来,因为我们最近花了一些时间来考虑可伸缩的预测基础设施。也就是说,我绝对不是人工智能系统方面的专家,所以如果我在这里遗漏了什么,请告诉我。

设置Slackbot相当简单,但需要在Slake网站上进行大量点击。我在这里用一些屏幕截图记录了这个过程,但在更高的层面上,我创建了一个机器人,将它链接到我的工作区,并授予它查看消息和添加表情符号反应的权限。

下一步:选择一个机器学习模型,让我的Slackbot用表情符号对文本做出反应!

那么,我应该调用什么人工智能魔法呢?我没有训练模型的数据,但幸运的是,有大量预先训练好的模型可以重新使用。我的AI同事告诉我,这是模型设计的一个新兴趋势:从现有的模型开始,根据你的任务进行微调。在我的例子中,DeepMoji模型做的正是我需要的,并且已经经过培训并且是开源的。

作为一点背景知识,DeepMoji接受了12亿条带有表情符号的推文的培训,以理解语言情感及其与表情符号的关联。我的用例非常简单:向模型发送一条松弛消息,并使用模型认为最能反映消息情绪的表情符号作出反应。

坏消息:DeepMoji使用Python2(讨厌)。好消息:HugginFace的好心人开发了torchMoji,这是一个支持Python3的DeepMoji的PyTorch实现。TorchMoji代码库有一个bug,我必须修复它才能正确解析PackedSequencePyTorch对象。工作版本可以在我的叉子上找到。这部分只需要一台笔记本电脑,所以如果你感兴趣的话,可以在家里跟着看。

修复错误后,很容易获得经过训练的模型。首先,我以软件包的形式安装了torchMoji:

我需要模型权重和词汇文件来初始化模型。词汇文件已经在repo中(这里)。要下载重量,我运行:

现在已经下载了所有先决条件,做出预测只需要几行Python代码:

下一步:将其转换为具有REST Web接口的预测服务,我的Slackbot可以调用它!

提供预测服务是此场景中的系统挑战;将使该机器人实际工作的操作引擎。重要的问题是,预测服务应该住在哪里?

一个草人解决方案是将我上面编写的预测脚本包装在一个Flask服务器中,然后使用像ngrok这样的工具在我的笔记本电脑或EC2实例上生成一个REST端点。问题是我想把这个机器人部署到我实验室的Slake团队,这样每个人都可以玩它,所以这个机器人需要始终在线和可伸缩。

因此,我需要一些真实的东西,作为一名系统黑客,我有一部分想从头开始构建服务:将我的脚本打包到Docker映像中,启动Kubernetes集群,并通过AWS ELB公开REST端点。

另一方面,作为一名研究人员,我不想重新发明轮子,我知道像谷歌、亚马逊和微软这样的云提供商都提供预测服务。首先想到的平台是AWS SageMaker,这是AWS上的一项托管服务,涵盖了从模型开发到部署的整个机器学习生命周期。团队在SIGMOD‘20上发布了一篇关于SageMaker的论文,我多年来一直在使用AWS服务进行研究,所以我认为这一定是合理的。我没有意识到我正在步入深渊…。

我以为在SageMaker上部署模型会很简单。我已经有了一个Python依赖项列表和上面显示的预测脚本。我所要做的就是将脚本、依赖项和模型上传到SageMaker,创建一个REST端点,并将其连接到Slackbot。

但可惜的是,无法将模型上传到SageMaker。相反,我必须构建一个安装了所有Python依赖项的Docker映像。我还必须编写一个Flask服务器来包装我的预测脚本,并响应SageMaker的健康检查和模型调用请求-您可以在这里看到文档,在这里可以看到Dockerfile,在这里可以看到我的Flask服务器。这并不是那么复杂,但如果我不熟悉Docker和Flask,我可能需要一段时间才能弄明白这一点。

我已经使用Docker很多年了,但是我在人工智能领域的朋友们对此了解不多。你如何看待Docker:建造集装箱是人工智能的最新水平吗?人们对此很熟悉吗?

我开始想知道SageMaker为我做了什么。如果我要做这一切,为什么不运行我自己的Kubernetes集群呢?这甚至可能更简单,因为Kubernetes会自动为我做健康检查!

SageMaker不支持DockerHub,所以一旦我构建了Docker镜像,我就不得不将它推送到Amazon自己的Docker注册中心-AWS ECR(弹性容器注册中心)。接下来,我创建了一个SageMaker模型,它拉出这个Docker映像和一个使用我的模型的SageMaker“端点”。这需要选择节点类型(ml.m4.Large)和集群大小。最后,我可以创建我的REST端点!

在等待我的服务启动10分钟后,我非常兴奋地看到状态从“正在创建”变为“正在服务”,并带有一个绿色的复选标记。✅太棒了!我将端点URL复制粘贴到我的Slackbot配置中,准备好让实验室中的每个人眼花缭乱。和…。SLACK显示此错误:

该排除SageMaker故障了!我必须使用boto3(具有适当的权限)编写一个Python脚本,并进行InvokeEndpointcall来测试端点。使用此脚本调试半小时后,我发现端点本身实际上工作正常。真正的问题是,SageMaker只能从AWS虚拟专用集群内部访问,不应该接受来自外部互联网的请求,因此Slake无法访问它!

根据这篇博客文章,解决方案是“简单地”使用AWS的API Gateway服务接受来自Slake的流量,将请求路由到对请求进行身份验证的AWS Lambda函数,然后使用Lambda将预测查询发送到SageMaker。什么?!?这需要一个架构图:

这是一些疯狂的重定向,而我想做的就是让我的模型可以从网络上访问!好的所以…。该编写Lambda函数了。我总是为有机会使用无服务器系统而感到兴奋--毕竟这一直是我大部分研究的重点--但这一次比我预想的要复杂一些。

实际上,这比我预想的要复杂得多。在实际调用SageMaker模型(第47-52行)之前,我必须响应Slake的“挑战请求”(第24-29行),验证每个请求以抵御黑客(第31-37行),并从输入HTTP请求中显式解析文本字段(第38-43行)。最后,在第55行,我使用Slack Python API客户端向输入消息中添加了一个响应。

到目前为止,我还略过了一些其他值得注意的事情:

我必须使用sagemaker:InvokeEndpointpolicy创建一个IAM角色(AWS的安全和身份验证服务),并将其分配给Lambda函数,以便它可以查询我的SageMaker端点。

在使用Slake API客户端时,我必须提供bot的OAuth访问令牌(第13行)和签名秘密(第15行),这对每个Slackbot都是唯一的。

我必须显式地将第三方Python依赖项(Slake SDK)和Lambda函数脚本打包到一个zip文件中,并将其上传到AWS Lambda。详情请看这里。

等等,所以…。真的,SageMaker为我做了什么?我已经为我的模型构建了一个Docker容器,有效地编写了一个代理服务,手动验证了每个请求,并且还需要设置一个单独的REST端点。也许用EC2和Kubernetes手工操作会更容易?

最后一步是创建一个API Gateway,它将订阅消息从Slake路由到我的Lambda函数。一路上,我掉进了一些我想象中的常见陷阱。例如,我忘了选中use Lambda proxy Integration框,所以API Gateway在将每个请求转发到Lambda时都去掉了HTTP头。这会导致身份验证失败,因为Slake会将其令牌嵌入标头中。我已经记录了这里的所有(许多)步骤,这样您就不会重复我的错误了。

无论如何,这一切又花了一个小时来调试,但是API Gateway最终生成了一个真正的REST端点。我将端点粘贴到我的Slackbot订阅中,它终于起作用了!我在Slake工作区向我的机器人发送了一条消息,得到了回应。😎。

哇!我花了6个小时才把所有的碎片拼凑在一起,但它终于起作用了!每个请求需要几秒钟,即…。嗯,互动性不是很强。考虑到上面的“架构图”中显示的流量,这并不令人惊讶。这些服务中的大多数没有针对延迟进行优化。

总而言之,在SageMaker上部署torchMoji是一件痛苦的事情。更糟糕的是,在所有的努力之后,每个请求花费了超过一秒的时间!更不用说成本了-除了让模型服务器一直运行之外,我们现在还为每次同步Lambda调用向AWS付费。如果RISELab Slake上的400多名用户都开始玩这个机器人,那肯定不会便宜。

考虑到使用SageMaker不是在公园里散步,我对把更多的时间花在Microsoft Azure和Google Cloud的竞争服务上感到相当沮丧。但这可能是我的错误-如果你对这些产品有更好的体验,请在评论中让我知道。我很想了解更多!

取而代之的是,我决定研究一下我听说过的一家名为算法的初创公司-它专门从事模型部署和管理,所以希望它更容易使用…。

在这些文档之后,我首先创建了一个链接到Algorithmia的Git repo,并将我先前的预测脚本略微修改后的版本放入repo中。该脚本与我在本地使用的脚本非常相似-无需担心设置Web服务器和处理运行状况检查。我只需要更改几行Basic Python就可以使用Algorithm的API。开门红!

Repo还需要一个requirements.txt文件,该文件包含Python依赖项列表。这是Python项目的标准操作过程,所以我很高兴看到我不需要做任何疯狂的事情。

提交这些文件后,我所要做的就是发布我的模型,并用版本号(例如,0.0.1)对其进行标记。就这样,torchMoji模型在Algmia的平台上运行-比SageMaker容易得多!

Algorithmia的仪表盘有一个整齐的测试功能,我可以在那里输入测试句子,并获得表情符号输出。这真的很有帮助:我不需要另一个脚本来调用模型来确保一切按预期工作,就像我使用SageMaker所做的那样。

Algorithmia还生成了多种语言的复制-粘贴代码片段,我可以使用它们来调用我的模型。Python版本如下所示:

到目前为止,情况看起来很好。但是当涉及到与Slake的集成时,Algorithmia并不比SageMaker好多少。从这些文档中:

为了让您的Slake应用程序连接到Algorithmia,您需要一个中间函数:和API端点,该端点可以接受来自Slake的GET请求,验证内容,然后将其发布到Algorithmia的API之一。

我仍然需要早先的Lambda胶水代码,写起来很痛苦。对我来说,好消息是我可以将以前的大部分代码重用于lambda函数。我只需要将SageMaker端点调用替换为对Algorithm的调用,因此-考虑到我在第一次调试时已经耗费了几个小时-再做一次并不是那么糟糕。😃这里提供了完整的脚本。

不过,让我觉得奇怪的是,Algorithmia应该是一个无服务器模式的服务平台。但为了与我的Slackbot集成,我不得不使用另一个无服务器平台(AWS Lambda)来路由流量和执行安全检查。端到端延迟保持在个位数秒,因为请求仍然需要经历三跳:从Slake到API Gateway,从API Gateway到Lambda,以及从Lambda到Algmia。

我不禁想知道:如果要将我的模型与其他服务(如Slake)连接起来仍然如此痛苦,那么把我的模型放进盒子里--不管是SageMaker还是Algorithm--还有什么意义呢?如果“连接”意味着我必须了解、配置和支付另外两个服务,那么如果我将预测代码放到Lambda函数中并完全跳过特殊用途的服务,不是会更容易吗?我很难相信这真的是最先进的!

如果您想重现我的Slackbot,所有带有详细说明的代码都在这个存储库中。我与RISELab的几个博士生共享了这个存储库,他们都能在一小时内复制和部署机器人!然而,他们似乎并没有过一段非常愉快的经历。他们是这样说的:

为什么部署模型需要将多个服务组合在一起并学习它们的行话?如果模型可以像调用python脚本一样简单地在本地运行,那么将其部署到云中所增加的复杂性应该是最小的。

按照说明设置这个简单的机器人是在专家的带领下盲目摸黑的一种练习;出错的方法太多了,这使得诊断错误配置错误对于新手来说基本上是不可行的。

我们都知道,人工智能基础设施和像MLOPS这样的领域现在超级热门。每个人都在谈论这个。但在现实中,要满足在线预测服务的基本需求,还需要做很多工作。我在这里的野心不大--一个简单的模型,可伸缩性有限。走那么远很烦人,表演也很糟糕。

尽管如此,我相信外面还有其他的预测服务系统。我们自己刚刚在实验室的无服务器平台上构建了一个预测管道DSL。如果您知道更符合这里要求的生产系统或技术,或者只是想谈谈您认为这里讨论的服务中缺少的潜在功能,我很乐意通过Twitter或电子邮件听取您的意见。

感谢Vikram Sreekanti、Joseph Gonzalez和Joe Hellerstein对本文早期草稿的反馈。