YouTube Courses - Learn Smarter

YouTube-Courses.site transforms YouTube videos and playlists into structured courses, making learning more efficient and organized.

Building an AI Chatbot with Node.js and the ChatGPT API



Introduction

This chapter provides a step-by-step guide to building your own AI chatbot using Node.js and the ChatGPT API. By leveraging the power of OpenAI’s GPT-3.5 Turbo model, you will learn how to create a chatbot that can engage in interactive conversations directly within your terminal. This chapter will walk you through setting up your development environment, writing the necessary code, and implementing features such as maintaining chat history for ongoing conversations. Before we dive into the technical details, let’s briefly demonstrate what we will be building.

Imagine having a personal assistant accessible directly from your command line. You can ask questions, request information, and even get code samples, all powered by the intelligence of ChatGPT. For example, you could ask:

Hello

The chatbot might respond:

Hello! How can I assist you today?

And if you follow up with:

What is the capital of Florida?

The chatbot will accurately provide:

The capital of Florida is Tallahassee.

Furthermore, the chatbot is designed to remember the conversation history. This allows for contextual understanding in follow-up questions. If you then ask:

What is the population?

It intelligently infers that you are still referring to Tallahassee and responds with population data. This chapter will guide you through the process of creating this interactive and intelligent chatbot.

Prerequisites

Before you begin building your AI chatbot, ensure you have the following prerequisites in place:

  • Node.js: Node.js is a JavaScript runtime environment that allows you to run JavaScript code outside of a web browser. You will need Node.js installed on your system to execute the chatbot application.

    Node.js

    Node.js is an open-source, cross-platform JavaScript runtime environment that executes JavaScript code server-side. It allows developers to use JavaScript to write command-line tools and server-side scripts outside of a browser.

  • OpenAI API Key: Access to the ChatGPT API requires an API key from OpenAI. You will need to create an account on the OpenAI platform and generate an API key.

  • Text Editor: A text editor is essential for writing and editing the code. Popular choices include VS Code, Sublime Text, Atom, or any editor you are comfortable with.

  • Terminal: A terminal or command prompt is needed to execute commands, run the Node.js application, and interact with the chatbot.

Setting Up the Project

Let’s start by setting up your project environment.

Creating a Project Folder

  1. Create a new empty folder on your computer. You can name it something descriptive, such as chatgpt-chatbot.
  2. Open this folder in your chosen text editor.
  3. Open your terminal and navigate to this project folder using the cd command (change directory).

Initializing package.json

To manage project dependencies and scripts, we need to initialize a package.json file.

  1. In your terminal, within the project folder, run the following command:

    npm init

    npm init

    npm init is a command in Node Package Manager (npm) that initializes a new or existing Node.js project. It interactively guides you through creating a package.json file, which is used to manage project metadata and dependencies.

  2. You will be prompted with a series of questions. You can accept the defaults for most of them. When asked for the “package name,” you can enter chatbot. For the “description,” you might enter “Chatbot powered by ChatGPT.” For the “author,” include your name. For the “license,” MIT is a common choice.

  3. After answering the questions, a package.json file will be created in your project folder. This file will store information about your project, including its dependencies.

Installing Dependencies

Our chatbot relies on several external packages. We will use npm install to install them.

  1. In your terminal, run the following command to install the necessary packages:

    npm install openai readline-sync dotenv colors

    npm install

    npm install is a command in Node Package Manager (npm) used to install packages and their dependencies. These packages are listed in the package.json file or specified directly in the command.

    This command installs four packages:

    • openai: The official OpenAI library for Node.js, which allows us to interact with the ChatGPT API.
    • readline-sync: A package that provides synchronous, line-by-line user input, enabling conversational flow in the terminal.
    • dotenv: A package that loads environment variables from a .env file, allowing us to securely store our API key.
    • colors: An optional package to add colors to the terminal output, enhancing readability.

Creating index.js and Configuring package.json for ES Modules

