Paglikha ng isang stateful na kasanayan para kay Alice sa mga walang server na function ng Yandex.Cloud at Python

Magsimula tayo sa balita. Kahapon ay inihayag ng Yandex.Cloud ang paglulunsad ng isang serverless computing service Yandex Cloud Functions. Ibig sabihin: isusulat mo lang ang code ng iyong serbisyo (halimbawa, isang web application o isang chatbot), at ang Cloud mismo ay gumagawa at nagpapanatili ng mga virtual machine kung saan ito tumatakbo, at kahit na ginagaya ang mga ito kung tumaas ang pag-load. Hindi mo na kailangang mag-isip sa lahat, ito ay napaka-maginhawa. At ang pagbabayad ay napupunta lamang para sa oras ng mga kalkulasyon.

Gayunpaman, maaaring hindi nagbabayad ang ilang tao. Ito ang mga developer Ang mga panlabas na kakayahan ni Alice, iyon ay, mga chatbot na nakapaloob dito. Ang sinumang developer ay maaaring magsulat, mag-host at magrehistro ng ganoong kasanayan, at mula ngayon, hindi na kailangan pang i-host ang mga kasanayan — i-upload lang ang kanilang code sa cloud sa form ang parehong walang server na function.

Ngunit mayroong isang pares ng mga nuances. Una, ang iyong pet code ay maaaring mangailangan ng ilang dependencies, at hindi mahalaga na i-drag ang mga ito sa Cloud. Pangalawa, ang anumang normal na chatbot ay kailangang mag-imbak ng estado ng dialog sa isang lugar (samakatuwid ay stateful); paano ito gawin sa isang serverless function sa pinakamadaling paraan? Pangatlo, paano ka makakasulat ng mabilis-at-maruming kasanayan para kay Alice o kahit ilang uri ng bot na may hindi zero na plot? Tungkol sa mga nuances na ito, sa katunayan, ang artikulo.

Paglikha ng isang stateful na kasanayan para kay Alice sa mga walang server na function ng Yandex.Cloud at Python

moral na paghahanda

Para sa mga naiinip: Kinokolekta ko ang mga kinakailangang dependency na may makefile bago i-upload ang function sa cloud, iniimbak ko ang estado ng dialog sa Yandex Object Storage (sinusuportahan nito ang S3 API), at ginagamit ko ang sarili kong library para pamahalaan ang dialog tgalice. Bilang isang resulta, ito ay lumalabas tulad kasanayan sa demo. At ngayon, pag-aralan natin ang lahat ng ito nang mas detalyado.

Para sa medyo hindi gaanong naiinip, bago sumisid sa aking kwento ng pagiging kumplikado, lubos kong inirerekomenda ang pagsisimula ng simple. Ibig sabihin, lumikha ng isang single-file na echobot function, irehistro at subukan ito sa Dialog developer console; mga detalye - sa Blog Dialogues и dokumentasyon ng ulap. At pagkatapos lamang magsimula.

Kung gusto mong maramdaman agad ang pinaglalaban natin, tanungin mo si Alice 'i-on ang kasanayang "IT horoscope"'. Ang sumusunod na diyalogo ay dapat maganap:

Alice: Hello! Ikaw ay nasa "IT horoscope" na kasanayan. Sabihin ang "Start" para malaman kung ano ang ipinangako sa iyo ng mga bituin.
User: Magsimula
A: Pakisabi ang iyong pangalan.
Yu: Vasisualy
A: Ngayon sabihin sa akin ang taon ng iyong kapanganakan. Apat na digit lang, wala na.
Yu: pangalawa
A: Pakisubukang muli. Sabihin ang taon ng iyong kapanganakan - apat na numero.
Yu: 2002
A: Magaling! Ngayon pangalanan ang buwan ng iyong kapanganakan.
Yu: Pebrero
A: Magaling! Sa wakas, sabihin sa akin ang iyong petsa ng kapanganakan - isang numero lamang, isa o dalawang digit lamang.
Yu: 18
A: Salamat, Vasisual! Ngayon alam na namin: ikaw ay 17 taong gulang at ikaw ay isang Aquarius. Narito ka, siyempre, masuwerte! Sinasabi sa iyo ng mga bituin а что говорят звёзды, вы узнаете, запустив навык.

Ang problema ay upang mapanatili ang kahit na isang simpleng dialog, kailangan mong tandaan ang pangalan at petsa ng kapanganakan ng gumagamit, at sa isang walang server na kapaligiran na ito ay hindi mahalaga. Hindi gagana ang pag-imbak ng konteksto sa RAM o bilang isang file sa disk, dahil Maaaring patakbuhin ng Yandex.Cloud ang function sa ilang virtual machine nang sabay-sabay at arbitraryong lumipat sa pagitan ng mga ito. Kakailanganin mong gumamit ng ilang uri ng panlabas na storage. Ang Imbakan ng Bagay ay pinili bilang isang medyo mura at simpleng imbakan nang direkta sa Yandex.Cloud (iyon ay, malamang na mabilis). Bilang isang libreng alternatibo, maaari mong subukan, halimbawa, isang libreng piraso Maulap na Mongi sa isang lugar na malayo. Parehong Object Storage (sinusuportahan nito ang interface ng S3) at ang Mongo ay may maginhawang Python wrapper.

Ang isa pang problema ay upang pumunta sa Object Storage, MongoDB, at anumang iba pang database o data store, kailangan mo ng ilang mga panlabas na dependency na kailangan mong i-upload sa Yandex Functions kasama ang iyong function code. At gusto kong gawin ito nang kumportable. Ito ay ganap na maginhawa (tulad ng sa heroku), sayang, hindi ito gagana, ngunit maaari kang lumikha ng ilang pangunahing kaginhawahan sa pamamagitan ng pagsulat ng isang script upang bumuo ng kapaligiran (gumawa ng file).

Paano simulan ang kasanayan sa horoscope

  1. Humanda: pumunta sa ilang makina na may Linux. Sa prinsipyo, maaari ka ring magtrabaho sa Windows, ngunit pagkatapos ay kailangan mong mag-conjure sa paglulunsad ng makefile. At sa anumang kaso, kakailanganin mo ng hindi bababa sa 3.6 na naka-install na Python.
  2. I-clone mula sa github halimbawa ng kasanayan sa horoscope.
  3. Magrehistro sa Ya.Cloud: https://cloud.yandex.ru
  4. Gawin ang iyong sarili ng dalawang balde Imbakan ng Bagay, tawagin sila sa anumang pangalan {BUCKET NAME} и tgalice-test-cold-storage (Ang gitnang pangalan na ito ay naka-hardcode na ngayon sa main.py ang aking halimbawa). Ang unang bucket ay kakailanganin lamang para sa pag-deploy, ang pangalawa - para sa pag-iimbak ng mga estado ng dialog.
  5. lumikha account ng serbisyo, bigyan mo siya ng papel editor, at kumuha ng mga static na kredensyal para dito {KEY ID} и {KEY VALUE} - gagamitin natin ang mga ito para itala ang estado ng diyalogo. Ang lahat ng ito ay kailangan para ma-access ng function mula sa Ya.Cloud ang storage mula sa Ya.Cloud. Balang araw, umaasa ako, magiging awtomatiko ang awtorisasyon, ngunit sa ngayon - kaya.
  6. (Opsyonal) i-install interface ng command line yc. Maaari ka ring gumawa ng function sa pamamagitan ng web interface, ngunit maganda ang CLI dahil mas mabilis na lumalabas dito ang lahat ng uri ng inobasyon.
  7. Ngayon ay maaari mong, sa katunayan, ihanda ang pagpupulong ng mga dependencies: tumakbo sa command line mula sa folder na may halimbawa ng kasanayan make all. Isang grupo ng mga aklatan (karamihan, gaya ng dati, hindi kailangan) ay mai-install sa folder dist.
  8. Punan ng mga panulat sa Object Storage (sa isang bucket {BUCKET NAME}) ang archive na nakuha sa nakaraang hakbang dist.zip. Kung ninanais, maaari mo ring gawin ito mula sa command line, halimbawa, gamit AWS CLI.
  9. Gumawa ng walang server na function sa pamamagitan ng web interface o gamit ang utility yc. Para sa utility, ang utos ay magiging ganito:

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

Kapag manu-manong lumilikha ng isang function, ang lahat ng mga parameter ay pinupunan sa parehong paraan.

Ngayon ang function na iyong ginawa ay maaaring masuri sa pamamagitan ng developer console, at pagkatapos ay i-finalize at i-publish na kasanayan.

