在Yandex.Cloud和Python的无服务器功能上为Alice创建有状态技能

让我们从新闻开始。 昨天,Yandex.Cloud宣布推出无服务器计算服务Yandex Cloud Functions 。 这意味着:您只编写服务代码(例如Web应用程序或聊天机器人),而Cloud本身会在其启动时创建和维护虚拟机,甚至在负载增加时也可以复制它们。 完全没有必要思考,这非常方便。 费用仅在计算期间发生。


但是,有些可能根本不付款。 这些是Alice外部技能 (即内置在其中的聊天机器人)的开发人员。 任何开发人员都可以编写,托管和注册这种技能,从今天起,甚至不需要托管该技能,只需以无服务器功能的形式将其代码上传到云中即可。


但是有一些细微差别。 首先,您的宠物代码可能需要一些依赖关系,并且将它们引入云中并非易事。 其次,任何普通的聊天机器人都需要将对话的状态存储在某个地方(因此是有状态的); 如何在最简单的无服务器功能中做到这一点? 第三,如何快速而肮脏地为Alice或某种具有非零绘图的机器人编写技能? 关于这些细微差别,实际上是一篇文章。


图片

道德训练


对于不耐烦的人:在将函数上传到云之前,我会收集一个make文件中的必要依赖项,并将对话状态存储在Yandex Object Storage中(它支持S3 API),并使用我自己的tgalice库来管理对话。 结果就是这样的演示技能。 现在,让我们更详细地了解所有这些。


为了减少耐心:在深入探讨有关困难的故事之前,我强烈建议从简单的故事开始。 即,创建一个单文件回声测深仪功能,在Dialogs开发人员控制台中注册并测试它; 有关详细信息,请参见“ 对话框文档 博客” 。 只有这样才能继续。


如果您想立即感觉到我们正在为之奋斗,请让Alice 启用“ IT星座”技术。 将出现以下对话框:


爱丽丝:嗨! 您具有Aishish Horoscope的技能。 说“开始”以找出星星向您承诺的内容。
用户:开始
答:请输入您的名字。
于:Vasisuali
答:现在告诉我您的出生年份。 只有四个数字,仅此而已。
于:第二
答:请再试一次。 您的出生年份是-四位数。
U:2002
A:太好了! 现在命名您的出生月份。
U:二月
A:太好了! 最后,告诉我您的出生日期-只有一个数字,只有一个或两个数字。
U:18
答:谢谢Vasisuali! 现在我们知道:您今年17岁,您是水瓶座。 当然,您在这里很幸运! 星星告诉你: , , .


问题是,为了保持这样简单的对话,您需要记住用户的姓名和出生日期,在无服务器环境中,这并非易事。 将上下文存储在RAM中或磁盘上的文件将无法工作,因为 Yandex.Cloud可以在多个虚拟机上同时运行该功能,并可以在它们之间任意切换。 我们将不得不使用某种外部存储。 在Yandex.Cloud中,对象存储被选为一种非常便宜且不复杂的存储(即可能很快)。 作为一种免费的替代方法,您可以尝试在很远的地方免费获得一片蒙加蒙加 。 对象存储(它支持S3接口)和Mongo都有方便的Python包装器。


另一个问题是,要在对象存储,MongoDB以及任何其他数据库或数据仓库中运行,需要一些外部依赖项,这些依赖项需要与函数代码一起上传到Yandex Functions。 我想方便地做到这一点。 这样做很方便(例如heroku),但是不会成功,但是您可以通过编写脚本来构建环境(make-file)来创造一些基本的舒适感。


如何运行星座运势


  1. 准备自己:去一些Linux机器。 原则上,您可能也可以使用Windows,但是随后您必须想像一下make文件的启动。 在任何情况下,您都需要安装不低于3.6的Python。
  2. 用github克隆自己一个星座技巧的例子
  3. 在Y.Cloud中注册: https//cloud.yandex.ru
  4. 对象存储中为自己创建两个存储桶,用任何名称{BUCKET NAME}tgalice-test-cold-storage命名它们(此第二个名称现在在我的示例的main.py了硬编码)。 仅在部署时需要第一个存储桶,第二个存储桶用于存储对话状态。
  5. 创建一个服务帐户 ,为其指定editor角色,并为其获取静态信用卡{KEY ID}{KEY VALUE} -我们将使用它们来记录对话的状态。 所有这些都是必需的,以便Y.Cloud中的功能可以从Y.Cloud中访问存储库。 我希望有一天,授权会自动进行,但是暂时-这样。
  6. (可选)安装yc 命令行界面 。 您可以通过Web界面创建功能,但是CLI的好处在于,各种创新都可以更快地出现在其中。
  7. 现在,您实际上可以准备依赖程序集:在带有make all技能示例的文件夹中的命令提示符处运行。 一堆库(通常和往常一样是不必要的)将安装在dist文件夹中。
  8. 将上一步中获得的dist.zip档案倒入对象存储中(放入{BUCKET NAME} )。 如果需要,您可以从命令行执行此操作,例如,使用AWS CLI
  9. 通过Web界面或使用yc实用程序创建无服务器功能。 对于该实用程序,该命令将如下所示:

 yc serverless function version create\ --function-name=horoscope\ --environment=AWS_ACCESS_KEY_ID={KEY ID},AWS_SECRET_ACCESS_KEY={KEY VALUE}\ --runtime=python37\ --package-bucket-name={BUCKET NAME}\ --package-object-name=dist.zip\ --entrypoint=main.alice_handler\ --memory=128M\ --execution-timeout=3s 

