intents
intents copied to clipboard
We should prioritize intent matching in specific contexts over generic ones
Probably the most common phrase for turning off a light in Romanian is "inchide [light]". The most common phrase for closing a door/window is "inchide [opening]".
Notice that the verb is the same ("inchide") in Romanian, although in English the 2 are totally different.
As a consequence, a test written for the sentence "inchide homeassistant_HassTurnOff
intent, even when that specific entity name is a cover, which is more specific.
A working example (only relevant parts selected):
sentences/ro/_common.yaml
expansion_rules:
area: "{area} [(zona | zonă | regiune)]"
name: "({name}[ul] | {name})"
din: "(din | (î|i)n | pentru | [de] la)"
opreste: "(stop | opre(ș|s)te | (î|i)nchide | stinge | dezactiveaz(ă|a))"
inchide: "((î|i)nchide | coboar(ă|a))"
sentences/ro/cover_HassCloseCover.yaml
intents:
HassCloseCover:
data:
- sentences:
- "<inchide> <name>"
- "<inchide> <name> [<din>] <area>"
sentences/ro/homeassistant_HassTurnOff.yaml
intents:
HassTurnOff:
data:
- sentences:
- "<opreste> <name>"
tests/ro/_fixtures.yaml
entities:
- name: fereastra din stanga
id: cover.bedroom_window_left
device_class: window
area: bedroom
tests/ro/cover_HassCloseCover.yaml
tests:
- sentences:
- "inchide fereastra din stanga"
intent:
name: HassCloseCover
slots:
name: cover.bedroom_window_left
The test result:
FAILED tests/test_language_sentences.py::test_cover_HassCloseCover[ro] - AssertionError: For 'inchide fereastra din stanga' expected intent HassCloseCover, got HassTurnOff
Then we should have:
expansion_rules: area: "{area} [(zona | zonă | regiune)]" name: "({name}[ul] | {name})" din: "(din | (î|i)n | pentru | [de] la)" opreste: "(stop | opre(ș|s)te | stinge | dezactiveaz(ă|a))" inchide: "((î|i)nchide | coboar(ă|a))"
and then we can clearly use them. As example "inchide" make more sense to blinds, doors and covers them to lights ?
True, but we can't control how people are going to ask for certain actions to happen. And to be fair, mostly everyone says "inchide lumina" when trying to turn off the light.
If it comes to that, I'm more willing to sacrifice "inchide usa" in favor of "inchide lumina", as fewer people have door shutting devices than those who have smart lights.
I think then they need to use proper "aprinde / stinge" for lights.
This image might answer a lot better than I ever could.
Sure, you can force users to say "aprinde/stinge" instead of their usual "deschide/inchide". Dictionaries recommend it. But if you want to provide a good experience, you need to allow them to (also) use the colloquial wording they are accustomed to.
Plus, @synesthesiam said he may have a fix based on more/less context when defining the intent sentences. Let's see if that works and we'll figure out a workaround afterwards, if necessary.
ok, good point.
Jut did a test on current voice assistant and asking to "open light name" did not worked the same for "turn on gate name". So also looks that even in EN is strict usage. But as you mention let's see latter.
It doesn't make sense in English to "open a light". You turn it on. You open a gate, which you can't turn on. It's different in Romanian.
"A inchide" literally means "to shut [an opening]", but also "to darken [a color, the sky]" https://dexonline.ro/definitie/%C3%AEnchidere.
So that was my point that "inchide" should not be used for lights ;)
I agree with @tetele. Home Assistant should simply work. If Romanian people usually say "inchide lumina" to turn off a light, this case of use should be supported, no matter if the verb is the same as the one used to close doors.
I can see in #416 that this same case happens in Simplified Chinese, where the same verb is used to turn on a light and to open a curtain.
Also in #416, @synesthesiam said that he is working on the ability to restrict an intent match to a specific domain, so the test entities will have their domain with them... Not sure if this has progressed or not.
hm... for me, this looks like a design flaw...
I think - it would be more suitable to use the device / domain to define the possible actions and then, you could use what ever you want to activate the corresponding action.
For example - if I have a garage door and a light, the devices define the possible actions. Now, I could combine an intent like "get rid of..." either to "close", "shut down", "delete" - or whatever I want it to be.
The device / domain will then link to the required action:
"Get rid of the waste" -> deleting the trash on my computer "Get rid of the living room light" -> shut down the light in the living room "Get rid of the Garage door" -> is closing the garage door.
The user should be able to define ANYTHING he wants for an action, not only "most common" spoken terms etc.
Hope, my thoughts are somehow clear and understandable... :)
I'm working on a PR for this now. In short, you use requires_context
in the cover intent to only match on a specific domain. Then, excludes_context
in the generic turn on/off intent to skip matches with that domain.
Why are both needed? For matching speed. Intents are not ordered before matching, and the first match is always returned. So both intents need to be aware of the constraints.
When the PR lands, the changes needed in sentences/ro/cover_HassCloseCover.yaml
are:
intents:
HassCloseCover:
data:
- sentences:
- "<inchide> <name>"
- "<inchide> <name> [<din>] <area>"
requires_context:
domain: cover
and in sentences/ro/homeassistant_HassTurnOff.yaml
:
intents:
HassTurnOff:
data:
- sentences:
- "<opreste> <name>"
excludes_context:
domain: cover
Note that domain
can be a list as well.
Not sure if you've thought about this in advance, but it might help to "require context" with any value for certain slots.
For example a certain sentence should signal an intent only if an area is provided, explicitly or implicitly. Or if a certain entity name exists. Etc.
For example
intents:
HassCloseCover:
data:
- sentences:
- "turn off {name} [from] {area}"
requires_context:
area: *
domain: cover
That could cover the inferred context I was talking about elsewhere.
I'm working on a PR for this now. In short, you use
requires_context
in the cover intent to only match on a specific domain. Then,excludes_context
in the generic turn on/off intent to skip matches with that domain.
That is great!
PR is merged :slightly_smiling_face: