Generating Cooking Recipes with OpenAI's GPT-3 and Ruby
Time to read: 7 minutes
I enjoy cooking. When I decide to make a new recipe I typically go hunting for that perfect variation of a dish. Often this leads to food blogs. One of the things about food blogs that I find interesting is the need for the author to write a lengthy backstory on why a given recipe means so much to them. The enthusiasm for their recipes gave me the inspiration to make parody recipes using that same voice. The twist: let artificial intelligence do the heavy lifting.
Sloppy Joe Waffles:
What’s better than a sloppy joe? Sloppy joe waffles! These sloppy joe waffles are so so good! They’re almost like a cross between a sloppy joe and a classic waffle. They’re warm, hearty, and just all around delicious food meets breakfast food.
I’m a bit obsessed with the idea of breakfast for dinner. I love to make breakfast foods and dinner foods. They’re just so good. Spanakopita and breakfast tacos are among my favorite things to make for dinner. Like those, these sloppy joe waffles are complete comfort food. They’re warm, hearty, and so so good.
The possibilities for these sloppy joe waffles are endless. If you’re not a fan of sloppy joes, you can always make the waffles without the sauce and it’ll be just as delicious. No worries if you don’t have time to make the sloppy joe sauce. You can just serve the sloppy joe waffles with ketchup or hot sauce. They’re simple and delicious no matter what.
Ingredients:
Sloppy Joe filling, waffles, cheese, butter, green onions, ketchup, mustard
Recipe:
1. Heat waffle iron.
2. Spread a generous amount of ketchup and mustard onto the waffle.
3. Add a layer of cheese.
4. Add a layer of Sloppy Joe filling.
5. Add a layer of green onions.
6. Top with another layer of cheese.
7. Top with another layer of Sloppy Joe filling.
8. Top with another layer of green onions.
9. Close the waffle iron and cook until the cheese is melted and the waffle is golden brown.
10. Serve with a side of extra ketchup and mustard.
What is GPT-3?
I generated that story and recipe using the latest and greatest in AI technology: the GPT-3 API from OpenAI. I’ll show you how to build a simple app to create recipes and food journals just like this one. GPT-3 (Generative Pre-trained Transformer 3) is a model that was trained on a very large amount of text. In other words, it knows how people write and is very good at picking up written patterns based on user entry. It is surprisingly easy to use: you feed it some text and the model generates more text following the existing pattern and structure.
In high school English class one day I had access to the department computer lab to work on a poem writing assignment. After completing the task I goofed around online by generating new “poems”. This was done by writing sentences, throwing them through multiple translation sites, and seeing how “poetic” the mangled lines became. With GPT-3 I can generate poems with considerably less effort.
To get started we feed the GPT-3 API a prompt:
The AI detected the pattern that I supplied: a title, followed by a poem. By supplying a title at the end of the prompt, the API generated the poem based on that title, which is referred to as the “completion”.
In fact, all the poems provided for this example prompt were in turn created by GPT-3 based on real poems given as a prompt. How cool is that?
GPT-3 is non-deterministic, so you can supply the same prompt multiple times and get unique output each time. Here are a couple alternative versions of “Goose on the Loose”. Note that each generated poem is completely different from one another:
The pattern detection isn’t perfect. I initially set out to make haikus, but it failed to consistently create the 5-7-5 syllable pattern. It won’t be the last time technology has let me down.
Now that you understand how GPT-3 works let's get building.
Tutorial Requirements
To follow this tutorial you need to have the following:
- Ruby 2.0.0 or higher. To install refer to the instructions on ruby-lang.org.
- I recommend using a manager such as rbenv to handle your installation. This will allow for a user level install and you can avoid using sudo!
- An OpenAI API key. Request beta access here.
Creating Recipes with GPT-3 and Ruby
In this tutorial we will build an application that takes just a recipe name and generates a backstory and recipe.
Setup
First things first, let's create a new directory for our project and set up some dependencies.
If you are using a Unix or Mac OS system, open a terminal and enter the following commands to do the tasks described above:
If you are using Windows, enter the following commands in a command prompt window:
Open up your favorite code editor and create the file Gemfile
:
Save and go back to your terminal to install those gems.
Now create a .env
file and add in your OpenAI API key like so:
Create a Class to Communicate With OpenAI
Since OpenAI doesn’t have a Ruby client we are going to build a class to support our efforts.
To do that lets first create a new file named openai.rb
and put it in a new lib
directory.
With the editor of your choosing, open the newly created file and insert the code below.
The OpenAI endpoint takes a number of parameters, but we are focused on four for our method:
prompt
- the text we feedmax_tokens
- approximately the max amount of words we want returnedtemperature
- 1.0 means creative whereas 0 means a well defined answerstop
- where we want the completion to stop generating text
Now that we have a class set up to interface with the OpenAI API lets create a class to build a recipe based on ingredients!
Create a Class to Generate a Recipe
Again open up your editor and create a new file in lib
named recipe.rb
Now that we have created the file we want to build a method to generate a recipe based on a recipe name. We are going to be doing a few different things here let’s take this step by step.
Now we can create a method to actually generate the recipe. I am using memoization to store the result of our query to the OpenAI completion API endpoint. As mentioned earlier, “completions” are non-deterministic so if we want to reference this data again we need to store it.
We are setting the temperature to 0.4 as we want the recipe to be somewhat creative, but more deterministic based on our input. max_tokens
should be set high so we can ensure a complete recipe. To ensure that the “completion” doesn’t continue to generate new recipes we need to tell it to stop at “Name:”. That will ensure that we only get the body of the recipe. Finally we need to supply a prompt.
The prompts for this project are quite large so I decided to store them in a yaml file. I could have stored the text as a text file, but because we will have two prompts I decided a yaml file was more fitting for this project. One prompt for our backstory and another for our recipe. As you can see in the recipe_prompt
method we are loading a prompt file and then accessing the prompt by its key. We are also adding our recipe name and a new line to match the pattern of the prompt.
Before we try this out we need to create our prompts.yml
file.
Now that we have our YAML file with our prompts lets test the method in IRB via the terminal.
Delicious. Next we will craft a story for this recipe.
Create a Class to Generate a Recipe Story
The great news here is that this class will look and behave much like our Recipe class.
Open up your editor and create recipe_story.rb
in the lib
directory.
Now add the following code:
This time around I decided to make the temperature 0.8. This allows the completion to be more creative, but still ensuring I get the general style I am aiming for.
As you can see there is some duplication which presents a great opportunity to clean up our code.
Create a base class in lib
called recipe_base.rb
that our recipe classes can inherit from:
Extract all the common code between our two classes:
Finally lets update our recipe classes to utilize the base class and remove duplicate code. Here is the updated lib/recipe.rb
:
Tying it Together With a User Interface
It is all coming together now. We have our class to interface with the OpenAI API, we have our builder classes which output recipes and stories, and now we need to create a simple user interface for generating some delicious meals.
Time to go back to your editor and create recipe_generator.rb
.
In this class we are pulling in two new libraries: tty-prompt and titleize. tty-prompt
will allow the user to enter their recipe name in the prompt. titleize
ensures that the recipe name is properly capitalized for our input.
Outside of our class we are going to call RecipeGenerator.run
. Doing so will allow us to run our generator simply by opening the file with ruby. Inside of the run class method we are setting up the prompt, getting the user input, creating an instance of RecipeGenerator, and displaying the recipe to the user.
Time to try it out! In terminal enter:
Conclusion
While the last few months have been primarily monotonous through the pandemic, I want to thank Twilio and OpenAI for giving me the opportunity to explore this amazing technology. I had a ton of fun building this tutorial and learning about OpenAI’s GPT-3 API, and I hope that you did as well. If Ruby is not a language in your toolbelt, I hope you enjoyed seeing how it can be used.
If you liked this project, check out my blog https://soullessfood.com/, in which I post made-up recipes I generated. And if you want to use it as a resource, the full source code can be found on my GitHub.
This is a small example showcasing the power of GPT-3 and I hope you get the opportunity to build something amazing with it. If you do send me a message at @drewbaumann on Twitter.
Drew Baumann is the CTO of Repeat (We are hiring!). If you want to work with him on fun projects reach out to drewbaumann [at] gmail [dot] com.
Related Posts
Related Resources
Twilio Docs
From APIs to SDKs to sample apps
API reference documentation, SDKs, helper libraries, quickstarts, and tutorials for your language and platform.
Resource Center
The latest ebooks, industry reports, and webinars
Learn from customer engagement experts to improve your own communication.
Ahoy
Twilio's developer community hub
Best practices, code samples, and inspiration to build communications and digital engagement experiences.