Yandex.CloudとPythonのサーバーレス機能上でAliceのステートフルスキルを作成する

ニュースから始めましょう。 昨日、Yandex.Cloud はサーバーレス コンピューティング サービスの開始を発表しました Yandexクラウド機能。 これは、サービス (Web アプリケーションやチャットボットなど) のコードを記述するだけで、クラウド自体が実行される仮想マシンを作成して維持し、負荷が増加した場合にはそれらを複製することを意味します。 何も考える必要がなく、とても便利です。 そして、支払いは計算時のみに発生します。

ただし、まったく支払わない人もいます。 これらは開発者です アリスの外部スキル、つまりチャットボットが組み込まれています。 開発者は誰でもこのようなスキルを作成、ホスト、登録できます。今日からはスキルをホストする必要さえなくなり、コードを次の形式でクラウドにアップロードするだけです。 同じサーバーレス機能.

ただし、いくつかのニュアンスがあります。 まず、ペット コードにはいくつかの依存関係が必要な場合があり、それらをクラウドにドラッグするのは簡単ではありません。 次に、通常のチャットボットはダイアログの状態をどこかに保存する必要があります (したがってステートフルです)。 サーバーレス関数で最も簡単な方法でそれを行うにはどうすればよいですか? 第三に、アリス用の簡単なスキルや、ゼロ以外のプロットを持つある種のボットを作成するにはどうすればよいでしょうか? これらのニュアンスについては、実際には記事です。

Yandex.CloudとPythonのサーバーレス機能上でAliceのステートフルスキルを作成する

道徳的な準備

せっかちな人向け: 関数をクラウドにアップロードする前に、makefile で必要な依存関係を収集し、ダイアログの状態を Yandex Object Storage (S3 API をサポートしています) に保存し、独自のライブラリを使用してダイアログを管理します ツガリス. その結果、 そのような デモスキル。 それでは、これらすべてをもう少し詳しく分析してみましょう。

それほどせっかちではない方のために、複雑な話に入る前に、簡単なことから始めることを強くお勧めします。 つまり、単一ファイルのエコーボット関数を作成し、Dialog 開発者コンソールに登録してテストします。 詳細 - で ブログでの対話 и クラウドドキュメント。 そしてそれから始めてください。

私たちが何のために戦っているのかをすぐに知りたければ、アリスに聞いてください。」スキル「IT星占い」をオンにする'。 次のようなダイアログが表示されます。

アリス:こんにちは! あなたは「ITホロスコープ」スキルを持っています。 「スタート」と言って、星があなたに何を約束するかを調べてください。
ユーザー: 開始
A: お名前を言ってください。
ゆう:ヴァシジュアリー
A: では、あなたの生まれた年を教えてください。 たったの XNUMX 桁で、それ以上は何もありません。
ゆ:XNUMX番目
A: もう一度試してください。 あなたの誕生年を XNUMX 桁で入力してください。
ゆう:2002年
素晴らしい! では、あなたの誕生月に名前を付けてください。
ゆ:XNUMX月
素晴らしい! 最後に、あなたの生年月日を教えてください。数字だけ、XNUMX 桁か XNUMX 桁だけでいいです。
ゆう:18年
A: ありがとう、ヴァシシャル! 今、私たちは知っています:あなたは17歳で、水瓶座です。 もちろん、ここであなたは幸運です! 星が教えてくれる а что говорят звёзды, вы узнаете, запустив навык.

問題は、このような単純なダイアログを維持するためにも、ユーザーの名前と生年月日を覚えておく必要があることです。サーバーレス環境では、これは簡単ではありません。 コンテキストを RAM に保存したり、ディスク上のファイルとして保存したりすることはできません。 Yandex.Cloud は、複数の仮想マシンで同時に機能を実行し、それらを任意に切り替えることができます。 何らかの外部ストレージを使用する必要があります。 オブジェクト ストレージは、Yandex.Cloud 内で直接、かなり安価でシンプルなストレージ (つまり、おそらく高速) として選択されました。 無料の代替案として、たとえば無料の作品を試すことができます。 曇りモンギ どこか遠くに。 Object Storage (S3 インターフェースをサポート) と Mongo には両方とも便利な Python ラッパーがあります。

もう XNUMX つの問題は、オブジェクト ストレージ、MongoDB、その他のデータベースやデータ ストアにアクセスするには、関数コードとともに Yandex Functions にアップロードする必要がある外部依存関係が必要になることです。 そして気楽にやっていきたいと思います。 これは (heroku のように) 非常に便利ですが、残念ながら機能しませんが、環境を構築するためのスクリプト (メイク ファイル) を作成することで、基本的な快適さを作り出すことができます。

