Defined in nebulento/container.py:17.
Fuzzy intent matcher backed by rapidfuzz similarity strategies. Registers intent templates and entity samples, then scores an utterance against every registered intent.
IntentContainer(
fuzzy_strategy: MatchStrategy = MatchStrategy.DAMERAU_LEVENSHTEIN_SIMILARITY,
ignore_case: bool = True,
)| Parameter | Type | Default | Description |
|---|---|---|---|
fuzzy_strategy |
MatchStrategy |
DAMERAU_LEVENSHTEIN_SIMILARITY |
Similarity algorithm used for all comparisons. See Match Strategies. |
ignore_case |
bool |
True |
When True, utterances and templates are lowercased before comparison. |
nebulento/container.py:74
Register an intent with one or more training templates.
Templates support (a|b) alternation, [optional] syntax, and {entity} capture placeholders. All variants are expanded at registration time via expand_template(normalize_example(line)) and duplicates are discarded.
container.add_intent(
name="play",
lines=[
"play {song}",
"(put on|start) [some] {song}",
"I want to listen to {song}",
]
)| Parameter | Type | Description |
|---|---|---|
name |
str |
Unique intent identifier. Convention for OVOS skills: "skill_id:intent_name". |
lines |
List[str] |
Training templates. May use full template syntax. |
Raises RuntimeError if name is already registered. Call remove_intent first if re-registration is needed.
nebulento/container.py:98
Unregister an intent. Silently does nothing if name is not registered.
container.remove_intent("play")nebulento/container.py:55
Read-only list of all currently registered intent names.
names = container.intent_names
# ['hello', 'goodbye', 'play']nebulento/container.py:106
Register an entity with sample values. When a template containing {name} is the best match and a registered sample value appears in the utterance, the confidence score is boosted and the value is included in entities.
Entity names are stored lowercase regardless of input casing.
container.add_entity("song", ["jazz", "rock", "classical music", "the blues"])| Parameter | Type | Description |
|---|---|---|
name |
str |
Entity name. Case-insensitive; stored lowercase. |
lines |
List[str] |
Sample values. Alternation syntax (a|b) is expanded. |
Raises RuntimeError if name is already registered.
nebulento/container.py:129
Unregister an entity. Case-insensitive. Silently does nothing if not registered.
container.remove_entity("song")nebulento/container.py:46
Dict mapping entity name (lowercase) → list of expanded sample strings.
samples = container.registered_entities["song"]nebulento/container.py:341
Return the single best-matching intent for query.
Tie-breaking order when multiple intents share the highest score:
- Higher
confscore. - More words consumed (more specific template).
- Intent name alphabetically (deterministic tie-break).
When no intents are registered or all are suppressed by context/keyword gates, returns a result dict with name=None and all other keys present with empty/zero values.
result = container.calc_intent("play some jazz")| Parameter | Type | Description |
|---|---|---|
query |
str |
Raw utterance to evaluate. |
Returns MatchResult — a Dict[str, object] with the following keys:
| Key | Type | Description |
|---|---|---|
name |
str | None |
Matched intent name. None if no match. |
conf |
float |
Confidence score in [0.0, 1.0]. |
entities |
Dict[str, List[str]] |
Entity name → list of matched values (lowercase keys). |
best_match |
str | None |
Training template that scored highest. |
utterance |
str |
Normalised input query. |
utterance_consumed |
str |
Space-joined words accounted for by the match. |
utterance_remainder |
str |
Space-joined words not accounted for. |
match_strategy |
str |
Name of the MatchStrategy enum value used. |
result = container.calc_intent("play some jazz")
# {
# 'name': 'play',
# 'conf': 0.752,
# 'entities': {'song': ['jazz']},
# 'best_match': 'play {song}',
# 'utterance': 'play some jazz',
# 'utterance_consumed': 'play jazz',
# 'utterance_remainder': 'some',
# 'match_strategy': 'DAMERAU_LEVENSHTEIN_SIMILARITY'
# }nebulento/container.py:327
Yield a scored MatchResult for every registered intent that is not suppressed by context or keyword gates. Results are in registration order.
Useful for debugging confidence distributions or implementing custom ranking on top of the raw scores.
for r in container.calc_intents("play some jazz"):
print(f"{r['name']:20s} conf={r['conf']:.3f}")Context gating allows intents to be conditionally suppressed based on named application state. The context system has two axes:
- Required contexts — the intent only fires when all required contexts are active.
- Excluded contexts — the intent is suppressed when any excluded context is active.
Contexts are stored per intent name. Multiple requirements or exclusions can be stacked.
nebulento/container.py:139
Mark a context as active for intent_name.
container.set_context("confirm_delete", "delete_pending")
container.set_context("confirm_delete", "user_id", "alice")| Parameter | Type | Description |
|---|---|---|
intent_name |
str |
Intent whose context availability is updated. |
context_name |
str |
Context key. |
context_val |
object |
Optional associated value. Not used by the matcher itself. |
nebulento/container.py:150
Remove an active context for intent_name.
container.unset_context("confirm_delete", "delete_pending")nebulento/container.py:160
Gate intent_name so it only matches when context_name is active. Multiple calls accumulate — all named contexts must be satisfied simultaneously.
container.require_context("confirm_delete", "delete_pending")
container.require_context("confirm_delete", "user_authenticated")nebulento/container.py:171
Remove a context requirement from intent_name. Other requirements are unaffected.
container.unrequire_context("confirm_delete", "user_authenticated")nebulento/container.py:183
Suppress intent_name whenever context_name is active.
container.exclude_context("help", "expert_mode")nebulento/container.py:193
Lift a context-based suppression from intent_name.
container.unexclude_context("help", "expert_mode")nebulento/container.py:204
Suppress intent_name when any keyword in samples appears in the query.
Single-word keywords use whole-word matching against the tokenised query. Multi-word keywords use a word-boundary regex (\b) against the lowercased query string. Keyword matching is case-insensitive.
container.add_intent("play_music", ["play some music", "start the music"])
container.exclude_keywords("play_music", ["video", "movie", "film"])
# Suppressed — "video" appears:
result = container.calc_intent("play a video")
print(result["name"]) # some other intent or None
# Not suppressed:
result = container.calc_intent("play some music")
print(result["name"]) # 'play_music'| Parameter | Type | Description |
|---|---|---|
intent_name |
str |
Intent to suppress. |
samples |
List[str] |
Keywords or phrases that block the intent. |
These are documented for completeness; prefer the public API above.
nebulento/container.py:251
Find registered entity values present in sentence using quebra_frases.chunk for token-aware substring detection. Returns a dict mapping entity name → list of matched sample values found in the sentence.
nebulento/container.py:269
Core scoring loop. Yields one result dict per registered intent (excluding suppressed ones). Calls match_one for the best template score, applies entity confidence boost (score = 0.25 + score * 0.75 when an entity slot is filled), and constructs the full result dict.
Defined in nebulento/domain_engine.py:10.
Two-level intent engine: domain classification followed by intent matching. Intents are grouped into named domains. At query time the engine first selects the most likely domain, then runs the domain-specific IntentContainer.
See Domain Matching for a full guide.
DomainIntentContainer(
fuzzy_strategy: MatchStrategy = MatchStrategy.DAMERAU_LEVENSHTEIN_SIMILARITY,
ignore_case: bool = True,
)Both parameters are forwarded to every IntentContainer created internally, including domain_engine.
| Attribute | Type | Description |
|---|---|---|
domain_engine |
IntentContainer |
Top-level classifier mapping queries to domain names. |
domains |
Dict[str, IntentContainer] |
Per-domain containers keyed by domain name. |
training_data |
Dict[str, List[str]] |
Raw training samples per domain (accumulated at registration). |
nebulento/domain_engine.py:55
Remove a domain and all its intents, entities, and training data.
d.remove_domain("media")nebulento/domain_engine.py:68
Register an intent inside a domain. Creates the domain's IntentContainer on first use. Also accumulates intent_samples into training_data[domain_name].
d.register_domain_intent("media", "play", ["play {song}", "put on {song}"])
d.register_domain_intent("media", "pause", ["pause", "stop the music"])| Parameter | Type | Description |
|---|---|---|
domain_name |
str |
Target domain. Created if it does not exist. |
intent_name |
str |
Unique intent name within the domain. |
intent_samples |
List[str] |
Training templates. |
nebulento/domain_engine.py:87
Remove a specific intent from a domain. Silently does nothing if domain or intent does not exist.
nebulento/domain_engine.py:99
Register an entity inside a domain. Creates the domain's container on first use.
d.register_domain_entity("media", "song", ["jazz", "rock", "blues"])nebulento/domain_engine.py:116
Remove a specific entity from a domain.
nebulento/domain_engine.py:128
Classify query into the best-matching domain using domain_engine.calc_intent. The domain_engine must be trained with representative utterances per domain via domain_engine.add_intent.
match = d.calc_domain("play some jazz")
print(match["name"]) # 'media'nebulento/domain_engine.py:143
Return the best-matching intent for query.
If domain is None, the domain is inferred by calling calc_domain. If the resolved domain has no registered intents, a no-match result is returned.
# Auto-infer domain:
result = d.calc_intent("play some jazz")
# Force a specific domain:
result = d.calc_intent("play some jazz", domain="media")| Parameter | Type | Description |
|---|---|---|
query |
str |
Raw utterance to evaluate. |
domain |
str | None |
Domain to restrict matching to. None triggers automatic domain classification. |
Returns a MatchResult dict (same structure as IntentContainer.calc_intent). name is None when no domain or intent matched.