Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

Ask DeepWiki

OVOS Model2Vec Intent Pipeline

An intent matching pipeline for OpenVoiceOS (OVOS). It uses the Model2Vec model for intent classification.

This plugin uses a pretrained Model2Vec model to classify natural language utterances into intent labels registered with the system (Adapt, Padatious, and plugin-specific labels). It only considers intents from loaded skills and ignores labels from unregistered intents. Use this pipeline when deterministic engines fail to give a high-confidence match.


Features

  • Model2Vec drives intent classification.
  • The plugin integrates directly with OVOS pipelines.
  • The Model2Vec models train on GitLocalize exports.
  • English models come in several sizes, distilled from Potion.
  • The multilingual model is distilled from LaBSE.
  • The plugin syncs Adapt and Padatious intents dynamically at runtime.
  • The plugin considers only intents from loaded skills and ignores unregistered labels.

English models range from 8 MB to 150 MB. The multilingual model (the default) is over 500 MB.


Installation

Install the plugin with pip:

pip install ovos-m2v-pipeline

Configuration

In your mycroft.conf:

{
  "intents": {
    "ovos-m2v-pipeline": {
      "model": "Jarbas/ovos-model2vec-intents-LaBSE",
      "conf_high": 0.7,
      "conf_medium": 0.5,
      "conf_low": 0.15,
      "ignore_intents": []
    }
  }
}
  • model: Path to your pretrained Model2Vec model or huggingface repo.
  • conf_xxx: Minimum confidence threshold for intent matching.
  • ignore_intents: List of canonical labels to exclude from matching (deny-list, applied after label_map).
  • valid_labels: List of raw model labels eligible to match (allow-list, checked before label_map is applied). When unset, every label is eligible.
  • label_map: Maps a raw model label to its canonical skill_id:intent label. Merges over (and can override) the built-in OCP/common-query/stop remaps and any labels the model itself declares in labels.json; see Trained models document their labels.
  • prototype_strategy: Scoring strategy for prototype mode (default "max_over_all", back-compatible). See docs/strategies.md.
  • prototype_top_k: Top-k cosines averaged by the top_k_mean strategy (default 3).
  • prototype_tau: Softmax temperature for the softmax_weighted strategy (default 0.1).
  • preload_model: Load the embedding model at construction instead of on first use (default false). ovos-core builds every installed pipeline plugin at boot, so the default defers the load to the first registration or match; set this if a deployment would rather pay the load cost once at boot than on the first query. See model_load_budget below for what happens to that first query when the model is still loading.
  • model_load_budget: Seconds a match call waits for a cold-start model load before giving up on that one utterance (default 0.5). The load keeps running in the background regardless; matching resumes automatically once it completes. If the load itself fails (bad model id, unreachable host), it retries on its own after a backoff that starts at 30s and doubles on each consecutive failure, capped at 15 minutes.

The Model2Vec model is pretrained on GitLocalize exports. It cannot learn new skills dynamically.


Prototype cache (prototype mode)

Prototype mode rebuilds its label set from scratch on every boot: each registered skill's example utterances are re-encoded through the embedding model as padatious:register_intent / OVOS-INTENT-4 template registrations arrive. On an install with many skills, re-encoding the same, unchanged templates on every restart is pure repeated work.

To avoid that, each label's encoded prototypes are cached to disk, keyed on the inputs of its registration: the model id, the installed model2vec version, the anchor-selection parameters (prototype_k, prototype_strategy, the entity-expansion cap), the registration's raw (pre-expansion) template lines, and any registered entity values its {slot} placeholders reference. When a label's next registration hashes to the same key, its embeddings are loaded from the cache instead of being re-encoded; any other change to those inputs is a plain cache miss, so nothing needs to be told explicitly to invalidate a stale entry when a skill updates its templates or the model is swapped.

Removal (detach_intent, detach_skill, and their OVOS-INTENT-4 equivalents) is the one case that does need explicit invalidation: nothing about a removed skill's registration inputs changes when it unloads, so its cache entry is deleted immediately rather than left to resurrect the skill's intents on the next boot.

Cache files live under {XDG_DATA_HOME}/mycroft/m2v_prototypes/ by default (one small .npz file per label) and are local-disk-only: nothing here ever touches the network. A corrupt or unreadable entry is logged and treated as a miss, never as a fatal error.

Configuration (under the same intents.<entrypoint-name> block as above):

  • prototype_cache: Enable/disable the cache (default true).
  • prototype_cache_dir: Override the cache directory.

Which entrypoint do I want?

This plugin ships two opm.pipeline entrypoints. Both use the same Model2VecIntentPipeline class, running in different modes:

  • ovos-m2v-pipeline (Model2VecIntentPipeline, mode: "classifier", the default) loads a pretrained, frozen classification head with a fixed label set baked in at training time. It is fast and needs no runtime fitting, but it can only ever return the labels it was trained on. It still tracks OVOS-INTENT-4 ovos.intent.register.template registrations from skills so it can gate/allowlist a trained label, but registering a new intent that was not part of training does not teach it to that skill. That intent will never be matched.
  • ovos-m2v-prototype-pipeline (Model2VecPrototypePipeline, mode: "prototype") loads a bare embedding model with no classification head and builds its label set entirely at runtime, from the example utterances supplied by Adapt/Padatious registrations and OVOS-INTENT-4 template registrations. Use this entrypoint whenever skills need to register new intents (including custom/dynamically-created skills) that must actually be matched.

You can enable both entrypoints together. Configure each independently under its own intents.<entrypoint-name> key (see the Model2VecPrototypePipeline docstring for an example), so a deployment can keep the fast frozen classifier for its core trained intents while the prototype matcher picks up everything else.


