Opprette en stateful ferdighet for Alice på de serverløse funksjonene til Yandex.Cloud og Python

La oss starte med nyhetene. I går kunngjorde Yandex.Cloud lanseringen av en serverløs datatjeneste Yandex Cloud-funksjoner. Dette betyr: du skriver bare koden for tjenesten din (for eksempel en nettapplikasjon eller en chatbot), og skyen selv oppretter og vedlikeholder virtuelle maskiner der den kjører, og replikerer dem til og med hvis belastningen øker. Du trenger ikke tenke i det hele tatt, det er veldig praktisk. Og betalingen går bare for tidspunktet for beregninger.

Men noen mennesker betaler kanskje ikke i det hele tatt. Dette er utviklerne Alices ytre ferdigheter, det vil si chatbots innebygd i den. Enhver utvikler kan skrive, være vert for og registrere en slik ferdighet, og fra i dag trenger ikke ferdigheter engang å være vert – bare last opp koden deres til skyen i skjemaet samme serverløse funksjon.

Men det er et par nyanser. For det første kan kjæledyrkoden din kreve noen avhengigheter, og det er ikke trivielt å dra dem inn i skyen. For det andre må enhver vanlig chatbot lagre statusen til dialogen et sted (stateful derfor); Hva er den enkleste måten å gjøre dette på i en serverløs funksjon? For det tredje, hvordan kan du skrive en rask og skitten ferdighet for Alice eller til og med en slags bot med et plot som ikke er null? Artikkelen handler faktisk om disse nyansene.

Opprette en stateful ferdighet for Alice på de serverløse funksjonene til Yandex.Cloud og Python

moralsk forberedelse

For de utålmodige: Jeg samler de nødvendige avhengighetene med en makefil før jeg laster opp funksjonen til skyen, jeg lagrer statusen til dialogboksen i Yandex Object Storage (den støtter S3 API), og jeg bruker mitt eget bibliotek til å administrere dialogen tgalice. Som et resultat, viser det seg slik demo ferdigheter. Og la oss nå analysere alt dette litt mer detaljert.

For de litt mindre utålmodige, før du dykker ned i historien min om kompleksitet, anbefaler jeg på det sterkeste å starte enkelt. Nemlig opprette en enkelt-fil echobot-funksjon, registrer og test den i Dialog-utviklerkonsollen; detaljer - i Bloggdialoger и skydokumentasjon. Og først da begynne.

Hvis du umiddelbart vil føle hva vi kjemper for, spør Alice 'slå på ferdigheten "IT-horoskop"'. Følgende dialog bør finne sted:

Alice: Hei! Du er i ferdighetene "IT-horoskop". Si «Start» for å finne ut hva stjernene lover deg.
Bruker: Start
A: Vennligst oppgi navnet ditt.
Yu: Vasisualy
A: Fortell meg nå hvilket år du ble født. Bare fire sifre, ikke noe mer.
Yu: andre
A: Vennligst prøv igjen. Oppgi fødselsåret - fire sifre.
Yu: 2002
En stor! Gi nå navn til fødselsmåneden din.
Yu: februar
En stor! Til slutt, fortell meg fødselsdatoen din - bare et tall, bare ett eller to sifre.
Yu: 18
A: Takk Vasily! Nå vet vi: du er 17 år gammel og en vannmann. Vel, selvfølgelig, du er heldig! Stjernene forteller deg а что говорят звёзды, вы узнаете, запустив навык.

Problemet er at for å opprettholde selv en så enkel dialog, må du huske navnet og fødselsdatoen til brukeren, og i et serverløst miljø er dette ikke trivielt. Det vil ikke fungere å lagre konteksten i RAM eller som en fil på disk, fordi Yandex.Cloud kan kjøre funksjonen på flere virtuelle maskiner samtidig og bytte mellom dem vilkårlig. Du må bruke en slags ekstern lagring. Object Storage ble valgt som en ganske rimelig og enkel lagring direkte i Yandex.Cloud (det vil si sannsynligvis rask). Som et gratis alternativ kan du prøve for eksempel et gratis stykke Overskyet Mongi et sted langt borte. Både Object Storage (den støtter S3-grensesnittet) og Mongo har praktiske Python-innpakninger.

Et annet problem er at for å få tilgang til Object Storage, MongoDB og enhver annen database eller datalager, trenger du noen eksterne avhengigheter som må lastes opp til Yandex Functions sammen med funksjonskoden din. Og jeg vil gjerne gjøre det praktisk. Dessverre vil det ikke være helt praktisk (som på Heroku), men litt grunnleggende komfort kan skapes ved å skrive et skript for å bygge miljøet (lag fil).

