Izrada stateful vještine za Alisu na serverless funkcijama Yandex.Clouda i Pythonu

Počnimo s vijestima. Jučer je Yandex.Cloud najavio pokretanje servisa bez poslužitelja. Yandex Cloud Functions. To znači: pišete samo kod svoje usluge (na primjer, web-aplikacije ili chatbota), a Oblačno samo stvara i održava virtualne machine gdje se on pokreće, i čak ih replicira ako se poveća opterećenje. Ne morate razmišljati, vrlo je praktično. I plaćate samo za vrijeme računalnih operacija.

Međutim, neki možda uopće neće plaćati. To su programeri vanjskih vještina Alise, to jest ugrađenih u nju chatbota. Bilo koji programer može napisati, hostati i registrirati takvu vještinu, a od danas vještine čak ne trebate hostati - dovoljno je učitati njihov kod u oblak u obliku te iste funkcije bez poslužitelja.

Ali postoje par nuansi. Prvo, vaš Python kod može zahtijevati neke ovisnosti, a prenijeti ih u Oblak - nije jednostavno. Drugo, svakom normalnom chatbota treba negdje pohraniti stanje dijaloga (stateful, dakle); kako to najjednostavnije napraviti u funkciji bez poslužitelja? Treće, kako se može brzo i prljavo napisati vještina za Alisu ili bilo kojeg bota s nekakvim suvislim zapletom? O tim nijansama, zapravo, govori članak.

Izrada stateful vještine za Alisu na serverless funkcijama Yandex.Clouda i Pythonu

Moralna priprema

Za nestrpljive: potrebne ovisnosti prikupljam make datotekom prije učitavanja funkcije u oblak, stanje dijaloga čuvam u Yandexovom Object Storage (podržava S3 API), a za upravljanje dijalogom koristim svoju biblioteku tgalice. Na kraju, dobivam takve demo-vještinu. A sada ćemo to malo detaljnije razraditi.

Za malo manje nestrpljive: prije nego što se upustite u moju priču o poteškoćama, toplo preporučam da počnete s jednostavnim. A to jest, kreirati jednofajlsku funkciju eho-bota, registrirati je i testirati u konzoli za razvoj Dialoga; detalji - u blogu Dialoga i dokumentaciji Oblaka. I tek tada krenite.

Ako želite odmah osjetiti za što se borimo, zamolite Alisu 'uključi vještinu «IT horoskop»‘. Trebalo bi se dogoditi otprilike sljedeći dijalog:

Alisa: Pozdrav! Nalazite se u vještini «IT horoskop». Recite 'Start' kako biste saznali što vam zvijezde predviđaju.
Korisnik: Start
A: Molim vas, navedite svoje ime.
K: Vasisuvaliy
A: Sada recite godinu svog rođenja. Samo četiri znamenke, ništa više.
Ju: drugi
A: Molimo vas, pokušajte ponovo. Navedite godinu svog rođenja — četiri znamenke.
Ju: 2002
A: Odlično! Sada navedite mjesec svog rođenja.
Ju: Veljača
A: Super! Na kraju, navedite mi datum svog rođenja — samo broj, ukupno jedna ili dvije znamenke.
Ju: 18
A: Hvala, Vasisualy! Sada znamo: imate 17 godina, i vi ste Vodenjak. To vam sigurno ide na ruku! Zvijezde vam govore: Što zvijezde kažu, saznat ćete pokretanjem vještine.

Problem je u tome što za održavanje čak i tako jednostavnog dijaloga trebate zapamtiti ime i datum rođenja korisnika, a u okruženju bez poslužitelja to nije trivijalno. Čuvanje konteksta u operativnoj memoriji ili datotekama na disku neće biti moguće, jer Yandex.Cloud može pokrenuti funkciju na nekoliko virtualnih strojeva istovremeno i prebacivati se između njih proizvoljno. Morat ćete koristiti neko vanjsko skladište. Odabrano je Object Storage, kao prilično jeftino i jednostavno skladište direktno u Yandex.Cloud (tj. vjerojatno brzo). Kao besplatnu alternativu možete pokušati, na primjer, s besplatnim dijelom oblačne Monge neke daleko. I za Object Storage (on podržava S3 sučelje), i za Mongo postoje prikladne Python omotnice.

