Official Node.js client library

Hello!

We just released an official Node.js library for the OpenAI API. It’s available to install through npm, and you can find code examples in our API reference.

We hope you find this useful when developing Node.js apps that use our API!

16 Likes

Thank you! Good to see some additional support in nodejs for openai!

Juts one question - I noted that you used the ‘request’ package for the http client vs a package like axios (or even fetch). Are you aware that ‘request’ has been deprecated, and has not been actively maintained in over 2 years?

1 Like

Thanks for your reply!

This project is using the axios package, which you can verify here:

I don’t see a place where we’re using the ‘request’ package, but if you find one please point us to it.

1 Like

Good morning - Apologies! I mistakenly traced openai-node from the npm deployment to

GitHub - jtams/openai-node: A library for using the OpenAI GPT-3 API with Node. … which uses Request.

I can see now the right deployment using Axios is sitting at

1 Like

Nice!

I tried it but in my tests, I couldn’t find a way to pass the userId string in my API calls. How can I pass this parameter?

I use the openai-api package by Nikita Jerschow. Happy to migrate to the official library in the future :slight_smile:

1 Like

What do you mean by ‘userId string’? If you are referring to the api key, you will be able to access it from your process object on a nodejs server, and pass it that way. Here is the example from the docs:

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

Thanks for raising this @ediardo. I assume you’re referring to the “user” parameter mentioned in this Provide a user identifier section.

You’re correct that the “user” parameter is not explicitly supported by the current version of this package – typescript will throw and error if you try to pass it. As a temporary workaround, you can cast the request parameters to any in typescript and continue passing it:

const resp = await openai.createCompletion("text-davinci-001", {
    prompt: "Hello world",
    user: "user-1234",
} as any);

We’ll work on getting user natively supported in the next week or so.

2 Likes

Thank you for the prompt reply.

Cool, didn’t know it was this recent. I’m currently using this on my sideprojects :slight_smile: it works great

1 Like

explicit support for the user parameter is added in version 2.0.4

4 Likes

Is there a session param to maintain the context of a previous request? Or does the entire previous request need to be sent back as the next prompt? (im assuming that’s not the same thing you’re discussing above re: userId)

There’s no session parameter. If you have a use case like chat where you need to maintain the context across multiple requests, you’ll have to include the history in the prompt each time.

1 Like

Hi there.

I’ve been trying to make the package work, but all I get are 401 errors on every request.

There are two issues, mainly:

  1. The OpenAIApi constructor requires me to define an isJsonMime property (which is a function): without it, the TypeScript starts complaining.
  2. Requests are not sent with the Authorization header (same for OpenAI-Organization).

For #1, I’ve tried to set either isJsonMime: () => false or isJsonMime: () => true, thinking that it could have been the cause of #2.

To be sure about the API key and organization ID, I’ve tried a curl request, and it works, so they are not the cause of the problem.

I’m using version 3.1.0 of the package.

This a simple piece of code I’m using to replicate the issue:

const configuration = {
  apiKey: process.env.OPENAI_API_KEY,
  organization: process.env.OPENAI_ORGANIZATION_ID,
  isJsonMime: () => false,
};
console.log(configuration);
const openAIApi = new OpenAIApi(configuration);

Error:

Request failed with status code 401
Error: Request failed with status code 401
    at createError (/media/andrea/Data/projects/my-server/node_modules/axios/lib/core/createError.js:16:15)
    at settle (/media/andrea/Data/projects/my-server/node_modules/axios/lib/core/settle.js:17:12)
    at IncomingMessage.handleStreamEnd (/media/andrea/Data/projects/my-server/node_modules/axios/lib/adapters/http.js:322:11)
    at IncomingMessage.emit (node:events:525:35)
    at endReadableNT (node:internal/streams/readable:1359:12)
    at processTicksAndRejections (node:internal/process/task_queues:82:21)

With console.log(configuration); I could confirm I was using the right parameters: I’ve copied/pasted them in the successful curl call.

With more detailed logging, I could confirm that the request is missing the necessary authorization header.

I hope someone can help because I’m quite stuck, and I don’t want to resort to using plain fetch calls :slight_smile:

Welcome to the community.

401 means the request is unauthorized. Likely an error with the org-id or the API Key supplied when calling.

