Joe Regenstein, CPA, FPAC

Creating a Color Palette Assistant using Flask and the ChatGPT API

Sasquatch Process In the pursuit of distinctive color palettes for the Yellowstone Sunset t-shirt collection, ChatGPT was able to convert a theme or mood into colors. The designs feature the silhouette of an animal that could be found in Yellowstone (I added a Sasquatch for fun), filled with a colorful gradient background representing the terrain and sky. The silhouettes were initially generated by MidJourney (also used for the Anaimal Aviators) and then modified using PhotoShop to create a clipping mask. The Color Palette Assistant provided the initial colors to use for the background.

The idea of the Color Palette Assistant and code snippets came from Colton Steele, whose javascript knowledge greatly improves the end-user experience. Before diving deeper into the process, explore the Color Palette Generator app hosted at Render.com and the shirt designs. If interested in the process, keep reading to see how to integrate ChatGPT into a website.

Prerequisites

Step 1: Set Up Your Development Environment

1.1 Install Visual Studio Code

If not already installed, download and install VS Code or your preferred IDE. Visual Studio Code (VS Code) is a free, open-source code editor developed by Microsoft for Windows, Linux, and macOS, designed to support various programming languages and functionalities. It boasts a rich ecosystem and an active community of developers contributing to its vast library of extensions. You can download VS Code from here. PyCharm is also a popular choice and has a free community edition here.

1.2 Install Python

Ensure that Python and pip (Python’s package installer) are installed on your machine. If not, download and install Python from here or follow the instructions for installing and using VS Code here.

Step 2: Get OpenAI GPT API Key

Sign up for API access on OpenAI. As a new API user, you should get $5 in free credit for your first 3 months, which is more than enough. Once logged in, go to your user profile in the top right corner and go to 'View API Keys.' Here, you can create a new key for accessing the API. Copy it down because you will never be able to see the entire key again. If you lose the key, you can always create a new one. We will use a .env file to store this key for our application. Never expose this key to the public; others can access the API and use your credits.

Step 3: Clone the Repository

When starting a new project in VS Code, choose Clone Git Repository... and enter the URL https://github.com/joereg4/colorPalette.git, and choose where to set up the project.

Alternatively, if you already have the project folder set up, navigate there in the terminal and enter this code

git clone https://github.com/joereg4/colorPalette.git

Step 4: Set Up Your Project

4.1 Select Python Interpreter

On Windows, use ctrl+shitf+p; on Mac OS, use cmd+shift+p to bring up the command line and type Python: Select Interpreter. If you correctly set up Python, a list of interpreters will appear. For this project, just use the recommended option, Python 3.9 or higher.

4.2 Install Required Packages

Using your terminal or command line, navigate to the project directory and install the necessary Python packages listed in requirements.txt. In the VS Code terminal

pip install -r requirements.txt

4.3 Setup Environment Variables

Create a .env file in the project directory to securely store your OpenAI API key. In most operating systems, any file starting with . is hidden. However, you should be able to access it in your IDE.

OPENAI_API_KEY=your_openai_api_key
FLASK_APP=app.py
FLASK_ENV=development
FLASK_DEBUG=True

Replace your_openai_api_key with the API key you obtained from OpenAI. The remaining variables are for Flask and will make it easier to see error messages and what the server does as people interact with the website. It also restarts the server if we make changes to the code. We wouldn't use the DEBUG mode in production as there is no IDE to view the messages.

The .gitignore file is crucial for specifying files or directories that should be omitted from Git tracking to prevent sensitive information, such as API keys or credentials, from being exposed in public repositories. Ensuring that .env is listed in your .gitignore file protects your secret data. In the provided .gitignore .env is already included.

Step 5: Explore the Project Files

5.1 app.py

In simple terms, app.py in a Flask application is the starting point for running your web application. It starts the application, loads configurations (such as API keys from your .env file), and ties together various components (like routes from routes.py). When you run app.py, the web server starts and waits for the user's browser requests and responds to them, making the website interactive.

5.2 routes.py