ホロスコープスキルの始め方

  1. 準備を整えて、Linux を搭載したマシンに移動します。 原理的には、おそらく Windows でも作業できますが、その場合は Makefile を起動する必要があります。 いずれの場合も、少なくとも 3.6 の Python がインストールされている必要があります。
  2. github からクローンする 星占いスキルの例.
  3. Ya.Cloud に登録します。 https://cloud.yandex.ru
  4. XNUMX つのバケットを自分で作成します オブジェクト記憶域、任意の名前で呼んでください {BUCKET NAME} и tgalice-test-cold-storage (このミドルネームは現在ハードコードされています main.py 私の例)。 最初のバケットはデプロイメントにのみ必要で、XNUMX 番目のバケットはダイアログの状態を保存するために必要です。
  5. 作ります サービスアカウント、彼に役割を与えます editor、その静的認証情報を取得します {KEY ID} и {KEY VALUE} - 対話の状態を記録するために使用します。 これらはすべて、Ya.Cloud の関数が Ya.Cloud のストレージにアクセスできるようにするために必要です。 いつか認証が自動的に行われることを願っていますが、今のところはそうです。
  6. (オプション) インストール コマンドラインインターフェース yc。 Web インターフェイスを通じて関数を作成することもできますが、あらゆる種類のイノベーションがより速く表示されるため、CLI の方が優れています。
  7. これで、実際に依存関係のアセンブリを準備できます。スキルの例を含むフォルダーからコマンド ラインで実行します。 make all。 多数のライブラリ (通常どおり、ほとんどは不要) がフォルダーにインストールされます dist.
  8. オブジェクトストレージにペンで記入します(バケツに入れます) {BUCKET NAME}) 前のステップで取得したアーカイブ dist.zip。 必要に応じて、たとえば次のようにコマンドラインからこれを実行することもできます。 AWSCLI.
  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

関数を手動で作成する場合、すべてのパラメータが同じ方法で入力されます。

これで、作成した関数を開発者コンソールを通じてテストし、スキルを完成させて公開できるようになります。

Yandex.CloudとPythonのサーバーレス機能上でAliceのステートフルスキルを作成する

ボンネットの下には何があるのか

実際、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_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 準備ができたら何をすべきかを伝えます。

ユーザーのダイアログのこの主な流れに加えて、ユーザーに挨拶したり、「help」コマンドでヘルプを発行したり、「exit」コマンドでスキルを解放したりすることも必要です。 これについては、 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

ご覧のとおり、このコードの大部分は、Object Storage S3 インターフェイスへの接続を作成します。 この接続がどのように直接使用されるかは、次のとおりです。 tgaliceコードで.
最後の行は関数を作成します alice_handler - パラメーターを設定したときに Yandex.Cloud をプルするように注文したもの --entrypoint=main.alice_handler.

実際、それだけです。 ビルド用の Makefile、コンテキスト ストレージ用の S3 のようなオブジェクト ストレージ、および Python ライブラリ tgalice。 Python のサーバーレス機能と表現力を組み合わせると、これは健全な人間のスキルを開発するのに十分です。

なぜ作成する必要があるのか​​と疑問に思うかもしれません。 tgalice? JSON をリクエストからレスポンス、ストレージからメモリ、そしてその逆に転送する退屈なコードはすべてこの中にあります。 通常のアプリケーションや、「XNUMX月」が「XNUMX月」に似ていることを理解するための機能、その他貧困層向けのNLUもあります。 私の考えによれば、技術的な詳細にあまり気をとられることなく、yaml ファイルでスキルのプロトタイプをスケッチできるようにするには、これで十分なはずです。

より本格的な NLU が必要な場合は、自分のスキルに合わせて調整できます ラーザ または ディープパブロフただし、特にサーバーレスでは、それらをセットアップするには、タンバリンを使った追加のダンスが必要になります。 コーディングする気がまったくない場合は、ビジュアルタイプコンストラクターを使用してください。 アイミロジック。 tgalice を作成するとき、私はある種の中間パスを考えました。 しばらく様子を見てみましょう。

さて、今すぐ参加してください Aliy スキル開発者チャット、 読んだ ドキュメンテーションそして素晴らしいものを生み出す スキル!

出所: habr.com

コメントを追加します