mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-08 22:21:23 +00:00
fix: improve Azure OpenAI detection and update API version for o3 models
- Updated default Azure API version from 2024-08-01-preview to 2025-03-01-preview to support newer models like o3-mini - Enhanced Azure OpenAI detection logic to check for .openai.azure.com domains and /openai/deployments/ paths - Added comprehensive tests for Azure OpenAI detection scenarios - Fixed test mocks to properly support AzureOpenAI client Fixes #7498
This commit is contained in:
parent
aee531a143
commit
4f7a858a01
3 changed files with 102 additions and 44 deletions
|
|
@ -268,7 +268,8 @@ export const openAiModelInfoSaneDefaults: ModelInfo = {
|
|||
|
||||
// https://learn.microsoft.com/en-us/azure/ai-services/openai/api-version-deprecation
|
||||
// https://learn.microsoft.com/en-us/azure/ai-services/openai/reference#api-specs
|
||||
export const azureOpenAiDefaultApiVersion = "2024-08-01-preview"
|
||||
// Updated to support newer models like o3-mini
|
||||
export const azureOpenAiDefaultApiVersion = "2025-03-01-preview"
|
||||
|
||||
export const OPENAI_NATIVE_DEFAULT_TEMPERATURE = 0
|
||||
export const GPT5_DEFAULT_TEMPERATURE = 1.0
|
||||
|
|
|
|||
|
|
@ -12,19 +12,43 @@ const mockCreate = vitest.fn()
|
|||
|
||||
vitest.mock("openai", () => {
|
||||
const mockConstructor = vitest.fn()
|
||||
return {
|
||||
__esModule: true,
|
||||
default: mockConstructor.mockImplementation(() => ({
|
||||
chat: {
|
||||
completions: {
|
||||
create: mockCreate.mockImplementation(async (options) => {
|
||||
if (!options.stream) {
|
||||
return {
|
||||
id: "test-completion",
|
||||
const mockImplementation = () => ({
|
||||
chat: {
|
||||
completions: {
|
||||
create: mockCreate.mockImplementation(async (options) => {
|
||||
if (!options.stream) {
|
||||
return {
|
||||
id: "test-completion",
|
||||
choices: [
|
||||
{
|
||||
message: { role: "assistant", content: "Test response", refusal: null },
|
||||
finish_reason: "stop",
|
||||
index: 0,
|
||||
},
|
||||
],
|
||||
usage: {
|
||||
prompt_tokens: 10,
|
||||
completion_tokens: 5,
|
||||
total_tokens: 15,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
[Symbol.asyncIterator]: async function* () {
|
||||
yield {
|
||||
choices: [
|
||||
{
|
||||
message: { role: "assistant", content: "Test response", refusal: null },
|
||||
finish_reason: "stop",
|
||||
delta: { content: "Test response" },
|
||||
index: 0,
|
||||
},
|
||||
],
|
||||
usage: null,
|
||||
}
|
||||
yield {
|
||||
choices: [
|
||||
{
|
||||
delta: {},
|
||||
index: 0,
|
||||
},
|
||||
],
|
||||
|
|
@ -34,38 +58,17 @@ vitest.mock("openai", () => {
|
|||
total_tokens: 15,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
[Symbol.asyncIterator]: async function* () {
|
||||
yield {
|
||||
choices: [
|
||||
{
|
||||
delta: { content: "Test response" },
|
||||
index: 0,
|
||||
},
|
||||
],
|
||||
usage: null,
|
||||
}
|
||||
yield {
|
||||
choices: [
|
||||
{
|
||||
delta: {},
|
||||
index: 0,
|
||||
},
|
||||
],
|
||||
usage: {
|
||||
prompt_tokens: 10,
|
||||
completion_tokens: 5,
|
||||
total_tokens: 15,
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
}),
|
||||
},
|
||||
},
|
||||
}
|
||||
}),
|
||||
},
|
||||
})),
|
||||
},
|
||||
})
|
||||
|
||||
return {
|
||||
__esModule: true,
|
||||
default: mockConstructor.mockImplementation(mockImplementation),
|
||||
AzureOpenAI: mockConstructor.mockImplementation(mockImplementation),
|
||||
}
|
||||
})
|
||||
|
||||
|
|
@ -849,6 +852,46 @@ describe("OpenAiHandler", () => {
|
|||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("Azure OpenAI Detection", () => {
|
||||
it("should detect Azure OpenAI from .openai.azure.com domain", () => {
|
||||
const azureHandler = new OpenAiHandler({
|
||||
...mockOptions,
|
||||
openAiBaseUrl: "https://myresource.openai.azure.com",
|
||||
})
|
||||
expect(azureHandler).toBeInstanceOf(OpenAiHandler)
|
||||
// The handler should use AzureOpenAI client internally
|
||||
})
|
||||
|
||||
it("should detect Azure OpenAI from URL containing /openai/deployments/", () => {
|
||||
const azureHandler = new OpenAiHandler({
|
||||
...mockOptions,
|
||||
openAiBaseUrl: "https://myresource.openai.azure.com/openai/deployments/mymodel",
|
||||
})
|
||||
expect(azureHandler).toBeInstanceOf(OpenAiHandler)
|
||||
// The handler should use AzureOpenAI client internally
|
||||
})
|
||||
|
||||
it("should detect Azure OpenAI when openAiUseAzure is true", () => {
|
||||
const azureHandler = new OpenAiHandler({
|
||||
...mockOptions,
|
||||
openAiBaseUrl: "https://custom-endpoint.com",
|
||||
openAiUseAzure: true,
|
||||
})
|
||||
expect(azureHandler).toBeInstanceOf(OpenAiHandler)
|
||||
// The handler should use AzureOpenAI client internally
|
||||
})
|
||||
|
||||
it("should use updated Azure API version for o3 models", () => {
|
||||
const azureHandler = new OpenAiHandler({
|
||||
...mockOptions,
|
||||
openAiBaseUrl: "https://myresource.openai.azure.com",
|
||||
openAiModelId: "o3-mini",
|
||||
})
|
||||
expect(azureHandler).toBeInstanceOf(OpenAiHandler)
|
||||
// The handler should use the updated API version (2025-03-01-preview)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("getOpenAiModels", () => {
|
||||
|
|
|
|||
|
|
@ -40,7 +40,8 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
|
|||
const apiKey = this.options.openAiApiKey ?? "not-provided"
|
||||
const isAzureAiInference = this._isAzureAiInference(this.options.openAiBaseUrl)
|
||||
const urlHost = this._getUrlHost(this.options.openAiBaseUrl)
|
||||
const isAzureOpenAi = urlHost === "azure.com" || urlHost.endsWith(".azure.com") || options.openAiUseAzure
|
||||
// Improved Azure detection: check for various Azure OpenAI URL patterns
|
||||
const isAzureOpenAi = this._isAzureOpenAi(this.options.openAiBaseUrl) || options.openAiUseAzure
|
||||
|
||||
const headers = {
|
||||
...DEFAULT_HEADERS,
|
||||
|
|
@ -403,6 +404,19 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
|
|||
return urlHost.endsWith(".services.ai.azure.com")
|
||||
}
|
||||
|
||||
private _isAzureOpenAi(baseUrl?: string): boolean {
|
||||
if (!baseUrl) return false
|
||||
const urlHost = this._getUrlHost(baseUrl)
|
||||
// Check for various Azure OpenAI URL patterns
|
||||
return (
|
||||
urlHost === "azure.com" ||
|
||||
urlHost.endsWith(".azure.com") ||
|
||||
urlHost.endsWith(".openai.azure.com") ||
|
||||
// Check if URL contains Azure OpenAI specific paths
|
||||
baseUrl.includes("/openai/deployments/")
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds max_completion_tokens to the request body if needed based on provider configuration
|
||||
* Note: max_tokens is deprecated in favor of max_completion_tokens as per OpenAI documentation
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue