The new language models give us access to services like ChatGPT or Dall-E, useful and accessible to everyone; but the most basic way to access these models is through their API.
The API allows us to make more precise use of the models’ capabilities, in addition to being able to integrate them into our own applications.
In this post, we will start by looking at how to create an account on OpenAI to begin calling its API, and we will see how we can start using it to make our own ChatGPT clone in Python and Node.js, very rudimentary but with its own personality.
The API key
The first thing we will need is an account on OpenAI. If we have used ChatGPT at some point, we will already have one, but if not, we must sign up at openai.com. Once in our account, we will need to generate a key (API key), which will be our way of identifying ourselves when making any call to the API, by going to the API keys section.
It is important not to share or ever make our key public, since anyone who has access to it will be able to use it to make calls at our expense. If you realize that your key has been compromised in any way, it is necessary to return to the API keys section, generate a new key (the system will always force us to have at least one generated key, although we can have more) and delete the previous one so that from that moment any call with the old key will be rejected.

Pay per use
While OpenAI offers free access to some of its services (ChatGPT with GTP 3.5, or Dall-E 2) all API calls have a cost, which varies depending on the type of call, the model, and the size. Therefore, before being able to start using the API, even just for testing, we will need to go to the Billing section to enter a payment method (which, at the time of writing this post, only accepts credit card) and make an initial deposit of funds.
The way billing works with OpenAI is through deposits that give us credit, and the use we make of the API will be deducted from our credit. This payment format, although advantageous for OpenAI because we pay in advance, has the good part that it gives us peace of mind that our spending will not give us too big of a scare, since our credit acts as a ceiling that will never be exceeded. Once we are more familiar with the use of the API and its billing, we can make use of the automatic reload option (disabled by default) and set our spending limits in the system to ensure that our spending stays aligned with our budget.

First API call: list of models
With our account created and loaded, and the key prepared, we are ready to start making calls to the API.
OpenAI publishes its API as REST web services accessible in a generic way, in addition to libraries for Python and Node.js that encapsulate and simplify its use for these platforms. To start, we can make an initial direct call to a web service using curl (substituting our API key):
curl https://api.openai.com/v1/models -H "Authorization: Bearer api-key"
Here we are calling the model listing service, which is a GET service that has no input parameters and returns the list of models currently supported by OpenAI. In addition to having served to make a first test and see that our key works, this call gives us an opportunity to discuss the available models that we can use in subsequent calls.
As we can see from the response to our call, OpenAI supports a good number of models of different types, including image generation, audio generation, transcription, etc. For now, we will focus only on natural language models, and among them, the main ones (at the time of writing this post) are:
- gpt-3.5-turbo: GPT 3.5 model, currently used by the free version of ChatGPT.
- gpt-4: GPT 4 model, used in the paid version of ChatGPT.
- gpt-4-1106-preview: GPT 4-Turbo, their most powerful model, currently in beta and only accessible through APIs.
Interestingly, the most recent model, GPT 4-Turbo, is currently cheaper than GPT 4 (probably because it is in beta). We will take advantage of this to make the most out of this new model.
The chat completions service
The basic service we will have to use to build our chatbot is chat completions, which allows us to make queries to the model with text input and output. This POST service accepts a wide variety of parameters that allow us to make adjustments to the query, but only two of them are mandatory:
- model, through which we will identify the model we want to consult, using one of the possibilities that the model listing service returned to us.
- messages, this is the gist of the service; here, we will pass the list of messages from the conversation to which we expect a response.
Each message in the list we send to the service, in addition to the message’s text itself, is accompanied by one of these three roles:
- user: messages sent by the user. For example, if we enter ChatGPT and ask a question, it will be sent to the model with this role.
- assistant: messages returned by the model.
- system: message that describes the general behavior we expect from the model throughout the conversation. Its use is optional.
It is necessary to keep in mind that calls to the model do not have state; the model does not have memory of our previous calls. Each call is received and answered by the model completely independently.
So … how does ChatGPT manage to maintain a conversation, and be able to refer to what we have talked about before?
The way to do this is to send the complete conversation in each call, everything we have sent, and everything we have been previously answered. That is the reason for the existence of the assistant role: it is the role we will use to mark, when we send the previous conversation messages, the responses the service had given us, and differentiate them from our own messages.
Grumpy chatbot
It’s time to, with everything we’ve seen, build our own chatbot. ChatGPT is fine, but it’s a bit bland and lacks personality. We will give ours a bit more spark … we’ll build the grumpy chatbot.
To build it, we will use the libraries provided by OpenAI for Python or Node.js. The complete code in both languages is available on GitHub. To describe the operation, I’m going to base myself on the Node.js version, but both scripts are practically identical.
We start by instantiating the OpenAI object, which gives us access to all the functionality of the library. Here we must pass the API key, either explicitly passing the value to apiKey in the entry object, or letting it be picked up from the environment variable OPENAI_API_KEY.
const client = new OpenAI();
or
const client = new OpenAI({ apiKey: 'api-key' });
We will maintain a list (array) with the messages of the conversation. We’ll create it with an initial message with the system role, which will allow us to modify the general behavior of our chatbot, giving it its special personality:
let messages = [{ 'role': 'system', 'content': 'You\'re an old grump and grumbler. Respond to everything with complaints and reluctance, although you end up helping with what is asked of you.' }];
We enter the main loop of the script, in which we will capture the user’s input message, and it will repeat until it is left empty. The user’s message, we add it to the list of messages with the user role:
messages.push({ 'role': 'user', 'content': text });
We call the chat completions service with the list of messages and the model we want to use (in this case GPT 4-Turbo):
const response = await client.chat.completions.create({
model: 'gpt-4-1106-preview',
messages: messages
});
Lastly, the response we receive from the model, in addition to showing it to the user, we save it in the list of messages with the assistant role so that the next call has the complete conversation:
messages.push({ 'role': 'assistant', 'content': response.choices[0].message.content });
And with that, we already have our chatbot functioning! Of course, this simple chatbot, although it works, has several problems, the main one being the lack of control over the growing size of the stored conversation, so if it extends, there will come a time when it exceeds the allowed size limit in the call. In the next post, we will see possible solutions to this problem, and other improvements we can make to our chatbot.
