AI-Powered Pair Programming: Enhance Your Web Development Skills with GPT-4 Assistance

In this article, I will show you how to use GPT-4 as your pair programming companion. If you are unfamiliar with pair programming, it’s a setup where two programmers share one screen. One of them is the driver, who is typing the code and checking if the application works, and the other is the navigator, who is thinking about the problem and giving directions to the driver. The navigator is also responsible for the overall design of the code. In this article, I will use GPT-4 as both the driver and the navigator.

I will build a web application as a static page because I can deploy the website to GitHub Pages. Let me explain what I am going to create.

If you write a lot, you may be familiar with the situation. You have a concept in mind, and look for a perfect word to describe it. You could write a detailed description using the words you can recall, but you are sure there is one word that summarizes it all and fits perfectly. But you can’t recall it.

I will build an AI-powered web application that finds words you cannot recall — a “reverse dictionary.” Instead of looking for word definitions, you can type the description of the concept you want to convey and the situation in which you want to use it. As a result, the AI will give us three suggestions, examples of using those words in the given context, and a short explanation of their meaning.

Planning the Work with AI

I have a vague idea of what I’m going to need. First, I need to display a page where the user can put their OpenAI API key (I don’t want to pay for their queries), the description of the word, and the context in which they wish to use it. Then, I must send the request to the OpenAI API and display the results. All of this must run in the browser without installing any additional libraries.

However, let’s pretend I don’t know anything yet. Instead, I will describe the idea to GPT-4 and ask AI about the steps I need to take to build the application. I will use the following prompt:

I want to build a web application that will help me find a word that describes a given situation. I want to deploy it as a static page to GitHub Pages. The application should ask the user for their OpenAI API key, the description of the word, and the context in which they want to use it. Then, it should send the request to the OpenAI API and display the results. All of this must run in the browser without installing any additional libraries. What are the steps I need to take to build the application? List the steps, don’t generate any code yet.

Here is the response generated by GPT-4:

To build a web application that meets your requirements, follow these steps:

  1. Set up a GitHub repository: Create a new public GitHub repository for your project. Clone the repository to your local machine.
  2. Create the static HTML page: Create an index.html file in your repository that will serve as the main page for your application. This file should include the following:
    • A form to collect the OpenAI API key, description of the word, and context.
    • A button to submit the form and trigger the API request.
    • An area to display the results.
  3. Add CSS for styling: Create a styles.css file to add custom styling to your web application. Link this file to your index.html.
  4. Write JavaScript for functionality: Create a script.js file and link it to your index.html. In this file, write JavaScript code to perform the following tasks:
    • Collect the user’s input from the form.
    • Validate the input and ensure the API key and descriptions are not empty.
    • Create a function to call the OpenAI API using the Fetch API. Make sure to use the user’s API key for authentication and send the description and context as part of the request.
    • Parse the API response and extract the suggested word or words.
    • Display the result on the index.html page in the designated results area.
  5. Test your web application locally: Open the index.html file in a web browser to test the functionality of your application.
  6. Deploy to GitHub Pages: Once you are satisfied with your application’s functionality, commit and push your changes to the GitHub repository. In your repository’s settings, enable GitHub Pages and select the appropriate branch (usually main or gh-pages) as the source.
  7. Verify the deployment: After GitHub Pages finishes building your site, visit the provided URL to ensure your application is working correctly.

Remember, you can use vanilla JavaScript, HTML, and CSS to build this application without installing any additional libraries, since the Fetch API is built into modern browsers.

Generating the Application Template

The plan looks decent. Actually, it’s even more detailed than I would like it to be. Let’s start typing the code. I created the repository and three empty files, as listed in the GPT-4 response. Now, I have to write the HTML code. Instead, I will ask GPT-4 to generate the website for me. Here is the prompt:

I created empty index.html, script.js, and style.css files. What should I put in the index.html file to link the scripts and styles? For now, I want to display an empty page with the title “AI-powered Reverse Dictionary - get a word from its description”

I got:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>AI-powered Reverse Dictionary - get a word from its description</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <!-- Your application's content will go here -->

  <script src="script.js"></script>
</body>
</html>

The code does indeed display an empty page with the title I wanted. I like that GPT-4 puts the script at the end so the user doesn’t wait for the scripts to load before seeing the page.

Now, I need to add the form. Let’s ask GPT-4 to generate the form for me:

Display the page title in the center of the page. Below it, add a text input field for the OpenAI API key. The label should be displayed on the left side of the field.
Below the API Key, add an input field for the situation description and another input field for the word description. Their labels should be displayed above the fields.
Below the fields, add a “Find the words” button. The button width should be 60% of the text fields.
Below the button, add a placeholder element for the response.

