Creando unha habilidade con estado para Alice nas funcións sen servidor de Yandex.Cloud e Python

Comezamos coas noticias. Onte Yandex.Cloud anunciou o lanzamento dun servizo de computación sen servidor Funcións de Yandex Cloud. Isto significa: só escribes o código do teu servizo (por exemplo, unha aplicación web ou un chatbot), e a propia Nube crea e mantén as máquinas virtuais onde se executa, e mesmo as replica se a carga aumenta. Non necesitas pensar nada, é moi cómodo. E o pago é só polo tempo de cálculo.

Non obstante, algúns poden non pagar en absoluto. Estes son os desenvolvedores As habilidades externas de Alicia, é dicir, chatbots integrados nel. Calquera desenvolvedor pode escribir, aloxar e rexistrar tal habilidade, e a partir de hoxe as habilidades nin sequera precisan estar aloxadas; só tes que cargar o seu código na nube no formulario a mesma función sen servidor.

Pero hai un par de matices. En primeiro lugar, o teu código pit pode requirir algunhas dependencias e arrastralas á nube non é trivial. En segundo lugar, calquera chatbot normal necesita almacenar o estado do diálogo nalgún lugar (con estado polo tanto); Cal é a forma máis sinxela de facelo nunha función sen servidor? En terceiro lugar, como podes escribir unha habilidade rápida e sucia para Alice ou incluso algún tipo de bot cunha trama distinta de cero? O artigo trata, de feito, destes matices.

Creando unha habilidade con estado para Alice nas funcións sen servidor de Yandex.Cloud e Python

Preparación moral

Para os impacientes: recompilo as dependencias necesarias cun makefile antes de cargar a función na nube, almacene o estado do diálogo en Yandex Object Storage (soporta a API S3) e uso a miña propia biblioteca para xestionar o diálogo tgalice. Ao final resulta tal habilidade de demostración. Agora vexamos todo isto cun pouco máis de detalle.

Para aqueles un pouco menos impacientes, antes de mergullarse na miña historia sobre a complexidade, recoméndolles comezar por algo sinxelo. É dicir, crea unha función de echobot dun só ficheiro, rexístraa e proba na consola de desenvolvedores de Dialogs; detalles - en Blog de diálogos и Documentación na nube. E só entón comeza.

Se queres sentir de inmediato o que estamos loitando aquí, pregúntalle a Alicia.habilitar a habilidade "horóscopo informático".'. Debería producirse un diálogo similar ao seguinte:

Alicia: Ola! Estás na habilidade "Horóscopo de TI". Di "Comezar" para descubrir o que che prometen as estrelas.
Usuario: Iniciar
R: Indica o teu nome
Yu: Vasisualiy
R: Agora dime o ano do teu nacemento. Só catro díxitos, nada extra.
Yu: segundo
R: Téntao de novo. Introduce o ano do teu nacemento: catro díxitos.
Iu: 2002
A: Xenial! Agora pon o teu mes de nacemento.
Yu: febreiro
A: Xenial! Finalmente, dime a túa data de nacemento: só un número, só un ou dous díxitos.
Iu: 18
R: Grazas, Vasisualiy! Agora sabemos: tes 17 anos e un Acuario. Ben, claro, tes sorte! As estrelas dinche: а что говорят звёзды, вы узнаете, запустив навык.

O problema é que, para manter mesmo un diálogo tan sinxelo, cómpre lembrar o nome e a data de nacemento do usuario, e nun ambiente de función sen servidor isto non é trivial. Non será posible almacenar o contexto na RAM ou como un ficheiro no disco, porque Yandex.Cloud pode executar unha función en varias máquinas virtuais ao mesmo tempo e cambiar entre elas cando queira. Terás que usar algún tipo de almacenamento externo. O almacenamento de obxectos escolleuse como un almacenamento bastante económico e sen complicacións directamente en Yandex.Cloud (é dicir, probablemente rápido). Como alternativa gratuíta, podes probar, por exemplo, unha peza gratuíta Monga nubrada nalgún lugar lonxe. Hai envoltorios de Python convenientes tanto para Object Storage (que admite a interface S3) como para Mongo.

Outro problema é que para acceder ao Object Storage, MongoDB e calquera outra base de datos ou almacén de datos, necesitas algunhas dependencias externas que hai que cargar en Yandex Functions xunto co teu código de función. E gustaríame facelo convenientemente. Desafortunadamente, non será completamente conveniente (como en Heroku), pero pódese crear unha comodidade básica escribindo un script para construír o ambiente (crear ficheiro).

Como iniciar unha habilidade de horóscopo

  1. Preparar: vai a algunha máquina con Linux. En principio, probablemente tamén poidas traballar con Windows, pero entón terás que facer algo de maxia ao lanzar o makefile. E en calquera caso, necesitarás polo menos Python 3.6 instalado.
  2. Clonalo desde Github exemplo de habilidade horóscopo.
  3. Rexistrarse en Y.Cloud: https://cloud.yandex.ru
  4. Crea dous baldes dentro Almacenamento de obxectos, chámaos por calquera nome {BUCKET NAME} и tgalice-test-cold-storage (Este segundo nome agora está codificado en main.py o meu exemplo). O primeiro depósito só será necesario para a implantación, o segundo para almacenar estados de diálogo.
  5. crear conta de servizo, dálle un papel editor, e obtén credenciais estáticas para iso {KEY ID} и {KEY VALUE} — utilizarémolos para rexistrar o estado do diálogo. Todo isto é necesario para que unha función de Ya.Cloud poida acceder ao almacenamento desde Ya.Cloud. Algún día, espero, a autorización se fará automática, pero de momento é así.
  6. (Opcional) instalar interface de liña de comandos yc. Tamén podes crear unha función a través da interface web, pero a CLI é boa porque todo tipo de innovacións aparecen nela máis rápido.
  7. Agora podes preparar o conxunto de dependencias: executa na liña de comandos desde o cartafol co exemplo de habilidade make all. No cartafol instalaranse unha morea de bibliotecas (a maioría, como é habitual, innecesarias). dist.
  8. Verter a man no almacenamento de obxectos (no balde {BUCKET NAME}) arquivo obtido no paso anterior dist.zip. Se o desexa, pode facelo desde a liña de comandos, por exemplo, usando AWS CLI.
  9. Cree unha función sen servidor a través da interface web ou mediante unha utilidade yc. Para a utilidade, o comando terá o seguinte aspecto:

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

Ao crear unha función manualmente, todos os parámetros enchen do mesmo xeito.

Agora a función que creaches pódese probar a través da consola do programador e, a continuación, pódese mellorar e publicar a habilidade.

Creando unha habilidade con estado para Alice nas funcións sen servidor de Yandex.Cloud e Python

O que hai debaixo do capó

O makefile en realidade contén un script bastante sinxelo para instalar dependencias e poñelas nun arquivo dist.zip, aproximadamente así:

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

O resto son algunhas ferramentas sinxelas envoltas nunha biblioteca tgalice. O proceso de encher os datos do usuario descríbese na configuración 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: Пожалуйста, попробуйте ещё раз. Вам нужно назвать число своего рождения (например, двадцатое); это одна или две цифры.

O traballo de analizar esta configuración e calcular o resultado final corre a cargo da clase 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

Máis precisamente, a clase base FormFillingDialogManager ocúpase de cubrir o "formulario" e do método de clase infantil handle_completed_form dille que facer cando estea lista.

Ademais deste fluxo principal de diálogo, o usuario tamén debe ser saudado, así como recibir axuda mediante o comando "axuda" e liberado da habilidade mediante o comando "saír". Para tal fin en tgalice Tamén hai un modelo, polo que todo o xestor de diálogo está formado por pezas:

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 forma sinxela: tenta aplicar todos os seus compoñentes ao estado actual do diálogo á súa vez e selecciona o primeiro axeitado.

O xestor de diálogo devolve un obxecto Python como resposta a cada mensaxe. Response, que despois se pode converter en texto simple ou nunha mensaxe en Alice ou Telegram, dependendo de onde estea executando o bot; tamén contén o estado modificado do diálogo que hai que gardar. Toda esta cociña encárgase outra clase, DialogConnector, polo que o guión directo para iniciar unha habilidade en funcións de Yandex ten o seguinte aspecto:

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

Como podes ver, a maior parte deste código crea unha conexión coa interface S3 de Object Storage. Podes ler como se usa directamente esta conexión en código tgalice.
A última liña crea a función alice_handler — o mesmo que dixemos a Yandex.Cloud que tirase cando definimos o parámetro --entrypoint=main.alice_handler.

Iso é todo, en realidade. Makefiles para a montaxe, S3-like Object Storage para almacenar contexto e unha biblioteca Python tgalice. Combinado coas funcións sen servidor e a expresividade de Python, isto é suficiente para desenvolver unha habilidade humana saudable.

Podes preguntar por que foi necesario crear tgalice? Todo o aburrido código que transfire JSONs da solicitude á resposta e do almacenamento á memoria e viceversa reside nel. Tamén hai unha aplicación de código normal, unha función para entender que "febreiro" é semellante a "febreiro" e outras NLU para os pobres. Segundo a miña idea, isto xa debería ser suficiente para que poida esbozar prototipos de habilidades en ficheiros yaml sen distraerse demasiado polos detalles técnicos.

Se queres un NLU máis serio, podes asocialo á túa habilidade Rasa ou DeepPavlov, pero configuralos requirirá bailes adicionais cunha pandeireta, especialmente no servidor sen servidor. Se non tes ganas de codificar, deberías usar un construtor visual como Aimylogic. Ao crear tgalice, pensei nalgún tipo de camiño intermedio. A ver que sae disto.

Ben, agora únete chat para desenvolvedores de habilidades de alice, ler documentación, e crea marabillosas habilidades!

Fonte: www.habr.com

Engadir un comentario