Skip to content

Release 1.4.0a1 #685

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Changelog

## [1.3.1a1](https://github.com/OpenVoiceOS/ovos-core/tree/1.3.1a1) (2025-05-15)
## [1.4.0a1](https://github.com/OpenVoiceOS/ovos-core/tree/1.4.0a1) (2025-05-22)

[Full Changelog](https://github.com/OpenVoiceOS/ovos-core/compare/1.3.0...1.3.1a1)
[Full Changelog](https://github.com/OpenVoiceOS/ovos-core/compare/1.3.1...1.4.0a1)

**Merged pull requests:**

- fix: update requirements skill package names [\#683](https://github.com/OpenVoiceOS/ovos-core/pull/683) ([JarbasAl](https://github.com/JarbasAl))
- feat: m2v pipeline [\#681](https://github.com/OpenVoiceOS/ovos-core/pull/681) ([JarbasAl](https://github.com/JarbasAl))



Expand Down
68 changes: 48 additions & 20 deletions ovos_core/intent_services/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import json
import warnings
import time
from collections import defaultdict
from typing import Tuple, Callable, Union, List

Expand All @@ -40,10 +41,16 @@
from ovos_core.transformers import MetadataTransformersService, UtteranceTransformersService
from ovos_persona import PersonaService

# TODO - to be dropped once pluginified
# just a placeholder during alphas until https://github.com/OpenVoiceOS/ovos-core/pull/570
try:
from ovos_ollama_intent_pipeline import LLMIntentPipeline
except ImportError:
LLMIntentPipeline = None
try:
from ovos_m2v_pipeline import Model2VecIntentPipeline
except ImportError:
Model2VecIntentPipeline = None


class IntentService:
Expand All @@ -55,13 +62,13 @@ class IntentService:

def __init__(self, bus, config=None):
"""
Initializes the IntentService with intent parsing pipelines, transformer services, and messagebus event handlers.
Initializes the IntentService with all intent parsing pipelines, transformer services, and messagebus event handlers.

Args:
bus: The messagebus connection for event handling.
bus: The messagebus connection used for event-driven communication.
config: Optional configuration dictionary for intent services.

Sets up skill name mapping, loads all supported intent matching pipelines, initializes utterance and metadata transformer services, connects the session manager, and registers all relevant messagebus event handlers for utterance processing, context management, intent queries, and skill tracking.
Sets up skill name mapping, loads all supported intent matching pipelines (including Adapt, Padatious, Padacioso, Fallback, Converse, CommonQA, Stop, OCP, Persona, and optionally LLM and Model2Vec pipelines), initializes utterance and metadata transformer services, connects the session manager, and registers all relevant messagebus event handlers for utterance processing, context management, intent queries, and skill deactivation tracking.
"""
self.bus = bus
self.config = config or Configuration().get("intents", {})
Expand All @@ -78,6 +85,7 @@ def __init__(self, bus, config=None):
self._stop = None
self._ocp = None
self._ollama = None
self._m2v = None
self._load_pipeline_plugins()

self.utterance_plugins = UtteranceTransformersService(bus)
Expand Down Expand Up @@ -107,9 +115,9 @@ def __init__(self, bus, config=None):
def _load_pipeline_plugins(self):
# TODO - replace with plugin loader from OPM
"""
Initializes and configures all intent matching pipeline plugins used by the service.
Initializes and configures all intent matching pipeline plugins for the service.

Loads and sets up the Adapt, Padatious, Padacioso, Fallback, Converse, CommonQA, Stop, OCP, Persona, and optionally LLM intent pipelines based on the current configuration. Handles conditional loading and disabling of Padatious and Padacioso pipelines, and logs relevant status or errors.
Sets up Adapt, Padatious, Padacioso, Fallback, Converse, CommonQA, Stop, OCP, Persona, and optionally LLM and Model2Vec intent pipelines based on the current configuration. Handles conditional loading and disabling of Padatious and Padacioso pipelines, and logs relevant status or errors.
"""
self._adapt_service = AdaptPipeline(bus=self.bus, config=self.config.get("adapt", {}))
if "padatious" not in self.config:
Expand Down Expand Up @@ -140,14 +148,24 @@ def _load_pipeline_plugins(self):
self._ocp = OCPPipelineMatcher(self.bus, config=self.config.get("OCP", {}))
self._persona = PersonaService(self.bus, config=self.config.get("persona", {}))
if LLMIntentPipeline is not None:
self._ollama = LLMIntentPipeline(self.bus, config=self.config.get("ovos-ollama-intent-pipeline", {}))
try:
self._ollama = LLMIntentPipeline(self.bus, config=self.config.get("ovos-ollama-intent-pipeline", {}))
except Exception as e:
LOG.error(f"Failed to load LLMIntentPipeline ({e})")
if Model2VecIntentPipeline is not None:
try:
self._m2v = Model2VecIntentPipeline(self.bus, config=self.config.get("ovos-m2v-pipeline", {}))
except Exception as e:
LOG.error(f"Failed to load Model2VecIntentPipeline ({e})")

LOG.debug(f"Default pipeline: {SessionManager.get().pipeline}")

def update_skill_name_dict(self, message):
"""
Updates the mapping of skill IDs to skill names based on a messagebus event.
Updates the internal mapping of skill IDs to skill names from a message event.

Args:
message: A message containing 'id' and 'name' fields for the skill.
message: A message object containing 'id' and 'name' fields for the skill.
"""
self.skill_names[message.data['id']] = message.data['name']

Expand Down Expand Up @@ -205,19 +223,21 @@ def disambiguate_lang(message):

def get_pipeline(self, skips=None, session=None) -> Tuple[str, Callable]:
"""
Returns an ordered list of intent matcher functions for the current session pipeline.
Constructs and returns the ordered list of intent matcher functions for the current session.

The pipeline is determined by the session's configuration and may be filtered by
the optional `skips` list. Each matcher is paired with its pipeline key, and the
resulting list reflects the order in which utterances will be processed for intent
matching. If a requested pipeline component is unavailable, it is skipped with a warning.
The pipeline sequence is determined by the session's configuration and may be filtered by
an optional list of pipeline keys to skip. Each entry in the returned list is a tuple of
the pipeline key and its corresponding matcher function, in the order they will be applied
for intent matching. If a requested pipeline component is unavailable, it is skipped and a
warning is logged.

Args:
skips: Optional list of pipeline keys to exclude from the matcher sequence.
session: Optional session object; if not provided, the current session is used.

Returns:
A list of (pipeline_key, matcher_function) tuples in the order they will be applied.
A list of (pipeline_key, matcher_function) tuples representing the active intent
matching pipeline for the session.
"""
session = session or SessionManager.get()

Expand Down Expand Up @@ -253,6 +273,10 @@ def get_pipeline(self, skips=None, session=None) -> Tuple[str, Callable]:
}
if self._ollama is not None:
matchers["ovos-ollama-intent-pipeline"] = self._ollama.match_low
if self._m2v is not None:
matchers["ovos-m2v-pipeline-high"] = self._m2v.match_high
matchers["ovos-m2v-pipeline-medium"] = self._m2v.match_medium
matchers["ovos-m2v-pipeline-low"] = self._m2v.match_low
if self._padacioso_service is not None:
matchers.update({
"padacioso_high": self._padacioso_service.match_high,
Expand Down Expand Up @@ -616,29 +640,33 @@ def handle_get_intent(self, message):
utterance = message.data["utterance"]
lang = get_message_lang(message)
sess = SessionManager.get(message)

match = None
# Loop through the matching functions until a match is found.
for pipeline, match_func in self.get_pipeline(skips=["converse",
"common_qa",
"fallback_high",
"fallback_medium",
"fallback_low"],
session=sess):
s = time.monotonic()
match = match_func([utterance], lang, message)
LOG.debug(f"matching '{pipeline}' took: {time.monotonic() - s} seconds")
if match:
if match.match_type:
intent_data = match.match_data
intent_data = dict(match.match_data)
intent_data["intent_name"] = match.match_type
intent_data["intent_service"] = pipeline
intent_data["skill_id"] = match.skill_id
intent_data["handler"] = match_func.__name__
self.bus.emit(message.reply("intent.service.intent.reply",
{"intent": intent_data}))
LOG.debug(f"final intent match: {intent_data}")
m = message.reply("intent.service.intent.reply",
{"intent": intent_data, "utterance": utterance})
self.bus.emit(m)
return

LOG.error(f"bad pipeline match! {match}")
# signal intent failure
self.bus.emit(message.reply("intent.service.intent.reply",
{"intent": None}))
{"intent": None, "utterance": utterance}))

def handle_get_skills(self, message):
"""Send registered skills to caller.
Expand Down
6 changes: 3 additions & 3 deletions ovos_core/version.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# START_VERSION_BLOCK
VERSION_MAJOR = 1
VERSION_MINOR = 3
VERSION_BUILD = 1
VERSION_ALPHA = 0
VERSION_MINOR = 4
VERSION_BUILD = 0
VERSION_ALPHA = 1
# END_VERSION_BLOCK

# for compat with old imports
Expand Down
2 changes: 2 additions & 0 deletions requirements/plugins.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ ovos-translate-server-plugin>=0.0.2, <1.0.0
ovos-utterance-normalizer>=0.2.1, <1.0.0
ovos-number-parser>=0.0.1,<1.0.0
ovos-date-parser>=0.0.3,<1.0.0
ovos-m2v-pipeline>=0.0.5,<1.0.0
ovos-ollama-intent-pipeline-plugin>=0.0.1,<1.0.0
2 changes: 1 addition & 1 deletion requirements/skills-essential.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
ovos-skill-fallback-unknown>=0.1.5,<1.0.0
ovos-skill-alerts>=0.1.10,<1.0.0
ovos-skill-personal>=0.1.7,<1.0.0
ovos-skill-date-time>=0.4.2,<1.0.0
ovos-skill-date-time>=0.4.2,<2.0.0
ovos-skill-hello-world>=0.1.10,<1.0.0
ovos-skill-spelling>=0.2.5,<1.0.0
ovos-skill-diagnostics>=0.0.2,<1.0.0
6 changes: 3 additions & 3 deletions requirements/skills-internet.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# skills that require internet connectivity, should not be installed in offline devices
ovos-skill-weather>=0.1.11,<1.0.0
ovos-skill-ddg>=0.1.9,<1.0.0
ovos-skill-wolfie>=0.2.9,<1.0.0
ovos-skill-weather>=0.1.11,<2.0.0
skill-ddg>=0.1.9,<1.0.0
skill-wolfie>=0.2.9,<1.0.0
ovos-skill-wikipedia>=0.5.3,<1.0.0
ovos-skill-wikihow>=0.2.5,<1.0.0
ovos-skill-speedtest>=0.3.2,<1.0.0
Expand Down