[38;5;244m┌─[0m [38;5;40mroot@joaocosta:~#[0m [38;5;245mcat posts/8.md[0m [38;5;244m────────────────────────────────────────────[0m

[38;5;40m#[0m [1mDeveloping a skill for Mycroft[0m
[38;5;245mpublished 2021-02-02 · 5 min read · https://joaocosta.dev/blog/8[0m

On my previous post (the one about Ubuntu and my school exam day), I briefly
mentioned that I created a small skill for the Mycroft A.I. assistant
(https://mycroft.ai/). Let's talk about that.

[38;5;38m##[0m [1mRecap[0m

On my previous post (the one about Ubuntu and my school exam day), I briefly
mentioned that I created a small skill for the [38;5;40mMycroft A.I. assistant[0m
[38;5;244m(https://mycroft.ai/)[0m. If you read it, you should remember that, because it was
the reason for the whole Ubuntu ordeal after all.

[38;5;38m##[0m [1mThe current state of my skill[0m

The skill was meant to be a really quick and 'dirty' hack to get youtube music
playback working, but it turned out a lot nicer than I thought it would ever be.
As a matter of fact, it turned out so nicely that I even added to my blog's
[38;5;40mprojects page[0m [38;5;244m(https://www.joaocosta.dev/projs)[0m. At the moment of writing, there
are only 4 things about the skill that I'm not happy with:

[38;5;40m→[0m I haven't created tests, which are (probably) important, for the skill;
[38;5;40m→[0m Instead of telling you the [3mtitle[0m of the video that's currently playing (when
  queried), it tells you the name that it heard from you;
[38;5;40m→[0m The skill can't search for youtube playlists. It can only find youtube
  playlists if you give it a link to the playlist, but it can't do that using
  keywords. This is because I couldn't find a way to do that using [38;5;40myoutube-dl[0m
  [38;5;244m(https://youtube-dl.org/)[0m;
[38;5;40m→[0m It is not possible to cancel a download after it has started.

From this 4 problems, the ones that I'm most likely to take care of are the
first two, because a fix for the third problem would most likely require me to
implement something that [1myoutube-dl[0m can't do (which and I don't feel like doing)
and the last problem is not very important.

[1mTLDR:[0m The skill is working very well in its current state but could use more
features, namely: better youtube playlist support.

[38;5;38m##[0m [1mThe start of the skill development[0m

I'm going to be honest, I was a bit scared of it being too difficult to start
the skill development, but I still told my friend that it would be [3m'easy peasy'[0m.
This was mostly because the only problem I was seeing was: "How does Mycroft
work?".

Turns out it really was easy to start. The development is in Python, which is
extremely easy, and Mycroft provides a really great [38;5;40mintroductory guide[0m
[38;5;244m(https://mycroft-ai.gitbook.io/docs/skill-development/introduction)[0m to skill
development. If you have experience with object-oriented programming, you should
have no problems developing new skills for Mycroft (you don't really need to
know Python to code in Python). If you're thinking about creating a new
skill/editing an existing one, I recommend you to check out [38;5;40mMycroft's Hello
World skill[0m
[38;5;244m(https://github.com/mycroftai/skill-hello-world/tree/4f47a7b23ed4a5e086001f80f3ca4c3f7f7c061b)[0m.

[38;5;38m##[0m [1mStuff about 'intents'[0m

Intents are the only thing I found about [1mMycroft[0m that can be somewhat confusing
in the beginning (at least it was for me).

There are 2 types of intents:

[38;5;40m→[0m [1mAdapt[0m intents - these are triggered by a list of [3mkeywords[0m (the list can be a
  single keyword). Bellow is an example [3madapt[0m intent handler taken from
  Mycroft's hello world skill:

[38;5;244m┄────────────────────────────────────────────────────────────────────────── py [0m
[38;5;245m│[0m # example taken from Mycroft's Hello world skill
[38;5;245m│[0m 
[38;5;245m│[0m @intent_handler(IntentBuilder('ThankYouIntent').require('ThankYouKeyword')) def
[38;5;245m│[0m handle_thank_you_intent(self, message): """ This is an Adapt intent handler, it
[38;5;245m│[0m is triggered by a keyword.""" self.speak_dialog("welcome")
[38;5;244m┄──────────────────────────────────────────────────────────────────────────────[0m

[38;5;40m→[0m [1mPedatious[0m intents - these are triggered by a list of sample sentences. They
  are fascinating, because you can quickly train the A.I. using a relatively
  small list of sentences. This list of sentences, supports [3mregex[0m, so you can
  quickly and easily increase your sample size. Below is an example [3mpedatious[0m
  intent handler adapted from the skill I created:

[38;5;244m┄────────────────────────────────────────────────────────────────────────── py [0m
[38;5;245m│[0m # example adapted from the skill I developed
[38;5;245m│[0m @intent_handler("Youtubedl.intent")
[38;5;245m│[0m def handle_youtubedl_intent(self, message):
[38;5;245m│[0m   """ This is a Padatious intent handler.
[38;5;245m│[0m   It is triggered using a list of sample phrases."""
[38;5;245m│[0m   vid_name = message.data.get("vid")
[38;5;245m│[0m   self.log.debug("Current queue:", self.queue)
[38;5;245m│[0m   if not vid_name:
[38;5;245m│[0m     self.speak_dialog("youtubedl")
[38;5;245m│[0m   else:
[38;5;245m│[0m     self.download_vid(vid_name)
[38;5;245m│[0m     self.log.info("Done downloading video youtubedl.")
[38;5;245m│[0m   self.log.debug("Done youtubedl.")
[38;5;245m│[0m </code></pre>
[38;5;244m┄──────────────────────────────────────────────────────────────────────────────[0m

It should be noted that you need to import [38;5;38mfrom adapt.intent import
IntentBuilder[0m and [38;5;38mfrom mycroft import MycroftSkill, intent_handler[0m to use
[1mMycroft[0m (import other modules too if you need them).

[38;5;38m##[0m [1mVocab files and getting information from the user[0m

These files are located inside the [1mvocab/<country-code>/[0m directory of a
project's root (<country-code> could be, for example, [1men-us[0m and they can either
contain keywords to trigger [3madapt[0m intents or a list of sentences (supporting
regex) to train an [3mpedatious[0m intent.

For example, you could have a [1mThankYouKeyword.voc[0m file with the following
contents (file used on the decorator of [3madapt[0m intent example):

[38;5;244m┄───────────────────────────────────────────────────────────────────────── txt [0m
[38;5;245m│[0m thank you
[38;5;245m│[0m thanks
[38;5;244m┄──────────────────────────────────────────────────────────────────────────────[0m

So the intent in the first code example above would be triggered by either one
of these sentences.

You can also have, as an example, a [1mYoutubeddl.intent[0m file with the following
contents (file used on the decorator of [3mpedatious[0m intent example):

[38;5;244m┄───────────────────────────────────────────────────────────────────────── txt [0m
[38;5;245m│[0m youtube {vid}
[38;5;245m│[0m youtube (play | start | download) {vid}
[38;5;244m┄──────────────────────────────────────────────────────────────────────────────[0m

This allows out intent to be triggered by a more complex set of sentences. In
the example above, Our intent would be triggered by sentences like: "youtube
stream of consciousness", "youtube play dora the explorer" and "youtube start
something" (the [1m|[0m means [1mor[0m). It is also possible to get information from the
user using this type of intent ([3mpedatious[0m). In this case, we can extract the
[1m{vid}[0m component of the message (you can define all the component you want) using
[38;5;38mmessage.data.get("vid")[0m, e.g.: if the user says "youtube start dora the
explorer", our intent will be triggered and the [1m{vid}[0m component will be "dora
the explorer".

[38;5;38m##[0m [1mDialog[0m

It is possible to tell Mycroft to speak a given sentence using
[38;5;38mself.speak_dialog(string)[0m, where [3mstring[0m is either a sentence or the name of a
dialog File. You could use [38;5;38mself.speak_dialog("Hello, my name is Mycroft!")[0m to
make Mycroft say: [1m"Hello, my name is Mycroft!"[0m, but using [3mvocab files[0m has an
important extra feature.

[3mVocab files[0m allow you to simulate a more human-like speech pattern by writing
multiple sentences with the same meaning in the file, so one is selected
randomly each time. You could have a [1mgreeting.dialog[0m file inside the
[1mdialog/<country-code>/[0m directory of your project's root (<country-code> could
be, for example, [1men-us[0m) with the following contents:

[38;5;244m┄───────────────────────────────────────────────────────────────────────── txt [0m
[38;5;245m│[0m Good to see you!
[38;5;245m│[0m Greeting!
[38;5;245m│[0m Hello!
[38;5;245m│[0m Hey!
[38;5;245m│[0m Hi!
[38;5;245m│[0m Nice to see you!
[38;5;245m│[0m Pleased to see you!
[38;5;244m┄──────────────────────────────────────────────────────────────────────────────[0m

To tell Mycroft to speak a sentence from that file, you'd use
[38;5;38mself.speak_dialog("greeting")[0m. Notice the [1m.dialog[0m part missing from the file
name. You can omit that part when calling files (it was something that took me a
while to notice).

[38;5;38m##[0m [1mLogs[0m

It is useful to log information of what's happening in your skill, both for
debugging and to provide extra information to the end user. At the time of
writing, Mycroft provides 5 different types of log messages: info, debug,
warning, error, and exception. To use them, you just need to write
[38;5;38mself.log.<log-type>(string)[0m, where [1m[38;5;38m<log-type>[0m[0m is one of the types above and
[3mstring[0m is the text that will be written, e.g.: [38;5;38mself.log.info("Potato evaluation
skill triggered.")[0m. The aspect (for example color) of the log message depends on
its type.

[38;5;38m##[0m [1mClosing words[0m

There isn't a lot needed to start creating a skill for Mycroft (besides an idea
and some programming skills). It is simple to use and develop for.

I hope this blog post isn't too disorganized. It was based on the notes I took
when learning how to develop a skill for Mycroft so it might be a little [3m'all
over the place'[0m. I believe it still should be a good resource to show some small
usage examples, and to incentivize people to give Mycroft a try.

This post will come out a few days later than I was expecting (I was having
trouble concentrating on writing). Still, I hope you had a good St. Valentine's
Day (even if you're single). Mine was pretty good. Stay safe :P

[38;5;244m└─[0m [38;5;40m→[0m view online: [38;5;40mhttps://joaocosta.dev/blog/8[0m
