Empowering GPT: A Technical Guide to Fine-tuning with Custom Data

Empowering GPT: A Technical Guide to Fine-tuning with Custom Data

While GPT and ChatGPT are already powerful on their own, they are limited in that the training data is not up to date and could be missing information on niche topics. I wanted to learn how to easily train a GPT model using arbitrary, custom data, so I did. Next, I decided to document the process for other people to use.

In this tutorial you’ll learn how to fine-tune GPT with your own custom data from scratch.

To view the final codebase for this tutorial, click here.

API

The OpenAI GPT APIs and SDKs make it easy to fine-tune a model using either Python, Node.js, or just an HTTP request. There are also quite a few community-maintained libraries for other languages like PHP and Ruby.

In this tutorial we’ll be using the OpenAI Node.js SDK. This SDK is simple to use and allows you to make API calls to OpenAI in just a couple of lines of code.

For instance, to retrieve a completion we can just call the createCompletion method:

const response = await openai.createCompletion({
  model: 'davinci',
  prompt: "What is Lens Protocol",
  max_tokens: 200
})

In our case, we’ll just be replacing the davinci model with our own model that will use our custom data set we’ve uploaded for training.

Prerequisites

To follow along with this tutorial, you’ll need to have the following installed on your machine:

  • Python

  • Node.js

You’ll also need an OpenAI API Key. You can get one at https://openai.com.

Getting started

To get started, we’ll create a new Node.js project in an empty directory:

mkdir custom-ai-model
cd custom-ai-model
npm init --y

Update the new package.json file to use ES Modules by adding this line of configuration:

"type": "module",

Next, set the environment variable to hold your OpenAI API Key. You can set this in your terminal session or in a configuration file like .bashrc or .zshrc:

export OPENAI_KEY="your-api-key"

Next, we’ll install the openai npm package:

npm install openai

Finally we’ll install the OpenAI CLI and the OpenAI datalib:

pip install --upgrade openai openai"[datalib]"

Now we’re ready to start writing some code!

Creating the training data

There are a handful of models available from OpenAI, but when fine-tuning the original GPT-3 base models are currently the only models available to start from, like davinci, curie, babbage, and ada. We’ll be using davinci.

Your data needs to be created in a JSONL document in the following format, with each declaration separated in a new line:

{"prompt": "<prompt text>", "completion": "<ideal generated text>"}
{"prompt": "<prompt text>", "completion": "<ideal generated text>"}
{"prompt": "<prompt text>", "completion": "<ideal generated text>"}

It is recommended to provide at least a few hundred of these examples, most sources recommending 500 or more.

In my experience, creating a few dozen inputs will at least give you some basic result that you can test out in this tutorial, but it is not enough to use as a production ready product.

From the docs: … performance tends to linearly increase with every doubling of the number of examples. Increasing the number of examples is usually the best and most reliable way of improving performance.

Once you’ve created your document, OpenAI provides a command line utility which will improve the format of your data and is recommended to run before you upload.

openai tools fine_tunes.prepare_data -f <LOCAL_FILE>

You can view, and even copy and use, my example data set here for this tutorial.

Once your data set is ready, we can create a script to upload it to OpenAI.

Creating the API interface

This file will define the API that we’ll be using to interact with the OpenAI APIs.

Since we’ll be re-using this code over and over, we’ll separate it into it’s own file and just import it into our other files.

Create a file named api.js and add the following code:

/* api.js */
import { Configuration, OpenAIApi } from 'openai'
const openaiApiKey = process.env.OPENAI_KEY
const configuration = new Configuration({
  apiKey: openaiApiKey
})

export const openai = new OpenAIApi(configuration)

Uploading the training data

Now that we’ve created the API, we can use it to upload our file to use later.

Create a file named uploadFile.js and add the following code:

/* uploadFile.js */
import { openai } from './api.js'
import fs from 'fs'

async function upload() {
  try {
    const response = await openai.createFile(
      fs.createReadStream('./data_prepared.jsonl'),
      "fine-tune"
    );
    console.log('File ID: ', response.data.id)
  } catch (err) {
    console.log('err: ', err)
  }
}

upload()

Next, run the script:

node uploadFile.js

When the upload is complete, take note of the the File ID that is logged out, we’ll be needing it in the next step.

Creating the Fine Tune

Now that we’ve uploaded the training data and have the file ID, we can use it to custom train our model.

To do so, create a new file named createFineTune.js and add the following code:

/* createFineTune.js */
import { openai } from './api.js'

async function createFineTune() {
  try {
    const response = await openai.createFineTune({
      training_file: 'your-file-id',
      model: 'davinci'
    })
    console.log('response: ', response)
  } catch (err) {
    console.log('error: ', err.response.data.error)
  }
}

createFineTune()

Next, execute the script to start fine tuning your model:

node createFineTune.js

Listing your Fine Tunes

Once the fine tune is created, it will take some time to process. We can get the status of the fine tune, as well as the model ID, by calling the listFineTunes API method.

Create a new file named listFineTunes.js and add the following code:

/* listFineTunes.js */
import { openai } from './api.js'

async function listFineTunes() {
  try {
    const response = await openai.listFineTunes()
    console.log('data: ', response.data.data)
  } catch (err) {
    console.log('error:', err)
  }
}

listFineTunes()

Run the script.

node listFineTunes.js

It will take the process a few minutes to finish. Once the process is completed and you run the script again, you should see the fine_tuned_model field populated with the new model ID.

Take note of this fine_tuned_model ID, you’ll need it in the next step.

Testing it out

Now that the fine tune has processed and our. new model is ready, we can try it out!

Create a new file named createCompletion.js. Here, add the following code. Be sure to update the fine_tuned_model value with your model name:

/* createCompletion.js */
import { openai } from './api.js'

async function createCompletion() {
  try {
    const response = await openai.createCompletion({
      model: 'your-custom-model-name',
      prompt: 'What is Lens Protocol',
      max_tokens: 200
    })
    if (response.data) {
      console.log('choices: ', response.data.choices)
    }
  } catch (err) {
    console.log('err: ', err)
  }
}

createCompletion()

Run the script:

node createCompletion.js

🎉 Congratulations

You’ve successfully deployed your own custom model using GPT3!

To view the final codebase for this tutorial, click here.