Skapa en tillståndsfull färdighet för Alice på de serverlösa funktionerna i Yandex.Cloud och Python

Låt oss börja med nyheterna. Igår meddelade Yandex.Cloud lanseringen av en serverlös datortjänst Yandex molnfunktioner. Det betyder: du skriver bara koden för din tjänst (till exempel en webbapplikation eller en chatbot), och molnet själv skapar och underhåller de virtuella maskinerna där det körs, och replikerar dem till och med om belastningen ökar. Du behöver inte tänka alls, det är väldigt bekvämt. Och betalningen går bara för tidpunkten för beräkningar.

Men vissa människor kanske inte betalar alls. Dessa är utvecklarna Alices yttre färdigheter, det vill säga chatbots inbyggda i den. Vilken utvecklare som helst kan skriva, vara värd för och registrera en sådan färdighet, och från och med idag behöver färdigheter inte ens vara värd - ladda bara upp sin kod till molnet i formuläret samma serverlösa funktion.

Men det finns ett par nyanser. För det första kan din husdjurskod kräva vissa beroenden, och det är inte trivialt att dra dem in i molnet. För det andra måste alla normala chatbotar lagra dialogens tillstånd någonstans (tillståndsfull därför); hur gör man det enklast i en serverlös funktion? För det tredje, hur kan du skriva en snabb och smutsig färdighet för Alice eller till och med någon form av bot med en plot som inte är noll? Om dessa nyanser, faktiskt, artikeln.

Skapa en tillståndsfull färdighet för Alice på de serverlösa funktionerna i Yandex.Cloud och Python

moralisk förberedelse

För den otåliga: jag samlar in de nödvändiga beroenden med en makefil innan jag laddar upp funktionen till molnet, jag lagrar tillståndet för dialogrutan i Yandex Object Storage (den stöder S3 API), och jag använder mitt eget bibliotek för att hantera dialogen tgalice. Som ett resultat visar det sig sådan demo skicklighet. Och låt oss nu analysera allt detta lite mer i detalj.

För de lite mindre otåliga, innan jag dyker in i min berättelse om komplexitet, rekommenderar jag starkt att börja enkelt. Nämligen, skapa en enfils echobot-funktion, registrera och testa den i dialogens utvecklarkonsol; detaljer - in Dialoger blogg и molndokumentation. Och först då börja.

Om du direkt vill känna vad vi kämpar för, fråga Alice 'aktivera färdigheten "IT-horoskop".'. Följande dialog bör äga rum:

Alice: Hej! Du är i färdigheten "IT-horoskop". Säg "Börja" för att ta reda på vad stjärnorna lovar dig.
Användare: Starta
S: Vänligen ange ditt namn.
Yu: Vasisualiy
S: Berätta nu för mig vilket år du föddes. Bara fyra siffror, inget mer.
Yu: andra
S: Försök igen. Ange ditt födelseår - fyra siffror.
Yu: 2002
En bra! Namnge nu din födelsemånad.
Yu: Februari
En bra! Slutligen, berätta för mig ditt födelsedatum - bara ett nummer, bara en eller två siffror.
Yu: 18
A: Tack, Vasisual! Nu vet vi: du är 17 år och du är en Vattuman. Här har du såklart tur! Stjärnorna säger dig а что говорят звёзды, вы узнаете, запустив навык.

Problemet är att för att upprätthålla en så enkel dialog måste du komma ihåg användarens namn och födelsedatum, och i en serverlös miljö är detta inte trivialt. Det kommer inte att fungera att lagra sammanhanget i RAM eller som en fil på disken, eftersom Yandex.Cloud kan köra funktionen på flera virtuella maskiner samtidigt och växla mellan dem godtyckligt. Du måste använda någon form av extern lagring. Object Storage valdes som en ganska billig och enkel lagring direkt i Yandex.Cloud (det vill säga förmodligen snabbt). Som gratisalternativ kan du prova till exempel en gratisbit Molnigt Mongi någonstans långt borta. Det finns praktiska Python-omslag för både Object Storage (som stöder S3-gränssnittet) och Mongo.

Ett annat problem är att för att kunna gå till Object Storage, MongoDB och någon annan databas eller datalager behöver du några externa beroenden som du behöver ladda upp till Yandex Functions tillsammans med din funktionskod. Och jag skulle vilja göra det bekvämt. Det är helt bekvämt (som på heroku), tyvärr, det kommer inte att fungera, men du kan skapa lite grundläggande komfort genom att skriva ett skript för att bygga miljön (gör fil).

