How I Created A Lyrics Generator

Using AI To Write A Hit Song

Eric Borgos
Towards Data Science

--

Lyrics Generator
image: IB306660, via pixabay.com (CC0)

There are many lyrics generators online, and while they are fun to fool around with, the songs they create just don’t make much sense. As a real human songwriter (I have written over 100 songs), I figured there must be a better way to do it, so I decided to build my own using the latest advances in machine learning. There is no good method to teach an AI the concept of a “song,” but it can be trained using NLP to imitate whatever text you show it. I fed it lots of songs to learn from, and eventually, it was able to output lines that sounded coherent. Overall the project involved around 50 hours of programming, but the end result was worth it: https://boredhumans.com/lyrics_generator.php.

Here are the details on how I did it:

I started by fine-tuning GPT-2, which is an open-source language model trained on over 8 million web pages to predict the next word in the text. To do this, I used GPT-2 Simple (it has a link where anyone can run it on a free GPU via Google Colab) with a database of 13,000 poems. I was originally going to train it on a database of 400,000 song lyrics that I downloaded, but many of those had swears, sexual content, drug references, and other stuff not appropriate for kids, and I didn’t want my model to learn all that. Plus I wanted my version to sound “smarter” than the other sites, so using poetry instead seemed like a better plan.

Once I had it working well to create poetry, I then fine-tuned it even more on 7,000 song lyrics from artists I consider poetic (such as Bob Dylan, U2, Taylor Swift, and several dozen more). But the result of that was still poetry, so I added a bunch of non-ML post-processing steps to make it look more like song lyrics. After GPT-2 produces the raw content, I use the first 6 lines and call that the “Verse 1”, then the next 4 lines are the “Chorus,” then the next 6 lines as “Verse 2”, and then to make the chorus sound like a chorus, I repeat the first chorus again. I also make all sorts of other small adjustments like filtering out r-rated content, deleting the last line of the raw lyrics because most of the time it is unfinished (cut off), and getting a whole new set of lyrics if the song becomes too short after all the deletions. Sometimes it has phrases like [Repeat Chorus] or (instrumental break), which are no good, so I automatically delete those lines also. All of these tasks were accomplished with simple PHP programming such as using str_replace to get rid of various characters I didn’t want to show up:

$title = str_replace("/", "", $title);

and this for deleting lines that are repeated too much:

// find repeated lines
for ($i = 0; $i < count($words); $i++) {
if (str_word_count($words[$i])) {
if ($counts[$words[$i]] > 5) array_push($repeated_lines, $i);
}
}
// remove repeated lines
for ($i = 0; $i < count($repeated_lines); $i++) {
if ($i > 3) {
unset($words[$repeated_lines[$i]]);
}

Figuring out the best way to give each song a title turned out to be much harder than I anticipated. It sometimes is hard for human songwriters to do this, and I am not sure an ML model could be trained to do a good job for it, so instead, I choose to create some hard-coded rules to pick the title. I mainly use whatever line is repeated the most , but with limits that it can’t be too short or too long.

One reason all of this became complicated is that it is a website, not just a plain Python program. Simply figuring out the best way to deploy the Python ML model to the web was an ordeal because it was slightly too big for Google Cloud Run or AWS Lambda, and running it on a regular AWS server would be too expensive. I ended up using AWS LightSail, which is like a regular web host (such as DigitalOcean) but still has many of the advantages of regular AWS.

Also, once the model was deployed, more work was needed to actually make it function as a website, using PHP and JavaScript/Ajax. And I had endless CORS cross-domain issues getting my PHP page to work with the REST API feed of the ML model (which uses Starlette/uvicorn [similar to Flask]). It involved fixes like adding lines such as these to the Python API part:

middleware = [Middleware(CORSMiddleware, allow_origins=['*'])]# Needed to avoid cross-domain issues
response_header = {'Access-Control-Allow-Origin': '*'}

and referencing my server’s SSL certificate like:

if __name__ == '__main__':
uvicorn.run(
app,
host='0.0.0.0',
port=int(os.environ.get('PORT', 6006)),
ssl_version=ssl.PROTOCOL_SSLv23,
ssl_cert_reqs=ssl.CERT_OPTIONAL,
ssl_keyfile="./ssl/server.key",
ssl_certfile="./ssl/server.crt"
)

My plan is to eventually add AI-generated music and AI-generated vocals to the lyrics. I have already experimented with state-of-the-art audio programs such as Google’s Magenta , and while it does output nice music, it is nowhere near the level of what is needed to create a real song. And adding vocals is even harder because, in addition to trying to make it sound like a singer instead of just a generic computer voice, the words have to be timed to go with the melody/music. Ideally, all of this can be automatically generated to go with the AI lyrics, and I then will have a complete song from start to finish, so that is what I will be working on next.

--

--

I am the owner of Impulse Communications, Inc. which is a 25 year-old Internet company specializing in artificial intelligence and website development.