Migrating to the OpenAI JavaScript API library 4.x
As of June 2024, we recommend migrating to the OpenAI JavaScript API library 4.x, the latest version of the official OpenAI JavaScript client library that supports the Azure OpenAI Service API version 2022-12-01
and later. This article helps you bring you up to speed on the changes specific to Azure OpenAI.
Authenticating the client
There are several ways to authenticate API requests to Azure OpenAI. We highly recommend using Microsoft Entra ID tokens. See the Azure Identity documentation for more information.
Microsoft Entra ID
There are several ways to authenticate with the Azure OpenAI service using Microsoft Entra ID tokens. The default way is to use the DefaultAzureCredential
class from the @azure/identity
package, but your application might be using a different credential class. For the purposes of this guide, we assume that you are using the DefaultAzureCredential
class. A credential can be created as follows:
import { DefaultAzureCredential } from "@azure/identity";
const credential = new DefaultAzureCredential();
This object is then passed to the second argument of the OpenAIClient
and AssistantsClient
client constructors.
In order to authenticate the AzureOpenAI
client, however, we need to use the getBearerTokenProvider
function from the @azure/identity
package. This function creates a token provider that AzureOpenAI
uses internally to obtain tokens for each request. The token provider is created as follows:
import { DefaultAzureCredential, getBearerTokenProvider } from "@azure/identity";
const credential = new DefaultAzureCredential();
const scope = "https://cognitiveservices.azure.com/.default";
const azureADTokenProvider = getBearerTokenProvider(credential, scope);
azureADTokenProvider
is passed to the options object when creating the AzureOpenAI
client.
(Highly Discouraged) API Key
API keys are not recommended for production use because they are less secure than other authentication methods. Previously, AzureKeyCredential
objects were created as follows to authenticate OpenAIClient
or AssistantsClient
:
import { AzureKeyCredential } from "@azure/openai";
const apiKey = new AzureKeyCredential("your API key");
On the other hand, AzureOpenAI
can be authenticated with an API key by setting the AZURE_OPENAI_API_KEY
environment variable or by setting the apiKey
string property in the options object when creating the AzureOpenAI
client.
Important
Use API keys with caution. Don't include the API key directly in your code, and never post it publicly. If you use an API key, store it securely in Azure Key Vault. For more information about using API keys securely in your apps, see API keys with Azure Key Vault.
For more information about AI services security, see Authenticate requests to Azure AI services.
Constructing the client
import { AzureOpenAI } from "openai";
const deployment = "Your Azure OpenAI deployment";
const apiVersion = "2024-04-01-preview";
const options = { azureADTokenProvider, deployment, apiVersion }
const client = new AzureOpenAI(options);
The endpoint of the Azure OpenAI resource can be specified by setting the endpoint
option but it can also be loaded by the client from the environment variable AZURE_OPENAI_ENDPOINT
. This is the recommended way to set the endpoint because it allows the client to be used in different environments without changing the code and also to protect the endpoint from being exposed in the code.
The API version is required to be specified, this is necessary to ensure that existing code doesn't break between preview API versions. Refer to API versioning documentation to learn more about Azure OpenAI API versions. Additionally, the deployment
property isn't required but it's recommended to be set. Once deployment
is set, it's used as the default deployment for all operations that require it. If the client isn't created with the deployment
option, the model
property in the options object should be set with the deployment name. However, audio operations such as audio.transcriptions.create
require the client to be created with the deployment
option set to the deployment name.
API differences
There are key differences between the OpenAIClient
and AssistantsClient
clients and the AzureOpenAI
client:
- Operations are represented as a flat list of methods in both
OpenAIClient
andAssistantsClient
, for exampleclient.getChatCompletions
. InAzureOpenAI
, operations are grouped in nested groups, for exampleclient.chat.completions.create
. OpenAIClient
andAssistantsClient
rename many of the names used in the Azure OpenAI service API. For example, snake case is used in the API but camel case is used in the client. InAzureOpenAI
, names are kept the same as in the Azure OpenAI service API.
Migration examples
The following sections provide examples of how to migrate from OpenAIClient
and AssistantsClient
to AzureOpenAI
.
Chat completions
const result = await client.chat.completions.create({ messages, model: '', max_tokens: 100 });
Note the following:
- The
getChatCompletions
method has been replaced with thechat.completions.create
method. - The
messages
parameter is now passed in the options object with themessages
property. - The
maxTokens
property has been renamed tomax_tokens
and thedeploymentName
parameter has been removed. Generally, the names of the properties in theoptions
object are the same as in the Azure OpenAI service API, following the snake case convention instead of the camel case convention used in theAssistantsClient
. This is true for all the properties across all requests and responses in theAzureOpenAI
client. - The
deploymentName
parameter isn't needed if the client was created with thedeployment
option. If the client was not created with thedeployment
option, themodel
property in the option object should be set with the deployment name.
Streaming chat completions
const stream = await client.chat.completions.create({ model: '', messages, max_tokens: 100, stream: true });
Azure On Your Data
import "@azure/openai/types";
const azureSearchEndpoint = "Your Azure Search resource endpoint";
const azureSearchIndexName = "Your Azure Search index name";
const result = await client.chat.completions.create({ model: '', messages, data_sources: [{
type: "azure_search",
parameters: {
endpoint: azureSearchEndpoint,
index_name: azureSearchIndexName,
authentication: {
type: "system_assigned_managed_identity",
}
}
}]
});
"@azure/openai/types"
is imported which adds Azure-specific definitions (for example,data_sources
) to the client types.- The
azureExtensionOptions
property has been replaced with the innerdata_sources
property. - The
parameters
property has been added to wrap the parameters of the extension, which mirrors the schema of the Azure OpenAI service API. - Camel case properties have been replaced with snake case properties.
Audio transcription
import { createReadStream } from "fs";
const result = await client.audio.transcriptions.create({
model: '',
file: createReadStream(audioFilePath),
});
- The
getAudioTranscription
method has been replaced with theaudio.transcriptions.create
method. - The
AzureOpenAI
has to be constructed with thedeployment
option set to the deployment name in order to use audio operations such asaudio.transcriptions.create
. - The
model
property is required to be set in the options object but its value isn't used in the operation so feel free to set it to any value. - The
file
property accepts various types includingBuffer
,fs.ReadaStream
, andBlob
but in this example, a file is streamed from disk usingfs.createReadStream
.
Audio translation
import { createReadStream } from "fs";
const result = await client.audio.translations.create({
model: '',
file: createReadStream(audioFilePath),
});
- The
getAudioTranslation
method has been replaced with theaudio.translations.create
method. - All other changes are the same as in the audio transcription example.
Assistants
The following examples show how to migrate some of the AssistantsClient
methods.
Assistant creation
const options = ...;
const assistantResponse = await assistantsClient.beta.assistants.create(
options
);
- The
createAssistant
method has been replaced with thebeta.assistants.create
method
Thread creation
The following example shows how to migrate the createThread
method call.
const assistantThread = await assistantsClient.beta.threads.create();
- The
createThread
method has been replaced with thebeta.threads.create
method
Message creation
The following example shows how to migrate the createMessage
method call.
const threadResponse = await assistantsClient.beta.threads.messages.create(
assistantThread.id,
{
role,
content: message,
}
);
- The
createMessage
method has been replaced with thebeta.threads.messages.create
method. - The message specification has been moved from a parameter list to an object.
Runs
To run an assistant on a thread, the createRun
method is used to create a run, and then a loop is used to poll the run status until it is in a terminal state. The following example shows how to migrate the run creation and polling.
This code can be migrated and simplified by using the createAndPoll
method, which creates a run and polls it until it is in a terminal state.
const runResponse = await assistantsClient.beta.threads.runs.createAndPoll(
assistantThread.id,
{
assistant_id: assistantResponse.id,
},
{ pollIntervalMs: 500 }
);
- The
createRun
method has been replaced with thebeta.threads.runs.create
andcreateAndPoll
methods. - The
createAndPoll
method is used to create a run and poll it until it is in a terminal state.
Processing Run results
Pages can be looped through by using the for await
loop.
for await (const runMessageDatum of runMessages) {
for (const item of runMessageDatum.content) {
...
}
}
Embeddings
The following example shows how to migrate the getEmbeddings
method call.
const embeddings = await client.embeddings.create({ input, model: '' });
- The
getEmbeddings
method has been replaced with theembeddings.create
method. - The
input
parameter is now passed in the options object with theinput
property. - The
deploymentName
parameter has been removed. ThedeploymentName
parameter isn't needed if the client was created with thedeployment
option. If the client was not created with thedeployment
option, themodel
property in the option object should be set with the deployment name.
Image generation
The following example shows how to migrate the getImages
method call.
const results = await client.images.generate({ prompt, model: '', n, size });
- The
getImages
method has been replaced with theimages.generate
method. - The
prompt
parameter is now passed in the options object with theprompt
property. - The
deploymentName
parameter has been removed. ThedeploymentName
parameter isn't needed if the client was created with thedeployment
option. If the client was not created with thedeployment
option, themodel
property in the option object should be set with the deployment name.
Content filter
Content filter results are part of the chat completions response types in OpenAIClient
. However, AzureOpenAI
does not have a direct equivalent to the contentFilterResults
property in the ChatCompletion.Choice
interface. The content filter results can be accessed by importing "@azure/openai/types"
and accessing the content_filter_results
property. The following example shows how to access the content filter results.
import "@azure/openai/types";
const result = await client.chat.completions.create({ model: '', messages });
for (const choice of results.choices) {
const filterResults = choice.content_filter_results;
if (!filterResults) {
console.log("No content filter is found");
return;
}
if (filterResults.error) {
console.log(
`Content filter ran into the error ${filterResults.error.code}: ${filterResults.error.message}`);
}
const { hate, sexual, self_harm, violence } = filterResults;
...
}
- Camel case properties have been replaced with snake case properties.
"@azure/openai/types"
is imported which adds Azure-specific definitions (for example, content_filter_results) to the client types, see the Azure types section for more information.
Comparing Types
The following table explores several type names from @azure/openai
and shows their nearest openai
equivalent. The names differences illustrate several of the above-mentioned changes. This table provides an overview, and more detail and code samples are provided in the following sections.
Old Type Name | Nearest New Type | Symbol Type | Change description |
---|---|---|---|
OpenAIClient |
AzureOpenAI |
Class | This class replaces the former and has no methods in common with it. See the section on AzureOpenAI below. |
AudioResult |
Transcription /Transcription |
Interface | Depending on the calling operation, the two interfaces replace the former one |
AudioResultFormat |
inline union type of the response_format property |
Alias | It doesn't exist |
AudioResultSimpleJson |
Transcription /Transcription |
Interface | Depending on the calling operation, the two interfaces replace the former one |
AudioResultVerboseJson |
N/A | Interface | |
AudioSegment |
N/A | Interface | |
AudioTranscriptionTask |
N/A | Alias | |
AzureChatEnhancementConfiguration , AzureChatEnhancements , AzureChatExtensionConfiguration , AzureChatExtensionConfigurationUnion , AzureChatExtensionDataSourceResponseCitation , AzureChatExtensionsMessageContext , AzureChatExtensionType , AzureChatGroundingEnhancementConfiguration , AzureChatOCREnhancementConfiguration , AzureCosmosDBChatExtensionConfiguration , AzureCosmosDBFieldMappingOptions , AzureExtensionsOptions , AzureGroundingEnhancement , AzureGroundingEnhancementCoordinatePoint , AzureGroundingEnhancementLine , AzureGroundingEnhancementLineSpan , AzureMachineLearningIndexChatExtensionConfiguration , AzureSearchChatExtensionConfiguration , AzureSearchIndexFieldMappingOptions , AzureSearchQueryType , ContentFilterBlocklistIdResult , ContentFilterCitedDetectionResult , ContentFilterDetectionResult , ContentFilterErrorResults , ContentFilterResult , ContentFilterResultDetailsForPrompt , ContentFilterResultsForChoice , ContentFilterSeverity , ContentFilterResultsForPrompt , ContentFilterSuccessResultDetailsForPrompt , ContentFilterSuccessResultsForChoice , ElasticsearchChatExtensionConfiguration , ElasticsearchIndexFieldMappingOptions , ElasticsearchQueryType , ImageGenerationContentFilterResults , ImageGenerationPromptFilterResults , OnYourDataAccessTokenAuthenticationOptions , OnYourDataApiKeyAuthenticationOptions , OnYourDataAuthenticationOptions , OnYourDataAuthenticationOptionsUnion , OnYourDataConnectionStringAuthenticationOptions , OnYourDataDeploymentNameVectorizationSource , OnYourDataEncodedApiKeyAuthenticationOptions , OnYourDataEndpointVectorizationSource , OnYourDataKeyAndKeyIdAuthenticationOptions , OnYourDataModelIdVectorizationSource , OnYourDataSystemAssignedManagedIdentityAuthenticationOptions , OnYourDataUserAssignedManagedIdentityAuthenticationOptions , OnYourDataVectorizationSource , OnYourDataVectorizationSourceType , OnYourDataVectorizationSourceUnion , PineconeChatExtensionConfiguration , PineconeFieldMappingOptions |
N/A | Interfaces and Aliases | See the Azure types section below |
AzureKeyCredential |
N/A | Class | The API key can be provided as a string value |
ChatChoice |
ChatCompletion.Choice |
Interface | |
ChatChoiceLogProbabilityInfo |
Logprobs |
Interface | |
ChatCompletions |
ChatCompletion and ChatCompletionChunk |
Interface | |
ChatCompletionsFunctionToolCall |
ChatCompletionMessageToolCall |
Interface | |
ChatRequestFunctionMessage |
ChatCompletionFunctionMessageParam |
Interface | |
ChatRequestMessage |
ChatCompletionMessageParam |
Interface | |
ChatRequestMessageUnion |
ChatCompletionMessageParam |
||
ChatRequestSystemMessage |
ChatCompletionSystemMessageParam |
Interface | |
ChatRequestToolMessage |
ChatCompletionToolMessageParam |
Interface | |
ChatRequestUserMessage |
ChatCompletionUserMessageParam |
Interface | |
ChatResponseMessage |
Delta / ChatCompletionMessage |
Interface | |
ChatRole |
N/A | Alias | |
ChatTokenLogProbabilityInfo |
TopLogprob |
Interface | |
ChatTokenLogProbabilityResult |
ChatCompletionTokenLogprob |
Interface | |
Choice |
Choice |
Interface | |
Completions |
Completion |
Interface | |
CompletionsFinishReason |
N/A | Alias | |
CompletionsLogProbabilityModel |
Logprobs |
Interface | |
CompletionsUsage |
CompletionUsage |
Interface | |
EmbeddingItem |
Embedding |
Interface | |
Embeddings |
CreateEmbeddingResponse |
Interface | |
EmbeddingsUsage |
CreateEmbeddingResponse.Usage |
Interface | |
EventStream |
Stream |
Interface | |
FunctionCall |
FunctionCall |
Interface | |
FunctionCallPreset |
N/A | Alias | |
FunctionDefinition |
Function |
Interface | |
FunctionName |
N/A | Alias | |
GetAudioTranscriptionOptions |
TranscriptionCreateParams |
Interface | |
GetAudioTranslationOptions |
TranslationCreateParams |
Interface | |
GetChatCompletionsOptions |
ChatCompletionCreateParamsNonStreaming and ChatCompletionCreateParamsStreaming |
Interface | |
GetCompletionsOptions |
CompletionCreateParams |
Interface | |
GetEmbeddingsOptions |
EmbeddingCreateParams |
Interface | |
GetImagesOptions |
ImageGenerateParams |
Interface | |
ImageGenerationData |
Image |
Interface | |
ImageGenerationQuality |
N/A | Alias | |
ImageGenerationResponseFormat |
N/A | Alias | |
ImageGenerations |
ImagesResponse |
Interface | |
ImageGenerationStyle |
N/A | Alias | |
ImageSize |
N/A | Alias | |
MaxTokensFinishDetails |
N/A | Interface | |
OpenAIClientOptions |
AzureClientOptions |
Interface | |
OpenAIError |
OpenAIError |
Interface | |
OpenAIKeyCredential |
N/A | Class | |
StopFinishDetails |
N/A | Interface |
Azure types
AzureOpenAI
connects to the Azure OpenAI service and can call all the operations available in the service. However, the types of the requests and responses are inherited from the OpenAI
and are not yet updated to reflect the additional features supported exclusively by the Azure OpenAI service. TypeScript users will need to import "@azure/openai/types"
from @azure/openai@2.0.0-beta.1
which will merge Azure-specific definitions into existing types. Examples in the Migration examples section show how to do this.