Question about handling Adapt .voc files

Hi all!
I’ve started to play with Adapt, but I’ve not found this information anywhere, is there a way to identify which line of a .voc file is being recognized by the intent parser?
Something like this:

@intent_handler(IntentBuilder('CheckLine').require('what').require('verb')
    .require('quote'))
    def handle_line_checker(self,message):
        quote = message.data.get('quote')
        if isline('verb') == 1:
            # this is line 1 do action 1
            self.log.info("Line 1")
        elif isline('verb') == 2:
             # this is line 2 do action 2
             self.log.info("Line 2")
        else:
            self.speak_dialog('generic')
            self.log.info("Generic request")

Or when Python 3.10 will be supported, by using match-case structure
I know the voc_match function, but that’s not what I need to do.

And also, is it possible to trigger the intent only when a keyword in a .voc file is pronounced alone?

@intent_handler(IntentBuilder('SingleWord').require('word')

So not to trigger when that word is present in another utterance. Can I do it by using voc_match?

Thank youThis text will be hiddenThis text will be hidden

Hey Esa, welcome to the community.

First a warning - this is my first try at writing a skill.

This video touches on Adapt, then moves to Padatious, but it might help:

I’m trying to write a skill with I believe similar requirements as yours. It tells people where they’re spending money. Here’s the (input) intent file and (output) dialog file:

$ cat costs.intent
(what is|what are|whats) my {interval} {bill_type}
$ cat costs.dialog
your {interval} {bill_type} is {amount}

The files interval.voc has time intervals such as ‘weekly’ and ‘monthly’, and bill_type.voc has places we spend money.

So if the question is “what are my annual taxes”, the code needs to know the interval of ‘annual’ and the bill_type of ‘taxes’.

@sgee commented yesterday in the general chat channel a technique which has been helpful (thank you!)

So I add this print statement to init.py:

print('TODO: get amount for bill_type of '+msg.data['bill_type']+' with interval of '+ msg.data['interval'])

This is what gets printed:

TODO: get amount for bill_type of "nnual taxes" with interval of "a"

So this seems like a bug - interval always gets set with just the first character, and bill_type gets set with the remainder of the interval as well as the bill type. Is it possible to trace where these variables are getting set?

Hope this helps (even though I’m adding a new issue).

-Mike M
1 Like

Hi Mike, thank you!

I’m a little rusty with programming, I’ve restarted when some students at school asked me for some help.
From what I’ve seen, this metod is not good for skill translation, correct me if I’m wrong
You still need to check keyword in english, what if whant to do the same in italian?
That’s why I need to check a line and not the term itself, because I know at which line a specific element is and pogram an action based on that, then that keyword could be translated without causing issues with the skill.

As for the issue, why not use an entity file? That way you force you keyword to match the exact word in your file, or not?

Try to answer both of you.

First off, using adapt, the voc file is an “entity” file. Mike is mixing adapt and padatious. Noticeable as he uses .intent while using .voc - which is adapt. (and the origin of those mixups)

Padatious has a similar approach with .entity files. Yet they have to be registered (and named alike ofc) to take effect.
So, using adapt you spare some LOC, decorating the function as Esa did @intent_handler(IntentBuilder('SomeName').require('interval').require('bill_type')) using the voc suffixed files

The noticed part of the voc file is found with in msg.data[“bill_type”]
content bill_type.voc

land taxes
state taxes
federal taxes

utterance: “What i have to pay monthly in federal taxes”

msg.data["bill_type"] would carry "federal taxes"

or in a check

if msg.data["bill_type"] == "federal taxes":
# better: if "federal" in msg.data["bill_type"]  # and add "federal tax" or whatever the SST might hear
     dothemath(msg) 

Yet this should be doable with one dothemath call and an organised database of some sort

1 Like

Thank you, @SGee

My concern is: isn’t this method forced to compare a fixed string in the code?
What if this skill is translated in italian (my native language, for example) and mycroft triggers the intent by anckwolegding the translated .voc files, in the code it will try to compare “tasse federali” (which is the italian equivalent) to “federal taxes” without entering the code inside the if body.

The other thing I was trying to understand is: adapt match an intent when it matches the group of keywords and their conditions. But if I want to use an adapt intent with a single .voc file?

@intent_handler(IntentBuilder('SingleWord').require('word')

In this case the intent triggers when word.voc entities are acknowledged, but this happens on standalone as much as it happens when found in other phrases.
For example word.voc contains “bye”
I can say “bye” or “bye bye” and trigger the intent and also say “do you want me to say bye” and trigger the intent. How can I prevent that? How can I trigger the intent only when my utterance is equivalent to the entity (or multiple of it)?

Ah thinking big picture. Hard coding is obviously bad if this is meant to be used from a wider audience,

if self.voc_match(msg.data["bill_type"], "federal") with federal.voc federali \n ...
This is more natural as you define a vocabulary of word variations or synonym words
(if used with the parameter exact=True those have to match… exactly)

totally hacky is
if self.translate("federal") in msg.data["bill_type"] with federal.dialog federali

The second problem would indicate you should use padatious instead as you can define the exact length/order of the intent. (The strength of adapt -in my book- is the relative freedom how you can formulate the phrase without defining every single variation of the phrase in a .intent) That said, i’m not exactly sure how the extreme “bye” “bye bye” would be handled there, but it is/can be much more rigorous.

So basically the first solution compares a root term and checks if federal ~= federali?
If this is how it works, that would be a problem for something like vocab/en-us/animal.voc with ’fox’ and vocab/it-it/animal.voc with ’volpe’ because they’re nothing alike.
About the second solution (alias the hacky one), is it possible to mistranslate the given entity? And also, would this solution force the skill to run online?

As for the ‘bye’ ‘bye bye’, why not, if it works, it works. Only question is, will padatious force me to run that online, or will Mimic 3 handle this offline without problems?