We will create the main file for our chatbot, index.js, and configure package.json to use ECMAScript modules (ES modules) for modern JavaScript syntax.

  1. Create a new file named index.js in your project folder. This will be the entry point for our chatbot application.

  2. Open your package.json file in your text editor.

  3. Add "type": "module" to the top-level JSON object in package.json. This tells Node.js to treat .js files as ES modules, allowing us to use import and export syntax. Your package.json file should now look something like this (content may vary based on your npm init answers):

    {
      "name": "chatbot",
      "version": "1.0.0",
      "description": "Chatbot powered by ChatGPT",
      "main": "index.js",
      "type": "module",
      "scripts": {
        "start": "node index.js",
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "author": "Your Name",
      "license": "MIT",
      "dependencies": {
        "colors": "^1.4.0",
        "dotenv": "^16.3.1",
        "openai": "^4.11.0",
        "readline-sync": "^1.4.10"
      }
    }
  4. In the "scripts" section of package.json, ensure there is a "start" script defined as "node index.js". This allows us to start the chatbot using the command npm start.

Obtaining an OpenAI API Key

To access the ChatGPT API, you need to obtain an API key from OpenAI.

  1. Go to the OpenAI website (https://www.openai.com/) and log in or sign up for an account.
  2. Navigate to your API keys page. This is typically found under your profile settings or a developer/API section.
  3. Click on “Create new secret key” or a similar button to generate a new API key.
  4. Copy the generated API key and store it in a safe place temporarily. Important: Treat your API key as confidential information and do not share it publicly.

Storing the API Key in a .env File

For security and better configuration management, we will store the API key in a .env file.

  1. In your project root directory, create a new file named .env.

  2. Open the .env file in your text editor.

  3. Add the following line to the file, replacing YOUR_API_KEY with the API key you copied from OpenAI:

    OPENAI_API_KEY=YOUR_API_KEY

    .env file

    A .env file (short for “environment variables”) is a text file used to store configuration settings, often sensitive information like API keys and database credentials, separately from the application code. This practice enhances security and makes configuration management easier across different environments.

  4. Save the .env file. The .env file should be in the root of your project, alongside index.js and package.json.

Writing the Code - Initial Setup

Now, let’s start writing the JavaScript code for our chatbot in index.js.

Importing Modules

First, we need to import the necessary modules we installed earlier.

  1. Open index.js in your text editor.

  2. Add the following import statements at the top of the file:

    import { Configuration, OpenAI } from 'openai';
    import * as dotenv from 'dotenv';
    import colors from 'colors';
    import readlineSync from 'readline-sync';

Configuring the OpenAI API

Next, we will configure the OpenAI API client using your API key.

  1. Below the import statements, add the following code to load environment variables from the .env file:

    dotenv.config();

    dotenv.config()

    dotenv.config() is a function from the dotenv package that loads environment variables from a .env file into process.env. This makes the variables accessible in your Node.js application.

  2. Create a configuration object using your API key:

    const configuration = new Configuration({
      apiKey: process.env.OPENAI_API_KEY,
    });

    Configuration Object (OpenAI)

    In the OpenAI library, the Configuration object is used to set up API authentication and other settings. It typically includes your API key and can be passed to the OpenAI class to initialize the API client.

  3. Instantiate the OpenAI API client:

    const openai = new OpenAI(configuration);

    OpenAI API Client

    The OpenAI class from the openai library provides methods to interact with the OpenAI API endpoints. Creating an instance of this class, configured with your API key, allows you to make requests like generating text completions or chat completions.

Testing the API Connection

Let’s test if our API configuration is working correctly by sending a simple request to the ChatGPT API.

  1. Wrap the following code in an asynchronous main function and call it immediately:

    async function main() {
      try {
        const chatCompletion = await openai.chat.completions.create({
          model: 'gpt-3.5-turbo',
          messages: [{ role: 'user', content: 'What is the capital of Massachusetts?' }],
        });
    
        console.log(chatCompletion.choices[0].message.content);
    
      } catch (error) {
        if (error.response) {
          console.error(colors.red(error.response.status));
          console.error(colors.red(error.response.data));
        } else {
          console.error(colors.red(`Error with OpenAI API request: ${error.message}`));
        }
      }
    }
    
    main();

    openai.chat.completions.create()

    openai.chat.completions.create() is a method in the OpenAI Node.js library used to send a request to the ChatGPT API for generating chat completions. It takes parameters like the model name and an array of messages defining the conversation history.

    GPT-3.5 Turbo

    GPT-3.5 Turbo is a specific model from the GPT (Generative Pre-trained Transformer) family developed by OpenAI. It is optimized for chat-based applications and offers a balance of performance and cost-effectiveness.

    Asynchronous Function (async/await)

    In JavaScript, an async function is a function declared with the async keyword. It enables the use of await inside the function to pause execution until a Promise resolves. This is commonly used for handling asynchronous operations like API calls in a more synchronous-looking manner.

    Model (in AI)

    In the context of AI and specifically large language models, “model” refers to the trained algorithm that performs a specific task, such as text generation or language understanding. Different models (like GPT-3.5 Turbo) have varying capabilities and are trained for different purposes.

    Messages (in API request)

    In the OpenAI Chat Completions API, the messages parameter is an array of message objects that define the conversation history. Each message object includes a role (e.g., “user” or “assistant”) and content (the actual text of the message). This history is used by the model to maintain context in the conversation.

    Role (user, assistant)

    In the OpenAI Chat Completions API, the role parameter within a message object specifies the speaker of the message. “User” indicates a message from the end-user, while “assistant” indicates a message from the AI model.

    Content (message text)

    In the OpenAI Chat Completions API, the content parameter within a message object holds the actual text of the message. This is the text input from the user or the text response generated by the AI assistant.

  2. Run the code in your terminal using:

    npm start
  3. If your API key and setup are correct, you should see the response from the ChatGPT API printed in your terminal, which should be: “Boston.” If you encounter errors, check your API key, internet connection, and the code for any typos.

Building the Chatbot Loop

Now that we have a basic API connection, let’s create the interactive chatbot loop.

Implementing readline-sync for User Input

We will use readline-sync to get user input in a loop, enabling continuous conversation.

  1. Remove or comment out the test API call within the main function from the previous step.

  2. Inside the main function, add a while(true) loop to continuously prompt the user for input:

    async function main() {
      console.log(colors.bold.green('Welcome to the chat bot program!'));
      console.log(colors.green('You can start chatting with the bot.'));
    
      while (true) {
        // ... chatbot logic will go here ...
      }
    }

    While Loop

    A while loop in programming is a control flow statement that repeatedly executes a block of code as long as a specified condition is true. The loop continues to iterate until the condition becomes false.

  3. Inside the while loop, use readlineSync.question() to get user input:

    while (true) {
      const userInput = readlineSync.question(colors.yellow('You: '));
      // ... process user input ...
    }

Handling User Input and the ‘exit’ Command

We need to process the userInput and allow the user to exit the chatbot by typing “exit”.

  1. Add an if condition to check if the user input is “exit” (case-insensitive) and break out of the loop if it is:

    while (true) {
      const userInput = readlineSync.question(colors.yellow('You: '));
    
      if (userInput.toLowerCase() === 'exit') {
        console.log(colors.green('Bot: Goodbye!'));
        return; // Exit the main function, ending the program
      }
    
      // ... API call and response handling will go here ...
    }

Implementing Error Handling

Wrap the API call within a try...catch block to handle potential errors gracefully.

  1. Place the API call and response handling within a try block inside the while loop. Keep the catch block from the previous test code to handle API errors:

    while (true) {
      const userInput = readlineSync.question(colors.yellow('You: '));
    
      if (userInput.toLowerCase() === 'exit') {
        console.log(colors.green('Bot: Goodbye!'));
        return;
      }
    
      try {
        // ... API call will go here ...
      } catch (error) {
        if (error.response) {
          console.error(colors.red(error.response.status));
          console.error(colors.red(error.response.data));
        } else {
          console.error(colors.red(`Error with OpenAI API request: ${error.message}`));
        }
      }
    }

    Try…Catch Block

    In programming, a try...catch block is used for error handling. Code that might throw an error is placed inside the try block. If an error occurs, the execution jumps to the catch block, where you can handle the error gracefully, preventing the program from crashing.

Integrating the ChatGPT API

Now, let’s integrate the ChatGPT API within the chatbot loop to process user input and get responses.

Calling createChatCompletion Method

Inside the try block of the while loop, we will call the openai.chat.completions.create() method to send the user’s input to the ChatGPT API and get a response.

  1. Replace the comment // ... API call will go here ... with the following code to make the API request:

    const chatCompletion = await openai.chat.completions.create({
      model: 'gpt-3.5-turbo',
      messages: [{ role: 'user', content: userInput }],
    });

Extracting and Displaying the Response Content

After getting the chatCompletion response, we need to extract the bot’s message content and display it in the terminal.

  1. Below the API call within the try block, add the following code to extract and log the bot’s response:

    const completionText = chatCompletion.choices[0].message.content;
    console.log(colors.green('Bot: '), completionText);

    Data Object, Choices Array, Message Object (API Response)

    The response from the OpenAI Chat Completions API is a structured JSON object. The relevant content is typically found within the choices array, which contains message objects. Each message object has a content property holding the text response from the AI. The data object is the top-level container of this structured response.

  2. Run the chatbot using npm start. You should now be able to type questions and receive responses from ChatGPT in your terminal. However, the chatbot currently does not remember the conversation history.

Implementing Chat History

To enable conversational context, we need to implement chat history.

Initializing chatHistory Array

Before the while loop, initialize an empty array to store the conversation history.

  1. Above the while loop in the main function, add the following line:

    const chatHistory = []; // Store conversation history

    Chat History

    In the context of chatbots, “chat history” refers to the record of past messages exchanged between the user and the bot. Maintaining chat history allows the chatbot to remember previous interactions and provide contextually relevant responses in ongoing conversations.

Constructing messages Array from chatHistory

Before each API call, construct the messages array by including the chat history along with the current user input.

  1. Inside the while loop, before the API call within the try block, add code to construct the messages array from chatHistory:

    const messages = chatHistory.map(([role, content]) => ({ role, content }));
    messages.push({ role: 'user', content: userInput });

    Map (Array Method)

    In JavaScript, map() is an array method that creates a new array by calling a provided function on every element in the calling array. It transforms each element based on the function’s logic.

    This code first maps over the chatHistory array to format previous messages into the required structure for the API. Then, it pushes the current user input to the messages array.

Updating chatHistory

After receiving the bot’s response, update the chatHistory array with both the user input and the bot’s response.

  1. After logging the bot’s response in the try block, add the following code to update chatHistory:

    chatHistory.push(['user', userInput]);
    chatHistory.push(['assistant', completionText]);

    Push (Array Method)

    In JavaScript, push() is an array method that adds one or more elements to the end of an array and returns the new length of the array.

Testing Conversational Flow

Run the chatbot again using npm start and test the conversational flow. You should now be able to ask follow-up questions, and the chatbot will remember the context of the conversation. For example, you can ask “What is the capital of France?” and then follow up with “What is its population?“. The chatbot should correctly understand that “its” refers to France.

Further Enhancements (Optional)

This chatbot provides a solid foundation. Here are some potential enhancements you can consider:

  • Saving Logs to Files: Implement logging to save conversations to text files or databases for record-keeping or analysis.

  • Integrating Other APIs: Extend the chatbot by integrating other APIs, such as weather APIs, news APIs, or more, to provide richer information and functionalities.

  • Function Calls: Explore OpenAI’s function calls feature to enable the chatbot to perform actions based on user requests, like sending emails or making calendar appointments.

  • Prompt Engineering: Experiment with prompt engineering techniques to guide the chatbot’s behavior and responses. You can prefix user inputs with specific instructions to influence the chatbot’s persona or response style.

    Function Calls (OpenAI API)

    Function calls in the OpenAI API allow the model to request external functions to be executed during a conversation. This enables the chatbot to interact with external tools and APIs, perform actions in the real world, and provide more dynamic and helpful responses.

    Prompt Engineering

    Prompt engineering is the process of designing and refining input prompts for large language models to elicit desired outputs. It involves crafting specific instructions, questions, or examples to guide the model towards generating more accurate, relevant, or creative responses.

Conclusion

Congratulations! You have successfully built an AI chatbot in your terminal using Node.js and the ChatGPT API. This chapter has provided a comprehensive guide, covering everything from setting up your project to implementing conversational memory. You can now expand upon this foundation to create more sophisticated and feature-rich chatbot applications.

Code Repository

For the complete code of this chatbot, you can refer to the following repository:

https://github.com/your-github-username/your-chatbot-repository (Replace with your actual repository link if you choose to share your code).

Repository (Code Repository)

A code repository, often referred to as a “repo,” is a storage location for software projects, typically using version control systems like Git. Repositories contain all project files, including source code, documentation, and history of changes, facilitating collaboration and version management among developers.