#16 API for command processing should have two stages

Closed
opened 7 years ago by clara · 1 comments
clara commented 7 years ago

Currently, the plugin API makes command processing all-or-nothing: as soon as a plugin sees a command, it must either handle it or pass it on to let another plugin handle it. This is bad for the successful recognition of commands. A prime example of this is the new MPRIS plugin. When music is not playing, its commands are easily understood, but when music is playing, the “pause music” command is often misunderstood by Pocketsphinx as “whats music”. This could be solved if the plugin knew that “whats music” means to pause, but for now that would mean it has to always handle that command. What if some other plugin would rather handle that command? If MPRIS was loaded first, it would always win.

I propose that to solve this, plugins should handle commands in two phases. First, they all get to see the command and say how confidently they want to handle it (floating point, range [0, 1], 0 being “definitely not” and 1 being “definitely”). Kaylee can then keep track of which plugin had the highest confidence, using loading order to break ties. After all plugins have chimed in, the winner gets another method called to actually handle the command. This could also create a new configuration option: the minimum confidence a plugin must have to be able to handle a command. Setting this option to 0.2 would mean if the highest confidence is 0.1, the command is not handled by anyone. This could be tuned to reduce false positives that may crop up from low-confidence results.

Note that this proposal would obsolete the “processed” signal, which is good. I always thought it seemed redundant anyway.

There would be other changes to plugin etiquette as well. Specifically: if a command can be handled by a plugin in some circumstances, but current state means it would be a no-op (e.g. “pause music” when no music player is running), it should return 0 confidence.

Currently, the plugin API makes command processing all-or-nothing: as soon as a plugin sees a command, it must either handle it or pass it on to let another plugin handle it. This is bad for the successful recognition of commands. A prime example of this is the new MPRIS plugin. When music is not playing, its commands are easily understood, but when music is playing, the "pause music" command is often misunderstood by Pocketsphinx as "whats music". This could be solved if the plugin knew that "whats music" means to pause, but for now that would mean it has to always handle that command. What if some other plugin would rather handle that command? If MPRIS was loaded first, it would always win. I propose that to solve this, plugins should handle commands in two phases. First, they all get to see the command and say how confidently they want to handle it (floating point, range [0, 1], 0 being "definitely not" and 1 being "definitely"). Kaylee can then keep track of which plugin had the highest confidence, using loading order to break ties. After all plugins have chimed in, the winner gets another method called to actually handle the command. This could also create a new configuration option: the minimum confidence a plugin must have to be able to handle a command. Setting this option to 0.2 would mean if the highest confidence is 0.1, the command is not handled by anyone. This could be tuned to reduce false positives that may crop up from low-confidence results. Note that this proposal would obsolete the "processed" signal, which is good. I always thought it seemed redundant anyway. There would be other changes to plugin etiquette as well. Specifically: if a command can be handled by a plugin in some circumstances, but current state means it would be a no-op (e.g. "pause music" when no music player is running), it should return 0 confidence.
clara commented 7 years ago
Owner

There is a potential for race conditions here. If the MPRIS plugin gets the phrase “next song” and sees that a music player is running, it will return confidence 1. If the music player exits before the MPRIS plugin gets to run “next song”, the MPRIS plugin still handles the command and will do nothing. This could possibly stop another plugin that wants to handle it with less confidence.

This could be solved by keeping track of every plugin’s answer (greater than the minimum confidence), sorting them as described above, then trying each one in order until one actually handles the command. This could be easily implemented as a queue.PriorityQueue with items (1 - confidence, plugin_index, plugin_obj) where confidence is the confidence returned by the plugin, plugin_index is the index of the plugin in Kaylee’s plugin list, and plugin_obj is the Plugin instance.

There is a potential for race conditions here. If the MPRIS plugin gets the phrase "next song" and sees that a music player is running, it will return confidence 1. If the music player exits before the MPRIS plugin gets to run "next song", the MPRIS plugin still handles the command and will do nothing. This could possibly stop another plugin that wants to handle it with less confidence. This could be solved by keeping track of every plugin's answer (greater than the minimum confidence), sorting them as described above, then trying each one in order until one actually handles the command. This could be easily implemented as a `queue.PriorityQueue` with items `(1 - confidence, plugin_index, plugin_obj)` where `confidence` is the confidence returned by the plugin, `plugin_index` is the index of the plugin in Kaylee's plugin list, and `plugin_obj` is the Plugin instance.
Sign in to join this conversation.
No Milestone
No Assignees
1 Participants
Due Date

Dec 31, 0000 Overdue

Dependencies

This issue currently doesn't have any dependencies.

Loading…
Cancel
Save
There is no content yet.