Hur man startar horoskopfärdigheten

  1. Gör dig redo: gå till någon maskin med Linux. I princip kan du säkert arbeta med Windows också, men då måste du trolla med lanseringen av makefilen. Och i alla fall behöver du minst 3.6 installerad Python.
  2. Klona från github exempel på en horoskopfärdighet.
  3. Registrera dig i Ya.Cloud: https://cloud.yandex.ru
  4. Skapa dig två hinkar i Objektförvaring, kalla dem valfritt namn {BUCKET NAME} и tgalice-test-cold-storage (detta mellannamn är nu hårdkodat till main.py mitt exempel). Den första hinken kommer endast att behövas för distribution, den andra - för att lagra dialogtillstånd.
  5. skapa servicekonto, ge honom en roll editor, och få statiska referenser för det {KEY ID} и {KEY VALUE} - vi kommer att använda dem för att registrera läget för dialogen. Allt detta behövs för att funktionen från Ya.Cloud ska komma åt lagringen från Ya.Cloud. En dag hoppas jag att auktorisering kommer att bli automatisk, men för nu - så.
  6. (Valfritt) installera kommandoradsgränssnitt yc. Du kan också skapa en funktion genom webbgränssnittet, men CLI är bra eftersom alla möjliga innovationer dyker upp i den snabbare.
  7. Nu kan du faktiskt förbereda beroendesammansättningen: kör den på kommandoraden från mappen med färdighetsexemplet make all. Ett gäng bibliotek (de flesta, som vanligt, onödiga) kommer att installeras i mappen dist.
  8. Fyll med pennor i Object Storage (i en hink {BUCKET NAME}) arkivet som erhölls i föregående steg dist.zip. Om så önskas kan du också göra detta från kommandoraden, till exempel med hjälp av AWS CLI.
  9. Skapa en serverlös funktion via webbgränssnittet eller med hjälp av verktyget yc. För verktyget kommer kommandot att se ut så här:

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 skapar en funktion manuellt fylls alla parametrar i på samma sätt.

Nu kan funktionen du skapade testas genom utvecklarkonsolen och sedan slutföras och publiceras färdighet.

Skapa en tillståndsfull färdighet för Alice på de serverlösa funktionerna i Yandex.Cloud och Python

Vad finns under huven

Makefilen innehåller faktiskt ett ganska enkelt skript för att installera beroenden och lägga in dem i ett arkiv dist.zip, något som det här:

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 är några enkla verktyg insvept i ett bibliotek tgalice. Processen att fylla i användardata beskrivs av konfigurationen 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: Пожалуйста, попробуйте ещё раз. Вам нужно назвать число своего рождения (например, двадцатое); это одна или две цифры.

Arbetet med att analysera denna konfiguration och beräkna slutresultatet tas över av Python-klassen

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 exakt basklassen FormFillingDialogManager är engagerad i att fylla i "formuläret", och metoden för barnklassen handle_completed_form berättar vad hon ska göra när hon är redo.

Utöver detta huvudflöde av användarens dialog är det också nödvändigt att hälsa användaren, samt utfärda hjälp på kommandot "hjälp" och släppa färdigheten på kommandot "avsluta". För detta i tgalice Det finns också en mall, så hela dialoghanteraren består av delar:

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 fungerar enkelt: den försöker tillämpa alla dess komponenter i sin tur på det aktuella tillståndet i dialogen och väljer den första relevanta.

Dialoghanteraren returnerar ett Python-objekt som ett svar på varje meddelande. Response, som sedan kan konverteras till vanlig text, eller till ett meddelande i Alice eller Telegram - beroende på var boten körs; den innehåller också det ändrade tillståndet för dialogrutan som måste sparas. Allt detta kök sköts av en annan klass, DialogConnector, så det direkta skriptet för att starta en färdighet på Yandex Functions ser ut så här:

...
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 skapar det mesta av denna kod en anslutning till S3-gränssnittet för Object Storage. Du kan läsa hur denna anslutning används direkt i tgalice-kod.
Den sista raden skapar en funktion alice_handler - den som vi beordrade att dra Yandex.Cloud när vi ställde in parametern --entrypoint=main.alice_handler.

Det är faktiskt allt. Makefiler för att bygga, S3-liknande objektlagring för kontextlagring och ett pythonbibliotek tgalice. I kombination med de serverlösa funktionerna och uttrycksfullheten hos Python är detta tillräckligt för att utveckla en hälsosam mänsklig färdighet.

Du kan fråga varför du behöver skapa tgalice? All tråkig kod som överför JSONs från begäran till svar och från lagring till minne och tillbaka ligger i den. Det finns också en vanlig applikation, en funktion för att förstå att "februari" liknar "februari", och andra NLU för fattiga. Enligt min idé borde detta redan vara tillräckligt för att kunna skissa skicklighetsprototyper i yaml-filer utan att bli alltför distraherad av tekniska detaljer.

Om du vill ha en mer seriös NLU kan du skruva på den till din skicklighet rasa eller DeepPavlov, men att sätta upp dem kommer att kräva ytterligare danser med en tamburin, särskilt på serverlösa. Om du inte känner för att koda alls, bör du använda en visuell konstruktor som Aimylogiskt. När jag skapade tgalice tänkte jag på någon form av mellanväg. Vi får se vad som händer.

Nåväl, gå med nu Aliy kompetensutvecklare chatt, läs dokumentationoch skapa fantastiska Kompetens!

Källa: will.com

Lägg en kommentar