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

Empecemos por las noticias. Ayer Yandex.Cloud anunció el lanzamiento de un servicio informático sin servidor Funciones de la nube de Yandex. Esto significa: tú solo escribes el código de tu servicio (por ejemplo, una aplicación web o un chatbot), y la propia Nube crea y mantiene las máquinas virtuales donde se ejecuta, e incluso las replica si la carga aumenta. No tienes que pensar en absoluto, es muy conveniente. Y el pago va sólo por el momento de los cálculos.

Sin embargo, es posible que algunas personas no paguen nada. Estos son los desarrolladores Las habilidades externas de Alice., es decir, chatbots integrados. Cualquier desarrollador puede escribir, alojar y registrar dicha habilidad y, a partir de hoy, ni siquiera es necesario alojar las habilidades: simplemente cargue su código en la nube en el formulario la misma función sin servidor.

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

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

preparación 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 uso mi propia biblioteca para administrar el diálogo. tgalice. Como resultado, resulta tal habilidad de demostración. Y ahora analicemos todo esto con un poco más de detalle.

Para los un poco menos impacientes, antes de sumergirse en mi historia de complejidad, recomiendo comenzar de manera simple. Es decir, cree una función echobot de un solo archivo, regístrela y pruébela en la consola de desarrollador de Dialog; detalles - en Diálogos de blogs и documentación en la nube. Y solo entonces empieza.

Si quieres sentir inmediatamente por qué estamos luchando, pregúntale a Alice 'activa la habilidad "horóscopo de TI"'. Debe tener lugar el siguiente diálogo:

Alicia: ¡Hola! Estás en la habilidad "Horóscopo de TI". Di "Empezar" para descubrir qué te prometen las estrellas.
Usuario: Inicio
R: Por favor indique su nombre.
Yu: Vasisualy
R: Ahora dime el año de tu nacimiento. Sólo cuatro dígitos, nada más.
Yu: segundo
R: Inténtelo de nuevo. Indique el año de su nacimiento: cuatro dígitos.
Yu: 2002
¡Un gran! Ahora nombra el mes de tu nacimiento.
Yu: febrero
R: ¡Excelente! Finalmente, dime tu fecha de nacimiento; solo un número, solo uno o dos dígitos.
Yu: 18
R: ¡Gracias Vasisual! Ahora lo sabemos: tienes 17 años y eres Acuario. ¡Aquí tienes, por supuesto, suerte! Las estrellas te lo dicen а что говорят звёзды, вы узнаете, запустив навык.

El problema es que para mantener incluso un diálogo tan simple, es necesario recordar el nombre y la fecha de nacimiento del usuario, y en un entorno sin servidor esto no es trivial. No funcionará almacenar el contexto en la RAM o como un archivo en el disco, porque Yandex.Cloud puede ejecutar la función en varias máquinas virtuales al mismo tiempo y alternar entre ellas de forma arbitraria. Tendrás que utilizar algún tipo de almacenamiento externo. Se eligió Object Storage como un almacenamiento bastante económico y simple directamente en Yandex.Cloud (es decir, probablemente rápido). Como alternativa gratuita, puedes probar, por ejemplo, una pieza gratuita. Mongi nublado Algún lugar lejano. Tanto Object Storage (es compatible con la interfaz S3) como Mongo tienen prácticos envoltorios de Python.

Otro problema es que para acceder a Object Storage, MongoDB y 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 cómodamente. Es completamente conveniente (como en heroku), lamentablemente no funcionará, pero puede crear algo de comodidad básica escribiendo un script para construir el entorno (crear archivo).

