Creació d'una habilitat amb estat per a Alice a les funcions sense servidor de Yandex.Cloud i Python

Comencem amb la notícia. Ahir Yandex.Cloud va anunciar el llançament d'un servei informàtic sense servidor Funcions Yandex Cloud. Això vol dir: només escriviu el codi del vostre servei (per exemple, una aplicació web o un chatbot), i el mateix Cloud crea i manté les màquines virtuals on s'executa, i fins i tot les replica si augmenta la càrrega. No cal pensar gens, és molt convenient. I el pagament és només pel temps de càlcul.

Tanmateix, és possible que alguns no paguin gens. Aquests són els desenvolupadors Habilitats externes d'Alice, és a dir, chatbots integrats en ell. Qualsevol desenvolupador pot escriure, allotjar i registrar aquesta habilitat, i des d'avui les habilitats ni tan sols cal que estiguin allotjades; només cal que carregueu el seu codi al núvol en el formulari la mateixa funció sense servidor.

Però hi ha un parell de matisos. En primer lloc, el vostre codi de box pot requerir algunes dependències i arrossegar-les al núvol no és trivial. En segon lloc, qualsevol chatbot normal necessita emmagatzemar l'estat del diàleg en algun lloc (per tant, amb estat); Quina és la manera més fàcil de fer-ho en una funció sense servidor? En tercer lloc, com podeu escriure una habilitat ràpida i bruta per a l'Alice o fins i tot algun tipus de bot amb una trama diferent de zero? L'article tracta, de fet, d'aquests matisos.

Creació d'una habilitat amb estat per a Alice a les funcions sense servidor de Yandex.Cloud i Python

Preparació moral

Per als impacients: recullo les dependències necessàries amb un makefile abans de carregar la funció al núvol, emmagatzeme l'estat del diàleg a Yandex Object Storage (admet l'API S3) i faig servir la meva pròpia biblioteca per gestionar el diàleg. tgalice. Al final resulta tal habilitat de demostració. Ara mirem tot això amb una mica més de detall.

Per a aquells una mica menys impacients, abans d'endinsar-me en la meva història sobre la complexitat, recomano molt començar amb alguna cosa senzilla. És a dir, creeu una funció d'ecobot d'un sol fitxer, registreu-la i proveu-la a la consola de desenvolupadors de Dialogs; detalls - a Bloc de diàlegs и Documentació al núvol. I només llavors començar.

Si voleu sentir immediatament el que estem lluitant aquí, pregunteu a l'Alice.habiliteu l'habilitat "horòscop informàtic".'. S'hauria de produir un diàleg semblant al següent:

Alícia: Hola! Ets a l'habilitat "Horòscop de TI". Digues "Comença" per saber què et prometen les estrelles.
Usuari: Inici
R: Si us plau, indiqueu el vostre nom
Yu: Vasisualiy
R: Ara digueu-me l'any del vostre naixement. Només quatre dígits, res més.
Yu: segon
R: Si us plau, torna-ho a provar. Introduïu l'any del vostre naixement: quatre dígits.
Iu: 2002
Un gran! Ara posa el teu mes de naixement.
Yu: Febrer
Un gran! Finalment, digueu-me la vostra data de naixement: només un número, només un o dos dígits.
Iu: 18
R: Gràcies, Vasisualiy! Ara ho sabem: tens 17 anys i ets Aquari. Bé, és clar, tens sort! Les estrelles et diuen: а что говорят звёзды, вы узнаете, запустив навык.

El problema és que per mantenir fins i tot un diàleg tan senzill, cal recordar el nom i la data de naixement de l'usuari, i en un entorn de funcions sense servidor això no és trivial. No serà possible emmagatzemar el context a la memòria RAM o com a fitxer al disc, perquè Yandex.Cloud pot executar una funció en diverses màquines virtuals alhora i canviar entre elles a voluntat. Haureu d'utilitzar algun tipus d'emmagatzematge extern. L'emmagatzematge d'objectes es va triar com un emmagatzematge bastant econòmic i senzill directament a Yandex.Cloud (és a dir, probablement ràpid). Com a alternativa gratuïta, podeu provar, per exemple, una peça gratuïta Monga ennuvolat en algun lloc llunyà. Hi ha embolcalls Python convenients tant per a Object Storage (que admet la interfície S3) com per a Mongo.

Un altre problema és que per accedir a Object Storage, MongoDB i qualsevol altra base de dades o magatzem de dades, necessiteu algunes dependències externes que s'han de carregar a Yandex Functions juntament amb el vostre codi de funció. I m'agradaria fer-ho còmodament. Malauradament, no serà del tot convenient (com a Heroku), però es pot crear una mica de comoditat bàsic escrivint un script per crear l'entorn (crear un fitxer).

