Creating a GPT-3 Twitch Chatbot with Node.js

December 16, 2020
Written by
Sam Agnew
Twilion

Copy of Generic Blog Header 4(4).png

A mainstay of many popular channels that stream on Twitch.tv is having a bot to engage with viewers in chat to automate things such as tasks for moderators or sharing contextual information with newcomers. OpenAI's API for their new GPT-3 model provides a very versatile, general-purpose “text in, text out” interface, making it applicable to virtually any language task.

Naturally, this seems like a match made in heaven. So let's walk through how to unleash the powers of GPT-3 with Twitch chat bots on your own channel using Node.js.

Taking care of dependencies

Before writing any code, you will need an up to date version of Node.js and npm installed.

Navigate to the directory where you want this code to live and run the following command in your terminal to create a package for this project:

npm init --yes

The --yes argument runs through all of the prompts that you would otherwise have to fill out or skip. Now that we have a package.json for our app, run this command in the same directory to install the tmi.js library for Twitch chat and the Got library for making HTTP requests:

npm install tmi.js@1.5.0 got@11.8.0

Twitch chat can be accessed through IRC, and we can programmatically connect to Twitch IRC with tmi.js.

OpenAI has an official helper library for Python, and there have been some third party Node libraries, but we will be using the REST API on its own so all we need to be able to do is make HTTP requests.

This project requires an API key from OpenAI. At the time I’m writing this, the only way to obtain one is by being accepted into their private beta program. You can apply on their site. If you have one, create an environment variable for your OpenAI API key called OPENAI_SECRET_KEY, which you can find as the "secret key" at the top of the Developer Quickstart:

export OPENAI_SECRET_KEY='YOUR_API_KEY_HERE'

You should now have everything you need to begin building your bot.

Getting started with GPT-3

GPT-3 (Generative Pre-trained Transformer 3) is a highly advanced language model trained on a giant amount of text. In spite of its internal complexity, it is surprisingly simple to operate: you feed it some text, and the model generates some more following a similar style and structure.

We can see how versatile it is even with a tiny amount of input. For example, let's try to generate some lyrics in the style of the Brazilian thrash metal band Sepultura with the input "Artist: Sepultura\n\nLyrics:":

Generating Sepultura lyrics

GPT-3 is non-deterministic in the sense that given the same input, multiple runs of the engine will return different responses. It's great at picking up on structure and context, so you can mess around with the prompt text to see what gets the best results.

The OpenAI Playground

Once you have an OpenAI account, you can use the Playground to play around with GPT-3This is the best way to get started exploring the API. It simply includes a text box where you write the prompt, and sliders on the side to change the parameters used for generation. The OpenAI docs have some great pointers on designing your prompt text.

The Playground also has a cool feature that allows you to grab some Python code you can run, using OpenAI's Python library, for whatever you used the Playground for.

GIF showing how to export code in the OpenAI playground

We won't be using Python in this tutorial, but as seen in the gif, it's possible to use the playground to structure an HTTP request to accomplish the same thing in any other language.

Using Node.js to generate text with GPT-3

Let's continue by writing some JavaScript code for what we were doing in the Playground. Create a file called textGenerator.js in the same directory as your package.json file and add the following code to it:

const got = require('got');

async function generate(prompt) {
  const url = 'https://api.openai.com/v1/engines/davinci/completions';
  const params = {
    "prompt": prompt,
    "max_tokens": 160,
    "temperature": 0.7,
    "frequency_penalty": 0.5
  };
  const headers = {
    'Authorization': `Bearer ${process.env.OPENAI_SECRET_KEY}`,
  };

  const response = await got.post(url, { json: params, headers: headers }).json();
  output = `${prompt}${response.choices[0].text}`;
  return output;
}

module.exports = { generate };

I'm in a thrash metal mood today, so let's generate some Megadeth lyrics this time. Test this code by opening a node shell (run node in your terminal in the same directory your code is in) and pasting the following code to it:

const generator = require('./textGenerator');

(async () => {
  try {
    console.log(await generator.generate(`Artist: Megadeth\n\nLyrics:\n`));
  } catch (err) {
    console.log(err);
  }
})();

You should see some lyrics logged to the console. The results I got involve Dave Mustaine being angry at people on his commute. Maybe it's a song he would have written on his long bus ride back to California after being kicked out of Metallica.

Generating Megadeth lyrics

You can tweak how you want GPT-3 to generate text by changing what you send in the body of your request. If you want to dig a little deeper, check out this other post about using GPT-3 with Node.js.

Creating a Twitch Chat Bot with Node.js