手动创建函数时,所有参数均以相同的方式填充。


现在,可以通过开发人员控制台测试您创建的功能,然后修改和发布该技能。



内幕是什么


makefile实际上包含一个相当简单的脚本,用于安装依赖项并将其放入dist.zip存档中,如下所示:


 mkdir -p dist/ pip3 install -r requirements.txt --target dist/ cp main.py dist/main.py cp form.yaml dist/form.yaml cd dist && zip --exclude '*.pyc' -r ../dist.zip ./* 

其余的是包装在tgalice库中的一些简单工具。 填写用户数据的过程由form.yaml form.yaml描述:


 form_name: 'horoscope_form' start: regexp: '|(|)' suggests: -  fields: - name: 'name' question: ,   . - name: 'year' question:      .   ,  . validate_regexp: '^[0-9]{4}$' validate_message: ,   .     -  . - name: 'month' question: !     . options: -  ... -  validate_message: ,   ,    . ,    ,   . - name: 'day' question: ! ,      -  ,     . validate_regexp: '[0123]?\d$' validate_message: ,   .       (, );     . 

解析此配置并计算最终结果的工作由python类承担


 class CheckableFormFiller(tgalice.dialog_manager.form_filling.FormFillingDialogManager): SIGNS = { '': '', ... } def handle_completed_form(self, form, user_object, ctx): response = tgalice.dialog_manager.base.Response( text=', {}!   :  {} ,   {}. \n' '  , , !   : {}'.format( form['fields']['name'], 2019 - int(form['fields']['year']), self.SIGNS[form['fields']['month']], random.choice(FORECASTS), ), user_object=user_object, ) return response 

更准确地说,基类FormFillingDialogManager填写“表单”,子类handle_completed_form的方法说明准备就绪时该怎么做。


除了用户对话的主要流程外,您还需要打招呼,并在“帮助”命令上提供帮助,并从“退出”命令上退出技能。 tgalice也为此提供了一个模板,因此整个对话框管理器由以下部分组成:


 dm = tgalice.dialog_manager.CascadeDialogManager( tgalice.dialog_manager.GreetAndHelpDialogManager( greeting_message=DEFAULT_MESSAGE, help_message=DEFAULT_MESSAGE, exit_message=' ,    " " !' ), CheckableFormFiller(`form.yaml`, default_message=DEFAULT_MESSAGE) ) 

CascadeDialogManager工作原理很简单:它将尝试将其所有组件依次应用于对话框的当前状态,然后选择第一个合适的组件。


作为对每条消息的回答,对话框管理器返回一个Response对象,该对象可以进一步转换为纯文本,或者转换为Alice或Telegram中的消息-取决于启动程序的位置。 它还包含对话的更改状态,必须保存。 所有此类厨房都使用另一个类DialogConnector进行操作,因此在Yandex Functions上启动该技能的直接脚本如下所示:


 ... session = boto3.session.Session() s3 = session.client( service_name='s3', endpoint_url='https://storage.yandexcloud.net', aws_access_key_id=os.environ['AWS_ACCESS_KEY_ID'], aws_secret_access_key=os.environ['AWS_SECRET_ACCESS_KEY'], region_name='ru-central1', ) storage = tgalice.session_storage.S3BasedStorage(s3_client=s3, bucket_name='tgalice-test-cold-storage') connector = tgalice.dialog_connector.DialogConnector(dialog_manager=dm, storage=storage) alice_handler = connector.serverless_alice_handler 

如您所见,大多数代码都创建了到Object Storage S3接口的连接。 可以直接在tgalice代码中了解如何直接使用此连接。
最后一行创建alice_handler函数-我们在设置--entrypoint=main.alice_handler时命令Yandex.Cloud拉出的--entrypoint=main.alice_handler


实际上,仅此而已。 程序集的Makefile,类似于S3的对象存储(用于存储上下文)以及tgalice python库。 再加上python的无服务器功能和表达能力,这足以培养健康人的技能。


您可能会问,为什么需要创建tgalice ? 所有将JSON从请求传输到响应,再从存储传输到内存,反之亦然的无聊代码都位于其中。 还有一个常规的控制器应用程序,一个用于了解“二月”类似于“二月”的功能,以及其他针对穷人的NLU。 根据我的想法,这应该已经足够了,以便您可以在yaml文件中绘制技能原型,而又不会被技术细节所干扰。


如果您想要更严重的NLU,可以根据自己的技能来固定RasaDeepPavlov ,但是要配置它们,您将需要带有手鼓的其他舞蹈,尤其是在无服务器上。 如果您根本不想编写代码,则应使用Aimylogic之类的可视构造函数 。 创建tgalice时,我在想某种中间路径。 让我们看看会发生什么。


好吧,现在加入他们的技能开发人员聊天 ,阅读文档 ,并创造精彩的技能

Source: https://habr.com/ru/post/zh-CN469723/


All Articles