Migrate Azure OpenAI Integration To v1 API | Enable Streaming for Reasoning Models in Azure OpenAI Basic Inference Provider (#4744)

* Refactor Azure OpenAI integration to use OpenAI SDK and the v1 API | Enable streaming for Azure Open AI basic inference provider

* Add info tooltip to inform user about 'Model Type' form field

* Add 'model_type_tooltip' key to multiple language translations

* Validate AZURE_OPENAI_ENDPOINT in provider construction

* remove unused import, update error handler, rescope URL utils

---------

Co-authored-by: Timothy Carambat <rambat1010@gmail.com>
This commit is contained in:
Marcello Fitton
2025-12-10 18:56:55 -08:00
committed by GitHub
parent 692fa755ee
commit a7da757c84
25 changed files with 89 additions and 23 deletions

View File

@@ -9,19 +9,23 @@ const {
class AzureOpenAiLLM {
constructor(embedder = null, modelPreference = null) {
const { AzureOpenAI } = require("openai");
const { OpenAI } = require("openai");
if (!process.env.AZURE_OPENAI_ENDPOINT)
throw new Error("No Azure API endpoint was set.");
if (!process.env.AZURE_OPENAI_KEY)
throw new Error("No Azure API key was set.");
this.apiVersion = "2024-12-01-preview";
this.openai = new AzureOpenAI({
this.openai = new OpenAI({
apiKey: process.env.AZURE_OPENAI_KEY,
apiVersion: this.apiVersion,
endpoint: process.env.AZURE_OPENAI_ENDPOINT,
baseURL: AzureOpenAiLLM.formatBaseUrl(process.env.AZURE_OPENAI_ENDPOINT),
});
this.model = modelPreference ?? process.env.OPEN_MODEL_PREF;
/*
Note: Azure OpenAI deployments do not expose model metadata that would allow us to
programmatically detect whether the deployment uses a reasoning model (o1, o1-mini, o3-mini, etc.).
As a result, we rely on the user to explicitly set AZURE_OPENAI_MODEL_TYPE="reasoning"
when using reasoning models, as incorrect configuration might result in chat errors.
*/
this.isOTypeModel =
process.env.AZURE_OPENAI_MODEL_TYPE === "reasoning" || false;
this.limits = {
@@ -37,6 +41,26 @@ class AzureOpenAiLLM {
);
}
/**
* Formats the Azure OpenAI endpoint URL to the correct format.
* @param {string} azureOpenAiEndpoint - The Azure OpenAI endpoint URL.
* @returns {string} The formatted URL.
*/
static formatBaseUrl(azureOpenAiEndpoint) {
try {
const url = new URL(azureOpenAiEndpoint);
url.pathname = "/openai/v1";
url.protocol = "https";
url.search = "";
url.hash = "";
return url.href;
} catch (error) {
throw new Error(
`"${azureOpenAiEndpoint}" is not a valid URL. Check your settings for the Azure OpenAI provider and set a valid endpoint URL.`
);
}
}
#log(text, ...args) {
console.log(`\x1b[32m[AzureOpenAi]\x1b[0m ${text}`, ...args);
}
@@ -54,13 +78,6 @@ class AzureOpenAiLLM {
}
streamingEnabled() {
// Streaming of reasoning models is not supported
if (this.isOTypeModel) {
this.#log(
"Streaming will be disabled. AZURE_OPENAI_MODEL_TYPE is set to 'reasoning'."
);
return false;
}
return "streamGetChatCompletion" in this;
}

View File

@@ -1,4 +1,5 @@
const { AzureOpenAI } = require("openai");
const { OpenAI } = require("openai");
const { AzureOpenAiLLM } = require("../../../AiProviders/azureOpenAi");
const Provider = require("./ai-provider.js");
const { RetryError } = require("../error.js");
@@ -9,10 +10,9 @@ class AzureOpenAiProvider extends Provider {
model;
constructor(config = { model: null }) {
const client = new AzureOpenAI({
const client = new OpenAI({
apiKey: process.env.AZURE_OPENAI_KEY,
endpoint: process.env.AZURE_OPENAI_ENDPOINT,
apiVersion: "2024-12-01-preview",
baseURL: AzureOpenAiLLM.formatBaseUrl(process.env.AZURE_OPENAI_ENDPOINT),
});
super(client);
this.model = config.model ?? process.env.OPEN_MODEL_PREF;
@@ -84,12 +84,12 @@ class AzureOpenAiProvider extends Provider {
} catch (error) {
// If invalid Auth error we need to abort because no amount of waiting
// will make auth better.
if (error instanceof AzureOpenAI.AuthenticationError) throw error;
if (error instanceof OpenAI.AuthenticationError) throw error;
if (
error instanceof AzureOpenAI.RateLimitError ||
error instanceof AzureOpenAI.InternalServerError ||
error instanceof AzureOpenAI.APIError // Also will catch AuthenticationError!!!
error instanceof OpenAI.RateLimitError ||
error instanceof OpenAI.InternalServerError ||
error instanceof OpenAI.APIError // Also will catch AuthenticationError!!!
) {
throw new RetryError(error.message);
}