If you’ve signed up for OpenAI and gotten your free trial money and API key, you’re ready to start putting it good use! If you haven’t done that yet, I’ve previously walked us through how to sign up and generate and API key. You’ll find a link to the article in the requirements below.
Luckily, OpenAI has a Python package that makes interacting with their API super easy. We’re going to walk through creating your first Python script to get you started on your AI journey.
Requirements
You’ll need an OpenAI API key as well as some money in the account (at the time of writing this, a free signup comes with an $18 grant)
pip install openai
OpenAI Text Completion Method
The API you’re most likely to start playing with from OpenAI is the text completion API, since that is probably the most similar to how you’ve been using ChatGPT. Text completion can do a variety of things for you including writing content, analyzing the sentiment of text, or summarizing text that you feed it.
We’re going to keep it simple for the first script and just set up the code so you can play with the prompts later.
Import the Modules
My goals with this were to create a repeatable or even importable script, so I’m actually importing more than you truly need to get started, but I’ll cover what I’m doing with the other modules later.
import openai
from types import SimpleNamespace
import json
Authenticate the API Key
If you followed my instructions from the previous article and saved api-key.txt
in the same folder where you’re writing this Python script, authenticating the API key will be very simple.
It’s a good practice not to code your API key into your script since you might mistakenly publish it to a Git repository or share your script with someone and it inadvertently becomes publicly available.
with open('api-key.txt', 'r') as f:
openai.api_key = f.read()
Set Up the Models
This is a bit extra work from what you really need to do to make your first call, but I like to build for future reproducibility. Not every task I have for GPT-3 requires the smartest (and most expensive) DaVinci model. I am also building in the Code completion Codex models, which you don’t need for this exercise.
I use a nested Python dictionary for this.
models = {
'text': {
'best': 'text-davinci-003',
'better': 'text-curie-001',
'good': 'text-babbage-001',
'base': 'text-ada-001'
},
'code': {
'best': 'code-davinci-002',
'base': 'code-cushman-001'
}
}
You could stop here and use bracket notation to call the models, but for whatever reason I wanted to use dot-notation.
This is the extra step I referred to in the imports. If you want to skip this part, you can skip the two additional imports from above.
models = json.loads(json.dumps(models), object_hook=lambda item: SimpleNamespace(**item))
Without getting into exactly what that line is doing, it allows me to use models.text.best
to call the value "text-davinci-003"
instead of using models['text']['best']
. I wanted to explain this in case you wanted to omit this part of your code because you’ll have to modify some of the rest of the code I’ll be providing.
Defining the Function to Generate Text
When defining the function, we are going to be asking for two arguments: the prompt and the model. I’m also setting the default model to the smarted and most expensive, since that’s the one I have had the best results with.
def generate_text(prompt=None, model=models.text.best):
The first thing I do in the function is check if the prompt input is a string. If it’s not, I convert it to a string. If nothing is provided, I just let the None
pass through. The API will return an error since the prompt is required.
if prompt and not isinstance(prompt, str):
prompt = str(prompt)
And then we’re on to making the request to OpenAI. We’re going to be using the Completion.create()
method. It takes a handful of arguments and I’ll go over what each one means.
model
: This is the language model that we’ll be passing it. The default argument ismobels.text.best
but you can feed it a different one or even write your own string for the model. You can find all the acceptable models on the OpenAI documentation.prompt
: The prompt is a string of instructions you are asking for. You can ask for pretty much anything you want. Get creative and start thinking of projects you want to work on.temperature
: This will be a number from 0 to 2. The higher the number you put in there, the more creative the response. If the number is lower, the response will tend to stick closer to the prompt instructions. An important note is that this should be 1 iftop_p
is not 1.top_p
: This is a number between 0 and 1. It is similar to temperature but changes the sampling in a different way. It’s pretty technical and more than we need to get into for this tutorial. The important thing to remember on this is that this should be set to 1 iftop_p
is not 1. As an aside, I’ve never played with thetop_p
to change the outputs. I’m almost always playing with thetemperature
instead.max_tokens
: This is essentially how much you want to spend on the response. If this is not high enough for what you’re asking, the API will just stop its output mid-sentence. You’ll still get a response from the API but it won’t be complete.frequency_penalty
: This is a number between -2.0 and 2.0. The higher the number goes on this, the less likely the response will repeat itself.presence_penalty
: Similar tofrequency_penalty
, this is a number between -2.0 and 2.0. The higher this number goes, the more likely the model will get into different topics.suffix
: This will be what the model returns at the end of a completion. I haven’t found a reason to use this yet in my work. I suppose you could use it to append your site’s name to generated title tags, for instance.n
: The default on this is 1. This is just how many completions you want the model to create. Just remember that the higher this is, the more tokens it will use (so make sure you are appropriately setting themax_tokens
parameter.stop
: You can set up to four sequences that will cause the API to stop generating text. I haven’t found a reliable use case for this yet.
There are a few others, but those are the big ones. They are also the ones we’ll be adding to our script. You can visit the OpenAI Completion documentation to find the full list. We’re going to set the return value of the completion to a variable called response
and return response
from our function.
response = openai.Completion.create(
model=model,
prompt=prompt,
temperature=1, # if top_p is not 1.0, this should be 1.0
max_tokens=100,
top_p=1.0, # if temperature is not 0, this should be 1.0
frequency_penalty=0.2,
presence_penalty=0.0,
suffix=None,
n=1,
stop=None
)
return response
Running an Example Prompt
Now that we have our code written out, we can run the script and start feeding it prompts. I’m running it in a IPython console, so I don’t have to add these to my script. You could add these to your script if you’d like to test it that way.
>>> prompt = "Write a tweet about how amazing ShortAutomaton is at guiding Python learners to scale their work in new and interesting ways"
>>> description = generate_text(prompt)
So now we have the response saved into a variable called description
. If you look at description
you’ll find it is a dictionary. Assuming you kept n=1
, we can extract the text using the code below.
>>> print(description['choices'][0]['text'])
"Couldn't be more #impressed with ShortAutomaton! This #Python platform is paving the way for learners to scale their work & explore new, innovative ways to learn and grow. #coding #datascience #blogging"
Well, we aren’t exactly a Python platform, but that’s still nice to hear. This might need a little tweaking. What do you come up with? Tweet @ShortAutomaton with your results or how you feel about our guides!
I also like to extract the total token cost.
>>> print(description['usage']['total_tokens'])
73
Token costs are broken down into the prompt and the response, and you can extract those individually, too. Keep that in mind when you’re setting the max_tokens
. max_tokens
is only the response parameter. In my experience, the prompt has always been multiple-times more tokens than the response. A clean, expected output hinges on a smart, well-thought-out prompt.
Now you’re well on your way to scaling your work up with OpenAI’s GPT-3!
OpenAI GPT-3 Text Completion Full Code Example
# Import Modules
import openai
from types import SimpleNamespace
import json
# Authenticate API Key
with open('api-key.txt', 'r') as f:
openai.api_key = f.read()
# Set up models
models = {
'text': {
'best': 'text-davinci-003',
'better': 'text-curie-001',
'good': 'text-babbage-001',
'base': 'text-ada-001'
},
'code': {
'best': 'code-davinci-002',
'base': 'code-cushman-001'
}
}
models = json.loads(json.dumps(models), object_hook=lambda item: SimpleNamespace(**item))
# Define a function to execute OpenAI prompt
def generate_text(prompt=None, model=models.text.best):
if prompt and not isinstance(prompt, str):
prompt = str(prompt)
response = openai.Completion.create(
model=model,
prompt=prompt,
temperature=1, # if top_p is not 1.0, this should be 1.0
max_tokens=100,
top_p=1.0, # if temperature is not 0, this should be 1.0
frequency_penalty=0.2,
presence_penalty=0.0,
suffix=None,
n=1,
stop=None
)
return response
# Run script
if __name__ == "__main__":
prompt = "Write a tweet about how amazing ShortAutomaton is at guiding Python learners to scale their work in " \
"new and interesting ways"
description = generate_text(prompt)
print(description['choices'][0]['text'])
print(description['usage']['total_tokens'])
Eric is a Python SEO with a passion for data. He uses Python to automate tasks and analyze large data sets. He is often the go-to for spreadsheet challenges, too. He sees every challenge as an opportunity to learn.
Trying to run this kept giving me the following error:
ValueError: Invalid header value b’Bearer sk-……….\n
Problem was the /n on the end of the api key.
This fixed it: openai.api_key = f.read().strip()
Hi Jack. Yes, if your
api-key.txt
file has a line break at the end, you need to adapt the script. You could also usef.readlines()[0]