OVOS Hierarchical KNN Intent Classifier — Granite 97m Multilingual R2
A multilingual intent-classification index for OpenVoiceOS (OVOS) built on top of IBM Granite Embedding 97M Multilingual R2 and a two-stage hierarchical k-NN classifier with Wu-Lin pairwise probability estimation.
What's in this repo
| File | Description |
|---|---|
onnx/model_quint8_avx2.onnx |
Quantised Granite 97m encoder (AVX2, ~94 MB) — recommended for inference |
onnx/model.onnx |
Full-precision Granite 97m encoder (~372 MB) |
tokenizer.json / tokenizer_config.json / special_tokens_map.json |
Tokenizer files (PreTrainedTokenizerFast) |
index.faiss |
FAISS IVF-PQ index (nlist=1024, pq_m=16, nprobe=32) |
meta.pkl |
Index hyper-parameters and label metadata |
label_ids.npy |
Per-vector label assignments |
class_names.npy |
Sorted array of domain:intent label strings |
class_to_train_ids.pkl |
Mapping from class index → training vector IDs |
Index details
- 201 intents across 39 OVOS skill domains
- Embedding model: Granite Embedding 97M Multilingual R2 (dim=384, CLS pooling)
- FAISS index type: IVF1024,PQ16 (inner-product / cosine similarity)
- Training langs:
en,pt,es,fr,it,de,nl,ca,gl,da,eu - Hyper-parameters:
k=7,n=2(top-2 domains → intent search),margin=0.1,tau=0.5
Covered skill domains (39)
common_query
ocp
stop
ovos-skill-alerts.openvoiceos
ovos-skill-application-launcher.openvoiceos
ovos-skill-audio-recording.openvoiceos
ovos-skill-boot-finished.openvoiceos
ovos-skill-camera.openvoiceos
ovos-skill-color-picker.krisgesling
ovos-skill-color-picker.krisgesling.openvoiceos
ovos-skill-confucius-quotes.openvoiceos
ovos-skill-count.openvoiceos
ovos-skill-date-time.openvoiceos
ovos-skill-days-in-history.openvoiceos
ovos-skill-ddg.openvoiceos
ovos-skill-diagnostics.openvoiceos
ovos-skill-dictation.openvoiceos
ovos-skill-fuster-quotes.openvoiceos
ovos-skill-hello-world.openvoiceos
ovos-skill-icanhazdadjokes.openvoiceos
ovos-skill-ip.openvoiceos
ovos-skill-iss-location.openvoiceos
ovos-skill-laugh.openvoiceos
ovos-skill-moviemaster.openvoiceos
ovos-skill-naptime.openvoiceos
ovos-skill-news.openvoiceos
ovos-skill-parrot.openvoiceos
ovos-skill-personal.OpenVoiceOS.openvoiceos
ovos-skill-personal.openvoiceos
ovos-skill-randomness.openvoiceos
ovos-skill-screenshot.openvoiceos
ovos-skill-speedtest.openvoiceos
ovos-skill-volume.openvoiceos
ovos-skill-wallpapers.openvoiceos
ovos-skill-weather.openvoiceos
ovos-skill-wikihow.openvoiceos
ovos-skill-wikipedia.openvoiceos
ovos-skill-wolfie.openvoiceos
ovos-skill-wordnet.openvoiceos
Supported languages
The index was trained with utterances in 11 languages. The base Granite model supports many more but only these are covered by the training data:
| Code | Language |
|---|---|
en |
English |
pt |
Portuguese |
es |
Spanish |
fr |
French |
it |
Italian |
de |
German |
nl |
Dutch |
ca |
Catalan |
gl |
Galician |
da |
Danish |
eu |
Basque |
How it works
Classification is a two-stage k-NN search:
- L1 — domain search: the query embedding is compared against all training vectors; Wu-Lin pairwise probabilities are computed per skill domain and the top-
ndomains are selected. - L2 — intent search: a second search is scoped to training vectors that belong only to those top-
ndomains; Wu-Lin probabilities are computed per intent label. - The L1 and L2 probabilities are multiplied and re-normalised to give a final
{label: probability}dict.
At runtime the search can be further restricted to the subset of domains whose skills are actually loaded (via set_active_domains()), which is what the OVOS plugin does automatically.
Usage
Install the OVOS plugin
pip install ovos-hierarchical-knn-pipeline
Load the index
from ovos_hierarchical_knn_pipeline.classifier import HierarchicalPairKNNClassifier
clf = HierarchicalPairKNNClassifier.from_pretrained()
utterances = [
"what's the weather like tomorrow?",
"play some jazz music",
"set an alarm for 7am",
"qual é a temperatura agora?", # pt
"qué hora es?", # es
]
predictions = clf.predict(utterances)
for utt, pred in zip(utterances, predictions):
print(f"{pred:<55} {utt}")
Get calibrated probabilities
probs_list = clf.predict_proba(utterances)
for utt, probs in zip(utterances, probs_list):
top = sorted(probs.items(), key=lambda x: x[1], reverse=True)[:3]
print(f"\n{utt}")
for label, p in top:
print(f" {p:.3f} {label}")
Restrict search to active skill domains
set_active_domains() pre-computes a FAISS bitmap so only vectors from the specified domains are searched. Call it once after loading the index:
active_skills = [
"ovos-skill-weather.openvoiceos",
"ovos-skill-date-time.openvoiceos",
"common_query",
"ocp",
"stop",
]
clf.set_active_domains(active_skills)
probs = clf.predict_proba(["what time is it?"])[0]
OVOS plugin configuration
The plugin downloads the index automatically on first run. Simply add the pipeline to your OVOS mycroft.conf:
{
"intents": {
"pipeline": [
"ovos-hierarchical-knn-pipeline-high",
"adapt-high",
"padatious-high",
"ovos-hierarchical-knn-pipeline-medium",
"adapt-medium",
"padatious-medium",
"ovos-hierarchical-knn-pipeline-low",
"adapt-low",
"padatious-low",
"fallback-low"
],
"ovos_hierarchical_knn_pipeline": {
"conf_high": 0.70,
"conf_medium": 0.50,
"conf_low": 0.15
}
}
}
To use a local copy (faster startup, no internet required on boot), set index_dir to a previously downloaded snapshot:
{
"intents": {
"ovos_hierarchical_knn_pipeline": {
"index_dir": "/path/to/local/snapshot"
}
}
}
Hardware requirements
| Component | Requirement |
|---|---|
| RAM | ~320 MB (index + quantised encoder) |
| CPU | x86-64 with AVX2 (model_quint8_avx2.onnx) |
| Storage | ~345 MB total |
The quantised ONNX model (model_quint8_avx2.onnx) is used for inference. The full-precision model.onnx is only required when rebuilding the index from scratch (see train/README.md).
License
Apache 2.0 — see LICENSE.
The base embedding model (IBM Granite Embedding 97M Multilingual R2) is also released under Apache 2.0.