Trained models document their labels

In classifier mode the label head is frozen at training time, so which bus intent each label denotes (ocp:play -> ovos.common_play:ovos.common_play.play_search, for example) is a property of that particular trained model, not of the plugin code. A model can ship this mapping alongside its weights as a labels.json file in its repo/directory:

{
  "valid_labels": ["my_domain:book_flight", "my_domain:cancel_flight"],
  "families": {
    "my_domain:book_flight": "skill",
    "my_domain:cancel_flight": "skill"
  }
}

A canonical label carries no .intent suffix: the suffix names the resource a skill ships, not the intent, and the legacy Padatious handler strips it before the label reaches the bus.

labels.json has the same shape as the label_map config option, plus an optional valid_labels list and an optional families map. valid_labels lists the model's raw labels - the ones it was actually trained on - not the label_map targets; the allow-list check happens before label_map resolution, so it also covers ocp:play / stop:stop / common_query:common_query before those get rewritten to their bus topics. families names the family each canonical label belongs to (skill, ocp, common_query, stop or persona), which is what the per-family claim filter keys on. A label missing from the map is logged once and treated as skill.

When present, list the labels a model was trained on in its model card too, so users know what to expect without downloading it first.

Three layers combine, each overriding the previous on a per-key basis:

  1. Built-in defaults (the OCP / common-query / stop remaps that predate this mechanism).
  2. The loaded model's own labels.json, if it ships one.
  3. The deployment's label_map / valid_labels config.

For a Hugging Face hub model id, labels.json rides the same local cache as the model's own weights: the plugin never fetches it over the network at construction time, and only ever consults the cache entry already populated by whatever downloaded the model. If the model has not been cached yet, or the cached copy has no labels.json, the manifest layer is treated as empty

  • it is never a reason for plugin construction to touch the network or block on one.

A missing or corrupt labels.json is logged and ignored; the plugin falls back to the layers below it rather than failing to load. A label_map target that is not a skill_id:intent string (no colon) is logged as a warning (once per label) and used as-is - the plugin never invents a bus topic from it.


Usage

The Model2VecIntentPipeline class integrates with the OVOS intent system. It:

  1. Receives an utterance (text).
  2. Predicts intent labels using the pretrained Model2Vec model.
  3. Filters out intents that are not part of the loaded skills.
  4. Returns a match for the highest-confidence intent from the list of valid intents.

Tips

  • Tune min_conf to control the confidence threshold for intent matching.
  • Use the ignore_intents list to filter out specific problematic intents from predictions.
  • The plugin syncs Adapt and Padatious intents automatically at runtime, over the OVOS message bus.

Pre-trained models are available in the ovos-model2vec-intents Hugging Face collection.


Related projects

  • OpenVoiceOS: the OVOS org, and the intent-pipeline system this plugin extends.
  • ovos-plugin-manager: the base pipeline class and plugin infrastructure.
  • ovos-workshop: the skill framework this plugin integrates with.

License

This project is licensed under the Apache 2.0 License.


Credits

The model2vec intent pipeline was first prototyped by TigreGótico under the ILENIA project for OpenVoiceOS and later extended with an embeddings-only mode and new models, through the NGI0 Commons Fund.

This project was funded by the Ministerio para la Transformación Digital y de la Función Pública and Plan de Recuperación, Transformación y Resiliencia - Funded by EU, NextGenerationEU within the framework of the project ILENIA with reference 2022/TL22/00215337

NGI0 Commons Fund

This project was funded through the NGI0 Commons Fund, a fund established by NLnet with financial support from the European Commission's Next Generation Internet programme, under the aegis of DG Communications Networks, Content and Technology under grant agreement No 101135429.


Training your own model

train/ builds the intent corpus from pinned sources and fits a classifier on it. See docs/training.md for the end-to-end recipe and the current hold on training runs, and docs/labels.md for the label scheme every model must follow.

Release files for ovos-m2v-pipeline 0.8.2a2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ovos-m2v-pipeline 0.8.2a2
File Size Uploaded
ovos_m2v_pipeline-0.8.2a2.tar.gz 76.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ovos-m2v-pipeline 0.8.2a2
File Interpreter ABI Platform
ovos_m2v_pipeline-0.8.2a2-py3-none-any.whl Python 3 none any Details

Total release size: 113.1 kB

Release files / ovos_m2v_pipeline-0.8.2a2.tar.gz

Download URL ovos_m2v_pipeline-0.8.2a2.tar.gz
Size 76.7 kB
Tags Source
SHA-256 checksum
How to use checksums
5564bf60e84b11d75b2b7a4f4995a3030a8ffe955dafdb290c35f6d29d6e6818
BLAKE2b-256 checksum
How to use checksums
29a3e035c298e6f3d5396c9495e35cba52aa2e26abe377488ff4d20ebe907d96
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / ovos_m2v_pipeline-0.8.2a2-py3-none-any.whl

Download URL ovos_m2v_pipeline-0.8.2a2-py3-none-any.whl
Size 36.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4d73225bb7ff86853ee89e6e6b3e8c6975a996d1288b5d5fde746f0720b0c28d
BLAKE2b-256 checksum
How to use checksums
08bb6f2f128708a9a11494412e48a842a5cc8717b35e9ea8f2488a27f4cec162
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release history Release notifications | RSS feed

This release

0.8.2a2 This release

2 release files

0.0.9

2 release files

0.0.8

2 release files

0.0.7

2 release files

0.0.6

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page