Paglikha ng isang stateful na kasanayan para kay Alice sa mga walang server na function ng Yandex.Cloud at Python

Ano ang nasa ilalim ng talukbong

Ang makefile ay talagang naglalaman ng isang medyo simpleng script para sa pag-install ng mga dependency at paglalagay ng mga ito sa isang archive. dist.zip, isang bagay na tulad nito:

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 ./*

Ang natitira ay ilang simpleng tool na nakabalot sa isang library tgalice. Ang proseso ng pagpuno sa data ng user ay inilarawan ng 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: Пожалуйста, попробуйте ещё раз. Вам нужно назвать число своего рождения (например, двадцатое); это одна или две цифры.

Kinukuha ng klase ng python ang gawain ng pag-parse ng config na ito at pagkalkula ng huling resulta

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

Mas tiyak, ang batayang klase FormFillingDialogManager ay nakikibahagi sa pagpuno ng "form", at ang paraan ng klase ng bata handle_completed_form nagsasabi kung ano ang gagawin kapag handa na siya.

Bilang karagdagan sa pangunahing daloy ng diyalogo ng gumagamit, kinakailangan ding batiin ang gumagamit, pati na rin magbigay ng tulong sa "help" na utos at paglabas mula sa kasanayan sa "exit" na utos. Para dito sa tgalice mayroon ding template, kaya ang buong dialog manager ay binubuo ng mga piraso:

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 gumagana nang simple: sinusubukan nitong ilapat sa kasalukuyang estado ng diyalogo ang lahat ng mga bahagi nito, at pinipili ang unang nauugnay.

Bilang tugon sa bawat mensahe, ang dialog manager ay nagbabalik ng isang python object Response, na maaaring ma-convert sa plain text, o sa isang mensahe sa Alice o Telegram - depende sa kung saan tumatakbo ang bot; naglalaman din ito ng binagong estado ng dialog na kailangang i-save. Ang lahat ng kusinang ito ay pinangangasiwaan ng ibang klase, DialogConnector, kaya ang direktang script para sa pagsisimula ng isang kasanayan sa Yandex Functions ay ganito ang hitsura:

...
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

Gaya ng nakikita mo, karamihan sa code na ito ay lumilikha ng koneksyon sa interface ng Object Storage S3. Kung paano direktang ginagamit ang koneksyon na ito, mababasa mo sa tgalice code.
Ang huling linya ay lumilikha ng isang function alice_handler - ang inutusan naming hilahin ang Yandex.Cloud kapag itinakda namin ang parameter --entrypoint=main.alice_handler.

Iyon, sa katunayan, ay lahat. Makefiles para sa pagbuo, S3-like Object Storage para sa context storage, at isang python library tgalice. Kasama ang walang server na mga tampok at pagpapahayag ng python, ito ay sapat na upang bumuo ng kakayahan ng isang malusog na tao.

Maaari kang magtanong kung bakit kailangan mong lumikha tgalice? Lahat ng nakakainip na code na naglilipat ng mga JSON mula sa kahilingan patungo sa tugon at mula sa imbakan patungo sa memorya at pabalik ay nasa loob nito. Mayroon ding regular na expression application, isang function para sa pag-unawa na ang "February" ay katulad ng "February", at iba pang NLU para sa mahihirap. Ayon sa aking ideya, ito ay dapat na sapat na upang makapag-sketch ng mga prototype ng kasanayan sa mga yaml file nang hindi masyadong ginulo ng mga teknikal na detalye.

Kung gusto mo ng mas seryosong NLU, maaari mo itong i-screw sa iyong kakayahan Rasa o DeepPavlov, ngunit ang pagse-set up sa mga ito ay mangangailangan ng karagdagang pagsasayaw na may tamburin, lalo na sa walang server. Kung hindi mo gusto ang coding, dapat mong gamitin ang visual type constructor Aimylogic. Kapag lumilikha ng tgalice, naisip ko ang tungkol sa ilang uri ng intermediate na landas. Tignan natin kung ano ang mangyayari.

Well, ngayon sumali Aliy skills developer chat, basahin dokumentasyonat lumikha ng kamangha-manghang kasanayan!

Pinagmulan: www.habr.com

Magdagdag ng komento