Vytváření stateful dovednosti pro Alici na serverless funkcích Yandex.Cloud a Pythonu

Začněme s novinkami. Včera Yandex.Cloud oznámil spuštění služby bezserverového výpočtu. Yandex Cloud FunctionsTo znamená: píšete pouze kód svého serveru (například webové aplikace nebo chatbotu) a Cloud sám vytváří a spravuje virtuální stroje, na kterých se spouští, a dokonce je replikují, pokud vzroste zátěž. Nemusíte se o nic starat, je to velmi praktické. A platíte pouze za čas výpočtů.

Někteří však mohou vůbec neplatit. To jsou vývojáři externích dovedností Alisy,, tedy integrovaných chatbotů. Napsat, hostit a zaregistrovat takovou dovednost může každý vývojář, a od dnešního dne není potřeba dovednosti ani hostit - stačí nahrát jejich kód do cloudu jako bezserverovou funkci..

Ale existuje pár nuancí. Za prvé, váš Python kód může vyžadovat nějaké závislosti, a přenášení je do Cloudu není jednoduché. Za druhé, každému normálnímu chatbotu je potřeba někde uchovávat stav dialogu (stateful proto); jak to udělat v bezserverové funkci co nejjednodušeji? A za třetí, jak rychle a jednoduše napsat dovednost pro Alisu nebo jakéhokoli bota s nějakým příběhem? O těchto nuancích vlastně článek je.

Vytváření stateful dovednosti pro Alici na serverless funkcích Yandex.Cloud a Pythonu

Morální příprava

Pro netrpělivé: potřebné závislosti shromažďuji makefilem před nahráním funkce do cloudu, stav dialogu uchovávám v Yandex Object Storage (ten podporuje API S3), a pro řízení dialogu používám svou vlastní knihovnu tgalice.Ve výsledku vzniká takový demo-dovednost. A teď si to rozebereme trochu podrobněji.

Pro trochu méně netrpělivé: než se ponoříte do mého příběhu o potížích, velmi doporučuji začít s jednoduchým. A to totiž vytvořit jednofilovou funkci-echo bota, zaregistrovat ji a otestovat ji v konzoli vývojářů Dialogů; podrobnosti najdete v blogu Dialogů a dokumentaci Cloudu.A teprve potom se pustit do další práce.

Pokud chcete hned pocítit, o co zde bojujeme, požádejte Alisu 'zapni dovednost „IT horoskop“' Mělo by proběhnout přibližně následující dialog:

Alisa: Ahoj! Jste v dovednosti „IT horoskop“. Řekněte „Start“, abyste zjistili, co vám hvězdy slibují.
Uživatel: Start
A: Prosím, řekněte mi své jméno.
U: Vasisauliy
A: Nyní mi řekněte svůj rok narození. Pouze čtyři číslice, nic víc.
U: druhý
A: Prosím, zkuste to ještě jednou. Uveďte rok svého narození — čtyři číslice.
J: 2002
A: Skvěle! Nyní uveďte měsíc svého narození.
J: Únor
A: Výborně! A nakonec mi uveďte datum vašeho narození — pouze číslo, maximálně dvě číslice.
J: 18
A: Děkujeme, Vasisuáli! Nyní víme, že vám je 17 let a jste Vodnář. To je štěstí! Hvězdy vám říkají: co říkají hvězdy, se dozvíte spuštěním dovednosti.

Problém je v tom, že pro udržení i tak jednoduchého dialogu je třeba si pamatovat jméno a datum narození uživatele, což není v prostředí serverless funkcí triviální. Kontext nelze uchovávat v operační paměti nebo v souboru na disku, protože Yandex.Cloud může spustit funkci na více virtuálních strojích současně a libovolně přepínat mezi nimi. Bude třeba využít nějaké externí úložiště. Bylo zvoleno Object Storage, jakožto relativně levné a jednoduché úložiště přímo v Yandex.Cloud (tedy patrně rychlé). Jako bezplatnou alternativu můžete vyzkoušet například kousek cloudové MongoDB někde daleko. A pro Object Storage (ten podporuje rozhraní S3) i pro Mongo existují pohodlné Python obálky.

