# Developing a skill for Mycroft

URL: https://joaocosta.dev/blog/8
Published: 2021-02-02 · 5 min read

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.

## Recap

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/). If you read it, you should
remember that, because it was the reason for the whole Ubuntu ordeal after all.

## The current state of my skill

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
[projects page](https://www.joaocosta.dev/projs).  
At the moment of writing, there are only 4 things about the skill that I'm not
happy with:

- I haven't created tests, which are (probably) important, for the skill;
- Instead of telling you the _title_ of the video that's currently playing (when
  queried), it tells you the name that it heard from you;
- 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
  [youtube-dl](https://youtube-dl.org/);
- 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 **youtube-dl** can't do (which and I don't feel like
  doing) and the last problem is not very important.

  **TLDR:** The skill is working very well in its current state but could use
  more features, namely: better youtube playlist support.

## The start of the skill development

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 _'easy
peasy'_. 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
[introductory guide](https://mycroft-ai.gitbook.io/docs/skill-development/introduction)
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
[Mycroft's Hello World skill](https://github.com/mycroftai/skill-hello-world/tree/4f47a7b23ed4a5e086001f80f3ca4c3f7f7c061b).

## Stuff about 'intents'

Intents are the only thing I found about **Mycroft** that can be somewhat
confusing in the beginning (at least it was for me).

There are 2 types of intents:

- **Adapt** intents - these are triggered by a list of _keywords_ (the list can
  be a single keyword). Bellow is an example _adapt_ intent handler taken from
  Mycroft's hello world skill:

```py
# example taken from Mycroft's Hello world skill

@intent_handler(IntentBuilder('ThankYouIntent').require('ThankYouKeyword')) def
handle_thank_you_intent(self, message): """ This is an Adapt intent handler, it
is triggered by a keyword.""" self.speak_dialog("welcome")
```

- **Pedatious** 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 _regex_,
  so you can quickly and easily increase your sample size. Below is an example
  _pedatious_ intent handler adapted from the skill I created:

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

It should be noted that you need to import
`from adapt.intent import IntentBuilder` and
`from mycroft import MycroftSkill, intent_handler` to use **Mycroft** (import
other modules too if you need them).

## Vocab files and getting information from the user

These files are located inside the **vocab/<country-code>/** directory of
a project's root (<country-code> could be, for example, **en-us** and they
can either contain keywords to trigger _adapt_ intents or a list of sentences
(supporting regex) to train an _pedatious_ intent.

For example, you could have a **ThankYouKeyword.voc** file with the following
contents (file used on the decorator of _adapt_ intent example):

```txt
thank you
thanks
```

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 **Youtubeddl.intent** file with the
following contents (file used on the decorator of _pedatious_ intent example):

```txt
youtube {vid}
youtube (play | start | download) {vid}
```

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 **|** means **or**).  
 It is also possible to get information from the user using this type of intent (_pedatious_).
In this case, we can extract the **{vid}** component of the message (you can define
all the component you want) using `message.data.get("vid")`, e.g.: if the user says
"youtube start dora the explorer", our intent will be triggered and the **{vid}**
component will be "dora the explorer".

## Dialog

It is possible to tell Mycroft to speak a given sentence using
`self.speak_dialog(string)`, where _string_ is either a sentence or the name of
a dialog File. You could use `self.speak_dialog("Hello, my name is Mycroft!")`
to make Mycroft say: **"Hello, my name is Mycroft!"**, but using _vocab files_
has an important extra feature.

_Vocab files_ 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 **greeting.dialog** file inside the
**dialog/<country-code>/** directory of your project's root
(<country-code> could be, for example, **en-us**) with the following
contents:

```txt
Good to see you!
Greeting!
Hello!
Hey!
Hi!
Nice to see you!
Pleased to see you!
```

To tell Mycroft to speak a sentence from that file, you'd use
`self.speak_dialog("greeting")`. Notice the **.dialog** part missing from the
file name. You can omit that part when calling files (it was something that took
me a while to notice).

## Logs

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 `self.log.<log-type>(string)`, where **`<log-type>`**
is one of the types above and _string_ is the text that will be written,
e.g.: `self.log.info("Potato evaluation skill triggered.")`.
The aspect (for example color) of the log message depends on its type.

## Closing words

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 _'all
over the place'_. 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
