Crear una habilidad con estado para Alice en las funciones sin servidor de Yandex.Cloud y Python

Comencemos con las noticias. Ayer, Yandex.Cloud anunció el lanzamiento del servicio informático sin servidor Yandex Cloud Functions . Esto significa: solo escribe el código de su servicio (por ejemplo, una aplicación web o chatbot), y la propia nube crea y mantiene máquinas virtuales donde se inicia, e incluso las replica si aumenta la carga. No es necesario pensar en absoluto, es muy conveniente. Y la tarifa va solo durante el cálculo.


Sin embargo, algunos pueden no pagar en absoluto. Estos son los desarrolladores de las habilidades externas de Alice , es decir, chatbots integrados en ella. Cualquier desarrollador puede escribir, alojar y registrar dicha habilidad, y desde hoy las habilidades ni siquiera necesitan ser alojadas, solo cargue su código en la nube en la forma de la función sin servidor .


Pero hay un par de matices. En primer lugar, su código de mascota puede requerir algunas dependencias, y atraerlos a la nube no es trivial. En segundo lugar, cualquier chatbot normal necesita almacenar el estado del diálogo en algún lugar (por lo tanto, con estado); ¿Cómo hacer esto en una función sin servidor más fácil? En tercer lugar, ¿cómo puedes escribir una habilidad rápida y sucia para Alice o algún tipo de bot con una trama distinta de cero? Sobre estos matices, de hecho, un artículo.


imagen

Entrenamiento moral


Para los impacientes: recopilo las dependencias necesarias con un archivo make antes de cargar la función en la nube, almaceno el estado del diálogo en Yandex Object Storage (es compatible con la API S3) y, para administrar el diálogo, uso mi propia biblioteca tgalice . El resultado es una habilidad de demostración. Ahora echemos un vistazo a todo esto con más detalle.


Para un poco menos impaciente: antes de sumergirme en mi historia sobre dificultades, recomiendo comenzar con una simple. A saber, crear una función de ecosonda de un solo archivo, registrarla y probarla en la consola de desarrollador de Dialogs; los detalles se encuentran en el Blog de Cloud Dialogs y documentación . Y solo entonces para proceder.


Si quiere sentir de inmediato por lo que estamos luchando, pídale a Alice que active la habilidad "horóscopo informático " . El siguiente diálogo debería suceder:


Alice: hola! Estás en la habilidad del Horóscopo Aishish. Di "Comenzar" para descubrir qué te prometen las estrellas.
Usuario: Inicio
A: por favor da tu nombre.
Yu: Vasisuali
A: Ahora dime el año de tu nacimiento. Solo cuatro números, nada más.
Yu: segundo
A: Por favor intente nuevamente. ¿Cuál es el año de su nacimiento? Cuatro dígitos.
U: 2002
A: genial! Ahora nombra el mes de tu nacimiento.
U: febrero
A: genial! Finalmente, dígame la fecha de su nacimiento: solo un número, solo uno o dos dígitos.
U: 18
A: ¡Gracias Vasisuali! Ahora lo sabemos: tienes 17 años y eres Acuario. ¡Aquí tienes, por supuesto, suerte! Las estrellas te dicen: , , .


El problema es que para mantener un diálogo tan simple, debe recordar el nombre y la fecha de nacimiento del usuario, y en un entorno sin servidor, esto no es trivial. Almacene el contexto en RAM o un archivo en el disco no funcionará, porque Yandex.Cloud puede ejecutar la función en varias máquinas virtuales al mismo tiempo y alternar entre ellas de forma arbitraria. Tendremos que usar algún tipo de almacenamiento externo. Object Storage fue elegido como un almacenamiento bastante económico y sencillo en Yandex.Cloud (es decir, probablemente rápido). Como alternativa gratuita, puede probar, por ejemplo, un trozo de Monga nublado en algún lugar lejano. Tanto Object Storage (es compatible con la interfaz S3) como Mongo tienen envoltorios Python convenientes.


Otro problema es que para caminar en Object Storage, en MongoDB y en cualquier otra base de datos o almacén de datos, necesita algunas dependencias externas que debe cargar en Yandex Functions junto con su código de función. Y me gustaría hacerlo convenientemente. Es bastante conveniente (como heroku), por desgracia, no funcionará, pero puede crear cierta comodidad básica escribiendo un script para construir el entorno (make-file).


Cómo ejecutar una habilidad de horóscopo


  1. Prepárese: vaya a alguna máquina Linux. En principio, probablemente también pueda trabajar con Windows, pero luego debe evocar el inicio del archivo make. Y en cualquier caso, necesitará instalar Python no menos de 3.6.
  2. Clonarte con github un ejemplo de una habilidad de horóscopo .
  3. Regístrese en Y. Cloud: https://cloud.yandex.ru
  4. Cree dos cubos para usted en Object Storage , tgalice-test-cold-storage nombre {BUCKET NAME} y tgalice-test-cold-storage (este segundo nombre ahora está codificado en main.py mi ejemplo). El primer depósito será necesario solo para el despliegue, el segundo, para almacenar estados de diálogo.
  5. Cree una cuenta de servicio , dele el rol de editor y obtenga tarjetas de crédito estáticas {KEY ID} y {KEY VALUE} ; las utilizaremos para registrar el estado del diálogo. Todo esto es necesario para que una función de Y. Cloud pueda acceder al repositorio desde Y. Cloud. Algún día, espero que la autorización se vuelva automática, pero por ahora, así es.
  6. (Opcional) instale la interfaz de línea de comando yc . Puede crear una función a través de la interfaz web, pero la CLI es buena ya que todo tipo de innovaciones aparecen más rápidamente.
  7. Ahora puede, de hecho, preparar el ensamblaje de dependencia: ejecutar en el símbolo del sistema desde una carpeta con el ejemplo make all skill. Se instalarán un montón de bibliotecas (principalmente, como de costumbre, innecesarias) en la carpeta dist .
  8. Vierta el almacenamiento de objetos (en el {BUCKET NAME} ) el archivo dist.zip obtenido en el paso anterior. Si lo desea, puede hacerlo desde la línea de comandos, por ejemplo, usando la AWS CLI .
  9. Cree una función sin servidor a través de la interfaz web o utilizando la utilidad yc . Para la utilidad, el comando se verá así:

 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 

Cuando se crea una función manualmente, todos los parámetros se completan de la misma manera.


Ahora la función que creó se puede probar a través de la consola del desarrollador y luego modificar y publicar la habilidad.



¿Qué hay debajo del capó?


El archivo MAKE en realidad contiene un script bastante simple para instalar las dependencias y ponerlas en el archivo dist.zip , algo como esto:


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

El resto son algunas herramientas simples envueltas en la biblioteca tgalice . El proceso de completar los datos del usuario se describe en la form.yaml 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 clase python realiza el trabajo de analizar esta configuración y calcular el resultado 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 precisamente, la clase base FormFillingDialogManager se dedica a completar el "formulario", y el método de la clase secundaria handle_completed_form dice qué hacer cuando está listo.


Además de este flujo principal del diálogo del usuario, también debe saludar, así como brindar ayuda con el comando "ayuda" y liberarse de la habilidad en el comando "salir". tgalice también tiene una plantilla para esto, por lo que todo el administrador de diálogo está formado por partes:


 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 simple: intenta aplicar todos sus componentes al estado actual del diálogo a su vez, y selecciona el primero apropiado.


Como respuesta a cada mensaje, el administrador de diálogo devuelve un objeto de Response , que se puede convertir en texto sin formato o en un mensaje en Alice o Telegram, dependiendo de dónde se inicie el bot; También contiene el estado modificado del diálogo, que debe guardarse. Otra clase, DialogConnector , se dedica a toda esta cocina, por lo que el guión directo para lanzar la habilidad en Yandex Functions se ve así:


 ... 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 puede ver, la mayor parte de este código crea una conexión con la interfaz Object Storage S3. La forma en que esta conexión se usa directamente se puede leer en el código tgalice .
La última línea crea la función alice_handler , la que le pedimos a Yandex.Cloud que extraiga cuando establecemos el --entrypoint=main.alice_handler .


Eso, de hecho, es todo. Makefiles para el ensamblaje, almacenamiento de objetos tipo S3 para almacenar el contexto y la biblioteca tgalice python. Junto con las funciones sin servidor y la expresividad de la pitón, esto es suficiente para desarrollar la habilidad de una persona sana.


Puede preguntar, ¿por qué necesitaba crear tgalice ? Todo el código aburrido que transfiere JSON de la solicitud a la respuesta y del almacenamiento a la memoria, y viceversa, se encuentra en él. También hay una aplicación de controlador regular, una función para comprender cómo es "febrero" y "otra NLU para los pobres". Según mi idea, esto ya debería ser suficiente para que pueda esbozar prototipos de habilidades en archivos yaml sin distraerse demasiado con los detalles técnicos.


Si desea una NLU más seria, puede atornillar Rasa o DeepPavlov a su habilidad, pero para configurarlos, necesitará bailes adicionales con una pandereta, especialmente en sin servidor. Si no tiene ganas de codificar en absoluto, debe usar un constructor visual como Aimylogic . Al crear tgalice, estaba pensando en algún tipo de camino intermedio. Veamos que pasa.


Bueno, ahora únete al chat de desarrolladores de sus habilidades , lee la documentación y crea habilidades maravillosas.

Source: https://habr.com/ru/post/469723/


All Articles