Skip to content
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

fix:move code to dependencies #571

Merged
merged 31 commits into from
Nov 2, 2024
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
b994db3
fox:update requirements
JarbasAl Oct 18, 2024
f06f549
remove methods marked for deprecation
JarbasAl Oct 31, 2024
dc5143c
fixes
JarbasAl Oct 31, 2024
3deb78d
fix re-activation of skills that just deactivated themselves during t…
JarbasAl Oct 31, 2024
dffc516
account for session_id
JarbasAl Oct 31, 2024
7b05cea
remove deleted messages from tests
JarbasAl Oct 31, 2024
3ff749c
remove deleted messages from tests
JarbasAl Oct 31, 2024
ab045c5
update tests
JarbasAl Oct 31, 2024
6271636
fix converse
JarbasAl Oct 31, 2024
f941f4c
update tests
JarbasAl Oct 31, 2024
74e18d2
@coderabbitai suggestion
JarbasAl Oct 31, 2024
6e60aaa
revert change, we still need to update timestamps on active skills
JarbasAl Oct 31, 2024
fe3cbd7
fix get_response
JarbasAl Oct 31, 2024
e8b7764
fix:workshop2_compat
JarbasAl Oct 31, 2024
1099588
fix:workshop2_compat
JarbasAl Nov 1, 2024
b00ea99
fix:workshop2_compat
JarbasAl Nov 1, 2024
2f09cd9
fix:workshop2_compat
JarbasAl Nov 1, 2024
be84533
fix:workshop2_compat
JarbasAl Nov 1, 2024
9bdceaf
fix:workshop2_compat
JarbasAl Nov 1, 2024
3af9b7d
fix:workshop2_compat
JarbasAl Nov 1, 2024
4d86011
fix:workshop2_compat
JarbasAl Nov 1, 2024
58af9d6
fix:workshop2_compat
JarbasAl Nov 1, 2024
ec37d78
fix:workshop2_compat
JarbasAl Nov 1, 2024
d3b0c85
fix:workshop2_compat
JarbasAl Nov 1, 2024
2971403
deprecation logs
JarbasAl Nov 1, 2024
0bcea32
deprecation logs
JarbasAl Nov 2, 2024
d8359f2
tests moved to adapt repo
JarbasAl Nov 2, 2024
cc84d2f
fix deprecation warning version
JarbasAl Nov 2, 2024
e5a667a
fix adapt init
JarbasAl Nov 2, 2024
5a888ec
keep intent api unittest
JarbasAl Nov 2, 2024
d16a335
dont access deprecated stuff in tests
JarbasAl Nov 2, 2024
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
7 changes: 2 additions & 5 deletions mycroft/skills/common_play_skill.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,17 +158,14 @@ def __handle_play_start(self, message):
data = message.data.get("callback_data")

# Stop any currently playing audio
if self.audioservice and self.audioservice.is_playing:
self.audioservice.stop()
self.stop()

message.context["skill_id"] = self.skill_id
self.bus.emit(message.forward("mycroft.stop"))

# Save for CPS_play() later, e.g. if phrase includes modifiers like
# "... on the chromecast"
self.play_service_string = phrase

self.activate()

# Invoke derived class to provide playback data
self.CPS_start(phrase, data)

Expand Down
18 changes: 9 additions & 9 deletions mycroft/skills/intent_services/__init__.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
from ovos_core.intent_services import AdaptService,\
ConverseService, \
CommonQAService, \
FallbackService, \
PadaciosoService
from ovos_core.intent_services import IntentMatch
from mycroft.skills.intent_services.adapt_service import AdaptIntent, IntentBuilder, Intent
from ovos_core.intent_services.fallback_service import FallbackService
from ovos_core.intent_services.converse_service import ConverseService
from ovos_adapt.opm import AdaptPipeline as AdaptService
from padacioso.opm import PadaciosoPipeline as PadaciosoService
from ovos_commonqa.opm import CommonQAService
from ovos_plugin_manager.templates.pipeline import IntentMatch
from ovos_workshop.intents import Intent as AdaptIntent, IntentBuilder, Intent

try:
from ovos_core.intent_services.padatious_service import PadatiousService, PadatiousMatcher
from ovos_padatious.opm import PadatiousPipeline as PadatiousService, PadatiousMatcher
except ImportError:
from ovos_utils.log import LOG
LOG.warning("padatious not installed")
from ovos_core.intent_services.padacioso_service import PadaciosoService as PadatiousService
from padacioso.opm import PadaciosoPipeline as PadatiousService
5 changes: 3 additions & 2 deletions mycroft/skills/intent_services/adapt_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@
# limitations under the License.
#
"""An intent parsing service using the Adapt parser."""
from ovos_adapt.context import ContextManagerFrame
from ovos_adapt.engine import IntentDeterminationEngine
from ovos_workshop.intents import IntentBuilder, Intent
from ovos_adapt.opm import ContextManager, AdaptPipeline as AdaptService
from ovos_adapt.opm import AdaptPipeline as AdaptService
from ovos_bus_client.session import IntentContextManagerFrame as ContextManagerFrame, \
IntentContextManager as ContextManager


