Building a Punk Lyrics Bot in Python with OpenAI's GPT-3 and Twilio SMS

October 14, 2020
Written by
Sam Agnew
Twilion

Copy of Generic Blog Header 1(2).png

In the midst of pandemic-related lockdowns, many people around the world miss seeing their favorite bands. What if you could bring the anti-authoritarian, do-it-yourself ethos of punk rock home in the form of new song lyrics created by your Python code?

OpenAI's new GPT-3 (Generative Pre-trained Transformer 3) model was trained on a massive corpus of text making it incredibly powerful. This can be used to generate song lyrics with surprisingly little input text given to it as a prompt.

Let's walk through how to create a text-message powered bot to write Punk songs in Python using Twilio Programmable Messaging and OpenAI's API for GPT-3.

STAGE DIVE

Before moving on, you'll need the following:

Introduction to 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 by giving it a tiny amount of input. Simply providing a format like you'd see on a lyrics website with an artist name can potentially generate lyrics in the style of that artist. For example, here's what it generates with the input "Artist: Bad Brains\n\nLyrics:\n":

Computer-generated Bad Brains song

Bad Brains is one of the classic early hardcore punk bands, which is my favorite iteration of the genre. They did sing a lot about having a positive mental attitude, so these lyrics seem to fit that. Let's try another classic band, Black Flag:

Computer-generated Black Flag song

Yeah that kind of sounds like something Henry Rollins would write.

As mentioned above, 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.

Once you have an OpenAI account, you can use the Playground to play around with GPT-3 by typing in text and having it generate more 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.

How to export Playground code

Working with GPT-3 in Python using the OpenAI helper library

To test this out yourself, you'll have to install the OpenAI Python module. You can do this with the following command, using pip:

pip install openai==0.2.4

Now create an environment variable for your OpenAI API key, which you can find when you try to export code from the Playground:

export OPENAI_API_KEY='YOUR_API_KEY_HERE'

We will access this in our Python code. To try this out, open a Python shell and run the following code, most of which I took directly from the Playground:

import os
import openai

openai.api_key = os.environ.get("OPENAI_API_KEY")
prompt_text = "Artist: Bad Brains\n\nLyrics:\n"

response = openai.Completion.create(
  engine="davinci",
  prompt=prompt_text,
  temperature=0.7,
  max_tokens=256,
  frequency_penalty=0.4
)

print(prompt_text + response['choices'][0]['text'])

This code uses Bad Brains again, but you can try it with any of your favorite bands. For the sake of variety I am going to use D.R.I., the fastest band around at the time, for this example. You should see something like this printed to your terminal:

Computer-generated D.R.I. song

Let's change the code to begin the prompt with a randomly selected band:

from random import choice
import os
import openai

bands = ['Bad Brains', 'Black Flag', 'D.R.I.', 'Crass', 'Subhumans', 'Dead Kennedys']

openai.api_key = os.environ.get("OPENAI_API_KEY")
prompt_text = "Artist: {}\n\nLyrics:\n".format(choice(bands))

response = openai.Completion.create(
  engine="davinci",
  prompt=prompt_text,
  temperature=0.7,
  max_tokens=256,
  frequency_penalty=0.4
)

print(prompt_text + response['choices'][0]['text'])

Run this code a few times to see what happens. You might have to try it a few times before getting a good one.

Configuring a Twilio phone number

Before being able to respond to messages, you’ll need a Twilio phone number. You can buy a phone number here.

We're going to create a web application using the Flask framework that will need to be visible from the Internet in order for Twilio to send requests to it. We will use ngrok for this, which you’ll need to install if you don’t have it. In your terminal run the following command:

ngrok http 5000

ngrok terminal screen

This provides us with a publicly accessible URL to the Flask app. Configure your phone number as seen in this image so that when a text message is received, Twilio will send a POST request to the /sms route on the app we are going to build, which will sit behind your ngrok URL:

Configuring your Twilio number

With this taken care of, we can move onto actually building the Flask app to respond to text messages with some AI-generated punk songs!

Responding to text messages in Python with Flask

So you have a Twilio number and are able to have the OpenAPI generate songs.

Before moving on, open a new terminal tab or window and install the Twilio and Flask Python libraries with the following command:

pip install twilio==6.44.2 Flask==1.1.2

Now create a file called app.py and add the following code to it for our Flask application:

import os
from random import choice

import openai
from flask import Flask
from twilio.twiml.messaging_response import MessagingResponse

openai.api_key = os.environ.get('OPENAI_API_KEY')

bands = ['Bad Brains', 'Black Flag', 'D.R.I.', 'Crass', 'Subhumans', 'Dead Kennedys']


app = Flask(__name__)


@app.route('/sms', methods=['POST'])
def sms():
    prompt_text = 'Artist: {}\n\nLyrics:\n'.format(choice(bands))

    response = openai.Completion.create(
      engine="davinci",
      prompt=prompt_text,
      temperature=0.7,
      max_tokens=256,
      frequency_penalty=0.4
    )

    story = response['choices'][0]['text']
    print(story)

    twiml_resp = MessagingResponse()

    # Respond with the full text including the initial prompt,
    # up until the last line break, just in case it was incomplete.
    twiml_resp.message(prompt_text + story[:story.rfind('\n')])

    return str(twiml_resp)


if __name__ == '__main__':
    app.run(debug=True)

This Flask app contains one route, /sms, which will receive a POST request from Twilio whenever a text message is sent to our phone number, as configured before with the ngrok URL.

A few changes were made to the OpenAI API code. First, we are having it generate only 128 tokens, because we are using the davinci engine, which is the most advanced model. This can potentially take a lot of time to generate text, so keeping the number of tokens small will make sure the HTTP response to Twilio doesn't timeout.

Save your code, and run it with the following command:

python app.py

Because we have ngrok running on port 5000, the default port for Flask, you can now text it and receive some hilarious or questionably sensical punk lyrics. Sometimes you get anti-war anthems:

Computer-generated Subhumans song

And sometimes you get meme-worthy, plagiarized gems:

Computer-generated Smash Mouth song

I'm pretty sure the Dead Kennedys didn't write that one!

Sailin' on

Hopefully you've had fun generating new Punk songs with code. You can do this with any form of music by just replacing the bands in the Flask app with your favorite artists. My good friend Brodan wrote a similar post about generating metal lyrics, which inspired me to write this one.

In terms of technical changes you can also experiment with generating more tokens, and making up for the added time that takes by using Redis Queue to send a text message asynchronously when generation is finished, rather than risking a timeout by responding to Twilio's HTTP request right away with TwiML.

If you want to do more with Twilio and GPT-3, check out this tutorial on how to generate Dragon Ball fan fiction.

Feel free to reach out if you have any questions or comments or just want to show off any songs you generate.