From 7d0a89fd23d3b686af5ebe6f81e9e55eb86c4b37 Mon Sep 17 00:00:00 2001 From: JarbasAI <33701864+JarbasAl@users.noreply.github.com> Date: Wed, 18 Dec 2024 15:53:11 +0000 Subject: [PATCH 1/9] feat: save/load game intent (#44) * feat: save/load game intent improve intent matching when games are the active media * update locale * update locale * update locale * Apply suggestions from code review Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- ocp_pipeline/locale/en-us/load_game.intent | 3 ++ ocp_pipeline/locale/en-us/next.intent | 3 +- ocp_pipeline/locale/en-us/open.intent | 2 +- ocp_pipeline/locale/en-us/pause.intent | 2 +- ocp_pipeline/locale/en-us/prev.intent | 3 +- ocp_pipeline/locale/en-us/read.intent | 2 +- ocp_pipeline/locale/en-us/resume.intent | 2 +- ocp_pipeline/locale/en-us/save_game.intent | 2 + ocp_pipeline/opm.py | 48 +++++++++++++++++++++- requirements.txt | 5 +-- translations/en-us/intents.json | 21 +++++++--- 11 files changed, 78 insertions(+), 15 deletions(-) create mode 100644 ocp_pipeline/locale/en-us/load_game.intent create mode 100644 ocp_pipeline/locale/en-us/save_game.intent diff --git a/ocp_pipeline/locale/en-us/load_game.intent b/ocp_pipeline/locale/en-us/load_game.intent new file mode 100644 index 0000000..2100c87 --- /dev/null +++ b/ocp_pipeline/locale/en-us/load_game.intent @@ -0,0 +1,3 @@ +load +load [the] game +load [the] (last|previous) [saved] game \ No newline at end of file diff --git a/ocp_pipeline/locale/en-us/next.intent b/ocp_pipeline/locale/en-us/next.intent index 0269afe..6c4ed2b 100644 --- a/ocp_pipeline/locale/en-us/next.intent +++ b/ocp_pipeline/locale/en-us/next.intent @@ -3,4 +3,5 @@ (play|go to) next (music|song|track|video|media) next next (song|track|music|movie|video|tune) -play next \ No newline at end of file +play next +(play|go to) [the] next (song|track|music|movie|video|tune) \ No newline at end of file diff --git a/ocp_pipeline/locale/en-us/open.intent b/ocp_pipeline/locale/en-us/open.intent index f03a7ee..e9e7dc8 100644 --- a/ocp_pipeline/locale/en-us/open.intent +++ b/ocp_pipeline/locale/en-us/open.intent @@ -1,4 +1,4 @@ open (OCP|O C P|common|ovos|open voice os) (player|media player) open (OCP|O C P|ovos common play|common play|ovos media player|open voice os player) (home screen|home page|homescreen|homepage|menu) open (OCP|O C P|ovos common play|open voice os common play|common play) -open (media|music|gui|video) (player|catalog|skills|menu|playback) \ No newline at end of file +open [the] (media|music|gui|video) (player|catalog|skills|menu|playback) \ No newline at end of file diff --git a/ocp_pipeline/locale/en-us/pause.intent b/ocp_pipeline/locale/en-us/pause.intent index 4161dcf..42e8ca7 100644 --- a/ocp_pipeline/locale/en-us/pause.intent +++ b/ocp_pipeline/locale/en-us/pause.intent @@ -1,2 +1,2 @@ pause -pause (music|song|track|video|media|playback) \ No newline at end of file +pause [the] (music|song|track|video|media|playback|game) \ No newline at end of file diff --git a/ocp_pipeline/locale/en-us/prev.intent b/ocp_pipeline/locale/en-us/prev.intent index e7c2b28..ee9a12e 100644 --- a/ocp_pipeline/locale/en-us/prev.intent +++ b/ocp_pipeline/locale/en-us/prev.intent @@ -2,4 +2,5 @@ (play previous|previous) (music|song|track|video|media) (play previous|previous|go back) previous -previous (song|track|music|movie|video|tune) \ No newline at end of file +previous (song|track|music|movie|video|tune) +(play|go to) [the] previous (song|track|music|movie|video|tune) \ No newline at end of file diff --git a/ocp_pipeline/locale/en-us/read.intent b/ocp_pipeline/locale/en-us/read.intent index 91c5ae0..3a5fe0c 100644 --- a/ocp_pipeline/locale/en-us/read.intent +++ b/ocp_pipeline/locale/en-us/read.intent @@ -1,3 +1,3 @@ -read (book|audiobook|audio book) {query} +read [the] (book|audiobook|audio book) {query} read {query} read {query} (book|audiobook|audio book) \ No newline at end of file diff --git a/ocp_pipeline/locale/en-us/resume.intent b/ocp_pipeline/locale/en-us/resume.intent index 40f5c97..4d46186 100644 --- a/ocp_pipeline/locale/en-us/resume.intent +++ b/ocp_pipeline/locale/en-us/resume.intent @@ -1,3 +1,3 @@ (unpause|resume) -(unpause|resume|continue|restart) (music|song|track|video|media|playback) +(unpause|resume|continue|restart) [the] (music|song|track|video|media|playback|game) play \ No newline at end of file diff --git a/ocp_pipeline/locale/en-us/save_game.intent b/ocp_pipeline/locale/en-us/save_game.intent new file mode 100644 index 0000000..c2a59a4 --- /dev/null +++ b/ocp_pipeline/locale/en-us/save_game.intent @@ -0,0 +1,2 @@ +save +save [the] game \ No newline at end of file diff --git a/ocp_pipeline/opm.py b/ocp_pipeline/opm.py index b723c6a..ebe89e0 100644 --- a/ocp_pipeline/opm.py +++ b/ocp_pipeline/opm.py @@ -37,6 +37,7 @@ class OCPPlayerProxy: player_state: PlayerState = PlayerState.STOPPED media_state: MediaState = MediaState.UNKNOWN media_type: MediaType = MediaType.GENERIC + skill_id: Optional[str] = None # for easier typing @@ -47,7 +48,7 @@ class OCPPlayerProxy: class OCPPipelineMatcher(ConfidenceMatcherPipeline, OVOSAbstractApplication): intents = ["play.intent", "open.intent", "media_stop.intent", "next.intent", "prev.intent", "pause.intent", "play_favorites.intent", - "resume.intent", "like_song.intent"] + "resume.intent", "like_song.intent", "save_game.intent", "load_game.intent"] intent_matchers = {} intent_cache = f"{xdg_data_home()}/{get_xdg_base()}/intent_cache" @@ -187,6 +188,8 @@ def register_ocp_intents(self): self.add_event("ocp:media_stop", self.handle_stop_intent, is_intent=True) self.add_event("ocp:search_error", self.handle_search_error_intent, is_intent=True) self.add_event("ocp:like_song", self.handle_like_intent, is_intent=True) + self.add_event("ocp:save_game", self.handle_save_intent, is_intent=True) + self.add_event("ocp:load_game", self.handle_load_intent, is_intent=True) def update_player_proxy(self, player: OCPPlayerProxy): """remember OCP session state""" @@ -289,6 +292,7 @@ def handle_track_state_update(self, message: Message): TrackState.PLAYING_MPRIS]: player = self.get_player(message) player.player_state = PlayerState.PLAYING + player = self._update_player_skill_id(player, message) LOG.info(f"Session: {player.session_id} OCP PlayerState: PlayerState.PLAYING") self.update_player_proxy(player) @@ -310,6 +314,7 @@ def handle_player_state_update(self, message: Message): if mtype is not None: player.media_type = MediaType(pstate) LOG.debug(f"Session: {player.session_id} MediaType: {player.media_type}") + player = self._update_player_skill_id(player, message) self.update_player_proxy(player) # pipeline @@ -347,6 +352,21 @@ def match_high(self, utterances: List[str], lang: str, message: Message = None) player = self.get_player(message) + if player.media_type == MediaType.GAME: + # if the user is currently playing a game + # disable: next/prev/shuffle/... intents + # enable: load/save intents + game_blacklist = ["next", "prev", "open", "like_song", "play_favorites"] + if match["name"] in game_blacklist: + LOG.info(f'Ignoring OCP intent match {match["name"]}, playing MediaType.GAME') + return None + else: + # if no game is being played, disable game specific intents + game_only = ["save_game"] + if match["name"] in game_only: + LOG.info(f'Ignoring OCP intent match {match["name"]}, not playing MediaType.GAME') + return None + if match["name"] == "play": utterance = match["entities"].pop("query") return self._process_play_query(utterance, lang, match) @@ -535,6 +555,14 @@ def _normalize_media_enum(m: Union[int, MediaType]): return e raise ValueError(f"{m} is not a valid media type") + def handle_save_intent(self, message: Message): + skill_id = self.get_player(message).skill_id + self.bus.emit(message.forward(f"ovos.common_play.{skill_id}.save")) + + def handle_load_intent(self, message: Message): + skill_id = self.get_player(message).skill_id + self.bus.emit(message.forward(f"ovos.common_play.{skill_id}.load")) + def handle_play_intent(self, message: Message): if not len(self.skill_aliases): # skill_id registered when skills load @@ -574,6 +602,8 @@ def handle_play_intent(self, message: Message): # ovos-PHAL-plugin-mk1 will display music icon in response to play message player = self.get_player(message) + player.skill_id = best.skill_id + self.update_player_proxy(player) if not player.ocp_available: self.legacy_play(results, query, message=message) else: @@ -603,6 +633,7 @@ def handle_stop_intent(self, message: Message): self.ocp_api.stop(source_message=message) player = self.get_player(message) player.player_state = PlayerState.STOPPED + player.skill_id = None self.update_player_proxy(player) def handle_next_intent(self, message: Message): @@ -633,6 +664,7 @@ def handle_pause_intent(self, message: Message): self.ocp_api.pause(source_message=message) player = self.get_player(message) player.player_state = PlayerState.PAUSED + player = self._update_player_skill_id(player, message) self.update_player_proxy(player) def handle_resume_intent(self, message: Message): @@ -645,6 +677,7 @@ def handle_resume_intent(self, message: Message): self.ocp_api.resume(source_message=message) player = self.get_player(message) player.player_state = PlayerState.PLAYING + player = self._update_player_skill_id(player, message) self.update_player_proxy(player) def handle_search_error_intent(self, message: Message): @@ -833,6 +866,13 @@ def get_player(self, message: Optional[Message] = None, timeout=1) -> OCPPlayerP player = self._player_sync(player, message, timeout) return player + @staticmethod + def _update_player_skill_id(player, message): + skill_id = message.data.get("skill_id") or message.context.get("skill_id") + if skill_id and skill_id != OCP_ID: + player.skill_id = skill_id + return player + @staticmethod def normalize_results(results: RawResultsList) -> NormalizedResultsList: # support Playlist and MediaEntry objects in tracks @@ -1055,6 +1095,7 @@ def legacy_play(self, results: NormalizedResultsList, phrase="", playing = True self.legacy_api.play(real_uri, utterance=phrase, source_message=message) player.player_state = PlayerState.PLAYING + player.skill_id = r.skill_id self.update_player_proxy(player) else: self.legacy_api.queue(real_uri, source_message=message) @@ -1064,6 +1105,7 @@ def _handle_legacy_audio_stop(self, message: Message): if not player.ocp_available: player.player_state = PlayerState.STOPPED player.media_state = MediaState.NO_MEDIA + player.skill_id = None self.update_player_proxy(player) def _handle_legacy_audio_pause(self, message: Message): @@ -1071,6 +1113,7 @@ def _handle_legacy_audio_pause(self, message: Message): if not player.ocp_available and player.player_state == PlayerState.PLAYING: player.player_state = PlayerState.PAUSED player.media_state = MediaState.LOADED_MEDIA + player = self._update_player_skill_id(player, message) self.update_player_proxy(player) def _handle_legacy_audio_resume(self, message: Message): @@ -1078,6 +1121,7 @@ def _handle_legacy_audio_resume(self, message: Message): if not player.ocp_available and player.player_state == PlayerState.PAUSED: player.player_state = PlayerState.PLAYING player.media_state = MediaState.LOADED_MEDIA + player = self._update_player_skill_id(player, message) self.update_player_proxy(player) def _handle_legacy_audio_start(self, message: Message): @@ -1085,6 +1129,7 @@ def _handle_legacy_audio_start(self, message: Message): if not player.ocp_available: player.player_state = PlayerState.PLAYING player.media_state = MediaState.LOADED_MEDIA + player = self._update_player_skill_id(player, message) self.update_player_proxy(player) def _handle_legacy_audio_end(self, message: Message): @@ -1092,6 +1137,7 @@ def _handle_legacy_audio_end(self, message: Message): if not player.ocp_available: player.player_state = PlayerState.STOPPED player.media_state = MediaState.END_OF_MEDIA + player.skill_id = None self.update_player_proxy(player) @classmethod diff --git a/requirements.txt b/requirements.txt index d656040..c324737 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,4 @@ ovos-workshop>=0.1.7,<4.0.0 ovos-classifiers -ovos-utils>=0.3.5,<1.0.0 -ovos-plugin-manager>=0.5.0,<1.0.0 -langcodes \ No newline at end of file +ovos-utils[extras]>=0.3.5,<1.0.0 +ovos-plugin-manager>=0.5.0,<1.0.0 \ No newline at end of file diff --git a/translations/en-us/intents.json b/translations/en-us/intents.json index 753db64..4d2b4c6 100644 --- a/translations/en-us/intents.json +++ b/translations/en-us/intents.json @@ -18,15 +18,16 @@ "(play|go to) next (music|song|track|video|media)", "play next", "next", - "next (song|track|music|movie|video|tune)" + "next (song|track|music|movie|video|tune)", + "(play|go to) [the] next (song|track|music|movie|video|tune)" ], "resume.intent": [ "(unpause|resume)", - "(unpause|resume|continue|restart) (music|song|track|video|media|playback)", +"(unpause|resume|continue|restart) [the] (music|song|track|video|media|playback|game)", "play" ], "read.intent": [ - "read (book|audiobook|audio book) {query}", + "read [the] (book|audiobook|audio book) {query}", "read {query}", "read {query} (book|audiobook|audio book)" ], @@ -34,18 +35,19 @@ "(play previous|go back one) (music|song|track|video|media)", "(play previous|previous) (music|song|track|video|media)", "(play previous|previous|go back)", + "(play|go to) [the] previous (song|track|music|movie|video|tune)", "previous", "previous (song|track|music|movie|video|tune)" ], "pause.intent": [ "pause", - "pause (music|song|track|video|media|playback)" + "pause [the] (music|song|track|video|media|playback|game)" ], "open.intent": [ "open (OCP|O C P|common|ovos|open voice os) (player|media player)", "open (OCP|O C P|ovos common play|common play|ovos media player|open voice os player) (home screen|home page|homescreen|homepage|menu)", "open (OCP|O C P|ovos common play|open voice os common play|common play)", - "open (media|music|gui|video) (player|catalog|skills|menu|playback)" + "open [the] (media|music|gui|video) (player|catalog|skills|menu|playback)" ], "featured.intent": [ "(open|show|display) (featured|) {media} (catalog|collection|playlist)", @@ -59,5 +61,14 @@ "stop", "stop (playback|media|media playback|music|movie|movies|noise)", "stop everything" + ], + "save_game.intent": [ + "save", + "save [the] game" + ], + "load_game.intent": [ + "load", + "load [the] game", + "load [the] (last|previous) [saved] game" ] } \ No newline at end of file From 7e8fadb4ac1a4bbe0b41b9fd154adbb0b2350e7a Mon Sep 17 00:00:00 2001 From: JarbasAl Date: Wed, 18 Dec 2024 15:53:27 +0000 Subject: [PATCH 2/9] Increment Version to 1.1.0a1 --- ocp_pipeline/version.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ocp_pipeline/version.py b/ocp_pipeline/version.py index 6233c92..c296309 100644 --- a/ocp_pipeline/version.py +++ b/ocp_pipeline/version.py @@ -1,6 +1,6 @@ # START_VERSION_BLOCK VERSION_MAJOR = 1 -VERSION_MINOR = 0 -VERSION_BUILD = 11 -VERSION_ALPHA = 0 +VERSION_MINOR = 1 +VERSION_BUILD = 0 +VERSION_ALPHA = 1 # END_VERSION_BLOCK From 818bc6cdc548ca8f96017dc2ed550d24c67ab04c Mon Sep 17 00:00:00 2001 From: JarbasAl Date: Wed, 18 Dec 2024 15:53:50 +0000 Subject: [PATCH 3/9] Update Changelog --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index da2c177..41491b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,12 @@ # Changelog -## [1.0.11a1](https://github.com/OpenVoiceOS/ovos-ocp-pipeline-plugin/tree/1.0.11a1) (2024-12-11) +## [1.1.0a1](https://github.com/OpenVoiceOS/ovos-ocp-pipeline-plugin/tree/1.1.0a1) (2024-12-18) -[Full Changelog](https://github.com/OpenVoiceOS/ovos-ocp-pipeline-plugin/compare/1.0.10...1.0.11a1) +[Full Changelog](https://github.com/OpenVoiceOS/ovos-ocp-pipeline-plugin/compare/1.0.11...1.1.0a1) **Merged pull requests:** -- performance: support padatious [\#42](https://github.com/OpenVoiceOS/ovos-ocp-pipeline-plugin/pull/42) ([JarbasAl](https://github.com/JarbasAl)) +- feat: save/load game intent [\#44](https://github.com/OpenVoiceOS/ovos-ocp-pipeline-plugin/pull/44) ([JarbasAl](https://github.com/JarbasAl)) From 4c313cdfbcbac62dd06f307ef9270b82c25ac615 Mon Sep 17 00:00:00 2001 From: JarbasAI <33701864+JarbasAl@users.noreply.github.com> Date: Thu, 19 Dec 2024 00:22:05 +0000 Subject: [PATCH 4/9] fix:improve_media_clf (#46) ensure correct MediaType if a skill is explicitly requested skip media classification if only 1 MediaType is available restrict valid media classifications to installed skills media types --- ocp_pipeline/opm.py | 71 +++++++++++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 29 deletions(-) diff --git a/ocp_pipeline/opm.py b/ocp_pipeline/opm.py index ebe89e0..d47093e 100644 --- a/ocp_pipeline/opm.py +++ b/ocp_pipeline/opm.py @@ -484,11 +484,15 @@ def _process_play_query(self, utterance: str, lang: str, match: dict = None, if skill_id not in sess.blacklisted_skills and any(s.lower() in utterance for s in samples) ] + valid_labels = [] if valid_skills: LOG.info(f"OCP specific skill names matched: {valid_skills}") + for mtype, skills in self.media2skill.items(): + if any([s in skills for s in valid_skills]): + valid_labels.append(mtype) # classify the query media type - media_type, conf = self.classify_media(utterance, lang) + media_type, conf = self.classify_media(utterance, lang, valid_labels=valid_labels) # extract the query string query = self.remove_voc(utterance, "Play", lang).strip() @@ -692,70 +696,77 @@ def handle_search_error_intent(self, message: Message): self.ocp_api.stop(source_message=message) # NLP - def voc_match_media(self, query: str, lang: str) -> Tuple[MediaType, float]: + def voc_match_media(self, query: str, lang: str, valid_labels: Optional[List[MediaType]] = None) -> Tuple[MediaType, float]: lang = standardize_lang_tag(lang) + valid_labels = valid_labels or [m for m, s in self.media2skill.items() if s] or list(MediaType) # simplistic approach via voc_match, works anywhere # and it's easy to localize, but isn't very accurate - if self.voc_match(query, "MusicKeyword", lang=lang): + if MediaType.MUSIC in valid_labels and self.voc_match(query, "MusicKeyword", lang=lang): # NOTE - before movie to handle "{movie_name} soundtrack" return MediaType.MUSIC, 0.6 - elif self.voc_match(query, "MovieKeyword", lang=lang): - if self.voc_match(query, "ShortKeyword", lang=lang): + elif any([s in valid_labels for s in [MediaType.MOVIE, MediaType.SHORT_FILM, MediaType.SILENT_MOVIE, MediaType.BLACK_WHITE_MOVIE]]) and \ + self.voc_match(query, "MovieKeyword", lang=lang): + if MediaType.SHORT_FILM in valid_labels and self.voc_match(query, "ShortKeyword", lang=lang): return MediaType.SHORT_FILM, 0.7 - elif self.voc_match(query, "SilentKeyword", lang=lang): + elif MediaType.SILENT_MOVIE in valid_labels and self.voc_match(query, "SilentKeyword", lang=lang): return MediaType.SILENT_MOVIE, 0.7 - elif self.voc_match(query, "BWKeyword", lang=lang): + elif MediaType.BLACK_WHITE_MOVIE in valid_labels and self.voc_match(query, "BWKeyword", lang=lang): return MediaType.BLACK_WHITE_MOVIE, 0.7 return MediaType.MOVIE, 0.6 - elif self.voc_match(query, "DocumentaryKeyword", lang=lang): + elif MediaType.DOCUMENTARY in valid_labels and self.voc_match(query, "DocumentaryKeyword", lang=lang): return MediaType.DOCUMENTARY, 0.6 - elif self.voc_match(query, "AudioBookKeyword", lang=lang): + elif MediaType.AUDIOBOOK in valid_labels and self.voc_match(query, "AudioBookKeyword", lang=lang): return MediaType.AUDIOBOOK, 0.6 - elif self.voc_match(query, "NewsKeyword", lang=lang): + elif MediaType.NEWS in valid_labels and self.voc_match(query, "NewsKeyword", lang=lang): return MediaType.NEWS, 0.6 - elif self.voc_match(query, "AnimeKeyword", lang=lang): + elif MediaType.ANIME in valid_labels and self.voc_match(query, "AnimeKeyword", lang=lang): return MediaType.ANIME, 0.6 - elif self.voc_match(query, "CartoonKeyword", lang=lang): + elif MediaType.CARTOON in valid_labels and self.voc_match(query, "CartoonKeyword", lang=lang): return MediaType.CARTOON, 0.6 - elif self.voc_match(query, "PodcastKeyword", lang=lang): + elif MediaType.PODCAST in valid_labels and self.voc_match(query, "PodcastKeyword", lang=lang): return MediaType.PODCAST, 0.6 - elif self.voc_match(query, "TVKeyword", lang=lang): + elif MediaType.TV in valid_labels and self.voc_match(query, "TVKeyword", lang=lang): return MediaType.TV, 0.6 - elif self.voc_match(query, "SeriesKeyword", lang=lang): + elif MediaType.VIDEO_EPISODES in valid_labels and self.voc_match(query, "SeriesKeyword", lang=lang): return MediaType.VIDEO_EPISODES, 0.6 - elif self.voc_match(query, "AudioDramaKeyword", lang=lang): + elif MediaType.RADIO_THEATRE in valid_labels and self.voc_match(query, "AudioDramaKeyword", lang=lang): # NOTE - before "radio" to allow "radio theatre" return MediaType.RADIO_THEATRE, 0.6 - elif self.voc_match(query, "RadioKeyword", lang=lang): + elif MediaType.RADIO in valid_labels and self.voc_match(query, "RadioKeyword", lang=lang): return MediaType.RADIO, 0.6 - elif self.voc_match(query, "ComicBookKeyword", lang=lang): + elif MediaType.VISUAL_STORY in valid_labels and self.voc_match(query, "ComicBookKeyword", lang=lang): return MediaType.VISUAL_STORY, 0.4 - elif self.voc_match(query, "GameKeyword", lang=lang): + elif MediaType.GAME in valid_labels and self.voc_match(query, "GameKeyword", lang=lang): return MediaType.GAME, 0.4 - elif self.voc_match(query, "ADKeyword", lang=lang): + elif MediaType.AUDIO_DESCRIPTION in valid_labels and self.voc_match(query, "ADKeyword", lang=lang): return MediaType.AUDIO_DESCRIPTION, 0.4 - elif self.voc_match(query, "ASMRKeyword", lang=lang): + elif MediaType.ASMR in valid_labels and self.voc_match(query, "ASMRKeyword", lang=lang): return MediaType.ASMR, 0.4 - elif self.voc_match(query, "AdultKeyword", lang=lang): - if self.voc_match(query, "CartoonKeyword", lang=lang) or \ + elif any([s in valid_labels for s in [MediaType.ADULT, MediaType.HENTAI, MediaType.ADULT_AUDIO]]) and self.voc_match(query, "AdultKeyword", lang=lang): + if MediaType.HENTAI in valid_labels and self.voc_match(query, "CartoonKeyword", lang=lang) or \ self.voc_match(query, "AnimeKeyword", lang=lang) or \ self.voc_match(query, "HentaiKeyword", lang=lang): return MediaType.HENTAI, 0.4 - elif self.voc_match(query, "AudioKeyword", lang=lang) or \ + elif MediaType.ADULT_AUDIO in valid_labels and self.voc_match(query, "AudioKeyword", lang=lang) or \ self.voc_match(query, "ASMRKeyword", lang=lang): return MediaType.ADULT_AUDIO, 0.4 return MediaType.ADULT, 0.4 - elif self.voc_match(query, "HentaiKeyword", lang=lang): + elif MediaType.HENTAI in valid_labels and self.voc_match(query, "HentaiKeyword", lang=lang): return MediaType.HENTAI, 0.4 - elif self.voc_match(query, "VideoKeyword", lang=lang): + elif MediaType.VIDEO in valid_labels and self.voc_match(query, "VideoKeyword", lang=lang): return MediaType.VIDEO, 0.4 - elif self.voc_match(query, "AudioKeyword", lang=lang): + elif MediaType.AUDIO in valid_labels and self.voc_match(query, "AudioKeyword", lang=lang): return MediaType.AUDIO, 0.4 return MediaType.GENERIC, 0.0 - def classify_media(self, query: str, lang: str) -> Tuple[MediaType, float]: + def classify_media(self, query: str, lang: str, valid_labels: Optional[List[MediaType]] = None) -> Tuple[MediaType, float]: """ determine what media type is being requested """ lang = standardize_lang_tag(lang) + valid_labels = valid_labels or [m for m, s in self.media2skill.items() if s] or list(MediaType) + LOG.debug(f"valid media types: {valid_labels}") + if len(valid_labels) == 1: + return valid_labels[0], 1.0 + # using a trained classifier (Experimental) if self.config.get("experimental_media_classifier", False): from ovos_classifiers.skovos.classifier import SklearnOVOSClassifier @@ -768,6 +779,8 @@ def classify_media(self, query: str, lang: str) -> Tuple[MediaType, float]: featurizer: OCPFeaturizer = self._media_clf[1] X = featurizer.transform([query]) preds = clf.predict_labels(X)[0] + preds = {k: v for k, v in preds.items() + if OCPFeaturizer.label2media(k) in valid_labels} label = max(preds, key=preds.get) prob = float(round(preds[label], 3)) LOG.info(f"OVOSCommonPlay MediaType prediction: {label} confidence: {prob}") @@ -779,7 +792,7 @@ def classify_media(self, query: str, lang: str) -> Tuple[MediaType, float]: return OCPFeaturizer.label2media(label), prob except: LOG.exception(f"OCP classifier exception: {query}") - return self.voc_match_media(query, lang) + return self.voc_match_media(query, lang, valid_labels) def is_ocp_query(self, query: str, lang: str) -> Tuple[bool, float]: """ determine if a playback question is being asked""" From 5506224ef82aca7773b2cb9cb7cde0e0fda15c04 Mon Sep 17 00:00:00 2001 From: JarbasAl Date: Thu, 19 Dec 2024 00:22:23 +0000 Subject: [PATCH 5/9] Increment Version to 1.1.1a1 --- ocp_pipeline/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ocp_pipeline/version.py b/ocp_pipeline/version.py index c296309..aa12d32 100644 --- a/ocp_pipeline/version.py +++ b/ocp_pipeline/version.py @@ -1,6 +1,6 @@ # START_VERSION_BLOCK VERSION_MAJOR = 1 VERSION_MINOR = 1 -VERSION_BUILD = 0 +VERSION_BUILD = 1 VERSION_ALPHA = 1 # END_VERSION_BLOCK From e61689d67924fe08fab958c77dd9e1d5e83af94c Mon Sep 17 00:00:00 2001 From: JarbasAl Date: Thu, 19 Dec 2024 00:22:45 +0000 Subject: [PATCH 6/9] Update Changelog --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41491b6..fa6a9d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [1.1.1a1](https://github.com/OpenVoiceOS/ovos-ocp-pipeline-plugin/tree/1.1.1a1) (2024-12-19) + +[Full Changelog](https://github.com/OpenVoiceOS/ovos-ocp-pipeline-plugin/compare/1.1.0a1...1.1.1a1) + +**Merged pull requests:** + +- fix:improve\_media\_clf [\#46](https://github.com/OpenVoiceOS/ovos-ocp-pipeline-plugin/pull/46) ([JarbasAl](https://github.com/JarbasAl)) + ## [1.1.0a1](https://github.com/OpenVoiceOS/ovos-ocp-pipeline-plugin/tree/1.1.0a1) (2024-12-18) [Full Changelog](https://github.com/OpenVoiceOS/ovos-ocp-pipeline-plugin/compare/1.0.11...1.1.0a1) From 23de18123d55cef5466db999cbafc9f15f186de9 Mon Sep 17 00:00:00 2001 From: JarbasAI <33701864+JarbasAl@users.noreply.github.com> Date: Thu, 19 Dec 2024 00:26:26 +0000 Subject: [PATCH 7/9] fix:dont_allow_load_game (#48) until we allow requesting load_game_name dont allow load_game intent unless game is already playing --- ocp_pipeline/opm.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ocp_pipeline/opm.py b/ocp_pipeline/opm.py index d47093e..91f89ca 100644 --- a/ocp_pipeline/opm.py +++ b/ocp_pipeline/opm.py @@ -362,7 +362,9 @@ def match_high(self, utterances: List[str], lang: str, message: Message = None) return None else: # if no game is being played, disable game specific intents - game_only = ["save_game"] + game_only = ["save_game", "load_game"] + # TODO - allow load_game without being in game already + # this can only be done if we match skill_id if match["name"] in game_only: LOG.info(f'Ignoring OCP intent match {match["name"]}, not playing MediaType.GAME') return None From cbb0ec0afd4f3489d99e5a94270d819870e8e95a Mon Sep 17 00:00:00 2001 From: JarbasAl Date: Thu, 19 Dec 2024 00:26:40 +0000 Subject: [PATCH 8/9] Increment Version to 1.1.2a1 --- ocp_pipeline/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ocp_pipeline/version.py b/ocp_pipeline/version.py index aa12d32..68d8055 100644 --- a/ocp_pipeline/version.py +++ b/ocp_pipeline/version.py @@ -1,6 +1,6 @@ # START_VERSION_BLOCK VERSION_MAJOR = 1 VERSION_MINOR = 1 -VERSION_BUILD = 1 +VERSION_BUILD = 2 VERSION_ALPHA = 1 # END_VERSION_BLOCK From c132858979231006ef6d24c094b8e6aae6ce8cd1 Mon Sep 17 00:00:00 2001 From: JarbasAl Date: Thu, 19 Dec 2024 00:27:06 +0000 Subject: [PATCH 9/9] Update Changelog --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa6a9d4..036a3fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [1.1.2a1](https://github.com/OpenVoiceOS/ovos-ocp-pipeline-plugin/tree/1.1.2a1) (2024-12-19) + +[Full Changelog](https://github.com/OpenVoiceOS/ovos-ocp-pipeline-plugin/compare/1.1.1a1...1.1.2a1) + +**Merged pull requests:** + +- fix:dont\_allow\_load\_game [\#48](https://github.com/OpenVoiceOS/ovos-ocp-pipeline-plugin/pull/48) ([JarbasAl](https://github.com/JarbasAl)) + ## [1.1.1a1](https://github.com/OpenVoiceOS/ovos-ocp-pipeline-plugin/tree/1.1.1a1) (2024-12-19) [Full Changelog](https://github.com/OpenVoiceOS/ovos-ocp-pipeline-plugin/compare/1.1.0a1...1.1.1a1)