I’m using the same package and I haven’t encountered any errors. I have never had to have used the isJsonMime property.

I see the error is that you have not created the Configuration object.

Take a look at this boilerplate code in the official doc to call the list Models endpoint:

const { Configuration, OpenAIApi } = require("openai");
const configuration = new Configuration({
  apiKey: process.env.OPENAI_API_KEY,
});
const openai = new OpenAIApi(configuration);
const response = await openai.listModels();

The Configuration object is what is used to create the OpenAIApi instance.

Use the new Configuration() to create the Configuration object.

Please read docs before you start making any API calls and always use the boilerplate code provided.

1 Like

Thanks for the quick reply.

I know the meaning of 401 and why it’s happening: the package is not sending the authentication headers.
Why it’s doing that, though, is still a mystery.

Org ID and API key are correct. As I mentioned, I’ve tested them using a simple curl command.

The console.log in the code snipped also confirms that the key and org-id are provided with the correct values.

The boilerplate does not use TypeScript, so the isJsonMime issue won’t show up for you, most likely.
Besides that, it works as much as the curl command I mentioned earlier.
Still, I can’t make it work in my NestJS app.

The type definition clearly says that the constructor needs an instance of Configuration which has this isJsonMime set as required (i.e. is not declared as optional):

export declare class Configuration {
    /**
     * parameter for apiKey security
     * @param name security name
     * @memberof Configuration
     */
    apiKey?: string | Promise<string> | ((name: string) => string) | ((name: string) => Promise<string>);
    /**
     * OpenAI organization id
     *
     * @type {string}
     * @memberof Configuration
     */
    organization?: string;
    /**
     * parameter for basic security
     *
     * @type {string}
     * @memberof Configuration
     */
    username?: string;
    /**
     * parameter for basic security
     *
     * @type {string}
     * @memberof Configuration
     */
    password?: string;
    /**
     * parameter for oauth2 security
     * @param name security name
     * @param scopes oauth2 scope
     * @memberof Configuration
     */
    accessToken?: string | Promise<string> | ((name?: string, scopes?: string[]) => string) | ((name?: string, scopes?: string[]) => Promise<string>);
    /**
     * override base path
     *
     * @type {string}
     * @memberof Configuration
     */
    basePath?: string;
    /**
     * base options for axios calls
     *
     * @type {any}
     * @memberof Configuration
     */
    baseOptions?: any;
    /**
     * The FormData constructor that will be used to create multipart form data
     * requests. You can inject this here so that execution environments that
     * do not support the FormData class can still run the generated client.
     *
     * @type {new () => FormData}
     */
    formDataCtor?: new () => any;
    constructor(param?: ConfigurationParameters);
    /**
     * Check if the given MIME is a JSON MIME.
     * JSON MIME examples:
     *   application/json
     *   application/json; charset=UTF8
     *   APPLICATION/JSON
     *   application/vnd.company+json
     * @param mime - MIME (Multipurpose Internet Mail Extensions)
     * @return True if the given MIME is JSON, false otherwise.
     */
    isJsonMime(mime: string): boolean;
}

As for the version on Node, it’s v18.7.0.

I’m using a brand-new Ubuntu 22.10 machine with everything installed on the most recent versions of the last 24 hours, so I assume that if there is an issue with versions, it’s because they are too new (?).

I’ve replicated the issue on this minimal repo.

It’s just a NestJS that does nothing but tries to initialize OpenAI from the bootstrap file (in src/main.ts): not something I would do, but I’ve tried to keep the code at the minimum while replicating my scenario as close as possible.

I hope it will help narrow down the cause of the issue because I’m out of ideas at the moment.

Thanks.

Have a look at your code.

Look specifically at const configuration definition.

You have not created an instance of OpenAI.Configuration, you simply have a const named configuration.

The fault is in your code, which is why if you just copy/paste the boilerplate code, it will run without errors.

1 Like

@sps, you’re perfectly right!

I’ve been spoiled by TypeScript, and, in cases like these, I seldom need to explicitly create a new instance of the constructor’s argument.

In these cases, it seems that OpenAi can only deal with a proper instance of Configuration, and I failed to see that.

Now things started working.

Thanks!

1 Like

Is it supported now? Just see last release was in March.