Jonathan
Jonathan

Reputation: 11355

Alexa custom slot that takes any word or phrase

What samples can one add to a custom slot to make it accept any word or phrase?

Upvotes: 3

Views: 2367

Answers (1)

Jonathan
Jonathan

Reputation: 11355

Update

This solution has been outdated with the introduction of phrase slots eg. AMAZON.SearchQuery.

From the Announcements

Phrase slots are designed to improve speech recognition accuracy for skills where you cannot include a majority of possible values in the slot while creating the interaction model. The first slot available in this category is AMAZON.SearchQuery is designed to provide improved ability for you to collect generic speech from users.

The Problem

Having worked on developing an urban dictionary skill over the weekend to polish up on my Alexa skills I ran into a problem which I think a lot of skill developers might encounter.

TL;DR

Namely, how do you train Alexa on a custom slot to be able to take any value you give it?

First Attempts

At first I added about 5 words to the custom slot samples like bae, boo, ship it. But I quickly found that the skill would only work with those 5 words and I'd get no calls to my lambda function for words outside that list.

I then used

from nltk.corpus import words
import json, random

words_list = random.shuffle(words.words()[:1000])

words_list = [word.lower() for word in words_list]
words_list = list(set(words_list))
values = []
for word in words_list:
    value = {}
    value['id'] = None
    value['name'] = {}
    value['name']['value'] = word
    value['name']['synonyms'] = []
    values.append(value)
print(json.dumps(values))

The above code uses nltk, which you can install with pip install nltk, to generate a 1000 words according to the schema you can find under code editor, it produce a thousand of these;

{
    "id": null,
    "name": {
        "value": "amblygeusia",
        "synonyms": []
    }
}

I copied and pasted these under values, you can find the whole file under Code Editor on the Skills Builder page.

  "languageModel": {
    "types": [
      {
        "name": "phrase", //my custom slot's name
        "values": [...] //pasted the thousand words generated here
...

After saving and building in the Skills Builder UI. This only allowed my skill to capture single word slot values. I tried generating 10 000 words in the same way and adding them as samples for the custom slot but two word and three words phrases weren't recognised and the skill failed to get the definition of phrases like;

ship it

The Solution;

What worked for me and worked really well was to generate two word samples. Despite all the examples being two worded, the skill was then able to recognise single word values and even three word values.

Here's the code to do that using nltk;

from nltk.corpus import words
import json, random

words_list = random.shuffle(words.words()[:1000])

words_list = [word.lower() for word in words_list]

words_list = list(set(words_list))

word_pairs = []
for word in words_list:
    pair = ' '.join(random.sample(words_list, 2))
    word_pairs.append(pair)

word_pairs = list(set(word_pairs))
for pair in word_pairs:
    value = {}
    value['id'] = None
    value['name'] = {}
    value['name']['value'] = pair
    value['name']['synonyms'] = []
    values.append(value)
print(json.dumps(values))

I put that in a file called custom_slot_value_geneator.py and ran it with;

python3 custom_slot_value_geneator.py | xclip -selection c

This generates the values and copies them to the clipboard.

I then copied them into the Code Editor under values, replacing the old values

  "languageModel": {
    "types": [
      {
        "name": "phrase", //my custom slot's name
        "values": [...] //pasted the thousand two word pairss generated here
...

Save & Build.

That's it! Your skill would then be able to recognize any word or phrase for your custom slot, whether or not it's in the sample you generated!

Upvotes: 3

Related Questions