class AdaptIntent(IntentBuilder):
Expand Down
2 changes: 1 addition & 1 deletion mycroft/skills/intent_services/commonqa_service.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
from ovos_core.intent_services.commonqa_service import CommonQAService
from ovos_commonqa.opm import CommonQAService
EXTENSION_TIME = 10
2 changes: 1 addition & 1 deletion mycroft/skills/intent_services/padatious_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@
# limitations under the License.
#
"""Intent service wrapping padatious."""
from ovos_core.intent_services.padatious_service import PadatiousMatcher, PadatiousService, PadatiousIntent
from ovos_padatious.opm import PadatiousMatcher, PadatiousPipeline as PadatiousService, PadatiousIntent

165 changes: 75 additions & 90 deletions ovos_core/intent_services/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,26 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
from typing import Tuple, Callable
from collections import defaultdict
from typing import Tuple, Callable, Union

from ocp_pipeline.opm import OCPPipelineMatcher
from ovos_adapt.opm import AdaptPipeline as AdaptService
from ovos_bus_client.message import Message
from ovos_bus_client.session import SessionManager
from ovos_bus_client.util import get_message_lang
from ovos_workshop.intents import open_intent_envelope

from ocp_pipeline.opm import OCPPipelineMatcher
from ovos_adapt.opm import AdaptPipeline as AdaptService
from ovos_commonqa.opm import CommonQAService
from ovos_config.config import Configuration
from ovos_config.locale import setup_locale, get_valid_languages, get_full_lang_code
from ovos_config.locale import setup_locale, get_valid_languages
from ovos_core.intent_services.converse_service import ConverseService
from ovos_core.intent_services.fallback_service import FallbackService
from ovos_core.intent_services.stop_service import StopService
from ovos_core.transformers import MetadataTransformersService, UtteranceTransformersService
from ovos_plugin_manager.templates.pipeline import IntentMatch
from ovos_plugin_manager.templates.pipeline import PipelineMatch, IntentHandlerMatch
from ovos_utils.lang import standardize_lang_tag
from ovos_utils.log import LOG, deprecated, log_deprecation
from ovos_utils.log import LOG, log_deprecation
from ovos_utils.metrics import Stopwatch
from ovos_workshop.intents import open_intent_envelope
from padacioso.opm import PadaciosoPipeline as PadaciosoService


Expand Down Expand Up @@ -90,6 +90,10 @@ def __init__(self, bus, config=None):
self.bus.on('intent.service.padatious.manifest.get', self.handle_padatious_manifest)
self.bus.on('intent.service.padatious.entities.manifest.get', self.handle_entity_manifest)

# internal, track skills that call self.deactivate to avoid reactivating them again
self._deactivations = defaultdict(list)
self.bus.on('intent.service.skills.deactivate', self._handle_deactivate)