The output wasn’t quite what I expected:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>AI-powered Reverse Dictionary - get a word from its description</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <div class="container">
    <h1>AI-powered Reverse Dictionary - get a word from its description</h1>

    <form id="word-finder-form">
      <label for="api-key">OpenAI API Key:</label>
      <input type="text" id="api-key" name="api-key" required>

      <label for="situation-description">Situation Description:</label>
      <input type="text" id="situation-description" name="situation-description" required>

      <label for="word-description">Word Description:</label>
      <input type="text" id="word-description" name="word-description" required>

      <button type="submit" id="find-words-button">Find the words</button>
    </form>

    <div id="response-placeholder"></div>
  </div>
  <script src="script.js"></script>
</body>
</html>

And the style.css:

body {
    font-family: Arial, sans-serif;
    text-align: center;
    margin: 0;
    padding: 0;
  }

  .container {
    max-width: 800px;
    margin: 0 auto;
    padding: 20px;
  }

  input {
    display: block;
    width: 100%;
    margin-bottom: 20px;
    padding: 10px;
  }

  label {
    display: block;
    margin-bottom: 5px;
  }

  button {
    width: 60%;
    padding: 10px;
    background-color: #007bff;
    color: #fff;
    border: none;
    cursor: pointer;
    font-size: 16px;
    margin-bottom: 20px;
  }

  button:hover {
    background-color: #0056b3;
  }

  #response-placeholder {
    margin-top: 20px;
  }

Tweaking the Generated Code

I wanted the label of the first input box on the left side of the text box, but it’s on the top. I will have to fix the mistake manually. Also, I will replace text input boxes with text areas so the user can enter more text. Moreover, the API key is technically a password, so I shouldn’t keep it visible. Let’s change the field to a password input box.

I replaced the AI-generated HTML with the code below:

<label for="api-key" class="on-left">OpenAI API Key:</label>
<input type="password" id="api-key" name="api-key" class="with-label-on-left" required>

<label for="situation-description">Situation Description:</label>
<textarea type="text" id="situation-description" name="situation-description" class="textarea" required></textarea>

<label for="word-description">Word Description:</label>
<textarea type="text" id="word-description" name="word-description" class="textarea" required></textarea>

and added the corresponding styles in the CSS file:

input.with-label-on-left {
    display: inline;
    width: 60%;
    margin-bottom: 20px;
    padding: 10px;
  }

  label.on-left {
    display: inline-block;
    text-align: right;
    margin-right: 10px;
  }

  .textarea {
    height: 100px;
    width: 100%;
  }

I think I won’t need to make any more changes in the UI, so I didn’t tell GPT-4 about the modifications I made. Instead, I moved on to the JavaScript code.

Generating the Event Handler

In the plan, GPT-4 suggested splitting the task into five parts. Now, I will ask AI to generate the first part of the code. Here is the prompt:

When the user clicks the “Find the words” button, read the values of the API key, situation description, and word description fields. Don’t send it anywhere yet. Just log the values to the console. Don’t log the API key.

I got the correct JavaScript event handler:

document.addEventListener('DOMContentLoaded', function() {
  const form = document.getElementById('word-finder-form');

  form.addEventListener('submit', function(event) {
    event.preventDefault();

    const apiKey = document.getElementById('api-key').value;
    const situationDescription = document.getElementById('situation-description').value;
    const wordDescription = document.getElementById('word-description').value;

    console.log('Situation Description:', situationDescription);
    console.log('Word Description:', wordDescription);

    // Call the OpenAI API or perform other tasks here
  });
});

Generating the Request and Sending it to the API

As the required attribute already does the basic request validation, I don’t need to check if the fields are empty. Therefore, I can skip the second task and move on to sending the request to the OpenAI API. I will use the chat completion API. Because I don’t want to install any additional libraries, instead of JS SDK, I will call the endpoints using the Fetch API.

I ask GPT-4 to generate the code for the third task:

Update the event listener. When the user clicks the button, send the query to the OpenAI endpoint. If you used curl, the command would look like this:

curl https://api.openai.com/v1/chat/completions
-H “Content-Type: application/json”
-H “Authorization: Bearer $OPENAI_API_KEY”
-d ‘{ “model”: “gpt-3.5-turbo”, “messages”: [ {“role”: “system”, “content”: “You are a reverse dictionary that can find a word from its description. The user explains the situation in which they want to use the word and the word’s meaning. In the response, you return 3 most suitable words using the following JSON format: {"words": [ {"word": "word1", "definition": "definition1", "examples": ["example1", "example2"], "usage": "explain why the word is relevant"} ]}”}, {“role”: “user”, “content”: “Situation $SITUATIONDESCRIPTION\nWord $WORDDESCRIPTION”}, ] }’

Log the response.

The updated JavaScript code looks like this:

document.addEventListener('DOMContentLoaded', function() {
    const form = document.getElementById('word-finder-form');

    async function callOpenAI(apiKey, situationDescription, wordDescription) {
      const response = await fetch('https://api.openai.com/v1/chat/completions', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${apiKey}`
        },
        body: JSON.stringify({
          model: 'gpt-3.5-turbo',
          messages: [
            {
              role: 'system',
              content: 'You are a reverse dictionary that can find a word from its description. The user explains the situation in which they want to use the word and the word\'s meaning. In the response, you return 3 most suitable words using the following JSON format: {\"words\": [{\"word\": \"word1\", \"definition\": \"definition1\", \"examples\": [\"example1\", \"example2\"], \"usage\": \"explain why the word is relevant\"}]}'
            },
            {
              role: 'user',
              content: `Situation ${situationDescription}\nWord ${wordDescription}`
            }
          ]
        })
      });

      const data = await response.json();
      console.log(data);
    }

    form.addEventListener('submit', function(event) {
      event.preventDefault();

      const apiKey = document.getElementById('api-key').value;
      const situationDescription = document.getElementById('situation-description').value;
      const wordDescription = document.getElementById('word-description').value;

      callOpenAI(apiKey, situationDescription, wordDescription);
    });
  });

Parsing the Response

Now, I have to tell GPT-4 about the response structure and ask how to display the results. I use the following prompt:

The API returns a response in the following format:
{
“id”: “chatcmpl-123”,
“object”: “chat.completion”,
“created”: 1677652288,
“choices”: [{
“index”: 0,
“message”: {
“role”: “assistant”,
“content”: “\n\nHello there, how may I assist you today?”,
},
“finish_reason”: “stop”
}],
“usage”: {
“prompt_tokens”: 9,
“completion_tokens”: 12,
“total_tokens”: 21
}
}

The “content” field contains the JSON string with the results. Parse it and display the results in the result placeholder section. Return only the modified part of the code.

Now, the callOpenAI function contains proper response parsing code:

async function callOpenAI(apiKey, situationDescription, wordDescription) {
    const response = await fetch('https://api.openai.com/v1/chat/completions', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${apiKey}`
    },
    body: JSON.stringify({
        model: 'gpt-3.5-turbo',
        messages: [
        {
            role: 'system',
            content: 'You are a reverse dictionary that can find a word from its description. The user explains the situation in which they want to use the word and the word\'s meaning. In the response, you return 3 most suitable words using the following JSON format: {\"words\": [{\"word\": \"word1\", \"definition\": \"definition1\", \"examples\": [\"example1\", \"example2\"], \"usage\": \"explain why the word is relevant\"}]}'
        },
        {
            role: 'user',
            content: `Situation ${situationDescription}\nWord ${wordDescription}`
        }
        ]
    })
    });

    const data = await response.json();

    const assistantMessage = data.choices[0].message.content;
    const parsedResults = JSON.parse(assistantMessage);
    const resultPlaceholder = document.getElementById('response-placeholder');

    if (parsedResults.words) {
        let resultHTML = '';

        for (const wordObj of parsedResults.words) {
        resultHTML += `<h3>${wordObj.word}</h3>`;
        resultHTML += `<p><strong>Definition:</strong> ${wordObj.definition}</p>`;
        resultHTML += `<p><strong>Examples:</strong> ${wordObj.examples.join(', ')}</p>`;
        resultHTML += `<p><strong>Usage:</strong> ${wordObj.usage}</p>`;
        resultHTML += '<hr>';
        }

        resultPlaceholder.innerHTML = resultHTML;
    } else {
        resultPlaceholder.innerHTML = '<p>No results found.</p>';
    }
}

The Final Result

I already have a working solution!

The final version
The final version

However, I want a few more improvements. When the user waits for the response, the button should be disabled, and a “Waiting…” text should be displayed. Also, the returned word should be a link to Google’s definition page, so the user can easily find the dictionary definition if they suspect the result may be AI’s hallucination. I won’t include those parts in the article. You can look at the final code in the GitHub repository.

If you want to play with the AI reverse-dictionary, you can find the application here: https://mikulskibartosz.github.io/reverse-dictionary/


Do you need help building AI-powered applications for your business?
You can hire me!

Older post

Build an AI-powered Newsletter Generator with dust.tt and OpenAI

How to create an AI-powered newsletter generator using the dust.tt and OpenAI API. You'll learn how to set up a website with the AI application, use the few-shot in-context learning technique to train the AI model, and deploy the API to generate newsletters.

Newer post

Alternatives to OpenAI GPT model: using an open-source Cerebras model with LangChain

Discover how to leverage the powerful open-source Cerebras model with LangChain in this comprehensive guide, featuring step-by-step instructions for loading the model with HuggingFace Transformers, creating prompt templates, and integrating it with LangChain Agents.