Drugi problem je što za pristup i Object Storage-u, i MongoDB-u, i svakom drugom bazi ili skladištu podataka, trebaju vam neke vanjske ovisnosti koje treba učitati na Yandex Functions zajedno s kodom vaše funkcije. I bilo bi lijepo to učiniti praktično. Potpuno praktično (poput onoga na Heroku), nažalost, neće biti moguće, ali neki osnovni komfor može se stvoriti pisanjem skripte za izradu okruženja (make-fajl).

Kako pokrenuti vještinu-horoskop

  1. Pripremiti se: ući na neki stroj s Linuxom. U principu, s Windowsom se također vjerojatno može raditi, ali s pokretanjem make-fajla tada ćete morati malo potrajati. I u svakom slučaju, trebat će vam instaliran Python ne stariji od 3.6.
  2. Klona s GitHuba primjer horoskopne vještine.
  3. Registrirati se u Y. oblaku: https://cloud.yandex.ru
  4. Stvoriti dva spremnika u Object Storage, nazvati ih bilo kojim imenom {BUCKET NAME} i tgalice-test-cold-storage (to drugo ime je sada hardkodirano u main.py mog primjera). Prvi spremnik bit će potreban samo za implementaciju, drugi — za čuvanje stanja dijaloga.
  5. Stvori servisni račun, dati mu ulogu editor, i dobiti statičke vjerodajnice za njega {KEY ID} i {KEY VALUE} — koristit ćemo ih za bilježenje stanja dijaloga. Sve ovo je potrebno kako bi funkcija iz Y.Cloud mogla pristupiti skladištu iz Y.Cloud. Nadam se da će autorizacija jednog dana postati automatska, ali za sada — ovako.
  6. (Nije obavezno) instalirati sučelje naredbenog retka yc. Funkciju je moguće izraditi i putem web-sučašća, ali CLI je dobar jer nova poboljšanja dolaze brže.
  7. Sada možemo pripremiti skup ovisnosti: pokrenuti u naredbenom retku iz mape s primjerom vještine make all. Instalirat će se mnoštvo knjižnica (uglavnom, kao obično, nepotrebnih) u mapu dist.
  8. Ručnim putem prenijeti u Object Storage (u bucket {BUCKET NAME}) dobijeni arhiv s prethodnog koraka dist.zip. Ako želite, to možete učiniti i iz naredbenog retka, na primjer, koristeći AWS CLI.
  9. Stvoriti beslužbenu funkciju putem web-sučašća ili koristeći alat yc. Za alat komanda će izgledati ovako:

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

Pri ručnom stvaranju funkcije svi parametri se ispunjavaju na sličan način.

Sada možete testirati funkciju koju ste stvorili putem konzole za programere, a zatim završiti i objaviti vještinu.

Izrada stateful vještine za Alisu na serverless funkcijama Yandex.Clouda i Pythonu

Što se skriva ispod haube

Make datoteka zapravo sadrži prilično jednostavan skript za instalaciju ovisnosti i njihovo pakiranje u arhiv dist.zip, otprilike ovako:

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

Ostalo su nekoliko jednostavnih alata, upakiranih u biblioteku tgalice. Proces ispunjavanja podataka o korisniku opisuje konfiguracija form.yaml:

form_name: 'horoscope_form'
start:
  regexp: 'start|begin'
  suggests:
    - Start
fields:
  - name: 'name'
    question: Molimo, recite mi svoje ime.
  - name: 'year'
    question: Sada mi recite godinu vašeg rođenja. Samo četiri cifre, ništa više.
    validate_regexp: '^[0-9]{4}$'
    validate_message: Molimo, pokušajte ponovo. Recite mi godinu svog rođenja - četiri cifre.
  - name: 'month'
    question: Odlično! Sada mi recite mjesec vašeg rođenja.
    options:
      - siječanj
      - veljača
      - ožujak
      - travanj
      - svibanj
      - lipanj
      - srpanj
      - kolovoz
      - rujan
      - listopad
      - studeni
      - prosinac
    validate_message: Ono što ste rekli ne izgleda kao mjesec. Molimo, recite mi mjesec svog rođenja, bez drugih riječi.
  - name: 'day'
    question: Odlično! Na kraju, recite mi datum vašeg rođenja - samo broj, samo jedna ili dvije cifre.
    validate_regexp: '[0123]?d$'
    validate_message: Molimo, pokušajte ponovo. Morate reći broj svog rođenja (na primjer, dvadeset); to je jedna ili dvije cifre.