Další problém je, že pro přístup jak k Object Storage, tak k MongoDB, i k jakékoli jiné databázi nebo úložišti dat jsou potřeba nějaké externí závislosti, které je třeba nahrát na Yandex Functions spolu s kódem vaší funkce. A chtělo by se to dělat pohodlně. Úplně pohodlně (třeba jako na heroku) to, bohužel, nebude možné, ale nějaký základní komfort lze vytvořit napsáním skriptu pro sestavení prostředí (make-file).

Jak spustit dovednost-horoskop

  1. Připravte se: přihlaste se na nějaký stroj s Linuxem. V zásadě by šlo pracovat i s Windows, ale při spuštění make-file byste museli trošku zaexperimentovat. A v každém případě budete potřebovat nainstalovaný Python verze 3.6 nebo vyšší.
  2. Naklonovat si z GitHubu příklad horoskopové dovednosti.
  3. Registrovat se v Y. Cloudu: https://cloud.yandex.ru
  4. Vytvořit si dva bucket přístupné v Object Storage, pojmenovat je libovolně {BUCKET NAME} a tgalice-test-cold-storage (to druhé jméno je v současnosti pevně zakódováno v main.py mém příkladu). První bucket bude potřebný pouze pro nasazení, druhý — pro uchovávání stavů dialogu.
  5. Vytvořit servisní účet, přiřadit mu roli editor, a získat k němu statické údaje o přihlášení {KEY ID} a {KEY VALUE} — budeme je používat k nahrávání stavu dialogu. To vše je potřeba, aby funkce z Y.Cloud mohla získat přístup k úložišti z Y.Cloud. Doufám, že se jednou autorizace stane automatickou, ale zatím je to tak.
  6. (Nepovinné) nainstalovat příkazový řádek yc. Funkci můžete vytvořit i přes webové rozhraní, ale CLI je dobré v tom, že různé novinky se objevují rychleji.
  7. Teď můžeme vlastně připravit sestavení závislostí: spustit v příkazovém řádku z adresáře s příkladem dovednosti make all. Nainstaluje se spousta knihoven (většinou, jak je obvyklé, zbytečných) do adresáře dist.
  8. Ručně nahrát do Object Storage (do bucketu {BUCKET NAME}) vytvořený v předchozím kroku archív dist.zip. Pokud byste chtěli, můžete to udělat i z příkazového řádku, například pomocí AWS CLI.
  9. Vytvořit serverless funkci přes webové rozhraní nebo pomocí utilitky yc. Pro utilitku bude příkaz vypadat takto:

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

Při ručním vytváření funkce se všechny parametry vyplňují obdobně.

Teď můžete svou funkci testovat přes konzolu vývojáře, poté ji upravit a publikovat dovednost.

Vytváření stateful dovednosti pro Alici na serverless funkcích Yandex.Cloud a Pythonu

Co se tam skrývá

Makefile obsahuje vlastně docela jednoduchý skript pro instalaci závislostí a jejich uložení do archivu dist.zip, přibližně takto:

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

Zbytek - několik jednoduchých nástrojů zabaleno v knihovně tgalice.. Proces vyplnění údajů o uživateli je popsán v konfiguraci form.yaml:

form_name: 'horoscope_form'
start:
  regexp: 'start|begin'
  suggests:
    - Start
fields:
  - name: 'name'
    question: Prosím, uveďte své jméno.
  - name: 'year'
    question: Nyní mi řekněte rok vašeho narození. Pouze čtyři číslice, nic víc.
    validate_regexp: '^[0-9]{4}$'
    validate_message: Prosím, zkuste to znovu. Uveďte rok vašeho narození - čtyři číslice.
  - name: 'month'
    question: Skvělé! Nyní uveďte měsíc vašeho narození.
    options:
      - leden
      ...
      - prosinec
    validate_message: To, co jste uvedli, se nezdá být měsícem. Prosím, uveďte měsíc vašeho narození, bez dalších slov.
  - name: 'day'
    question: Výborně! Nakonec mi uveďte datum vašeho narození - pouze číslo, maximálně dvě číslice.
    validate_regexp: '[0123]?d$'
    validate_message: Prosím, zkuste to znovu. Musíte uvést číslo svého narození (např. dvacáté); to jsou jedna nebo dvě číslice.

