From 3ceb881de2409022c3d7ee2c152d9b78a0f25a0d Mon Sep 17 00:00:00 2001 From: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com> Date: Wed, 11 Sep 2024 08:07:37 -0400 Subject: [PATCH] Add azure openai support --- src/api/openai.ts | 21 ++++++++++++++++----- src/utils/openai-format.ts | 3 ++- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/api/openai.ts b/src/api/openai.ts index c0b61e4..4e520d0 100644 --- a/src/api/openai.ts +++ b/src/api/openai.ts @@ -1,5 +1,5 @@ import { Anthropic } from "@anthropic-ai/sdk" -import OpenAI from "openai" +import OpenAI, { AzureOpenAI } from "openai" import { ApiHandler, ApiHandlerMessageResponse } from "." import { ApiHandlerOptions, ModelInfo, openAiModelInfoSaneDefaults } from "../shared/api" import { convertToAnthropicMessage, convertToOpenAiMessages } from "../utils/openai-format" @@ -10,10 +10,21 @@ export class OpenAiHandler implements ApiHandler { constructor(options: ApiHandlerOptions) { this.options = options - this.client = new OpenAI({ - baseURL: this.options.openAiBaseUrl, - apiKey: this.options.openAiApiKey, - }) + // Azure API shape slightly differs from the core API shape: https://github.com/openai/openai-node?tab=readme-ov-file#microsoft-azure-openai + if (this.options.openAiBaseUrl?.toLowerCase().includes("azure.com")) { + this.client = new AzureOpenAI({ + baseURL: this.options.openAiBaseUrl, + apiKey: this.options.openAiApiKey, + // 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 + apiVersion: "2024-08-01-preview", + }) + } else { + this.client = new OpenAI({ + baseURL: this.options.openAiBaseUrl, + apiKey: this.options.openAiApiKey, + }) + } } async createMessage( diff --git a/src/utils/openai-format.ts b/src/utils/openai-format.ts index ead1bc0..1bed7dc 100644 --- a/src/utils/openai-format.ts +++ b/src/utils/openai-format.ts @@ -65,6 +65,7 @@ export function convertToOpenAiMessages( // I ran into an issue where if I gave feedback for one of many tool uses, the request would fail. // "Messages following `tool_use` blocks must begin with a matching number of `tool_result` blocks." // Therefore we need to send these images after the tool result messages + // NOTE: it's actually okay to have multiple user messages in a row, the model will treat them as a continuation of the same input (this way works better than combining them into one message, since the tool result specifically mentions (see following user message for image) if (toolResultImages.length > 0) { openAiMessages.push({ role: "user", @@ -106,7 +107,7 @@ export function convertToOpenAiMessages( { nonToolMessages: [], toolMessages: [] } ) - // Process non-tool messages FIRST + // Process non-tool messages let content: string | undefined if (nonToolMessages.length > 0) { content = nonToolMessages