Building a soccer stats bot

I am a huge soccer fan and longtime active player so naturally I love talking about soccer facts and statistics. In my professional life I am very interested in the trend of chatbots (and to an extend the personal assistants like Amazon Alexa or Google Assistant). To combine the two I thought a the following project: a bot that answers questions about soccer players and teams. Comparting players or teams should be possible, too. In the following blog post I will write about my thoughts on the architecture of the bot and how my first (very basic) bot looks like in python.

KNOWLEDGE of the bot

First I had to define what sentences the bot should be able to understand. I want to start with three simple command-like queries:

  • team %team%
  • player %player%
  • compare with %team or player%

The first two commands should return some stats (undefined for now) about a team or a player. The third command should compare the current object (team or player) with another team or player.

ARCHITECTURE

My first idea was to make this bot a reddit bot and I still believe that in the end this will be the case. However at the moment I want to run the bot locally on my machine. Generally there are three important steps when it comes to the bots architecture:

  • notifying the bot that there is a new query
  • checking if the query is valid
  • computing the answer to that query
  • displaying the answer to the user

Since I do not own a machine that is connected the internet 24/7 I aimed to use a service like AWS Lambda. This service waits for events, runs your code and terminates. No need to have a server running 24/7. However, there is problem with the connection between reddit and AWS Lambda. If there is no server running that checks for new mentions of my bot I need some kind of notification. I looked into IFTTT, a service that connects other services using applets. However IFTTT does not offer a trigger that is fired when your account name is mentioned. I still recommend IFTTT though. It is a very cool tool.

 Sadly it is not possible to react to a new mention in a comment using IFTTT

Sadly it is not possible to react to a new mention in a comment using IFTTT

I briefly looked into RSS-Feeds and JSON-Files generated automatically by reddit however I still couldn't figure out a solution to fire a AWS lambda function when a new reddit comment mentions my bots username. To move forward with the project I decided to first implement my bot and then come back to the notification issue. In the worst case I can connect a raspberry pi to the internet and let it run the reddit bot. I great video tutorial on this can be found here. Computing the answer will consist of scraping a soccer database like whoscored.com or transfermarkt.de and then creating the answer in a format that fits the bot platform (for example a plain text answer for a reddit comment).

ARTIFICIAL INTELLIGENCE MARKUP LANGUAGE (AIML)

While looking for a smart way to create my bot I found the XML-like markup language AIML. It was developed by Dr. Richard S. Wallace and is a result of his research on A.L.I.C.E., a bot that won several prizes and can be checked out here. In this chapter I will paste my .aiml file and explain part for part what it does. If you want more detail on a tag you can refer to the official reference. So, first the complete file:

<aiml version="1.0.1" encoding="UTF-8">
    <category>
        <pattern>HELP</pattern>
        <template>
            The following commands are available: team, player and compare with. Type 'help %command%' to find out more.
        </template>
    </category>
    <category>
        <pattern>HELP TEAM</pattern>
        <template>
            To get the stats of a certain team enter "team %teamname%".
        </template>
    </category>
    <category>
        <pattern>HELP PLAYER</pattern>
        <template>
            To get the stats of a certain player enter "player %playername%".
        </template>
    </category>
    <category>
        <pattern>HELP COMPARE WITH</pattern>
        <template>
            To compare two teams type 'team x' and then 'compare with y'. To compare two players type 'player x' and then 'compare with y'.
        </template>
    </category>
    <category>
        <pattern>PLAYER *</pattern>
        <template>
            I will try to load the stats of <set name="player"><star/></set>.
            <think>
                <set name="op">load</set>
                <set name="topic">player</set>
                <set name="team"></set>
                <set name="team_compare"></set>
                <set name="player_compare"></set>
            </think>
        </template>
    </category>
    <category>
        <pattern>TEAM *</pattern>
        <template>
            I will try to load the stats of <set name="team"><star/></set>.
            <think>
                <set name="op">load</set>
                <set name="topic">team</set>
                <set name="player"></set>
                <set name="team_compare"></set>
                <set name="player_compare"></set>
            </think>
        </template>
    </category>

    <topic name="PLAYER">
        <category>
            <pattern>COMPARE WITH *</pattern>
            <template>
                Okay, let's compare <get name="player"/> with <set name="player_compare"><star/></set>.
                <think>
                    <set name="op">compare</set>
                </think>
            </template>
        </category>
    </topic>

    <topic name="TEAM">
        <category>
            <pattern>COMPARE WITH *</pattern>
            <template>
                Okay, let's compare <get name="team"/> with <set name="team_compare"><star/></set>.
                <think>
                    <set name="op">compare</set>
                </think>
            </template>
        </category>
    </topic>

    <category>
        <pattern>*</pattern>
        <template>
            The following commands are available: team, player. Type 'help %command%' to find out more.
        </template>
    </category>