Com iniciar una habilitat horòscop

  1. Prepareu-vos: aneu a alguna màquina amb Linux. En principi, probablement també podeu treballar amb Windows, però llavors haureu de fer una mica de màgia amb el llançament del makefile. I en qualsevol cas, necessitareu almenys Python 3.6 instal·lat.
  2. Clonar-lo des de Github exemple d'habilitat horòscop.
  3. Registra't a Y.Cloud: https://cloud.yandex.ru
  4. Crea't dos cubells Emmagatzematge d'objectes, crida'ls amb qualsevol nom {BUCKET NAME} и tgalice-test-cold-storage (Aquest segon nom ara està codificat en dur main.py el meu exemple). El primer cub només es necessitarà per al desplegament, el segon per emmagatzemar estats de diàleg.
  5. crear compte de servei, doneu-li un paper editor, i obteniu credencials estàtiques per a això {KEY ID} и {KEY VALUE} — els utilitzarem per registrar l'estat del diàleg. Tot això és necessari perquè una funció de Ya.Cloud pugui accedir a l'emmagatzematge des de Ya.Cloud. Algun dia, espero, l'autorització esdevingui automàtica, però de moment és així.
  6. (Opcional) instal·lar interfície de línia d'ordres yc. També podeu crear una funció a través de la interfície web, però la CLI és bona perquè hi apareixen tot tipus d'innovacions més ràpidament.
  7. Ara podeu preparar el conjunt de dependències: executeu-lo a la línia d'ordres des de la carpeta amb l'exemple d'habilitat make all. S'instal·laran un munt de biblioteques (la majoria, com és habitual, innecessàries) a la carpeta dist.
  8. Aboqueu a mà a l'emmagatzematge d'objectes (a la galleda {BUCKET NAME}) arxiu obtingut al pas anterior dist.zip. Si ho desitgeu, podeu fer-ho des de la línia d'ordres, per exemple, utilitzant AWS CLI.
  9. Creeu una funció sense servidor mitjançant la interfície web o mitjançant una utilitat yc. Per a la utilitat, l'ordre tindrà aquest aspecte:

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

Quan es crea manualment una funció, tots els paràmetres s'emplenen de la mateixa manera.

Ara la funció que heu creat es pot provar a través de la consola del desenvolupador i, a continuació, es pot millorar i publicar l'habilitat.

Creació d'una habilitat amb estat per a Alice a les funcions sense servidor de Yandex.Cloud i Python

Què hi ha sota el capó

El makefile en realitat conté un script bastant senzill per instal·lar dependències i posar-les en un arxiu dist.zip, aproximadament així:

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

La resta són unes quantes eines senzilles embolicades en una biblioteca tgalice. El procés d'ompliment de les dades de l'usuari es descriu a la configuració 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: Пожалуйста, попробуйте ещё раз. Вам нужно назвать число своего рождения (например, двадцатое); это одна или две цифры.

La classe Python assumeix el treball d'analitzar aquesta configuració i calcular el resultat final

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

Més precisament, la classe base FormFillingDialogManager s'ocupa d'omplir el "formulari" i el mètode de classe fill handle_completed_form li diu què ha de fer quan estigui a punt.

A més d'aquest flux principal de diàlegs, també s'ha de saludar l'usuari, així com rebre ajuda mitjançant l'ordre "ajuda" i alliberar-se de l'habilitat mitjançant l'ordre "sortir". Amb aquesta finalitat a tgalice També hi ha una plantilla, de manera que tot el gestor de diàlegs està format per peces:

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 Funciona de manera senzilla: intenta aplicar al seu torn tots els seus components a l'estat actual del diàleg i selecciona el primer adequat.

El gestor de diàlegs retorna un objecte Python com a resposta a cada missatge. Response, que després es pot convertir en text sense format o en un missatge a Alice o Telegram, depenent d'on s'executa el bot; també conté l'estat canviat del diàleg que cal desar. Tota aquesta cuina la gestiona una altra classe, DialogConnector, de manera que el guió directe per llançar una habilitat a les funcions de Yandex té aquest aspecte:

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

Com podeu veure, la major part d'aquest codi crea una connexió a la interfície S3 d'Object Storage. Podeu llegir com s'utilitza directament aquesta connexió en codi tgalice.
L'última línia crea la funció alice_handler — el mateix que vam dir a Yandex.Cloud que estigués quan establim el paràmetre --entrypoint=main.alice_handler.

Això és tot, de fet. Makefiles per al muntatge, emmagatzematge d'objectes semblant a S3 per emmagatzemar el context i una biblioteca de Python tgalice. Combinat amb les funcions sense servidor i l'expressivitat de Python, això és suficient per desenvolupar una habilitat humana saludable.

Podeu preguntar per què va ser necessari crear tgalice? Tot el codi avorrit que transfereix els JSON de la sol·licitud a la resposta i de l'emmagatzematge a la memòria i viceversa es troba en ell. També hi ha una aplicació de codi normal, una funció per entendre que "febrer" és similar a "febrer" i altres NLU per als pobres. Segons la meva idea, això ja hauria de ser suficient perquè pugueu dibuixar prototips d'habilitats en fitxers yaml sense distreure's massa amb els detalls tècnics.

Si voleu un NLU més seriós, podeu adjuntar-lo a la vostra habilitat Rasa o DeepPavlov, però configurar-los requerirà balls addicionals amb un tamborí, especialment en sense servidor. Si no teniu ganes de codificar, hauríeu d'utilitzar un constructor visual com Aimylogic. En crear tgalice, vaig pensar en algun tipus de camí intermedi. A veure què en surt d'això.

Bé, ara uneix-te xat per a desenvolupadors d'habilitats d'alice, llegiu documentació, i crear meravellós habilitats!

Font: www.habr.com

Afegeix comentari