Intro to AI Engineering with Python (2/6) – Exploring Other AI APIs by OpenAI

Hello and welcome back to part 2 of the Introduction to AI Engineering series. In this part, we’ll take a look at some other exciting APIs in the AI space, as there is much more out there than just ChatGPT.

Image generation using DALL-E

Let’s start with a look at image generation. We’ll be looking at DALL-E, which is an AI model that can generate images from textual descriptions. There are many AI image generators out there nowadays, but the process for using them will be roughly the same.

So let’s have a look at the sizing and price options we have available:

As you can see, we have both Standard and HD quality options available, with sizes either 1024x1024, 1024x1792, or 1792x1024. Depending on the choices we make the costs are anywhere between $0.04 to $0.12 per image. Now this may seem somewhat costly, but generally, you won’t really need the HD option (there is not a huge difference) and you can often get away with a 1024x1024 image. $0.04 for instant on-demand artwork is not too bad!

So let’s see how to use the API and create some cool images. Start by creating a new file called generate_image.py in your project root folder:

πŸ“ Intro_to_AI_engineering
    πŸ“„ .env
    πŸ“„ chat_gpt_request.py
    πŸ“„ generate_image.py     ✨ New file
    πŸ“„ text_to_summarize.txt

Now open the generate_image.py file and add the following code:

import os

from openai import OpenAI
from dotenv import load_dotenv

load_dotenv()
CLIENT = OpenAI(api_key=os.getenv('OPENAI_API_KEY'))

You will probably notice something interesting. The imports and setup we are doing here are exactly the same as in the first tutorial. We are using the same OpenAI class, and loading our API key using load_dotenv again, passing it into the CLIENT object we create. This is because OpenAI provides a unified interface for all their APIs, which is really convenient.

As the steps we’ll be taking will be reasonably similar to last time for ChatGPT, let’s step it up a notch and make this version a bit nicer using a function. Add the following code to the generate_image.py file:

def generate_image(image_description):
    response = CLIENT.images.generate(
        model="dall-e-3",
        prompt=image_description,
        n=1,
        size="1024x1024"
    )

    image_url = response.data[0].url
    print(f"Generated image: {image_url}")
    return image_url

We define a function generate_image that takes an image_description as input. We then call the CLIENT.images.generate method, which is conveniently also provided for us in the CLIENT object, and does exactly what the name suggests.

For the model, let’s use the latest version of DALL-E, which is dall-e-3 at the time of writing. We pass in the image_description as the prompt for this model, and request n=1 (number = 1) image to be generated. We also specify the size of the image we want, which in this case is 1024x1024.

The response object will contain a bunch of data, just like last time with the ChatGPT response. We’ll have to dig in a little bit to find the URL that we want. Without going into too much detail here (see other courses for more on this), we can access the URL of the generated image by accessing the url attribute of the first item in the data list, so response.data[0].url will give us the URL to our image.

Finally, we print out the URL to the terminal and return it as the output of the function. This url is hosted on OpenAI’s servers and you can click the link to see and download your image.

Now let’s make this into a runnable script so we can actually use the function we just wrote. Below the generate_image function, add the following code:

if __name__ == "__main__":
    image_description = input("Enter a description of the image you want to generate: ")
    generate_image(image_description)

The if __name__ == "__main__": block might look a bit confusing. There is no need to fully understand why it works here, as long as you know what it does. It basically means that the code inside this block will only run if you run the script directly, and not if you import it into another script. This is a common pattern in Python scripts.

What this will let us do is basically run this Python file as a script directly, in which case the code inside this block will be executed. The input function will prompt the user to enter a description of the image they want to generate in the terminal. We save whatever the user types in a variable called image_description.

We then call our generate_image function with this description of the image to generate as input, after which point our function will run and generate the image, printing the URL to the terminal.

So give it a test run just like our ChatGPT script last time, by either using the terminal window or the play button in VSCode. You should see your prompt question pop up in the terminal as we invoked the input function:

Enter a description of the image you want to generate:

So type anything and then press enter. You’ll get a response with the URL to your generated image. Click the link to see your image!

Enter a description of the image you want to generate: Japanese anime typical old fashioned street in the sunset art
Generated image: https://url.here.net/verylongurlhere

Here is what I got for my old-fashioned Japanese sunset street in anime style:

That looks pretty darn cool! It does look like a scene straight out of an anime. As this is an introduction-level tutorial we don’t have too much time to go into specific details, but let’s take it a step further before we move on and at least have the images automatically downloaded to our computer.

Downloading the image

First create a new folder named output in your project root folder:

πŸ“ Intro_to_AI_engineering
    πŸ“ output     ✨ New folder
    πŸ“„ .env
    πŸ“„ chat_gpt_request.py
    πŸ“„ generate_image.py
    πŸ“„ text_to_summarize.txt

This is where we will be saving our images. Now inside the generate_image.py script, we first need to add two new imports up top:

import os
import uuid # New import
import requests # New import

from openai import OpenAI
from dotenv import load_dotenv
... rest of the code ...

The requests library will allow us to have Python make an internet request to the URL we receive on our behalf, so we can download the image automatically. The uuid library helps us generate a unique name for the image file so we don’t overwrite existing files.

Now scroll down a bit and directly after the generate_image function but before the if __name__ == "__main__": block, add the following new function:

def download_and_save_image(url):
    response = requests.get(url)
    image_name = uuid.uuid4()
    image_path = os.path.join("output", f"{image_name}.png")

    with open(image_path, "wb") as file:
        file.write(response.content)

    print(f"Image saved to {image_path}")

    return image_path

We name this function download_and_save_image and it takes a url as input. We then use the requests.get function to make a request to the URL and get the image data, which we save in the response object.

We create a unique name to save the file (to avoid conflicts and overwriting existing files) using the uuid library. This will simply generate a random unique string for us.

After this we use the os (operating-system) library to create a file path using path by joining (join) the string "output", referring to the output folder we created before, with the unique string, and adding the .png extension. This is now a valid path we can use as a location to save the image.

Now we use the with open trick from part 1 again, and as we already have our path created we can just pass in image_path as the first argument. We open the file in write-binary mode (