JarbasAl marked this conversation as resolved.
Show resolved Hide resolved
@property
def adapt_service(self):
log_deprecation("direct access to self.adapt_service is deprecated, "
Expand Down Expand Up @@ -229,36 +233,6 @@ def get_skill_name(self, skill_id):
"""
return self.skill_names.get(skill_id, skill_id)

# converse handling
@property
def active_skills(self):
log_deprecation("self.active_skills is deprecated! use Session instead", "0.0.9")
session = SessionManager.get()
return session.active_skills

@active_skills.setter
def active_skills(self, val):
log_deprecation("self.active_skills is deprecated! use Session instead", "0.0.9")
session = SessionManager.get()
session.active_skills = []
for skill_id, ts in val:
session.activate_skill(skill_id)

@deprecated("handle_activate_skill_request moved to ConverseService, overriding this method has no effect, "
"it has been disconnected from the bus event", "0.0.8")
def handle_activate_skill_request(self, message):
self.converse.handle_activate_skill_request(message)

@deprecated("handle_deactivate_skill_request moved to ConverseService, overriding this method has no effect, "
"it has been disconnected from the bus event", "0.0.8")
def handle_deactivate_skill_request(self, message):
self.converse.handle_deactivate_skill_request(message)

@deprecated("reset_converse moved to ConverseService, overriding this method has no effect, "
"it has been disconnected from the bus event", "0.0.8")
def reset_converse(self, message):
self.converse.reset_converse(message)

def _handle_transformers(self, message):
"""
Pipe utterance through transformer plugins to get more metadata.
Expand All @@ -284,13 +258,14 @@ def disambiguate_lang(message):
"""
default_lang = get_message_lang(message)
valid_langs = get_valid_languages()
valid_langs = [standardize_lang_tag(l) for l in valid_langs]
JarbasAl marked this conversation as resolved.
Show resolved Hide resolved
lang_keys = ["stt_lang",
"request_lang",
"detected_lang"]
for k in lang_keys:
if k in message.context:
v = get_full_lang_code(message.context[k])
if v in valid_langs:
v = standardize_lang_tag(message.context[k])
if v in valid_langs: # TODO - use lang distance instead to choose best dialect
if v != default_lang:
LOG.info(f"replaced {default_lang} with {k}: {v}")
return v
Expand All @@ -314,8 +289,7 @@ def get_pipeline(self, skips=None, session=None) -> Tuple[str, Callable]:
"intent matching will be extremely slow in comparison")
padatious_matcher = self._padacioso_service
else:
from ovos_core.intent_services.padatious_service import PadatiousMatcher
padatious_matcher = PadatiousMatcher(self._padatious_service)
padatious_matcher = self._padatious_service

matchers = {
"converse": self._converse.converse_with_skills,
Expand Down Expand Up @@ -351,7 +325,8 @@ def get_pipeline(self, skips=None, session=None) -> Tuple[str, Callable]:
LOG.debug(f"Session pipeline: {pipeline}")
return [(k, matchers[k]) for k in pipeline]

def _validate_session(self, message, lang):
@staticmethod
def _validate_session(message, lang):
# get session
lang = standardize_lang_tag(lang)
sess = SessionManager.get(message)
Expand All @@ -373,42 +348,55 @@ def _validate_session(self, message, lang):
sess.touch()
return sess

def _emit_match_message(self, match: IntentMatch, message: Message):
def _handle_deactivate(self, message):
"""internal helper, track if a skill asked to be removed from active list during intent match
in this case we want to avoid reactivating it again
This only matters in PipelineMatchers, such as fallback and converse
in those cases the activation is only done AFTER the match, not before unlike intents
"""
sess = SessionManager.get(message)
skill_id = message.data.get("skill_id")
self._deactivations[sess.session_id].append(skill_id)

def _emit_match_message(self, match: Union[IntentHandlerMatch, PipelineMatch], message: Message):
"""Update the message data with the matched utterance information and
activate the corresponding skill if available.

Args:
match (IntentMatch): The matched utterance object.
match (IntentHandlerMatch): The matched utterance object.
JarbasAl marked this conversation as resolved.
Show resolved Hide resolved
message (Message): The messagebus data.
"""
message.data["utterance"] = match.utterance

if match.skill_id:
# ensure skill_id is present in message.context
message.context["skill_id"] = match.skill_id
reply = None
sess = SessionManager.get(message)

if match.intent_type is True:
# utterance fully handled
reply = message.reply("ovos.utterance.handled",
{"skill_id": match.skill_id})
self.bus.emit(reply)
# utterance fully handled by pipeline matcher
if isinstance(match, PipelineMatch):
if match.handled:
reply = message.reply("ovos.utterance.handled", {"skill_id": match.skill_id})
JarbasAl marked this conversation as resolved.
Show resolved Hide resolved
# Launch skill if not handled by the match function
elif match.intent_type:
elif isinstance(match, IntentHandlerMatch) and match.match_type:
# keep all original message.data and update with intent match
data = dict(message.data)
data.update(match.intent_data)

# NOTE: message.reply to ensure correct message destination
reply = message.reply(match.intent_type, data)

# let's activate the skill BEFORE the intent is triggered
# to ensure an accurate Session
# NOTE: this was previously done async by the skill,
# but then the skill was missing from Session.active_skills
sess = self.converse.activate_skill(message=reply,
skill_id=match.skill_id)
if sess:
reply.context["session"] = sess.serialize()
data.update(match.match_data)
reply = message.reply(match.match_type, data)

if reply is not None:
reply.data["utterance"] = match.utterance

# update active skill list
if match.skill_id:
# ensure skill_id is present in message.context
reply.context["skill_id"] = match.skill_id

# NOTE: do not re-activate if the skill called self.deactivate
# we could also skip activation if skill is already active,
# but we still want to update the timestamp
was_deactivated = match.skill_id in self._deactivations[sess.session_id]
if not was_deactivated:
sess.activate_skill(match.skill_id)
reply.context["session"] = sess.serialize()
# emit event for skills callback -> self.handle_activate
self.bus.emit(reply.forward(f"{match.skill_id}.activate"))

self.bus.emit(reply)

Expand Down Expand Up @@ -474,6 +462,8 @@ def handle_utterance(self, message: Message):
# match
match = None
with stopwatch:
self._deactivations[sess.session_id] = []

# Loop through the matching functions until a match is found.
for pipeline, match_func in self.get_pipeline(session=sess):
match = match_func(utterances, lang, message)
Expand All @@ -483,9 +473,9 @@ def handle_utterance(self, message: Message):
LOG.debug(
f"ignoring match, skill_id '{match.skill_id}' blacklisted by Session '{sess.session_id}'")
continue
if match.intent_type and match.intent_type in sess.blacklisted_intents:
if isinstance(match, IntentHandlerMatch) and match.match_type in sess.blacklisted_intents:
LOG.debug(
f"ignoring match, intent '{match.intent_type}' blacklisted by Session '{sess.session_id}'")
f"ignoring match, intent '{match.match_type}' blacklisted by Session '{sess.session_id}'")
JarbasAl marked this conversation as resolved.
Show resolved Hide resolved
continue
try:
self._emit_match_message(match, message)
Expand All @@ -503,6 +493,8 @@ def handle_utterance(self, message: Message):
# sync any changes made to the default session, eg by ConverseService
if sess.session_id == "default":
SessionManager.sync(message)
elif sess.session_id in self._deactivations:
self._deactivations.pop(sess.session_id)
return match, message.context, stopwatch

def send_complete_intent_failure(self, message):
Expand All @@ -529,7 +521,7 @@ def handle_register_vocab(self, message):
alias_of = message.data.get('alias_of')
lang = get_message_lang(message)
self._adapt_service.register_vocabulary(entity_value, entity_type,
alias_of, regex_str, lang)
alias_of, regex_str, lang)
self.registered_vocab.append(message.data)

def handle_register_intent(self, message):
Expand Down Expand Up @@ -559,7 +551,8 @@ def handle_detach_skill(self, message):
skill_id = message.data.get('skill_id')
self._adapt_service.detach_skill(skill_id)

def handle_add_context(self, message):
@staticmethod
def handle_add_context(message: Message):
"""Add context

Args:
Expand All @@ -581,7 +574,8 @@ def handle_add_context(self, message):
sess = SessionManager.get(message)
sess.context.inject_context(entity)

def handle_remove_context(self, message):
@staticmethod
def handle_remove_context(message: Message):
"""Remove specific context

Args:
Expand All @@ -592,7 +586,8 @@ def handle_remove_context(self, message):
sess = SessionManager.get(message)
sess.context.remove_context(context)

def handle_clear_context(self, message):
@staticmethod
def handle_clear_context(message: Message):
"""Clears all keywords from context """
sess = SessionManager.get(message)
sess.context.clear_context()
Expand All @@ -615,10 +610,10 @@ def handle_get_intent(self, message):
session=sess):
match = match_func([utterance], lang, message)
if match:
if match.intent_type:
intent_data = match.intent_data
intent_data["intent_name"] = match.intent_type
intent_data["intent_service"] = match.intent_service
if match.match_type:
intent_data = 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",
Expand All @@ -638,16 +633,6 @@ def handle_get_skills(self, message):
self.bus.emit(message.reply("intent.service.skills.reply",
{"skills": self.skill_names}))

@deprecated("handle_get_active_skills moved to ConverseService, overriding this method has no effect, "
"it has been disconnected from the bus event", "0.0.8")
def handle_get_active_skills(self, message):
"""Send active skills to caller.

Argument:
message: query message to reply to.
"""
self.converse.handle_get_active_skills(message)

def handle_get_adapt(self, message: Message):
"""handler getting the adapt response for an utterance.

Expand All @@ -657,7 +642,7 @@ def handle_get_adapt(self, message: Message):
utterance = message.data["utterance"]
lang = get_message_lang(message)
intent = self._adapt_service.match_intent((utterance,), lang, message.serialize())
intent_data = intent.intent_data if intent else None
intent_data = intent.match_data if intent else None
self.bus.emit(message.reply("intent.service.adapt.reply",
{"intent": intent_data}))

Expand Down
2 changes: 2 additions & 0 deletions ovos_core/intent_services/adapt_service.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
# backwards compat import
from ovos_adapt.opm import AdaptPipeline as AdaptService
from ovos_utils.log import log_deprecation
log_deprecation("adapt service moved to 'ovos-adapt-pipeline-plugin'. this import is deprecated", "1.0.0")
2 changes: 2 additions & 0 deletions ovos_core/intent_services/commonqa_service.py
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
from ovos_commonqa.opm import Query, CommonQAService
from ovos_utils.log import log_deprecation
log_deprecation("adapt service moved to 'ovos-common-query-pipeline-plugin'. this import is deprecated", "1.0.0")
Loading
Loading