How to Fine-Tune an OpenAI ML Model with Node.js
Tags: machinelearning, openai, ai
Published: 2023-05-02 17:40:54

---
title: How to Fine-Tune an OpenAI ML Model with Node.js
published: true
description: Need to customize a machine learning model? Learn how to add your own data and use it to fine-tune an existing OpenAI model!
tags: ml, machinelearning, openai, ai
cover_image: https://assets.cdn.prod.twilio.com/images/ADP-6oHrDTQcjOpYYm3Qpw6AXmfnnEnQ.width-1616.format-webp.webp
# Use a ratio of 100:42 for best results.
# published_at: 2023-05-02 17:16 +0000
---
This blog post was written for [Twilio](https://www.twilio.com/) and [originally published on the Twilio blog](https://www.twilio.com/blog/finetune-openai-ml-model-node).
OpenAI, the creator of [ChatGPT](https://chat.openai.com/), offers a [variety of Machine Learning models developers can use with different capabilities and price points](https://platform.openai.com/docs/models). Their API lets developers interface with the models, adding features like text completion, code completion, text or image generation, speech-to-text, and more to their applications.

ChatGPT's model is powerful ([this Twilio tutorial went over how to Build a Serverless ChatGPT SMS Chatbot with the OpenAI API](https://www.twilio.com/blog/sms-chatbot-openai-api-node)), but still limited. This tutorial will go over how to fine-tune an existing model from OpenAI with your own data so you can get more out of it.

### What is Fine-tuning?
OpenAI's models have been trained on a large amount of text from the web, but their training data is still finite and not as current as they could be: they still miss information on specific topics.

Transfer learning is a machine learning method where you use knowledge that was gained from solving one problem and apply it to a new but related problem. A model developed for a task is reused as the starting point for a model on a second task–for example, a model trained to specifically recognize pizza could be edited to recognize calzones.

Fine-tuning is similar to transfer learning in that it lets you modify and customize an existing ML model.

### Why Fine-tune?
Fine-tuning helps you achieve better results on a wide number of tasks. Once a model is fine-tuned, you won't need to provide samples via prompt anymore, helping you save on costs and enabling lower-latency requests.

Assuming the original task the model was trained for is similar to the new task, fine-tuning a model that has already been designed and trained allows developers to take advantage of what the model has already learned without having to develop it from scratch.

### Prerequisites
1. OpenAI Account - [create an OpenAI Account here](https://platform.openai.com/signup)
2. Node.js installed - [download Node.js here](https://nodejs.org/en/download/)

After making an OpenAI account, you'll need an API Key. You can get an OpenAI API Key here by clicking on <strong>+ Create new secret key</strong>.

Save that API key for later.

### Make a New Node.js project
To get started, create a new Node.js project in an empty directory:
```bash
mkdir finetune-model
cd finetune-model
npm init --y
```
### Get started with OpenAI
Make a *.env* file in your root directory and add the following line:
```bash
OPENAI_API_KEY=YOUR-OPENAI-API-KEY
```
Replace `YOUR-OPENAI-API-KEY` with the OpenAI API Key you took note of earlier. Now you will be able to access this API Key in your code with `process.env.OPENAI_API_KEY`.

Next, install the `openai` and `fs` npm packages:
```bash
npm install openai fs
```
Now it's time to prepare your data!

### Prepare Custom Data
Training data is how GPT-3 learns what you want it to say.

Your data should be in a [JSONL document](https://jsonlines.org/), where each line is a prompt-completion pair corresponding to a training sample.

Make a jsonl-file called *newdata.jsonl* and include prompt-completion pairs that look something like this:
```json
{"prompt": "<prompt text> ->", "completion": "<ideal generated text>\n"}
{"prompt": "<prompt text> ->", "completion": "<ideal generated text>\n"}
{"prompt": "<prompt text> -> ", "completion": "<ideal generated text>\n"}
```
The data I used includes [fun facts about me and can be found here on GitHub](https://github.com/elizabethsiegle/finetune-openai-model/blob/main/newdata.jsonl).

OpenAI recommends having at least a couple hundred examples and found that [each doubling of dataset size leads to a linear increase in model quality](https://platform.openai.com/docs/guides/fine-tuning/general-best-practices). Save at least thirty prompt-completion pairs (the more the better). This is not enough to make a fine-tuned model for a production-ready product, but is enough for the purposes of this tutorial.

Save your jsonl file, and on the command line, use [OpenAI's CLI data preparation tool](https://platform.openai.com/docs/guides/fine-tuning/cli-data-preparation-tool) to help you easily convert your data into the jsonl file format.
```bash
openai tools fine_tunes.prepare_data -f newdata.jsonl
```
With your prepared data, it's time to write some code to fine-tune an existing OpenAI machine learning model.
### Fine-tune an OpenAI Model
In this tutorial, you'll use `davinci`, but OpenAI currently lets you fine-tune its base models which also include `curie`, `babbage`, and `ada`. These are their original models and they lack any instruction after training (which `text-davinci-003` has, for example).

In a file called finetune.js, add the following code to the top which will be used for each step:
```javascript
const { Configuration, OpenAIApi } = require("openai");
const fs = require("fs");
const configuration = new Configuration({
  apiKey: process.env.OPENAI_API_KEY,
});
const openai = new OpenAIApi(configuration);
```
Beneath that, your first function uploads the jsonl file so you can use it next.
```javascript
async function uploadFile() {
    try {
        const f = await openai.createFile(
            fs.createReadStream("newdata.jsonl"),
            "fine-tune"
        );
        console.log(`File ID ${f.data.id}`);
        return f.data.id;
    }
    catch (err) {
        console.log('err uploadfile: ', err);
    } 
}
uploadFile();
```
Once you run the file with `node finetune.js`, take note of the ID printed out for the next step and comment out the `uploadFile()` function call.

Beneath the `uploadFile()` function, add the following function:
```javascript
async function makeFineTune() {
    try {
        const ft = await openai.createFineTune({
            training_file: 'YOUR-FILE-ID',
            model: 'davinci'
        });
        console.log(ft.data);
     }
    catch (err) {
        console.log('err makefinetune: ', err.response.data.error);
    }
}
makeFineTune();
```
Replace `YOUR-FILE-ID` with the file ID from the previous step, and rerun *finetune.js* to run the new function. After running it, comment out the `makeFineTune()` function call.

Wait a few minutes to let it process. You can check-in on the status of the fine tune, and additionally get the model ID, by calling the `listFineTunes` API method as shown below:
```javascript
async function getFineTunedModelName() {
    try {
        const modelName = await openai.listFineTunes();
        console.table(modelName.data.data, ["id", "status", "fine_tuned_model"]);

    }
    catch (err) {
        console.log('err getmod: ', err)
    }
 }
getFineTunedModelName();
```
The fine-tuned model is not ready for use when `status` is `running` and `fine_tuned_model` is `null`, but once you see `status` is `succeeded` and `fine_tuned_model` is something like `davinci:ft-personal-2023-05-01-22-05-28`, then comment out `getFineTunedModelName()`, copy the model name (beginning with `davinci`), and you're good to go and use the model!

### Test your Fine-Tuned OpenAI model
Add the following code to your *finetune.js* file.
```javascript
async function run() {
    try {
        const comp = await openai.createCompletion({
            model: 'YOUR-FINETUNED-MODEL-NAME',
            prompt: 'What is Lizzie Siegle's favorite food', //replace this prompt according to your data
            max_tokens: 200
        });
        if (comp.data) {
            console.log('choices: ', comp.data.choices)
        }
    } catch (err) {
        console.log('err: ', err)
    }
}
run();
```
Replace `YOUR-FINETUNED-MODEL-NAME` with the model name from the previous step.

Then, rerun `node finetune.js` and you should see your new custom model deployed in action making a new completion according to the prompt you passed in!
![Example usage of fine-tuned model that returns dumplings when i ask what my favorite food is](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w3wux4i9pdzk8q33bkqe.png)
Alternatively, you can test out your fine-tuned model in the [OpenAI Playground](https://platform.openai.com/playground).

![list of fine-tuned models to use in OpenAI Playground](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dzehgyswzpbxwwv0y4gw.png)
Complete code can be found here on GitHub.

### What's Next for Fine-tuning OpenAI models?
That's how to customize one of OpenAI's existing models to fit your own specific use case and data!

For next steps, you can
1. add more data to improve completions and make the model production-ready
2. try fine-tuning a different model other than `davinci`
3. use all the other [Completions](https://platform.openai.com/docs/api-reference/completions) parameters like `temperature`, `frequency_penalty`, `presence_penalty`, etc., on your requests to fine-tuned models
4. fine-tune a model in another programming language
5. and more!