Práci na rozboru tohoto konfiguračního souboru a výpočtu konečného výsledku přebírá pythoní třída

class CheckableFormFiller(tgalice.dialog_manager.form_filling.FormFillingDialogManager):
    SIGNS = {
        'leden': 'Kozoroh',
        ...
    }

    def handle_completed_form(self, form, user_object, ctx):
        response = tgalice.dialog_manager.base.Response(
            text='Děkujeme, {}! Nyní víme: je vám {} let, a jste {}. n'
                 'To se vám, samozřejmě, podařilo! Hvězdy vám říkají: {}'.format(
                form['fields']['name'],
                2019 - int(form['fields']['year']),
                self.SIGNS[form['fields']['month']],
                random.choice(FORECASTS),
            ),
            user_object=user_object,
        )
        return response

Přesněji řečeno, základní třída FormFillingDialogManager se zabývá vyplněním „formuláře“, a metoda odvozené třídy handle_completed_form určuje, co dělat, když je připravena.

Kromě tohoto hlavního toku dialogu s uživateli je třeba je také přivítat, a navíc poskytnout radu na příkaz „nápověda“ a ukončit dovednost na příkaz „konečně“. K tomu v tgalice. existuje také šablona, takže celý dialogový manažer je složen z kousků:

dm = tgalice.dialog_manager.CascadeDialogManager(
    tgalice.dialog_manager.GreetAndHelpDialogManager(
        greeting_message=DEFAULT_MESSAGE,
        help_message=DEFAULT_MESSAGE,
        exit_message='Na shledanou, přijďte do dovednosti "IT Horoskop" znovu!'
    ),
    CheckableFormFiller(`form.yaml`, default_message=DEFAULT_MESSAGE)
)

CascadeDialogManager funguje jednoduše: snaží se aplikovat na aktuální stav dialogu všechny své složky po sobě a vybere první relevantní.

Jako odpověď na každou zprávu dialogový manažer vrací pythoní objekt Odpověď, který lze dále převést na čistý text nebo na zprávu v Alici nebo Telegramu - podle toho, kde je bot spuštěn; zde je také obsažený měněný stav dialogu, který je třeba uchovat. Celým tímto zpracováním se zabývá jiná třída, DialogConnector, proto přímo skript pro spuštění dovednosti na Yandex Functions vypadá takto:

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

Jak vidíte, většina tohoto kódu vytváří spojení s S3 rozhraním Object Storage. Jak se toto spojení opravdu používá, si můžete přečíst v kódu tgalice.
Poslední řádek vytváří funkci alice_handler — tu, kterou jsme požádali Yandex.Cloud, když jsme nastavovali parametr --entrypoint=main.alice_handler.

To je vlastně vše. Make soubory pro sestavení, S3 podobné Object Storage pro uložení kontextu a pythoní knihovna tgalice.. Spolu s bezserverovými funkcemi a výstižnostmi Pythona je to dostatečné pro vývoj dovednosti pro normálního člověka.

Můžete se zeptat, proč bylo třeba vytvořit tgalice.? Весь скучный код, перекладывающий JSON’ы из запроса в ответ и из хранилища в память и обратно, лежит в ней. Там же лежит применялка регулярок, функция для понимания того, что «феврарь» похоже на «февраль», и прочее NLU для бедных. По моей задумке, этого уже должно быть достаточно, чтобы можно было набрасывать прототипы навыков в yaml-файлах, не слишком отвлекаясь на технические детали.

Pokud toužíte po serióznějším NLU, můžete k své dovednosti přidat Rasa nebo DeepPavlov, ale pro jejich nastavení budou potřeba další tanečky, zejména na serverless. Pokud se vůbec nechcete programovat, stojí za to využít vizuálního konstruktoru jako Aimylogic. Když jsem vytvářel tgalice, myslel jsem na nějakou střední cestu. Uvidíme, co z toho vzejde.

No a nyní se zapojte do chatu vývojářů dovedností Alice, čtěte dokumentaci, a vytvářejte skvělé dovednosti!

Zdroj: habr.com

Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster