Utterance Transformers¶
In a nutshell
An "utterance" is simply the text of what you said, once the assistant has transcribed your speech into words. These plugins get to fix and tidy that text before the assistant tries to understand it — for example correcting misheard words, smoothing out the phrasing, or handling more than one language — so it matches your request more reliably. See Transformer Plugins and the Glossary for unfamiliar terms.
📐 Formal specification
Utterance transformers are the utterance chain of OVOS-TRANSFORM-1 — Transformer Plugins §3.2 (a formal architecture spec). The spec's post-STT, pre-intent injection point receives the non-empty list of candidate transcriptions (utterances[0] is the primary candidate, later indices are n-best alternatives), an optional lang, and the full Message.context; it returns a possibly rewritten list plus mutated lang/context. Returning an empty list signals "no plausible transcription"; returning empty with canceled: true + cancel_reason invokes utterance cancellation (§3.2, §8). Ordering: the chain runs by ascending priority (lowest first), matching the spec.
Utterance Transformers in OpenVoiceOS (OVOS) are plugins that process and modify user utterances immediately after speech-to-text (STT) conversion but before intent recognition. They serve to enhance the accuracy and flexibility of the assistant by correcting errors, normalizing input, and handling multilingual scenarios.
How They Work¶
-
Speech Recognition: The user's spoken input is transcribed into text by the STT engine.
-
Transformation Phase: The transcribed text passes through any active utterance transformers.
-
Intent Recognition: The transformed text is then processed by the intent recognition system to determine the appropriate response.
This sequence ensures that any necessary preprocessing is applied to the user's input, improving the reliability of intent matching.
Utterance transformers register under the opm.transformer.text entry-point group and subclass UtteranceTransformer from ovos_plugin_manager.templates.transformers. They are loaded and chained by UtteranceTransformersService in ovos-core.
Configuration¶
A transformer is only loaded if its plugin name appears under the utterance_transformers section of your mycroft.conf; an empty {} is enough to enable it. Set "active": false to load-skip it. When several are active they run sorted by priority (lowest first), each operating on the output of the previous. An optional "order" list of plugin names in the same section overrides priority ordering entirely: plugins listed there run in that exact order (and are enabled even without their own config entry), while any loaded plugin absent from the list is not run.
Replace "plugin_name" with the identifier of the desired plugin and provide any necessary configuration parameters.
Available Utterance Transformer Plugins¶
OVOS Utterance Normalizer Plugin¶
-
Purpose: Standardizes user input by expanding contractions, converting numbers to words, and removing unnecessary punctuation.
-
Example:
-
Input:
"I'm 5 years old." -
Output:
"I am five years old"
-
-
Installation:
- Configuration:
- Source: GitHub Repository
OVOS Utterance Corrections Plugin¶
-
Purpose: Applies predefined corrections to common misrecognitions or user-defined replacements to improve intent matching.
-
Features:
-
Full utterance replacements via
corrections.json -
Word-level replacements via
word_corrections.json -
Regex-based pattern replacements via
regex_corrections.json
-
-
Example:
-
Input:
"shalter is a switch" -
Output:
"schalter is a switch"
-
-
Installation:
- Configuration:
- Source: GitHub Repository
OVOS Utterance Cancel Plugin¶
-
Purpose: Detects phrases indicating the user wishes to cancel or ignore the current command and prevents further processing.
-
Example:
-
Input:
"Hey Mycroft, can you tell me the... umm... oh, nevermind that" -
Output: Utterance is discarded; no action taken
-
-
Installation:
- Configuration (the installed package is
ovos-utterance-plugin-cancel, but its registered plugin name isovos-utterance-cancel-plugin):
- Source: GitHub Repository
OVOS Bidirectional Translation Plugin¶
-
Purpose: Detects the language of the user's input and translates it to the assistant's primary language if necessary, enabling multilingual interactions.
-
Features:
-
Language detection and translation to primary language
-
Optional translation of responses back to the user's language
-
-
Example:
-
Input:
"¿Cuál es el clima hoy?"(Spanish) -
Output:
"What is the weather today?"(translated to English for processing)
-
-
Installation:
- Configuration (the utterance half registers under the entry-point name
ovos-utterance-translation-plugin):
"utterance_transformers": {
"ovos-utterance-translation-plugin": {
"verify_lang": true,
"ignore_invalid_langs": true
}
}
- Source: GitHub Repository
OVOS Transcription Validator Plugin¶
- Purpose: Uses an OpenAI-compatible LLM to judge whether an STT transcription is a plausible utterance at all, filtering out garbled or nonsensical speech-to-text output before it reaches intent matching.
Note
This plugin makes a network call per utterance (to the configured LLM endpoint), so it trades latency for robustness against noisy STT.
- Installation:
- Configuration:
- Source: GitHub Repository
Writing your own Utterance Transformer¶
Subclass UtteranceTransformer (ovos_plugin_manager.templates.transformers) and
override its transform(utterances, context=None) -> Tuple[List[str], dict] method.
Register the class under the opm.transformer.text entry-point group.
Create a Python Class:
from typing import List, Tuple, Optional, Dict, Any
from ovos_plugin_manager.templates.transformers import UtteranceTransformer
class MyCustomTransformer(UtteranceTransformer):
def __init__(self, name: str = "my-custom-transformer", priority: int = 50,
config: Optional[Dict[str, Any]] = None):
super().__init__(name, priority, config)
def transform(self, utterances: List[str],
context: dict = None) -> Tuple[List[str], dict]:
# utterances is a list of strings; return (utterances, extra_context)
context = context or {}
modified_utterances = [u.lower() for u in utterances]
return modified_utterances, context
The base UtteranceTransformer.__init__(self, name, priority=50, config=None) requires name,
and the loader never supplies it: it inspects the constructor and calls
plug(config=plugin_config) where a config keyword is accepted, and plug() otherwise, in
which case the plugin reads its own section from Configuration(). Either way a plugin must
override __init__ to supply its own name, as shown above, and must pass name, priority,
and config through to super().__init__() so the base class still sees them.
The second return value is additional context that gets merged into the message context, not a replacement for it.
Config-driven priority¶
The loader passes only the plugin's config block into __init__, not a separate priority
argument. To let a deployment override priority from mycroft.conf instead of the hard-coded
default, read it back out of self.config after calling super().__init__():
class MyCustomTransformer(UtteranceTransformer):
def __init__(self, name: str = "my-custom-transformer", priority: int = 50,
config: Optional[Dict[str, Any]] = None):
super().__init__(name, priority, config)
self.priority = self.config.get("priority", self.priority)
Without that explicit self.config.get("priority", ...) line, a "priority" key in
mycroft.conf is inert — the loader does not read it back into self.priority on its own.
The default priority is 50; a lower number runs earlier in the chain.
Where lang fits
The spec box above describes the transform as receiving utterances, lang, and
Message.context; in the installed UtteranceTransformer.transform() signature
lang isn't a separate parameter — it travels inside the context dict (e.g.
context.get("lang")), matching the class actually shipped in
ovos_plugin_manager.templates.transformers.
Register as a Plugin. A full pyproject.toml for a standalone plugin package:
[project]
name = "ovos-utterance-transformer-mycustom"
version = "0.1.0"
dependencies = ["ovos-plugin-manager"]
[project.entry-points."opm.transformer.text"]
my-custom-transformer = "my_module:MyCustomTransformer"
An opm.transformer.text.config group is also available, for a dict of config
metadata an installer or GUI can read. It is optional; add it once the plugin has
settings worth advertising.
Install and Configure:
After installation, add your transformer to the mycroft.conf:
Test it without OVOS¶
UtteranceTransformer subclasses are plain classes, so a unit test needs no bus. Pass an
explicit config though: when it is omitted, the base __init__ reads the plugin's section
from the Configuration() singleton, which touches the on-disk config layers:
from my_module import MyCustomTransformer
transformer = MyCustomTransformer(config={})
utterances, context = transformer.transform(["Hello World"])
assert utterances == ["hello world"]
Verify discovery¶
After pip install -e .:
from ovos_plugin_manager.text_transformers import find_utterance_transformer_plugins
print(find_utterance_transformer_plugins())
# {'my-custom-transformer': <class 'my_module.MyCustomTransformer'>}
Checklist before you publish¶
transform()acceptsutterances: List[str]and returns(utterances, context).__init__hardcodes the pluginnameand forwardsname,priority,configtosuper().__init__().- The entry-point group in
pyproject.tomlisopm.transformer.text. - A unit test calls
transform()directly, with no OVOS services running. find_utterance_transformer_plugins()discovers the installed plugin under the expected name.
Read next: Intent Transformers Related: Transformers Overview · Language Selection · Bidirectional Translation