Ajattelin nyt kysyä vähän mielipiteitä tähän projektiini.
Eli aloitin eilen tekemään PHP:lla oppivaa Chattibottia. Olen nyt saanut kohtalaisen alkeellisen älykkään (eli hölmön) chattibotin aikaiseksi. Sen kanssa pystyy keskustelemaan tyyliin:
Käyttäjä: Moi!
Botti: No terve!
Käyttäjä: Mitä kuuluu?
Botti: Hyvää kiitos!
Käyttäjä: Kuka olet?
Botti: Joku.
Käyttäjä: Ok.
Botti: Mikä on lempivärisi?
Käyttäjä: Sininen.
Botti: Oletko hölmö?
Käyttäjä: En.
Botti: Onko Botti tyhmä?
Käyttäjä: On.
Botti: Onhan se.
Käyttäjä: Kuinka vanha olet.
Botti: Kyllä
Tuo oli hatusta vedetty keskustelu, mutta suurinpiirtein näin botti käyttäytyy.
Koodissa on määritelty mm. sanoihin "moi", "terve", "hei"... vastaaminen randomilla "No terve!", "Heippa!", "Moikka!"... Sama juttu "Mitä kuuluu":ssa eli vastaa jotain "Hyvää.", "Ikävää" tms.
Kysymyksiin botti oppii vastaamaan sillä tavalla, että ensiksi käyttäjä kysyy botilta jonkun kysymyksen(sen botti tunnistaa kysymysmerkistä). Kysymys lisätään kysymykset-tauluun ja vastaus haetaan vastaukset-taulusta aluksi randomilla. Sitten kun käyttäjä sanoo vaikka "ok" tms joka ei ole kysymys, botti saattaa kysyä jonkun kysymykset-taulusta löytyvän kysymyksen. Kun käyttäjä vastaa, vastaus lisätään vastaukset-tauluun ja tietyn sarakkeen arvoksi asetetaan kysymyksen id kysymykset taulussa. Sitten jos sama kysymys kysytään botilta uudestaan, se osaa vastata randomilla jonkun siihen kysymykseen aiemmin vastatun lauseen(tai sanan).
Kun käyttäjä sanoo jotakin mikä ei ole kysymys, saattaa botti vastata jotain jotakin muut-taulusta löytyvää, missä mainitaan käyttäjän syöttämä asia.
Tällä tavalla käyttäjä voi jotenkuten jutella botin kanssa, ja botti oppii samalla.
Botti on aika tönkkö vielä, mutta olisiko teillä ehdotuksia, miten botti osaisi jotenkuten vastata kysymyksiin, joita siltä ei ole ennen kysytty sillä nykyään käy usein esim. näin: "Mikä sinun nimesi on?" ja botti saattaisi vastata "Ei."?
Muutkin botin aitoutta edistävät ideat ovat tervetulleita. Minusta juuri tämän botin oppiminen on mielestäni erityisen mielenkiintoista kehitettävää.
Hmm.. en nyt ihan ajatuksen kanssa lukenut läpi tota, mutta ainaskin tuo, että laitat sen botin tunnistaan kysymys sanat, jos on vaikka 'miksi', niin tulee 'siksi','koska',jnejne..
Muinoin 60-luvulla kehitetyt keskustelua matkivat ohjelmat olivat aika yksinkertaisia, mutta sattuivat monesti huijaamaan ihmisiä luulemaan ainakin hetken aikaa, että ne osaavat oikeasti keskustella. Kaksi vanhaa ohjelmaa ovat nimeltään ELIZA ja PARRY, joita voit hakea sopivien lisähakusanojen kanssa. Ensimmäisestä ainakin on tehty monta versiota eri kielillä (niin ohjelmointikielillä kuin luonnollisilla).
Ne toimivat yksinkertaistaen niin, että niille annettuja lauseita sovitettiin erilaisiin malleihin, ja jos sovitus onnistui, mallin pohjalta laadittiin vastaus. Esimerkkinä voisi olla seuraavanlainen yksinkertainen pari malleja. En ota nyt huomioon välimerkkejä tai kirjainten kokoa.
Näissä iso kirjain X on merkki muuttujalle, johon sidotaan se osa sovitettua lausetta, joka jää yli. Esim. siis jos malli olisi "olen X", tulisi X:n arvoksi sovittamalla se lauseeseen "olen makkara" tietenkin X = makkara. Jos lause ei alkaisi sanalla olen, ei sovitus onnistuisi, ja ohjelma kokeilisi muita malleja.
malli: minulla on X vastaus -> kuinka kauan sinulla on ollut X? malli: olen hyvin X vastaus -> minäpä olen Xmpi
Jos käy hyvä (tai huono) tuuri, nämä voivat toimia näin:
Ihminen: Minulla on mopo
Vekotin: Kuinka kauan sinulla on ollut mopo?
Ihminen: Olen hyvin taitava kuski
Vekotin: Minäpä olen taitava kuskimpi
Eli heti menee vekotin metsään. Sellainen malli, jonka avulla voi generoida järkevämmän vastauksen "taitavampi kuski" on kuitenkin aika vaikea laatia. Varmaan keksit tavan, joka sopii tähän esimerkkiin, mutta siten joku toinen jossakin toisessa keskustelussa käyttää taas erilaista lauserakennetta ja metsään mennään jälleen kerran.
Voit yrittää tehdä yksinkertaisen mallinsovitus- ja vastauksenlaadintakoodin kokeilumielessä, ja keksiä itse näitä malleja. Ehkä siitä on apua. Ehkä ei. Vaikeaa se on tehdä hyvin. Luultavasti suomen kieli on vaikeampi kuin englanti, koska meillä on näitä kaikkia kivoja taivutusmuotoja niin runsaasti.
Kiitti vinkeistä. Rupesin yön pimeinä tunteina miettimään, että jos olisi taulu sanoille(:O aika iso taulu). Siinä olisi sarakkeet sana, luokka, aihe, muoto1, muoto2, muoto3...muoto11(jos nuo riittäisivät). Tauluun voisi laittaa sanoja eri sanaluokista:
Substantiivi: perusmuoto + normaalista poikkeavat taivutukset esim. äähän tai ööhön loppuvilla sanoilla ei a:n lisääminen toimisi esim. partitiivissä silmästä silmäa ei kuulosta kovin uskottavalta. Luokka-sarakkeeksi "subs". Sama kaikissa nomineissa. Botti siis saisi nomineista muodot (talo, talossa, talosta, taloon, talolla, talolta, talolle, taloa, talon, talot)
Verbistä(luokka:verb) tulisi perusmuoto + kaikki preesensin normaalista poikkeavat muodot. Botti osaisi sanoa (juoda, juon, juot, juo, juomme, juotte, juovat)... Ja koodi osaisi lisätä perään ko- tai kö-päätteitä kysymysten luomiseksi.
Jos olisi edes sen verran kaavamaiset sanojen taivutukset niin voisi saada sanat taipumaan koodissa eikä tietokantaan tarvitsisi kuin perusmuodon.
Sanojen aiheeksi tulisi esim. makkaralle ruoka, autolle kulkuväline jne, että saataisiin jotenkuten järkeviä keskusteluja aikaan. Esim. jos botti tunnistaa lauseesta jonkun tietokannassa olevan sanan, voi se saman aiheen sanasta tehdä uuden lauseen...
Sitten olisi lausekaavoja, jonka mukaan botti tekisi niitä yksinkertaisia lauseita.
Tarvitsisin apua tuohon vielä monessa asiassa ja ideat ja parannusehdotukset ovat tervetulleita. Nyt jos tästä tekee noinkin monimutkaiset (ainakin edelliseen versioon verrattuja) nousee mieleen kysymys, että saako tuota oppimaan muulla tavalla kun tietokantaan tunkemalla sanoja manuaalisesti...? Ja osaisiko joku muuten kertoa, miten lauseesta saisi sanat erilleen eri muuttujiin?
jos sulla tulee muotoja noin paljon, niin kannattaisiko niille olla sitten mieluummin oma taulu...
...puhutaan kuitenkin tietokannasta.
Lebe80 kirjoitti:
jos sulla tulee muotoja noin paljon, niin kannattaisiko niille olla sitten mieluummin oma taulu...
...puhutaan kuitenkin tietokannasta.
Meinaat siis, että sanat-taulussa olisi vai sarakkeet id, sana, luokka ja aihe ja sitten olisi muodot-taulu erikseen ja sinne tulisi kaikkien sanojen muodot ja idllä ne muodot sitten "linkitettäisiin" sanat-tauluun? Olisiko tämä nopeampi tapa, vai mikä etu siinä olisi?
Etu olisi siinä, ettei olisi väliä onko muotoja yksi vaiko sata.
Tietokannan huonosta suunnittelusta kielii heti, jos taulu on muotoa:
Ryhmän id, Ryhmän nimi, Käyttäjä1, Käyttäjä2, Käyttäjä3, Käyttäjä4, Käyttäjä5, Käyttäjä6, Käyttäjä7, Käyttäjä8, Käyttäjä9, Käyttäjä10
Aivan. Tuo oli vain pikainen suunnitelma ilman jatkokehittelyä. Onko mitään valmista functiota sanojen lauseesta omiin muuttujiin tallentamiseen vai onko jollakin siihen ideoita?
explode välilyönnillä?
Voithan tietenkin käyttää nykysuomensanalistaa (löytyy mm. jostain putkapostista). Se sisältää n. 90 000 sanaa taivutusohjeineen. Ei varmaankaan kannata lisätä kaikkia sanoja, mutta voit vaikka tehdä sanojen lisäykseen lomakkeen, joka hakee perusmuodon perusteella taivutukset listasta ja voit sitten itse korjata niitä tarvittaessa.
Huhhuh mikä määrä tekstiä! Laaksosen sanalistassa ei ollut taivutusmuotoja, joten latasin alkuperäisen sanalistan. Tuosta jos saisi jotenkin väkerrettyä koodin, joka osaa taivuttaa oikeassa muodossa niin hyvä olisi. On siinä hetki pähkäiltävää, kun tällaista en ole ennen tehnyt...
Lisää pähkäiltävää löytyy suomen yleisimpien sanojen listoista. Niistä on linkattu pari täältä Wikipedia-keskustelusta, jonka löysin juuri webbihaulla.
Näissä listoissa on sellaisia sanoja, jotka kuvastavat lähdeaineiston luonnetta. Sanomalehdistä kerätyissä sanoissa on esim. paljon maiden nimiä ja muuta yleisten uutisten aiheita. Joka tapauksessa niistä voi olla jonkin verran apua miettiessä mitä sanoja botin pitäisi ainakin tunnistaa. Esim. top ten eräästä listasta on seuraava:
Sija Lukumäärä Sana Osuus 1 552162 ja 3,1363 % 2 428026 on 2,4312 % 3 164098 ei 0,9321 % 4 154320 että 0,8765 % 5 126954 oli 0,7211 % 6 89469 se 0,5082 % 7 86711 hän 0,4925 % 8 78076 mutta 0,4434 % 9 77081 ovat 0,4378 % 10 70811 kuin 0,4022 %
(Nämä ovat Parole 5000 listasta. http://kaino.kotus.fi/sanat/taajuuslista/
Jos aikoisi tuollaisen listan pistää tauluun, miten se onnistuisi helpoiten? Haluaisin sinne nuo kaikki tiedot noista sanoista. Sitten tekisin koodilla jotain tähän tyyliin:
function taivuta($sana, $muoto){ /*tässä kohdassa koodi hakee taivutustyypit-taulusta sanan taivutustyyppiä vastaavan sanan ja perusmuodon, vertaa perusmuotoa ja taivutusmuotoa, laskee montako kirjainta perusmuodon lopusta on otettu taivuttaessa (jos on), ottaa $sana-muuttujan ja vähentää(jos tarvitsee) kirjaimia ja lisää perusmuodon ja taivutuksen erotuksesta jääneet kirjaimet ja tuo merkkijono laitetaan muuttujaan $taivutettusana*/ return $taivutettusana; }
En tiedä saako tuosta selvää ja onko tuo nyt ihan aukoton taivutus, mutta tuollaista jotakin kaavailin... Mitäs sanotte? :D
Mulla on kaksi kommenttia. Ensinnäkin, jos käytät pelkkää Kotuksen aineistoa, tuotat vain kirjakieltä ymmärtävän botin. Chättäilijät voivat kuitenkin tarjota sille jottai muun sortin kieltä, jonka sanamuodot eijjoo ihan kirjakielen mukasia. Niinku tässä yritän kirjottaa. (Tää ei oo kyllä mitään oikeaa murretta nähnykkää.)
Kannattaa siis kerätä aineistoa chattilogeista ym. ja katsoa minkälaisia sanamuotoja oikeasti käytetään. Tämä on sellainen prosessi joka voi kestää pitemmän aikaa ja hiljalleen parantaa bottiasi, joten älä hätäile :)
Toiseksi, arvelisin, että haluat tunnistaa annetusta sanasta sen, mikä on sanan perusmuoto ja miten se on taivutettu. Minulle tulisi mieleen kaksi tapaa lähestyä ongelmaa. Yksi on Prolog (juu, se olisi varmasti hyvä tässä), ja toinen olisi seuraava yksinkertaisempi ratkaisu, jonka voisi helpommin koodata esim. PHP-kielellä.
Jokaisella sanalla on muuttumaton vartalo, jonka lisäksi sillä on ehkä jokin taivutuspääte, jossa voi olla myös muita liitteitä. Itse asiassa yö-sanalla ei ole, koska sen monikkomuodot tiputtavat y-kirjaimen pois. Mutta puhumme nyt muista sanoista. Kieliopeissa yleensä puhutaan erilaisista vartaloista mitä suomen sanoilla on, mutta se ei taida auttaa sinua tätä ohjelmaa tehdessä.
Pitää siis löytää jokaiselle sanalla se etuosa, joka on sen kaikissa muodoissa aina sama. Sellainen löytyy siis aina kun sana ei ole yö, ainakin minun käsitykseni mukaan.
Esim. vesi-sanan eri taivutusmuodoissa on aina ve-alku. Veteen, vedeksi, vesille jne. Talo-sanan muuttumaton osa on talo.
Voit kerätä jokaisesta tarvitsemastasi sanasta tämän vartalon ja kaikki ohjelman tunnistamat loppuosat talteen tietorakenteeseen. Sitten analysoidessa ohjelman saamaa sanaa, voit katsoa sanan alusta eri pätkiä ja selvittää, onko sanan alku tallessa muuttumattomana vartalona ohjelman tiedoissa. Jos on, ja sanan loppu löytyy mahdollisista päätteistä, tunnistat sanan. Esim. veden tuottaisi kaksi osaa, ve ja den. Sen sijaan yritys v-eden ei sopisi mihinkään dataan ja ohjelma ei tulkitsisi sitä sillä tavalla.
En tiedä mikä on PHP:n nimi tietorakenteille, joihin voi tallettaa asioita merkkijonon periaattella. Hash? Array? Table? Joka tapauksessa, sehän tällaisen ratkaisun kanssa toimisi nopeasti. Silmukka kävisi läpi sanan alusta eri osia: ensin yksi merkki, sitten kaksi, ja aina koko sanan pituuteen asti.
Tässä on kuitenkin kaksi ongelmaa. Esim. sana häntä voi olla joko häntä (nominatiivi) tai hän-tä (hän-sanan partitiivi). Ohjelman pitää joskus löytää useita tulkintoja, tai sitten arvata villisti mitä yhtä sanaa tarkoitetaan, mikä ei varmasti aina osu oikeaan.
Lisäksi sanojen lopussa on päätteitä, kuten -ni tai -kin. Koska niiden yhdistelmiä on niin julmetusti, ne pitäisi ehkä tunnistaa erikseen katsomalla sanan rakennetta myös sen lopusta. Pitää kuitenkin muistaa, että joissakin sanoissa on näitä osia ilman, että ne ovat näitä ns. liitepartikkeleita. Sana ääni ei ole ää-ni eikä lukki-sanan genetiivin lukin ole lu-kin.
Ohjelman pitää siis pystyä tuottamaan useita arvauksia ja valita niistä ne mahdolliset tulkinnat, joita tulee olemaan nolla tai enemmän. Tästä ei taida tulla ihan helppoa. Toivottavasti kuitenkin jaksat pohtia ongelmaa ja löytää jonkinlaisen ratkaisun. Täydellisyyteen ei tässä kannnata pyrkiä, vaan riittänee olla joskus oikeassa
Loppuvihje: kerää paljon aineistoa. Chattilogeja ja tekstejä, joissa on erilaisia tapoja käyttää suomea. Niitä kokeilemalla löytyy varmasti paljon esimerkkejä, missä yksinkertaiset sanananalysointialgoritmit erehtyvät pahasti, ja löydät sitten ehkä parempia keinoja.
No tällaisia ideoita. Minun tietenkin pitäisi koodata tästä itse joku pieni versio, että näkisin onko näistä ajatuksista mihinkään, mutta en nyt valitettavasti oikein jaksa aloittaa niin isoa projektia. En yritä kuitenkaan pelotella sinua pois tästä jutusta. Varmasti saat jotakin aikaiseksi, kunhan jaksat tehdä, ja ajan myötä se paranee.
(Tulipa sepustus. Kiitos kärsivälliselle lukijalle :))
Pekka Karjalainen kirjoitti:
Mulla on kaksi kommenttia. Ensinnäkin, jos käytät pelkkää Kotuksen aineistoa, tuotat vain kirjakieltä ymmärtävän botin. Chättäilijät voivat kuitenkin tarjota sille jottai muun sortin kieltä, jonka sanamuodot eijjoo ihan kirjakielen mukasia. Niinku tässä yritän kirjottaa. (Tää ei oo kyllä mitään oikeaa murretta nähnykkää.)
Kannattaa siis kerätä aineistoa chattilogeista ym. ja katsoa minkälaisia sanamuotoja oikeasti käytetään. Tämä on sellainen prosessi joka voi kestää pitemmän aikaa ja hiljalleen parantaa bottiasi, joten älä hätäile :)
Tuo vaikuttaa jo niin monimutkaiselta, että en tiedä jäätyykö koko projekti pian. :D Tuo ensimmäisessä viestissäni selittämä botti on ainakin 100 kertaa helpompi, mutta rutkasti tyhmempi. Pitäisiköhän tehdä tästä botista "kirjakielibotti", eli se ei murteista ymmärrä...? Kaiken maailman murteet menevät jo vähän liian pitkälle...
Tuo sanojen pätkiminen voisi olla ihan kätevää, mutta kaikista eniten haluaisin välttää manuaalista naputtelua tietokantaan... Olisipa jokin koodi, joka osaisi tehdä tietokantaan nuo muuttumattomat pätkät ja taivutuspäätteet... Esim. sitä nykysuomen sanalistaa apuna käyttäen... Tai osaisinpa tehdä sellaisen. Pitää yrittää. En meinaa millään viitsisi ruveta yli 90 000 sanaa taivutusmuotoineen näpyttelemään tietokoneelle...
Edit. Kirjoitin vahingossa 90 000 yhdeksäskikymmeneksi.
ZuBer kirjoitti:
Pitäisiköhän tehdä tästä botista "kirjakielibotti", eli se ei murteista ymmärrä...? Kaiken maailman murteet menevät jo vähän liian pitkälle...
Löytyisiköhän avuksi jotain Soundex:ia vastaavaa algoritmia, mikä toimisi suomenkielellä englannin sijaan? Voisit indeksoida bottisi sanavaraston samalta kuulostavan lausuntatavan mukaan, jolloin samalta kuulostavat murresanat saattaisivat tunnistua oikeaksi sanaksi...
http://alice.pandorabots.com/
judge: well then I am not your becoming husband
ALICE: Nobody said you were.
judge: well you had that certain sparkle in your eyes
ALICE: What happened to it.
judge: well it kinda gladez to my 3 nipple. right between my eyes
ALICE: What does "it" refer to? How far is that?
judge: looks baby looks
ALICE: Try putting that in a more specific context.
judge: you are not even a blond
ALICE: Give me an example of a blond.
judge: What do Blondes say after sex? Thanks Guys
ALICE: They do their own thing. Don't mention it. Where are you located?
judge: finland, land of polar beers and penguins.
ALICE: Tell me a little about your life in finland land of polar beers. Do your friends call you penguins.
judge: I think I mispelled bear as beer. I am drinking one or another. Anyway I ment bear as animal. No, no one calls me panguin
ALICE: That is interesting. How does it taste? What kind of food do you like? That was not a yes or no question.. That is a rather sweeping generalization about people.
judge: well I usually eat raw meat
ALICE: How does it taste?
judge: taste like blood
ALICE: My brain does not have a response for that.
judge: for what?
ALICE: I can't say why specifically.
Aihe on jo aika vanha, joten et voi enää vastata siihen.