Hvordan starte horoskopferdigheten

  1. Gjør deg klar: gå til en maskin med Linux. I prinsippet kan du sikkert jobbe med Windows også, men da må du trylle med lanseringen av makefilen. Og i alle fall trenger du minst 3.6 installert Python.
  2. Klone fra github eksempel på en horoskopferdighet.
  3. Registrer deg i Ya.Cloud: https://cloud.yandex.ru
  4. Lag deg to bøtter inn Objektlagring, kall dem ved hvilket som helst navn {BUCKET NAME} и tgalice-test-cold-storage (dette mellomnavnet er nå hardkodet inn main.py mitt eksempel). Den første bøtten vil bare være nødvendig for distribusjon, den andre - for lagring av dialogtilstander.
  5. skape tjenestekonto, gi ham en rolle editor, og få statisk legitimasjon for det {KEY ID} и {KEY VALUE} – vi vil bruke dem til å registrere status for dialogen. Alt dette er nødvendig for at funksjonen fra Ya.Cloud skal få tilgang til lagringen fra Ya.Cloud. En dag, håper jeg, vil autorisasjon bli automatisk, men foreløpig - så.
  6. (Valgfritt) installer kommandolinjegrensesnitt yc. Du kan også lage en funksjon gjennom webgrensesnittet, men CLI er bra fordi alle slags innovasjoner dukker opp i den raskere.
  7. Nå kan du faktisk forberede sammenstillingen av avhengigheter: kjør på kommandolinjen fra mappen med ferdighetseksemplet make all. En haug med biblioteker (for det meste, som vanlig, unødvendig) vil bli installert i mappen dist.
  8. Fyll med penner i Object Storage (i en bøtte {BUCKET NAME}) arkivet hentet i forrige trinn dist.zip. Om ønskelig kan du gjøre dette fra kommandolinjen, for eksempel ved å bruke AWS CLI.
  9. Lag en serverløs funksjon via webgrensesnittet eller ved hjelp av verktøyet yc. For verktøyet vil kommandoen se slik ut:

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

Når du oppretter en funksjon manuelt, fylles alle parametere ut på samme måte.

Nå kan funksjonen du opprettet testes gjennom utviklerkonsollen, og deretter ferdigstilles og publiseres ferdigheter.

Opprette en stateful ferdighet for Alice på de serverløse funksjonene til Yandex.Cloud og Python

Hva er under panseret

Makefilen inneholder faktisk et ganske enkelt skript for å installere avhengigheter og sette dem inn i et arkiv. dist.zip, noe sånt som dette:

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

Resten er noen få enkle verktøy pakket inn i et bibliotek tgalice. Prosessen med å fylle ut brukerdata er beskrevet av konfigurasjonen 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: Пожалуйста, попробуйте ещё раз. Вам нужно назвать число своего рождения (например, двадцатое); это одна или две цифры.

Python-klassen tar over arbeidet med å analysere denne konfigurasjonen og beregne det endelige resultatet

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

Mer presist, basisklassen FormFillingDialogManager er engasjert i å fylle ut "skjemaet", og metoden til barneklassen handle_completed_form forteller henne hva hun skal gjøre når hun er klar.

I tillegg til denne hovedflyten av brukerens dialog, er det også nødvendig å hilse på brukeren, samt gi hjelp på "help"-kommandoen og frigjøre ferdigheten på "exit"-kommandoen. For dette i tgalice det er også en mal, så hele dialogbehandleren består av deler:

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 Det fungerer enkelt: det prøver å bruke alle komponentene til den nåværende statusen til dialogen etter tur, og velger den første passende.

Som et svar på hver melding returnerer dialogadministratoren et python-objekt Response, som deretter kan konverteres til ren tekst, eller til en melding i Alice eller Telegram - avhengig av hvor boten kjører; den inneholder også den endrede tilstanden til dialogboksen som må lagres. Alt dette kjøkkenet håndteres av en annen klasse, DialogConnector, så det direkte skriptet for å lansere en ferdighet på Yandex Functions ser slik ut:

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

Som du kan se, skaper det meste av denne koden en forbindelse til Object Storage S3-grensesnittet. Hvordan denne forbindelsen brukes direkte, kan du lese i tgalice-kode.
Den siste linjen lager en funksjon alice_handler - den som vi bestilte for å trekke Yandex.Cloud når vi satte parameteren --entrypoint=main.alice_handler.

Det er faktisk alt. Make-filer for bygging, S3-lignende objektlagring for kontekstlagring og et python-bibliotek tgalice. Sammen med de serverløse funksjonene og uttrykksevnen til python, er dette nok til å utvikle ferdighetene til en sunn person.

Du kan spørre hvorfor du trenger å lage tgalice? All kjedelig kode som overfører JSON-er fra forespørsel til svar og fra lagring til minne og tilbake ligger i den. Det er også en vanlig kodeapplikasjon, en funksjon for å forstå at "februar" ligner på "februar", og annen NLU for de fattige. Ifølge ideen min burde dette allerede være nok slik at du kan skissere prototyper av ferdigheter i yaml-filer uten å bli for distrahert av tekniske detaljer.

Hvis du vil ha en mer seriøs NLU, kan du skru den til dine ferdigheter Rasa eller DeepPavlov, men å sette dem opp vil kreve ekstra dans med en tamburin, spesielt på serverløs. Hvis du ikke har lyst til å kode i det hele tatt, bør du bruke den visuelle typekonstruktøren Aimylogisk. Da jeg opprettet tgalice, tenkte jeg på en slags mellombane. La oss se hva som skjer.

Vel, bli med nå Aliy ferdighetsutviklerchat, les dokumentasjon, og skape fantastisk ferdigheter!

Kilde: www.habr.com

Legg til en kommentar