Tutorial: Fine-Tuning for Prompt Generation

Ever wanted your GPT-3.5-Turbo to whip up some hypothetical prompts based on “some content”? Let me show you how!. By the end of this quick guide, you’ll have your AI model doing just that, and guess what? It’ll be both fun & easy.

Step 1: Export Your ChatGPT Data

Start by exporting and downloading all of your data from ChatGPT. Just head over to the settings and press this button:

You’ll receive a download link via email shortly after that.

Step 2: Prepare Your Data

we’re working on crafting a fine tune that spits out prompts all on its own, so, we really don’t want a bunch of different custom instructions or plugin messages muddling our dataset. And we definitely don’t need examples where we had to correct ChatGPT to get the answer right. We’re keeping things simple by sticking to messages from conversations with just one pair of text messages between the user and assistant.

The following script will do just that, just create a new python script in your extracted conversations folder run it there:

import json
import random

def filter_single_pairs(conversations):
    single_pairs = []

    for conversation in conversations:
        mapping = conversation['mapping']
        messages = [item for item in mapping.values() if item['message'] is not None]

        # Check for any message containing user_context_message_data
        if any('user_context_message_data' in m['message']['metadata'] for m in messages):
            continue
        
        # Check for exactly one user message and one assistant message
        user_messages = [m for m in messages if m['message']['author']['role'] == 'user' and 
                         m['message']['status'] == "finished_successfully" and 
                         m['message']['content']['content_type'] == "text"]
        
        assistant_messages = [m for m in messages if m['message']['author']['role'] == 'assistant' and 
                              m['message']['status'] == "finished_successfully" and 
                              m['message']['content']['content_type'] == "text"]
        
        if len(user_messages) == 1 and len(assistant_messages) == 1:
            user_message = user_messages[0]
            assistant_message = assistant_messages[0]
            
            # Add to single_pairs
            single_pairs.append((user_message['message']['content']['parts'][0], 
                                 assistant_message['message']['content']['parts'][0]))
        
    return single_pairs

def create_response_template(system_content, user_content, assistant_content):
    return {
        "messages": [
            {"role": "system", "content": system_content},
            {"role": "user", "content": user_content},
            {"role": "assistant", "content": assistant_content}
        ]
    }

# Create a few examples using the extracted data
examples = []
system_content = "provide instructions"
num_examples = 1000



# Usage:
# Load your conversations JSON file
import json
with open('conversations.json', 'r') as f:
    conversations = json.load(f)

# Get the filtered message pairs
filtered_pairs = filter_single_pairs(conversations)

# Display the first 2 pairs as a check
for user_message, assistant_message in filtered_pairs[:2]:
    print(f"User: {user_message}\nAssistant: {assistant_message}\n---\n")

# Get the count of valid pairs
num_pairs = len(filter_single_pairs(conversations))

print(f"The number of valid user-assistant message pairs is: {num_pairs}")

# Generate examples using the generic response format template
for user_message, assistant_message in filtered_pairs[:num_pairs]:
    examples.append(create_response_template(system_content, assistant_message, user_message))

# Shuffle the examples to ensure a random distribution
random.shuffle(examples)

# Define the split ratio for training and validation
train_ratio = 0.8  # 80% for training
num_train = int(len(examples) * train_ratio)

# Split the examples into training and validation sets
train_examples = examples[:num_train]
val_examples = examples[num_train:]
num_val = num_pairs - num_train

# Save the training examples to a JSON file
with open('training_file.jsonl', 'w', encoding='utf-8') as f:
    for example in train_examples:
        json.dump(example, f, ensure_ascii=False)
        f.write('\n')

print(f"created a training file with {num_train} examples")
# Save the validation examples to a JSON file
with open('validation_file.jsonl', 'w', encoding='utf-8') as f:
    for example in val_examples:
        json.dump(example, f, ensure_ascii=False)
        f.write('\n')
print(f"created a validation file with {num_val} examples")

Did you notice that I swapped the order of the content of the user_message and assistant_message? That’s the trick, I’ve also replaced all the system messages with “provide instructions”, in any case we’re ready for the final step:

Step 3: Fine-tuning.

Head over to the fine tuning dashboard and create a new one using your newly created training & validation file. You’ll find your model in the playground when it’s done. I’ll recommend you start with a temperature setting of 0 for the best results.

To test the model we’ve created, I’ll simply paste this entire post, and see what prompt it creates:

Write a tutorial for the following task:

You have been tasked with creating a fine tune that spits out prompts all on its own. To do this you will need to create a dataset of messages from conversations with just one pair of text messages between the user and assistant. You will then need to create a fine tune using this dataset.

3 Likes