Cómo iniciar la habilidad del horóscopo

  1. Prepárate: ve a alguna máquina con Linux. En principio, probablemente también puedas trabajar con Windows, pero luego tendrás que conjurar el lanzamiento del archivo MAKE. Y en cualquier caso, necesitarás al menos 3.6 de Python instalado.
  2. Clonar desde github ejemplo de una habilidad del horóscopo.
  3. Regístrate en Ya.Cloud: https://cloud.yandex.ru
  4. Crea dos cubos en Almacenamiento de objetosllámalos por cualquier nombre {BUCKET NAME} и tgalice-test-cold-storage (este segundo nombre ahora está codificado en main.py mi ejemplo). El primer depósito será necesario solo para la implementación, el segundo, para almacenar los estados del diálogo.
  5. crear cuenta de servicio, dale un papel editory obtener credenciales estáticas para ello {KEY ID} и {KEY VALUE} - los usaremos para registrar el estado del diálogo. Todo esto es necesario para que la función de Ya.Cloud pueda acceder al almacenamiento desde Ya.Cloud. Espero que algún día la autorización sea automática, pero por ahora así es.
  6. (Opcional) instalar interfaz de línea de comando yc. También puede crear una función a través de la interfaz web, pero la CLI es buena porque todo tipo de innovaciones aparecen en ella más rápidamente.
  7. De hecho, ahora puede preparar el ensamblaje de dependencias: ejecute en la línea de comando desde la carpeta con el ejemplo de habilidad make all. Se instalarán un montón de bibliotecas (en su mayoría, como de costumbre, innecesarias) en la carpeta. dist.
  8. Llénelo con bolígrafos en el Almacenamiento de objetos (en un cubo {BUCKET NAME}) el archivo obtenido en el paso anterior dist.zip. Si lo desea, también puede hacerlo desde la línea de comando, por ejemplo, usando CLI de AWS.
  9. Cree una función sin servidor a través de la interfaz web o utilizando la utilidad yc. Para la utilidad, el comando tendrá este 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

Al crear manualmente una función, 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 finalizarla y publicarla.

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

¿Qué hay debajo del capó?

El archivo MAKE en realidad contiene un script bastante simple para instalar dependencias y guardarlas en un 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 una biblioteca. tgalice. El proceso de completar los datos del usuario se describe en la 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: Пожалуйста, попробуйте ещё раз. Вам нужно назвать число своего рождения (например, двадцатое); это одна или две цифры.

La clase Python se hace cargo del 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 le dice qué hacer cuando esté lista.

Además de este flujo principal de diálogo, el usuario también debe ser saludado, así como brindarle ayuda con el comando "ayuda" y liberarlo de la habilidad con el comando "salir". Para esto en tgalice También hay una plantilla, por lo que todo el administrador de diálogo se compone de 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 al estado actual del diálogo todos sus componentes por turno y selecciona el primero relevante.

Como respuesta a cada mensaje, el administrador de diálogo devuelve un objeto de Python. Response, que luego se puede convertir en texto sin formato o en un mensaje en Alice o Telegram, dependiendo de dónde se esté ejecutando el bot; también contiene el estado modificado del cuadro de diálogo que debe guardarse. Toda esta cocina la maneja otra clase, DialogConnector, por lo que el script directo para iniciar una 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 a la interfaz de Object Storage S3. Cómo se utiliza directamente esta conexión, puedes leer en código tgalice.
La última línea crea una función. alice_handler - el que ordenamos extraer Yandex.Cloud cuando configuramos el parámetro --entrypoint=main.alice_handler.

Eso, de hecho, es todo. Makefiles para construcción, almacenamiento de objetos similar a S3 para almacenamiento de contexto y una biblioteca de Python tgalice. Junto con las funciones sin servidor y la expresividad de Python, esto es suficiente para desarrollar la habilidad de una persona sana.

Quizás te preguntes por qué necesitas 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 normal, una función para comprender que "febrero" es similar a "febrero" y otras NLU para los pobres. Según mi idea, esto ya debería ser suficiente para poder esbozar prototipos de habilidades en archivos yaml sin distraerse demasiado con detalles técnicos.

Si quieres una NLU más seria, puedes atornillarla a tu habilidad. Rasa o ProfundoPavlov, pero configurarlos requerirá baile adicional con una pandereta, especialmente en sistemas sin servidor. Si no tienes ganas de codificar en absoluto, deberías utilizar el constructor de tipos visuales. Aimylogic. Al crear tgalice, pensé en algún tipo de camino intermedio. Veamos qué pasa.

Bueno, ahora únete Chat de desarrollador de habilidades de Aliy, leer documentacióny crear increíbles навыки!

Fuente: habr.com

Añadir un comentario