Giter VIP home page Giter VIP logo

ovos-workshop's Introduction

OVOS Workshop

OVOS Workshop contains skill base classes and supporting tools to build skills and applications for OpenVoiceOS systems.

ovos-workshop's People

Contributors

aiix avatar builderjer avatar emphasize avatar fidesachates avatar jarbasal avatar jaredcobb avatar lbt avatar mikejgray avatar neondaniel avatar neonjarbas avatar putnik avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

ovos-workshop's Issues

PHAL and admin PHAL failures to successfully initialize started evening of Jul 13

This may or may not be related to recent changes in OVOS-workshop. Problems seen while testing headless raspbian build.

ovos-systemd-phal[744]: 2023-07-14 07:11:36.669 - OVOS - ovos_workshop.skills.layers::3 - WARNING - Deprecation version=0.1.0. Caller=ovos_workshop.skills.ovos:16. Import from ovos_workshop.decorators.layers
ovos-systemd-phal[744]: 2023-07-14 07:11:36.713 - PHAL - ovos_workshop.skills.mycroft_skill:call:56 - WARNING - skill initialized without bus!! this is legacy behaviour and requires you to call skill.bind(bus) or skill._startup(skill_id, bus)
ovos-systemd-phal[744]: bus will be required starting on ovos-core 0.1.0
ovos-systemd-phal[744]: 2023-07-14 07:11:36.722 - PHAL - ovos_workshop.skills.base:bus:390 - WARNING - Skill not fully initialized.to correct this add kwargs init(bus=None, skill_id='') to skill class PHAL
ovos-systemd-phal[744]: 2023-07-14 07:11:36.727 - PHAL - ovos_workshop.skills.base:bus:394 - ERROR - Traceback:
ovos-systemd-phal[744]: File "/home/ovos/.local/bin/ovos-systemd-phal", line 30, in
ovos-systemd-phal[744]: main(ready_hook=notify_ready, stopping_hook=notify_stopping)
ovos-systemd-phal[744]: File "/home/ovos/.local/lib/python3.9/site-packages/ovos_PHAL/main.py", line 14, in main
ovos-systemd-phal[744]: phal = PHAL(on_error=error_hook, on_ready=ready_hook, on_stopping=stopping_hook)
ovos-systemd-phal[744]: File "/home/ovos/.local/lib/python3.9/site-packages/ovos_workshop/skills/mycroft_skill.py", line 60, in call
ovos-systemd-phal[744]: return super().call(*args, **kwargs)
ovos-systemd-phal[744]: File "/home/ovos/.local/lib/python3.9/site-packages/ovos_PHAL/service.py", line 42, in init
ovos-systemd-phal[744]: super().init(skill_id=f"ovos.{name}")
ovos-systemd-phal[744]: File "/home/ovos/.local/lib/python3.9/site-packages/ovos_workshop/app.py", line 31, in init
ovos-systemd-phal[744]: super().init(skill_id=skill_id, bus=bus, gui=gui,
ovos-systemd-phal[744]: File "/home/ovos/.local/lib/python3.9/site-packages/ovos_workshop/skills/ovos.py", line 36, in init
ovos-systemd-phal[744]: super(OVOSSkill, self).init(*args, **kwargs)
ovos-systemd-phal[744]: File "/home/ovos/.local/lib/python3.9/site-packages/ovos_workshop/skills/mycroft_skill.py", line 136, in init
ovos-systemd-phal[744]: super().init(name=name, bus=bus, *args, **kwargs)
ovos-systemd-phal[744]: File "/home/ovos/.local/lib/python3.9/site-packages/ovos_workshop/skills/base.py", line 215, in init
ovos-systemd-phal[744]: if self.skill_id and self.bus:
ovos-systemd-phal[744]: Traceback (most recent call last):
ovos-systemd-phal[744]: File "/home/ovos/.local/bin/ovos-systemd-phal", line 30, in
ovos-systemd-phal[744]: main(ready_hook=notify_ready, stopping_hook=notify_stopping)
ovos-systemd-phal[744]: File "/home/ovos/.local/lib/python3.9/site-packages/ovos_PHAL/main.py", line 14, in main
ovos-systemd-phal[744]: phal = PHAL(on_error=error_hook, on_ready=ready_hook, on_stopping=stopping_hook)
ovos-systemd-phal[744]: File "/home/ovos/.local/lib/python3.9/site-packages/ovos_workshop/skills/mycroft_skill.py", line 60, in call
ovos-systemd-phal[744]: return super().call(*args, **kwargs)
ovos-systemd-phal[744]: File "/home/ovos/.local/lib/python3.9/site-packages/ovos_PHAL/service.py", line 42, in init
ovos-systemd-phal[744]: super().init(skill_id=f"ovos.{name}")
ovos-systemd-phal[744]: File "/home/ovos/.local/lib/python3.9/site-packages/ovos_workshop/app.py", line 31, in init
ovos-systemd-phal[744]: super().init(skill_id=skill_id, bus=bus, gui=gui,
ovos-systemd-phal[744]: File "/home/ovos/.local/lib/python3.9/site-packages/ovos_workshop/skills/ovos.py", line 36, in init
ovos-systemd-phal[744]: super(OVOSSkill, self).init(*args, **kwargs)
ovos-systemd-phal[744]: File "/home/ovos/.local/lib/python3.9/site-packages/ovos_workshop/skills/mycroft_skill.py", line 136, in init
ovos-systemd-phal[744]: super().init(name=name, bus=bus, *args, **kwargs)
ovos-systemd-phal[744]: File "/home/ovos/.local/lib/python3.9/site-packages/ovos_workshop/skills/base.py", line 215, in init
ovos-systemd-phal[744]: if self.skill_id and self.bus:
ovos-systemd-phal[744]: File "/home/ovos/.local/lib/python3.9/site-packages/ovos_workshop/skills/base.py", line 395, in bus
ovos-systemd-phal[744]: raise Exception('Accessed MycroftSkill.bus in init')
ovos-systemd-phal[744]: Exception: Accessed MycroftSkill.bus in init
systemd[495]: ovos-phal.service: Main process exited, code=exited, status=1/FAILURE
systemd[495]: ovos-phal.service: Failed with result 'exit-code'.
systemd[495]: Failed to start OVOS PHAL.

Proposal: adding metadata to dialog files

Problems being solved

  • 1 - in some languages TTS utterances may depend on the gender of the person listening
  • 2 - in some languages TTS utterances may depend on the gender of the speaker
    • eg. in portuguese you there is no gender neutral way to say "thank you", you say "obrigado"/"obrigada"
    • this would be a setting of the voice assistant
  • 3 - personality settings
    • "increase sarcasm by 20%"

Dialog Json

New file format, .jsonl, where each line in the file contains a json of the format

{"utterance": "XXX", "attitude": "sarcastic", "assistant_gender": "male", "listener_gender": "male", "weight": 0.3}

jsonl format info: https://jsonlines.org

Personality Settings

in mycroft.conf users can tweak personality

weights reflect how likely a dialog is to be selected

"persona": {
    "gender": "male",
    "attitudes": {
        "normal": 10,
        "flippant": 8.0,
        "funny": 8.0,
        "irritable": 0
      }
}

How it works

  • 1 - load .jsonl file if it exists, else old .dialog file
  • 2 - filter samples per assistant gender
  • 3 - select an attitude based on weights defined in mycroft.conf
  • 4 - filter samples per attitudes
  • 5 - select based on weights of .jsonl file

references

previous discussions

OVOSSkill full CRUD for events

Currently, there is no way to list existing events from the OVOSSkill methods. Once the feature exists in ovos-bus-client, the helper methods should be added to the base class

ERROR - No module named 'ovos_utils.lang.translate'

2023-04-20 11:37:30.887 - OVOS - ovos_workshop.skills.auto_translatable:<module>:11 - ERROR - No module named 'ovos_utils.lang.translate'
Traceback (most recent call last):
  File "/home/ovos/.venv/lib/python3.11/site-packages/ovos_workshop/skills/auto_translatable.py", line 7, in <module>
    from ovos_utils.lang.translate import detect_lang, translate_text
ModuleNotFoundError: No module named 'ovos_utils.lang.translate'

When core restarts, I got this trace in the "hello world" skill

exception calling callback for <Future at 0x7f8c947890 state=finished raised RuntimeError>
Traceback (most recent call last):
  File "/usr/lib/python3.11/concurrent/futures/_base.py", line 340, in _invoke_callbacks
    callback(self)
  File "/usr/lib/python3.11/site-packages/pyee/_executor.py", line 57, in _callback
    self.emit("error", exc)
  File "/usr/lib/python3.11/site-packages/pyee/_base.py", line 118, in emit
    self._emit_handle_potential_error(event, args[0] if args else None)
  File "/usr/lib/python3.11/site-packages/pyee/_base.py", line 88, in _emit_handle_potential_error
    raise error
  File "/usr/lib/python3.11/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/ovos_utils/messagebus.py", line 564, in wrapper
    on_end(message)
  File "/usr/lib/python3.11/site-packages/ovos_workshop/skills/base.py", line 1427, in on_end
    self._on_event_end(message, handler_info, skill_data)
  File "/usr/lib/python3.11/site-packages/ovos_workshop/skills/mycroft_skill.py", line 112, in _on_event_end
    return super()._on_event_end(message, handler_info, skill_data)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/ovos_workshop/skills/base.py", line 1375, in _on_event_end
    self._initial_settings = copy(self.settings)
                             ^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/copy.py", line 102, in copy
    return _reconstruct(x, None, *rv)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/copy.py", line 300, in _reconstruct
    for key, value in dictiter:
RuntimeError: dictionary changed size during iteration

SkillResources: add method to create resource/intent test yaml files

To curb the time spent to define (and maintain) the test files, this should be automated (as a part of CI/CD)

test_resources.yml

languages:
  - "en-us"
  # - ...

# below files taken from en-us
vocab:
  - HelloKeyword
  - NoKeyword
  - YesKeyword
  - ThankYouKeyword
  - WorldKeyword

dialog:
  - hello_world
  - how_are_you
  - welcome

regex: []

intents:
  padatious:
    -HowAreYou.intent
  
  adapt:
    - HelloWorldIntent
    - YesNoIntent

test_intents.yaml

en-us:
  HelloWorldIntent:
    - hello world
  HowAreYou.intent:
    - how have you been
  YesNoIntent:
    - yes world
    - no world
 
# xx-xx:
#  ...

unmatched intents:  # this has to be manually added ofc
  en-us:
    - hello there everyone
    - what is this
    - maybe world every

handle file change errors in logs

Not exactly sure which repo to open this in, but this seemed maybe the best?

I have this error

10:13:19.751 - skills - ovos_utils.file_utils:on_any_event:383 - ERROR - An error occurred handling file change event callback                                                                                                                                
Traceback (most recent call last):                                                                                                                                                                                                                             
  File "/home/ovos/.local/lib/python3.9/site-packages/ovos_utils/file_utils.py", line 381, in on_any_event                                                                                                                                                     
    self._callback(event.src_path)                                                                                                                                                                                                                             
TypeError: _handle_filechange() takes 1 positional argument but 2 were given    

Whenever I make a change to my manually installed skills. Digging around, I think it's because this is invoking the callback with the changed file path, but the callback being passed in doesn't take an argument

BaseSkill.schedule_repeating_event has wrong type annotation

def schedule_repeating_event(self, handler: callable,
when: Union[int, float, datetime.datetime],
frequency: Union[int, float],
data: Optional[dict] = None,
name: Optional[str] = None,
context: Optional[dict] = None):
"""
Schedule a repeating event.
Args:
handler: method to be called
when (datetime): time (in system timezone) for first
calling the handler, or None to
initially trigger <frequency> seconds
from now
frequency (float/int): time in seconds between calls
data (dict, optional): data to send when the handler is called
name (str, optional): reference name, must be unique
context (dict, optional): context (dict, optional): message
context to send when the handler
is called
"""
message = dig_for_message()
context = context or message.context if message else {}
context["skill_id"] = self.skill_id
self.event_scheduler.schedule_repeating_event(handler, when, frequency,

The type annotation for when should be Optional[Union[int, float, datetime.datetime]] because, as per the comment, it is valid to pass None to initially trigger frequency seconds from now

You get the type error:

Argument of type "None" cannot be assigned to parameter "when" of type "int | float | datetime" in function "schedule_repeating_event"

MessageBusClient compat

BaseSkill.bus setter checks for FakeBus or ovos-bus-client.MessageBusClient instances but fails to validate mycroft-bus-client.MessageBusClient instances. Maybe this can check against the super class of ovos-bus-client.MessageBusClient?

When core restart, the skill returns an error

When running skill as standalone, with the core is restarted then a trace is generated inside the skill log.

2023-04-29 21:59:38.985 - OVOS - ovos_workshop.skill_launcher:_execute_instance_shutdown:334 - INFO - Skill ovos-skill-personal.OpenVoiceOS shut down successfully
exception calling callback for <Future at 0x7f9ac4b190 state=finished raised TypeError>
Traceback (most recent call last):
  File "/usr/lib/python3.11/concurrent/futures/_base.py", line 340, in _invoke_callbacks
    callback(self)
  File "/usr/lib/python3.11/site-packages/pyee/_executor.py", line 57, in _callback
    self.emit("error", exc)
  File "/usr/lib/python3.11/site-packages/pyee/_base.py", line 118, in emit
    self._emit_handle_potential_error(event, args[0] if args else None)
  File "/usr/lib/python3.11/site-packages/pyee/_base.py", line 88, in _emit_handle_potential_error
    raise error
  File "/usr/lib/python3.11/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/ovos_workshop/skill_launcher.py", line 514, in load_skill
    self.skill_loader.reload()
  File "/usr/lib/python3.11/site-packages/ovos_workshop/skill_launcher.py", line 298, in reload
    return self._load()
           ^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/ovos_workshop/skill_launcher.py", line 359, in _load
    self.skill_module = self._load_skill_source()
                        ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/ovos_workshop/skill_launcher.py", line 390, in _load_skill_source
    main_file_path = os.path.join(self.skill_directory, SKILL_MAIN_MODULE)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen posixpath>", line 76, in join
TypeError: expected str, bytes or os.PathLike object, not NoneType

feat - verbosity level

i propose adding a new concept of VerbosityLevel

this would correspond to a integer from 0 - 10, added to Session

  • 0 corresponds to the default, it means a skill should speak only essential messages
  • 10 corresponds to the skill speaking a lot, ideally explaining everything it is doing along the way

a skill would check for self.verbosity_level (session aware) and conditionally speak more messages, backwards compat is retained

if self.verbosity_level > 3:
    self.speak("extra info")
if self.verbosity_level >= 9:
    self.speak("extra very redundant info")

using session allows verbosity level to be set per client (such as hivemind voice satellites), the default value would come from mycroft.conf as usual. a companion skill can also be made to control this by voice

FallbackSkill `__new__()` fails for FallbackSkillV1

When creating a FallbackSkill under ovos-core 0.0.7, the follosing exception is raised and the skill is not created:

cls = <class 'skill_fallback_llm.LLMSkill'>, args = ()
kwargs = {'bus': <ovos_utils.fakebus.FakeBus object at 0x7f4d98193b20>, 'skill_id': 'test_skill.test'}

    def __new__classic__(cls, *args, **kwargs):
        if cls is FallbackSkill:
            # direct instantiation of class, dynamic wizardry for unittests
            # return V2 as expected, V1 will eventually be dropped
            return FallbackSkillV2(*args, **kwargs)
        cls.__bases__ = (FallbackSkillV1, FallbackSkill, _MetaFB)
>       return super().__new__(cls, *args, **kwargs)
E       TypeError: object.__new__() takes exactly one argument (the type to instantiate)

Apparently related to #131
Failure obseved in unit tests: https://github.com/NeonGeckoCom/skill-fallback_llm/actions/runs/7392338109/job/20110646544

When core restarts, I got this trace in the "wikipedia" and "weather" skills

2023-06-03 16:32:15.181 - OVOS - ovos_workshop.skill_launcher:load_skill:576 - INFO - detected core reload, reloading skill
2023-06-03 16:32:15.252 - OVOS - ovos_workshop.skill_launcher:reload:275 - INFO - ATTEMPTING TO RELOAD SKILL: skill-ovos-wikipedia.openvoiceos
2023-06-03 16:32:15.305 - skill-ovos-wikipedia.openvoiceos - ERROR - Failed to stop skill: skill-ovos-wikipedia.openvoiceos
Traceback (most recent call last):
  File "/usr/lib/python3.11/site-packages/ovos_workshop/skills/base.py", line 1866, in default_shutdown
    self.stop()
  File "/home/ovos/.local/lib/python3.11/site-packages/skill_ovos_wikipedia/__init__.py", line 142, in stop
    self.gui.release()
  File "/usr/lib/python3.11/site-packages/ovos_utils/gui.py", line 999, in release
    raise RuntimeError("bus not set, did you call self.bind() ?")
RuntimeError: bus not set, did you call self.bind() ?

settings changed decorator

we should add a decorator for skill settings, instead of the current way

    def initialize(self):
        self.settings_change_callback = self.on_settings_changed

this would make the code more readable and help avoiding user mistakes (such as assigning the callback before the call to super)

feat - "local_only" kwarg in intent decorators

i propose adding a new kwarg to the intent decorators, allowing to signal an intent as local only

this means the intent only triggers if session_id == "default", but won't work if coming from a voice satellite

this way we can add extra "local only" functionality or in case of TODOS allows to keep the intents around until they are expanded to support voice satellites

missing tests for conversational intents

tests for #12

from ovos_utils.fakebus import FakeBus, Message
from ovos_workshop.decorators import intent_handler, conversational_intent
from ovos_workshop.skills import OVOSSkill


class DogFactsSkill(OVOSSkill):

    @intent_handler("dog_facts.intent")
    def handle_intent(self, message):
        fact = "Dogs sense of smell is estimated to be 100,000 times more sensitive than humans"
        self.speak(fact)

    @conversational_intent("another_one.intent")
    def handle_followup_question(self, message):
        fact2 = "Dogs have a unique nose print,  making each one distinct and identifiable."
        self.speak(fact2)


if __name__ == "__main__":
    s = DogFactsSkill(skill_id="test", bus=FakeBus())

    r = s.converse_matchers["en-us"].calc_intent("another one")
    print(r)  # {'entities': {}, 'conf': 1, 'name': 'test.converse:another_one.intent'}

    m = Message(f"test.converse.request", {"utterances": ["one more"]})


    def handle_speak(m):
        print(m.data)
        # {'utterance': 'Dogs have a unique nose print,  making each one distinct and identifiable.',
        # 'expect_response': False, 'meta': {'skill': 'test'}, 'lang': 'en-us'}


    s.bus.on("speak", handle_speak)

    s.bus.emit(m)

Add helper function `voc_list` to the OvosSkill class

We need access to a vocabulary list (for instance to match_one, ...)

Proposal:

def voc_list(self, voc_filename, lang=None):
        """ returns the vocabulary list of a given term"""
        lang = lang or self.lang
        cache_key = lang + voc_filename

        if cache_key not in self.voc_match_cache:
            self.voc_match("", voc_filename, lang)

        return self.voc_match_cache.get(cache_key) or []

`NameError: name '_get_skill_dirs' is not defined.`

for p in _get_skill_dirs():

Commit 308ff2d4430442c10cb077003ba51cf305fb1b67 broke the skill launcher, crashing some skills: chatgpt fallback, and mikejgray/neon-homeassistant-skill

2023-12-29 10:14:28.163 - OVOS - ovos_utils.intents.intent_service_interface:<module>:8 - WARNING - Deprecation version=0.1.0. Caller=ovos_utils.intents:1. ovos_utils.intents moved to ovos_workshop.intents
2023-12-29 10:14:28.179 - OVOS - ovos_utils.intents.converse:<module>:7 - WARNING - Deprecation version=0.1.0. Caller=ovos_utils.intents:3. ConverseTracker has been deprecated without replacement
2023-12-29 10:14:28.192 - OVOS - ovos_utils.intents.layers:<module>:3 - WARNING - Deprecation version=0.1.0. Caller=ovos_utils.intents:4. IntentLayers moved to ovos_workshop.decorators.layers
2023-12-29 10:14:28.206 - OVOS - ovos_utils.intents:<module>:7 - WARNING - Deprecation version=0.1.0. Caller=ovos_utils.events:7. ovos_utils.intents moved to ovos_workshop.intents
2023-12-29 10:14:28.342 - OVOS - ovos_utils.enclosure:<module>:8 - WARNING - Deprecation version=0.1.0. Caller=ovos_plugin_manager.templates.tts:41. ovos_utils.enclosure has been deprecated!
2023-12-29 10:14:28.380 - OVOS - ovos_utils.enclosure.api:<module>:3 - WARNING - Deprecation version=0.1.0. Caller=ovos_plugin_manager.templates.tts:41. EnclosureApi has moved to ovos_bus_client.apis.enclosure
2023-12-29 10:14:28.401 - OVOS - ovos_utils.skills.locations:<module>:10 - WARNING - Deprecation version=0.1.0. Caller=ovos_utils.skills:3. ovos_utils.skills.locations moved to ovos_plugin_manager.skills
2023-12-29 10:14:28.474 - OVOS - mycroft:<module>:37 - WARNING - mycroft has been deprecated! please start importing from ovos_core and companion packages
mycroft module remains available for backwards compatibility and will be removed in version 0.2.0
Traceback (most recent call last):
  File "/home/ovos/.venv/bin/ovos-skill-launcher", line 8, in <module>
    sys.exit(_launch_script())
             ^^^^^^^^^^^^^^^^
  File "/home/ovos/.venv/lib/python3.11/site-packages/ovos_workshop/skill_launcher.py", line 657, in _launch_script
    skill = SkillContainer(skill_id)
            ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ovos/.venv/lib/python3.11/site-packages/ovos_workshop/skill_launcher.py", line 566, in __init__
    for p in _get_skill_dirs():
             ^^^^^^^^^^^^^^^
NameError: name '_get_skill_dirs' is not defined. Did you mean: 'get_skill_class'?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.