</aiml>

Fixed Answers

The tag <aiml> starts and ends the file. You can set the version and encoding. So far that should be familiar from HTML or XML. Tags of type <category> define a conversation between the bot and the user. A category always has a pattern and if that pattern matches a template will be used to generate an answer. Let us look at an example.

<category>
    <pattern>HELP</pattern>
    <template>
            The following commands are available: team, player and compare with. Type 'help %command%' to find out more.
    </template>
</category>

I created the pattern HELP so that the bot can print a helpful message if the user does not know what to do. Note that you have to write the pattern in uppercase or it won't work (at least not in the python implementation of AIML that I am using). In a similay fashion I created help texts for the three commands (refer to the complete .aiml to see them).

MATCHING ARBITRARY PATTERNS

Sometimes the user says something that should be re-used in the answer. An example would be the following conversation:

  • User: Hi, I am Michael.
  • Bot: Hi Michael. How are you?

It would be impossible to create a category for every name that is out there. So you can create a category like this:

    <category>
        <pattern>PLAYER *</pattern>
        <template>
            I will try to load the stats of <star/>.
        </template>
    </category>

The user says player Lionel Messi and the bot will answer using everything that was matched by the * (referenced by <star/>). So his answer will be: I will try to load the stats of Lionel Messi.

Setting predicates (Variables)

To make the bot more dynamic and real it needs to remember stuff the user told it. To do this you can set predicates. These predicates are basically just variables that are stored in the bots brain. For now I created 5 variables and used an existing one:

  • op: stores the current operation. Can be 'load', 'compare' or ''
  • topic: pre-defined variable that stores the current topic of the conversation
  • player: the current player
  • team: the current team
  • player_compare: the player to compare the current player with
  • team_compare: the team to compare the current team with

You can store predicates using the following syntax:

<set name='predicate'>value</set>

Sometimes you want to set some variables in the background. This can be done using the tag <think>. Everything inside this tag will not be part of the response. It simulates the internal thinking process of the bot. Look at the following example for the commands player and compare with:

<category>
    <pattern>PLAYER *</pattern>
        <template>
            I will try to load the stats of <set name="player"><star/></set>.
        <think>
            <set name="op">load</set>
            <set name="topic">player</set>
            <set name="team"></set>
            <set name="team_compare"></set>
            <set name="player_compare"></set>
        </think>
    </template>
</category>
<topic name="PLAYER">
    <category>
        <pattern>COMPARE WITH *</pattern>
        <template>
            Okay, let's compare <get name="player"/> with <set name="player_compare"><star/></set>.
            <think>
                <set name="op">compare</set>
            </think>
        </template>
    </category>
</topic>

As you can see if the user enters player Lionel Messi the bot will set the operation to load, the topic to player and the player to Lionel Messi. The other variables are cleared. Note, that the command compare with is inside the tag <topic>. This makes it possible to use the same command for both players and teams (refer to the complete file above).

Catching unknown phrases

To make the bot feel more realistic and to not run into a situation where the bot has no answer I created a category that catches everything. It will simply return the help answer.

<category>
    <pattern>*</pattern>
    <template>
        The following commands are available: team, player. Type 'help %command%' to find out more.
    </template>
</category>

Summary

In this blog post I shared my idea and the first approaches to a soccer stats bot. If you have any suggestions for me on how to implement the bot using AWS Lambda and especially on how to get around the notification problem please leave a comment or tweet at me. I will post about my bot implementation in Python using python-aiml in the upcoming weeks.