Azuren LUIS (Language Understanding) –palvelua hyödyntävät chatbotit ovat todella siistejä. Ne tunnistavat käyttäjän syöttämästä sisällöstä mitä hän yrittää saavuttaa (aikomus, intent).

Käyttäjän kirjoittaessa ”I would like to order pizza” tai ”Could I have one pizza please?” LUIS ymmärtää käyttäjän haluavan pitsaa ja chatbot osaa käynnistää pitsan tilausprosessin (= kysyä käyttäjältä millaisen pitsan hän haluaa).

Toteuttajan ei tarvitse arvata millä kaikilla tavoilla käyttäjä voi ilmaista haluavansa pitsaa. LUIS tekee sen hänen puolestaan.  Mutta… LUIS ei tue (ainakaan vielä) suomea.

Miten mahtavaa olisi jos tämän voisi tehdä myös suomen kielellä?

Azuresta löytyy monenlaisia käteviä palveluja. Yksi näistä on tekstin kääntämiseen tarkoitettu palvelu (Azure Translator API). Mitä jos tekisimme chatbotin jossa

  1. käännämme kaikki käyttäjän chatbotille antamat syötteet englanniksi
  2. lähetämme käännetyt syötteet LUIS-palvelulle (joka ymmärtää englantia, muttei suomea)
  3. LUIS tunnistaa käyttäjän aikomuksen
  4. tunnistetun aikomuksen perusteella chatbottimme tekee työnsä
  5. käännämme chatbotin vastaukset suomeksi?

Kuulostaa kyllä aika pommilta. Juuri niin uskomattomalta että tätä on aivan pakko kokeilla.

Esimerkkitoteutus – Milloin lähtee seuraava juna?

Jalostetaan aikaisempaa chatbot esimerkkiäni. Toteutetaan avustaja jolta voi:

  • kysyä seuraavaa junaa paikkaan x (lähtöpaikkana käytetään Helsinkiä)
  • kysyä seuraavaa junaa paikasta x paikkaan y

Chatbotin tajutessa käyttäjän kysyvän seuraavaa junaa, hakee se liikenneviraston tarjoamasta avoimesta rajapinnasta pyydetyt tiedot. Tyäpaikkani on rautatieaseman lähellä. Nyt voin kotiin lähtiessä kysyä Teams:ssa (joka minulla on aina auki) chatbotilta, milloin seuraava juna lähtee. Ei enää turhaa odottelua asemalla.

Varsinainen äly – LUIS

Aloitetaan ratkaisun varsinaisen älyn toteuttamisesta. Kirjaudutaan luis.ai -palveluun ja luodaan uusi sovellus (app). Määritellään kolme aikomusta:

  • GetHelp = käyttäjä pyytää apua chatbotin käytössä
  • GetNextTrain = käyttäjä kysyy seuravaa junaa
  • None = emme ymmärrä mitä käyttäjä kysyy

Näyttökuva 2018-2-1 kello 18.45.45.png

Opettaminen alkaa esimerkkien syöttämisellä. Naputellaan malliksi erilaisia seuraavaa junaa tiedustelevia lauseita.

Näyttökuva 2018-2-1 kello 18.44.40.png

Seuraavaksi määritellään lähtöasema (TrainstationFrom), sekä määränpää (TrainsstaionTo) omiksi entiteeteiksiin (entity).

Näyttökuva 2018-2-1 kello 18.49.15

LUIS pyrkii tunnistamaan tekstistä aikomuksen lisäksi entiteettejä. LUIS tarvii niistäkin esimerkkejä. Siirrytään takaisin aikomuksiin ja merkitään jokaisesta esimerkkilauseestamme lähtöasema ja määränpää niitä vastaaviksi entiteetiksi.

Näyttökuva 2018-2-1 kello 18.53.03.png

Lopputulos näyttää tältä. Huomaa että kaikissa esimerkkilauseissa ei ole molempia entiteettejä. Käyttäjä voi kysyä vain seuraavaa junaa paikkaan x.

Näyttökuva 2018-2-1 kello 18.59.03.png

Mallia pitää muutosten jälkeen harjoittaa (yläpalkin Train), minkä jälkeen se voidaan julkaista (Publish). Mallin ensimmäinen versio on valmis.

Chatbottimme liitetään LUIS palveluun avaimien avulla. Nämä löytyvät Publish-välilehden alaosasta.

text api keys 3.png

Käännöspalvelun luominen

Ratkaisumme käyttää Azuren Translator Text API:a, joten käydään luomassa sellainen.  Painetaan plussaa (New) Azuressa ja sieltä se löytyy hakemalla.

create text api.png

Kun kääntäjäpalvelu on luotu, poimitaan talteen yksi sen avaimista. Sen avulla chatbottimme voi käyttää palvelua.

text api keys.png

Vihdoinkin voimme avata Visual Studion.

ChatBotin rakentaminen

Varsinaisen toteutus tehdään tällä kertaa c#:lla. Google helpottaa työtä kummasti. Ideani ei ole niin vallankumouksellinen, etteikö joku olisi jo vastaavaa tehnyt. Otetaan pohjaksi  githubista löytyvä BotTranslator -projekti, jossa vastaavaa temppu tehdään kiinaksi.

Chatbottimme käyttää kahta palvelua (Translator Text API ja LUIS). Lisätään näiden avaimet SecurityKeys.cs -tiedostoon.

text api keys 2.png

Käydään vaihtamassa MessageTranslator -luokan FromLocale -muuttujan arvoksi ”fi-FI”. Nyt käännökset tehdään englannin ja suomen välillä.

Chatbotin mielenkiintoisin osa on RootDialog -luokka. Siellä reagoidaan LUIS-palvelun tunnistamiin aikomuksiin. Siivotaan esimerkin intentit pois ja laitetaan tilalle omamme (GetNextTrain).

vs_trainintent.png

Chatbottimme lähettää käyttäjän (suomesta englantiin käännetyn) syötteen LUIS-palveluun. Mikäli LUIS toteaa käyttäjän kysyvän juna-aikataulua, suoritetaan yllä oleva koodi.

LUIS pyrkii tunnistamaan myös lähtöaseman ja matkan määränpään. Mikäli käyttäjä ei kerro lähtöasemaa, oletamme sen olevan Helsinki. Kun halutut asemat ovat selvillä, on seuraavien junien selvittäminen helppoa liikenneviraston digitraffic -rajapintaa käyttämällä.

Toimiiko se?

Käännetään chatbot ja kokeillaan sitä bot emulaattorin avulla. Näin voimme testata chatbottia helposti omalla työasemalla. Haetaan aikataulua Tampereelta Helsinkiin.

bot test1.png

Uskomatonta, tämähän toimii!

Käytännössä:

  • Kirjoitin ”Milloin lähtee seuraava juna tampereelta helsinkiin”
  • chatbot käännätti lauseen Translator API:lla ja lähetti LUIS-palveluun tekstin ”When is the next train from Tampere to Helsinki”
  • LUIS päätteli
    • Intent  = GetNextTrain
    • fromStation = Tampere
    • toStation = Helsinki
  • Chatbottimme vastaa: ”The next train (IC 22) from tampere to helsinki leaves at 13:02:00”. Vastaus ajetaan jälleen käännöksen läpi ja käyttäjälle näytetään: ”Seuraava juna (IC 22) Tampereelta Helsinkiin lähtee klo 12:58:00”

Jos tämä ei ole siistiä niin ei mikään.

Mallin harjoittaminen

Chatbotin testaamisen jälkeen on aika siirtyä takaisin LUIS-palveluun.

Näyttökuva 2018-2-3 kello 18.52.03.png

LUIS on kerännyt ilmaisuja (utterance), joista se ei ole varma mihin aikomukseen ne liittyvät. Merkitään näihin ilmaisuihin oikeat entiteetit (TrainstationTo ja TrainstationFrom). Lopuksi ilmaukset liitetään oikeisiin aikomuksiin (Aligned intent + Add to aligned intent). Ja tietenkin harjoitetaan mallia painamalla Train-painikkeella.

Chatbotin koodi ja ”äly” ovat täysin irrallaan toisistaan. Asiakas voi parantaa chatbotin osumatarkkuutta itse LUIS-palvelussa.

Yhteenveto

Alun vilpittömän innostuksen jälkeen havaitsen ratkaisun ongelman. Nimittäin paikannimet. Selaimella käytettävä Microsoftin kääntäjä jättää suomenkieliset paikannimet kääntämättä (ja muuttaa paikannimen perusmuotoon).

bot translate bing.png

Hienoa. Mutta Translator API toimii toisin. Se kääntää kaiken. Leppävaara kääntyy muotoon danger of alder, Lahti on bay ja Joensuu taas the mouth of the river.

Määränpäiden selvittäminen menee nopeasti hankalaksi. Osa LUIS -palvelun palauttamista entiteeteistä on suomeksi (Tampere, Helsinki, Oulu, Turku…), osa taas on kauniisti käännetty (1 kg, sauce…). Loput ovat mystisiä palasia käännöksestä (the danger of, in the…).

Korjaus 1

Translation API käyttää oletuksena statistical machine translation (SMT) -teknologiaa. Vaihdoin sen käyttämään Neural Networks (NN) -teknologiaa, jota myös Bing-kääntäjä käyttää. Muutoksen jälkeen käännökset toimivat paremmin, mutta eivät vieläkään täydellisesti. Osaa paikannimistä ei edelleenkään ymmärretä mikäli ne on annettu taivutetussa muodossa.

Ei toimi: ”Milloin lähtee seuraava juna kiloon”

Toimii: ”Milloin lähtee seuraava juna kilo”

Korjaus 2

Translation Hub:in käyttö voisi olla oikea ratkaisu. Sen avulla luodaan käännöspalveluun omia sanastoja. Säästän kuitenkin sen kokeilun toiseen kertaan.

Joka tapauksessa LUIS-palvelua voi käyttää suomenkielisen chatbotin toteuttamiseen kohtuullisen hyvin, mikäli ei aio hyödyntää entiteettejä. Harmi vain että entiteetit ovat chatbot-toteutuksessa todella keskeisiä.