我們先從新聞說起。 昨天 Yandex.Cloud 宣布推出無服務器計算服務
然而,有些人可能根本不付錢。 這些是開發商
但有一些細微差別。 首先,您的寵物代碼可能需要一些依賴項,將它們拖到雲中並不是一件容易的事。 其次,任何正常的聊天機器人都需要將對話的狀態存儲在某處(因此是有狀態的); 如何以最簡單的方式在無服務器功能中做到這一點? 第三,如何為 Alice 甚至某種具有非零情節的機器人編寫快速而骯髒的技能? 關於這些細微差別,其實有文章。
道德準備
對於不耐煩的人:我在將函數上傳到雲之前使用 makefile 收集必要的依賴項,將對話框的狀態存儲在 Yandex 對象存儲中(它支持 S3 API),並使用我自己的庫來管理對話框
對於不太耐心的人,在深入研究我的複雜故事之前,我強烈建議從簡單的開始。 即創建一個單文件echobot函數,在Dialog開發者控制台中註冊並測試; 詳細信息 - 在
如果你想立即感受到我們為何而戰,就去問愛麗絲吧。
愛麗絲:你好! 您處於“IT 占星”技能中。 說“開始”,看看星星向您承諾了什麼。
用戶:開始
答:請說出您的姓名。
於:瓦西蘇利
A:現在告訴我你的出生年份。 只有四位數,僅此而已。
於:第二
答:請再試一次。 註明您的出生年份 - 四位數。
於:2002年
一個了不起的! 現在說出您的出生月份。
於:二月
一個了不起的! 最後,告訴我你的出生日期——只是一個數字,只是一兩位數字。
於:18年
答:謝謝你,瓦西蘇爾! 現在我們知道:你今年17歲,你是水瓶座。 當然,你很幸運! 星星告訴你 а что говорят звёзды, вы узнаете, запустив навык.
問題是,即使要維護這樣一個簡單的對話框,您也需要記住用戶的姓名和出生日期,而在無服務器環境中,這並不是一件小事。 將上下文存儲在 RAM 中或作為磁盤上的文件是行不通的,因為Yandex.Cloud可以同時在多個虛擬機上運行該功能,並在它們之間任意切換。 您必須使用某種外部存儲。 對象存儲被選為直接在 Yandex.Cloud 中相當便宜且簡單的存儲(也就是說,可能很快)。 作為免費的替代方案,您可以嘗試例如免費的作品
另一個問題是,為了訪問對象存儲、MongoDB 和任何其他數據庫或數據存儲,您需要一些外部依賴項,您需要將這些依賴項與函數代碼一起上傳到 Yandex Functions。 我想舒服地做這件事。 它非常方便(就像在heroku上一樣),可惜它不起作用,但是您可以通過編寫腳本來構建環境(make文件)來創建一些基本的舒適感。
如何開始占星技能
- 準備好:轉到裝有 Linux 的機器。 原則上,您也可以使用 Windows,但是您必須啟動 makefile。 無論如何,您至少需要安裝 3.6 版本的 Python。
- 從 github 克隆
占星技能的例子 . - 在Ya.Cloud註冊:
https://cloud.yandex.ru - 為自己創建兩個桶
對象存儲 ,用任何名字稱呼他們{BUCKET NAME}
иtgalice-test-cold-storage
(這個中間名現在被硬編碼到main.py
我的例子)。 第一個存儲桶僅用於部署,第二個存儲桶用於存儲對話框狀態。 - 創建
服務帳戶 ,給他一個角色editor
,並獲取它的靜態憑證{KEY ID}
и{KEY VALUE}
- 我們將使用它們來記錄對話的狀態。 所有這些都是為了讓Ya.Cloud 中的功能可以訪問Ya.Cloud 中的存儲。 我希望有一天,授權將變得自動,但目前 - 如此。 - (可選)安裝
命令行界面 yc
。 您還可以通過 Web 界面創建函數,但 CLI 很好,因為各種創新都可以更快地出現在其中。 - 事實上,現在您可以準備依賴項的組裝:從包含技能示例的文件夾中在命令行上運行
make all
。 一堆庫(大部分是不必要的)將安裝在該文件夾中dist
. - 將筆填充到對象存儲中(放入桶中
{BUCKET NAME}
) 上一步獲得的存檔dist.zip
。 如果需要,您還可以從命令行執行此操作,例如使用命令行界面 . - 通過 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
。 config描述了填寫用戶數據的過程 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
工作原理很簡單:它嘗試依次將其所有組件應用於對話的當前狀態,並選擇第一個相關組件。
作為對每條消息的響應,對話管理器返回一個 python 對象 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
如您所見,大部分代碼都會創建與對象存儲 S3 接口的連接。 這個連接是如何直接使用的,可以閱讀
最後一行創建一個函數 alice_handler
- 我們在設置參數時命令拉取 Yandex.Cloud 的那個 --entrypoint=main.alice_handler
.
事實上,僅此而已。 用於構建的 Makefile、用於上下文存儲的類似 S3 的對象存儲以及一個 Python 庫 tgalice
。 再加上Python的無服務器特性和表現力,這足以培養一個健康人的技能。
您可能會問為什麼需要創建 tgalice
? 所有將 JSON 從請求傳輸到響應、從存儲傳輸到內存並返回的無聊代碼都在其中。 還有一個常規應用程序,一個用於理解“二月”與“二月”類似的功能,以及其他針對窮人的 NLU。 按照我的想法,這應該已經足夠能夠在 yaml 文件中勾勒出技能原型,而不會被技術細節過多分散注意力。
如果你想要更嚴肅的 NLU,你可以將其運用到你的技能中
嗯,現在加入
來源: www.habr.com