The routes.py file in a Flask application lays out the roadmap of different URLs (or "routes") and specifies the actions that should occur when each URL is accessed. It basically directs your web application by saying, "When a user visits [this URL], carry out [this function], and present them with [this result]." In the provided code, there are two key routes defined:

  1. / (the homepage): When a user visits the home URL (like http://yourapp.com/), the route associated with / determines that the index function should run, rendering and displaying the index.html template. This gives users an initial page to interact with the application, such as entering a color theme for which they want a palette.
  2. /palette: This route is linked to the prompt_to_palette function. When a user submits a form on the front end (like asking for a color palette based on a specific theme), the data is sent to this /palette URL. The prompt_to_palette function takes that input, passes it to the get_colors function (which talks to ChatGPT and gets a color palette), and returns the generated color palette to the user's browser. We'll talk more about how we interact with ChatGPT in the prompt section.

5.3 index.html

The index.html file is the front door to our web application and is the only part the user views.

The index.html serves 3 functions for our application:

  1. Content: It lays out the structure and content of the web page, defining elements like input boxes and buttons, which users can interact with. In the provided code, there's an input box for users to type a theme (like "sunset") and a button to generate color palettes.
  2. Style: It links to the cascading style sheet (CSS), which dictates how the webpage looks. CSS allows us to control the layout, colors, fonts, spacing, and the overall look of the webpage.
  3. Interactivity: It links to the JavaScript (app.js) file, which adds interactivity to the page. In the context of this app, when a user types a theme and clicks the button, the JavaScript takes that input, sends it to the server (using the /palette route defined in routes.py), receives the generated color palette in return, and then updates the page to display these colors.

5.4 app.js

The app.js isn't required, but it gives us a more sophisticated user experience. The flow begins when the form submit button is pressed.

  1. Event Listener: An event listener is set up right at the start, listening for the "submit" event on the form on the index.html. When the form is submitted, it prevents the default form submission behavior and triggers the getColors function instead. By default, when the form with the theme or mood is submitted without JavaScript's intervention, the page reloads and sends data to the server. This causes a disruption in user experience due to the visible reload.
  2. getColors(): This function retrieves the color theme input the user typed into the form and sends it to the /palette route, where we interact with the OpanAI API. It then waits for a response from the server, which will contain the generated color palette. Once the palette is received, the function updates the webpage to display the colors by calling createColorBoxes without a visible page reload.
  3. createColorBoxes(colors, parent): Given a list of color codes and a parent HTML element, this function creates a set of color boxes on the webpage. For each color code, it creates a new div element, sets its background color, and adds it to the parent element. Additionally, it allows users to click on a color box to copy the color code to the clipboard.

5.5 The Chat Prompt

When the user submits an input, we must package this up for ChatGPT and send it to the OpenAI API. This occurs when the /pallette route is chosen, which calls the get_colors() function. This function does 3 things:

  1. Message Construction: It builds the message we will send to ChatGPT.
  2. API Interaction: It sends the message and other required parameters to ChatGPT, such as the model to use.
  3. Response Handling: It then parses the ChatGPT response so we can extract the colors.

To build the message, we utilize different roles to train ChatGPT what role it plays and what we want, which in this case is 2 to 8 colors. The system role is for ChatGPT and doesn't return a response:

{"role": "system",
     "content": "You are a color palette generating assistant that responds to text prompts for color palettes.  You should generate color palettes that fit the theme, mood, or instructions in the prompt.  The palettes should be between 2 and 8 colors."},

Next, we pretend to be a user by asking it to take the verbal description The Mediterranean Sea and then pretend to be ChatGPT in the assistant role by providing the content and format we expect. We do this twice to increase the chances that ChatGPT will only respond with the hexadecimal codes. Providing example prompts is called few-shot learning. We could use zero-shot learning, which saves some money, but we risk getting a response back we can't parse. We use a short message, which has an immaterial cost and ensures our app won't break. Similar to the system role this does not generate a response since we provided the assistant role's response.

{"role": "user",
"content": "Convert the following verbal description of a color palette into a list of colors: The Mediterranean Sea"},

{"role": "assistant", "content": '["#006699", "#66CCCC", "#F0E68C", "#008000", "#F08080"]'},

{"role": "user",
"content": "Convert the following verbal description of a color palette into a list of colors: sage, nature, earth"},

{"role": "assistant", "content": '["#EDF1D6", "#9DC08B", "#609966", "#40513B"]'},

Lastly, we act as the user again by passing along the submitted theme or mood.

{"role": "user",
"content": f"Convert the following verbal description of a color palette into a list of colors: {msg}"},

Since we did not provide the assistant role's response this time, ChatGPT responds to the prompt. We take the entire response, pull out what we need, and send it to app.js, which renders the colors on the webpage.

Result

Step 6: Run the Flask App

Run the Flask application from the terminal, ensuring you are in the project directory.

flask run

Your Flask application should now be running on http://127.0.0.1:5000/. Open this URL in your browser and see the Color Palette Generator web application. To quit the application, press ctrl+c.

Step 7: Test the Application

Troubleshooting

The application is set to use the gpt-4 model; if you do not have access, simply replace gpt-4 with gpt-3.5-turbo instead. To see what models are available, go here and use the drop-down on the right-hand side of the Playground.

To change the model, find the get_colors() function in routes.py and edit the response

    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=messages,
        max_tokens=200,
    )

Conclusion

Congratulations! You have successfully set up and run a Flask application that interacts with the ChatGPT API to generate color palettes. You may now further explore and customize the application according to your needs.

#AI #ChatGPT