Zadatak razrade ovog konfiguracija i izračunavanje konačnog rezultata preuzima Python klasa

class CheckableFormFiller(tgalice.dialog_manager.form_filling.FormFillingDialogManager):
    SIGNS = {
        'siječanj': 'Jarac',
        ...
    }

    def handle_completed_form(self, form, user_object, ctx):
        response = tgalice.dialog_manager.base.Response(
            text='Hvala, {}! Sada znamo: imate {} godina, i vi ste {}. n'
                 'Sreća je na vašoj strani! Zvijezde vam poručuju: {}'.format(
                form['fields']['name'],
                2019 - int(form['fields']['year']),
                self.SIGNS[form['fields']['month']],
                random.choice(FORECASTS),
            ),
            user_object=user_object,
        )
        return response

Točnije, osnovna klasa FormFillingDialogManager bavi se ispunjavanjem 'forme', a metoda podklase handle_completed_form govori što učiniti kada je ona spremna.

Osim ovog glavnog toka dijaloga, korisnika također treba pozdraviti, a također pružiti pomoć na naredbu 'pomoć' i završiti sa vještinom na naredbu 'izlaz'. Za to u tgalice također postoji šablon, pa se cjelokupni dijalog menadžer sastoji od dijelova:

dm = tgalice.dialog_manager.CascadeDialogManager(
    tgalice.dialog_manager.GreetAndHelpDialogManager(
        greeting_message=DEFAULT_MESSAGE,
        help_message=DEFAULT_MESSAGE,
        exit_message='Doviđenja, dođite ponovo u vještinu "IT horoskop"!'
    ),
    CheckableFormFiller(`form.yaml`, default_message=DEFAULT_MESSAGE)
)

CascadeDialogManager radi jednostavno: pokušava primijeniti sve svoje komponente na trenutni dijalog redom, i odabire prvi prikladan.

Kao odgovor na svaku poruku, dijalog menadžer vraća Python objekt Response, koji se može pretvoriti u običan tekst ili u poruku u Alisi ili Telegramu - ovisno o tome gdje je bot pokrenut; u njemu se također nalazi i izmijenjeno stanje dijaloga koje treba očuvati. Svi tim poslovima bavi se još jedna klasa, DialogConnector, tako da izvorni skript za pokretanje vještine na Yandex Functions izgleda ovako:

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

Kao što vidite, veći dio ovog koda stvara vezu s S3 sučeljem Object Storage. O tome kako se ta veza koristi, možete pročitati u kodu tgalice.
Posljednja linija stvara funkciju alice_handler — onu koju smo rekli Yandex. Oblaku da pozove kada smo postavili parametar --entrypoint=main.alice_handler.

To bi bilo to. Make datoteke za izgradnju, S3-sličan Object Storage za pohranu konteksta i Python biblioteka tgalice. U kombinaciji s besposlužnim funkcijama i izražajnošću Pythona, to je dovoljno za razvoj vještine normalne osobe.

Možete pitati zašto je potrebno stvarati tgalice? Весь скучный код, перекладывающий JSON’ы из запроса в ответ и из хранилища в память и обратно, лежит в ней. Там же лежит применялка регулярок, функция для понимания того, что «феврарь» похоже на «февраль», и прочее NLU для бедных. По моей задумке, этого уже должно быть достаточно, чтобы можно было набрасывать прототипы навыков в yaml-файлах, не слишком отвлекаясь на технические детали.

Ako želite ozbiljniji NLU, možete dodati Rasa ili DeepPavlov, ali za njihovo postavljanje bit će potrebni dodatni napori, posebno na besposlužnom. Ako ne želite kodirati, vrijedi iskoristiti vizualni konstruktor poput Aimylogic. Prilikom stvaranja tgalice, razmišljao sam o nekom srednjem putu. Vidjet ćemo što će iz toga ispasti.

Pa, danas se pridružite četu developera Alisnih vještina, čitajte dokumentaciju, i stvarajte prekrasne vještine!

Izvor: habr.com

Kupite pouzdan hosting za web stranice s DDoS zaštitom, VPS VDS servere 🔥 Kupite pouzdan hosting za web stranice s DDoS zaštitom, VPS VDS servere | ProHoster