Amazon Echo + Akka = Akkazon Ekko

I recently started working on a project that may or may not make it into my book on Scala and functional programming. I’m currently calling it “Akkazon Ekko” — or “Ekko” — because it’s a little like the Amazon Echo, but written with Scala and Akka.

Running Ekko

Right now Ekko works from the command line, and I typically start it from the Mac/Unix command line with SBT:

$ sbt

The I run the project:

> run

Running Ekko commands

Then I start typing commands that Ekko can understand:

ekko: hello
Buenos dias

ekko: weather
stand by ...
The current temperature is 78 degrees, and the sky is partly cloudy.

ekko: forecast
stand by ...
Here's the forecast.
For Sunday, a low of 59, a high of 85, and Partly Cloudy skies. 
For Monday, a low of 53, a high of 72, and Scattered Thunderstorms skies.

ekko: todo add Wake Up
1. Wake Up

ekko: todo add Make Coffee
1. Wake Up
2. Make Coffee

ekko: bye
Goodbye

> _

Listing commands Ekko understands

To get a list of the commands that Ekko currently understands, you can type what can i say, or the much shorter w:

ekko: w

1. adios
2. aloha
3. bye
4. exit
5. goodbye
6. hasta.*
7. quit
8. hello
9. hi
10. hola
11. yo
12. todo add <foo>
13. todo list
14. todo view
15. todo del <foo>
16. todo rem <foo>
17. trib
18. tribune
19. trib.* sports
20. weather
21. forecast
22. current weather
23. weather forecast

Ekko can currently get sports headlines from the Chicago Tribune’s sports RSS feed, but I didn’t show that here because the output is currently a little long. But I have code in the project like this that kinda shows how to read RSS feeds and scrape information of off  websites.

Written with Akka (and Scala)

The code is written with Akka and Scala, so inside of Ekko you’ll find a lot of actors, like this HelloActor:

class HelloActor extends Actor with ActorLogging {

    val mouth = context.actorSelection("/user/Mouth")
    
    val helloRegexesWeRespondTo = List(
        "hello",
        "hi",
        "hola",
        "yo"
    )

    def receive = {

        case WillYouHandlePhrase(s) =>
            val weWillHandle = Utils.matchesARegex(helloRegexesWeRespondTo, s)
            sender ! weWillHandle
            if (weWillHandle) {
                log.info(s"HelloActor will handle '$s'")
                mouth ! SpeakText(getRandomHelloPhrase)
            }

        case WhatPhrasesCanYouHandle =>
            sender ! helloRegexesWeRespondTo

        case unknown =>
            log.info("HelloActor got an unknown message: " + unknown)

    }

    private def getRandomHelloPhrase: String = {
        val phrases = List(
            "Good day",
            "Hello!",
            "How are you?",
            "Buenos dias",
            "It's a good day to be alive.",
            "Yo")
        Utils.getRandomElement(phrases)
    }

}

Next steps

The “get stuff working” part of me wants to throw more and more actors into Ekko to make it more and more functional, but the “get it working well” part of me wants to clean up the bad parts of the project before I do anything more with it, and I suspect the latter part of me will win this battle. I don’t want to add more actors to the mix while the way I do some of the things is pretty yukky.

Putting your imagination to work, you know that Akka can be a really nice core for building something like an Amazon Echo device. Because this code runs on the JVM, it could be run on Android devices, Raspberry Pi devices, and many other computer systems. (If you haven’t seen it before, the CMUSphinx project is a Java/JVM-based voice-recognition library you can add to your applications.)

Add actors with reflection? (plugins)

The way to really make something like this work well is to add actors using reflection. That way anyone can write an Ekko plugin. I did this with Sarah, and I may eventually bring that capability to Ekko.

But — and that’s a Big But — I really want Ekko to be a learning project, so I don’t know if I will ever do that. I may just take what I learn from Ekko and use it to fix Sarah. (So, if you want to fork the project to do something productive, go ahead and do so.)

The source code

The source code is currently kinda crappy — I’ve just been using this as an experimental project so far — but if you want to check it out, you can find it at this Github URL:

More ...

I’ll write more about Ekko as time goes on, but for today I just thought I’d put this code out here in case someone wants an Akka “starter project” that might be interesting ... something a little more than an Akka “Hello, world” project.