Now that we can generate text, let's work on creating a basic Twitch chat bot that interacts with viewers using GPT-3.

Connecting to a Twitch stream and reading chat messages

On the Twitch side of things, let's begin by making an anonymous, read-only connection to a Twitch channel's chat. No authentication credentials are needed to read messages sent to a channel, so we can just log all incoming messages with tmi.js without overcomplicating things.

Create a file called index.js in the same directory as your package.json. Add the following code to it for logging all messages sent to a given channel as they come in:

const tmi = require('tmi.js');

const client = new tmi.Client({
  connection: {
    secure: true,
    reconnect: true
  },
  channels: [ 'channel_name' ]
});

client.connect();

client.on('message', (channel, tags, message, self) => {
  console.log(`${tags['display-name']}: ${message}`);
});

Replace the channel_name with the Twitch username of whoever's stream you're testing with, and run the code with the command node index.js from your terminal. You should see messages being logged which looks something like this:

Testing the bot

Generating an Oauth token and sending messages to a channel

In order to send messages, from either your personal account or one you create specifically for your bot, you'll need a token to authenticate your chatbot with Twitch's servers. Go to https://twitchapps.com/tmi/ and log in with your Twitch credentials to authenticate TMI with your account.

After logging in, click "Authorize" and you should be given a token. Save this Oauth token you received in an environment variable to be used in your code later:

export TWITCH_OAUTH_TOKEN='oauth:YOUR_TOKEN_HERE'

You can use this token to connect to Twitch chat with tmi.js and send messages from whichever Twitch account you authenticated with.

As an example, let's try some code to respond to people who say hello. Replace the code in index.js with the following:

const tmi = require('tmi.js');

const client = new tmi.Client({
  options: { debug: true },
  connection: {
    secure: true,
    reconnect: true
  },
  identity: {
    username: 'your_username',
    password: process.env.TWITCH_OAUTH_TOKEN
  },
  channels: ['channel_name']
});

client.connect();

client.on('message', (channel, tags, message, self) => {
  // Ignore echoed messages.
  if(self) return;

  if(message.toLowerCase() === '!hello') {
    client.say(channel, `@${tags.username}, Yo what's up`);
  }
});

This time you'll have to replace your_username with whatever Twitch account you're using to test this with, preferably one you created for your bot. I am just going to use my personal account for this. To avoid being rude and testing my bot in someone else's channel, I am going to connect to my own, but if you have any friends who are streaming it can be fun to connect to their streams.

Run the code with index.js again, and try saying "!hello" in the chat to get a response:

Responding to messages in the chat

Because I am using the same account for both it may appear as if I'm talking to myself, but one of those messages is automated and one is not.

Using GPT-3 with your Twitch Chat Bot

It's time to combine all of the work we've done so far. Let's implement a Twitch chat bot command that allows the viewers of your stream to play around with GPT-3. They can give your chat bot prompt text, and have it "finish their sentences".

Change the code in your index.js to the following, which uses the module we wrote earlier for generating text:

const tmi = require('tmi.js');
const generator = require('./textGenerator');

const reputation ={};
const client = new tmi.Client({
  options: { debug: true },
  connection: {
    secure: true,
    reconnect: true
  },
  identity: {
    username: 'your_username',
    password: process.env.TWITCH_OAUTH_TOKEN
  },
  channels: [ 'channel_name' ]
});

client.connect();

client.on('message', (channel, tags, message, self) => {
  if(self || !message.startsWith('!')) {
    return;
  }

  const args = message.slice(1).split(' ');
  const command = args.shift().toLowerCase();

  if(command === 'hello') {
    client.say(channel, `@${tags.username}, Yo what's up`);
  } else if(command === 'generate') {
    (async () => {
      const prompt = args.join(' ');
      client.say(channel, `@${tags.username}, ${await generator.generate(prompt)}`);
    })();
  }
});

Run the code again with node index.js, connect to your Twitch chat, and try sending a message that starts with "!generate" followed by the prompt text you want to feed to GPT-3.

Here's an example where I am getting GPT-3 to generate some Dragonball Z dialogue and talk about Pokemon in my Twitch chat.

Generating text with GPT-3 in the chat

The Next Level

We've covered some of the basics of creating a Twitch chatbot for you and your friends' channels as well as generating text with GPT-3 and combining the two. You can continue working on this by interacting with other APIs such as Twilio Programmable Messaging, or adding new features that your friends think would be useful.

Feel free to reach out if you have any questions or comments, or just want to show off any cool things your Twitch bot can do.