mirror of
https://github.com/fbarrca/obsidian-inlineAI.git
synced 2026-07-22 11:50:24 +00:00
[feat] Add Azure OpenAI support to ChatApiManager and update settings interface for Azure configuration.
This commit is contained in:
parent
149953d1bd
commit
3e25d3e8d1
2 changed files with 121 additions and 8 deletions
76
src/api.ts
76
src/api.ts
|
|
@ -1,5 +1,5 @@
|
|||
// api.ts
|
||||
import { ChatOpenAI } from "@langchain/openai";
|
||||
import { ChatOpenAI, AzureChatOpenAI } from "@langchain/openai";
|
||||
import { ChatOllama } from "@langchain/ollama";
|
||||
import { ChatGoogleGenerativeAI } from "@langchain/google-genai";
|
||||
import {
|
||||
|
|
@ -25,7 +25,12 @@ export type HistoryMessage = {
|
|||
* Class to manage interactions with different chat APIs.
|
||||
*/
|
||||
export class ChatApiManager {
|
||||
private chatClient: ChatOpenAI | ChatOllama | ChatGoogleGenerativeAI | null;
|
||||
private chatClient:
|
||||
| ChatOpenAI
|
||||
| ChatOllama
|
||||
| ChatGoogleGenerativeAI
|
||||
| AzureChatOpenAI
|
||||
| null;
|
||||
private app: App;
|
||||
private settings: InlineAISettings;
|
||||
private messageHistory: MessageQueue<HistoryMessage>;
|
||||
|
|
@ -43,14 +48,45 @@ export class ChatApiManager {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the instance name from an Azure endpoint URL.
|
||||
* @param endpoint - The Azure endpoint URL.
|
||||
* @returns The instance name or null if invalid.
|
||||
*/
|
||||
private extractAzureInstanceName(endpoint: string): string | null {
|
||||
const trimmedEndpoint = endpoint.trim();
|
||||
|
||||
// Match both openai.azure.com and cognitiveservices.azure.com formats
|
||||
const openaiMatch = trimmedEndpoint.match(
|
||||
/https:\/\/([^.]+)\.openai\.azure\.com/,
|
||||
);
|
||||
if (openaiMatch) {
|
||||
return openaiMatch[1];
|
||||
}
|
||||
|
||||
const cognitiveservicesMatch = trimmedEndpoint.match(
|
||||
/https:\/\/([^.]+)\.cognitiveservices\.azure\.com/,
|
||||
);
|
||||
if (cognitiveservicesMatch) {
|
||||
return cognitiveservicesMatch[1];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the appropriate chat client based on the provider specified in settings.
|
||||
* @param settings - Configuration settings for the chat API.
|
||||
* @returns An instance of ChatOpenAI, ChatOllama, or null if initialization fails.
|
||||
* @returns An instance of ChatOpenAI, ChatOllama, AzureChatOpenAI, or null if initialization fails.
|
||||
*/
|
||||
private initializeChatClient(
|
||||
settings: InlineAISettings,
|
||||
): ChatOpenAI | ChatOllama | ChatGoogleGenerativeAI | null {
|
||||
):
|
||||
| ChatOpenAI
|
||||
| ChatOllama
|
||||
| ChatGoogleGenerativeAI
|
||||
| AzureChatOpenAI
|
||||
| null {
|
||||
try {
|
||||
if (settings.messageHistory) {
|
||||
this.messageHistory = new MessageQueue<HistoryMessage>(
|
||||
|
|
@ -83,6 +119,33 @@ export class ChatApiManager {
|
|||
model: settings.model,
|
||||
apiKey: settings.apiKey,
|
||||
});
|
||||
case "azure":
|
||||
if (!settings.apiKey || !settings.azureEndpoint) {
|
||||
new Notice(
|
||||
"⚠️ API key and Azure endpoint are required for Azure provider.",
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Extract instance name from the endpoint URL
|
||||
const instanceName = this.extractAzureInstanceName(
|
||||
settings.azureEndpoint,
|
||||
);
|
||||
if (!instanceName) {
|
||||
new Notice(
|
||||
"⚠️ Invalid Azure endpoint format. Expected: https://your-resource.openai.azure.com",
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
return new AzureChatOpenAI({
|
||||
azureOpenAIApiKey: settings.apiKey,
|
||||
azureOpenAIApiInstanceName: instanceName,
|
||||
azureOpenAIApiDeploymentName: settings.model,
|
||||
azureOpenAIApiVersion:
|
||||
settings.azureApiVersion || "2024-02-15-preview",
|
||||
temperature: 0,
|
||||
});
|
||||
case "custom":
|
||||
if (!settings.apiKey || !settings.customURL) {
|
||||
new Notice(
|
||||
|
|
@ -134,7 +197,10 @@ export class ChatApiManager {
|
|||
];
|
||||
|
||||
try {
|
||||
const aiMessage: AIMessage = await this.chatClient.invoke(messages);
|
||||
const aiMessage = await this.chatClient.invoke(messages);
|
||||
if (typeof aiMessage === "string") {
|
||||
return aiMessage;
|
||||
}
|
||||
return aiMessage.content.toString();
|
||||
} catch (error: any) {
|
||||
console.error("Error calling the chat model:", error);
|
||||
|
|
|
|||
|
|
@ -5,10 +5,12 @@ import { SlashCommand } from "./modules/commands/source";
|
|||
|
||||
// Interface for the settings
|
||||
export interface InlineAISettings {
|
||||
provider: "openai" | "ollama" | "custom" | "gemini";
|
||||
provider: "openai" | "ollama" | "custom" | "gemini" | "azure";
|
||||
model: string;
|
||||
apiKey?: string;
|
||||
customURL?: string;
|
||||
azureEndpoint?: string;
|
||||
azureApiVersion?: string;
|
||||
selectionPrompt: string;
|
||||
cursorPrompt: string;
|
||||
customCommands: SlashCommand[];
|
||||
|
|
@ -22,6 +24,8 @@ export const DEFAULT_SETTINGS: InlineAISettings = {
|
|||
model: "llama3.2",
|
||||
apiKey: "",
|
||||
customURL: "",
|
||||
azureEndpoint: "",
|
||||
azureApiVersion: "2024-02-15-preview",
|
||||
selectionPrompt: selectionPrompt,
|
||||
cursorPrompt: cursorPrompt,
|
||||
customCommands: [],
|
||||
|
|
@ -51,12 +55,13 @@ export class InlineAISettingsTab extends PluginSettingTab {
|
|||
new Setting(containerEl)
|
||||
.setName("Provider")
|
||||
.setDesc(
|
||||
"Choose between OpenAI, Ollama, or a custom OpenAI-compatible endpoint.",
|
||||
"Choose between OpenAI, Ollama, Azure OpenAI, Gemini, or a custom OpenAI-compatible endpoint.",
|
||||
)
|
||||
.addDropdown((dropdown) =>
|
||||
dropdown
|
||||
.addOption("openai", "OpenAI")
|
||||
.addOption("ollama", "Ollama")
|
||||
.addOption("azure", "Azure OpenAI")
|
||||
.addOption("gemini", "Gemini")
|
||||
.addOption("custom", "Custom/OpenAI-compatible")
|
||||
.setValue(this.plugin.settings.provider)
|
||||
|
|
@ -64,6 +69,7 @@ export class InlineAISettingsTab extends PluginSettingTab {
|
|||
this.plugin.settings.provider = value as
|
||||
| "openai"
|
||||
| "ollama"
|
||||
| "azure"
|
||||
| "custom"
|
||||
| "gemini";
|
||||
await this.saveSettings();
|
||||
|
|
@ -88,7 +94,8 @@ export class InlineAISettingsTab extends PluginSettingTab {
|
|||
if (
|
||||
this.plugin.settings.provider === "openai" ||
|
||||
this.plugin.settings.provider === "custom" ||
|
||||
this.plugin.settings.provider === "gemini"
|
||||
this.plugin.settings.provider === "gemini" ||
|
||||
this.plugin.settings.provider === "azure"
|
||||
) {
|
||||
new Setting(containerEl)
|
||||
.setName("API key")
|
||||
|
|
@ -120,6 +127,46 @@ export class InlineAISettingsTab extends PluginSettingTab {
|
|||
});
|
||||
}
|
||||
|
||||
// Azure-specific settings
|
||||
if (this.plugin.settings.provider === "azure") {
|
||||
// Azure endpoint setting
|
||||
new Setting(containerEl)
|
||||
.setName("Azure endpoint")
|
||||
.setDesc(
|
||||
"Enter your Azure OpenAI endpoint URL (e.g. https://your-resource.openai.azure.com).",
|
||||
)
|
||||
.addText((text) => {
|
||||
text.setPlaceholder(
|
||||
"https://your-resource.openai.azure.com",
|
||||
)
|
||||
.setValue(this.plugin.settings.azureEndpoint || "")
|
||||
.inputEl.addEventListener("blur", async () => {
|
||||
this.plugin.settings.azureEndpoint = text
|
||||
.getValue()
|
||||
.trim();
|
||||
await this.saveSettings();
|
||||
});
|
||||
});
|
||||
|
||||
// Azure API version setting
|
||||
new Setting(containerEl)
|
||||
.setName("Azure API version")
|
||||
.setDesc("Enter the Azure OpenAI API version to use.")
|
||||
.addText((text) => {
|
||||
text.setPlaceholder("2024-02-15-preview")
|
||||
.setValue(
|
||||
this.plugin.settings.azureApiVersion ||
|
||||
"2024-02-15-preview",
|
||||
)
|
||||
.inputEl.addEventListener("blur", async () => {
|
||||
this.plugin.settings.azureApiVersion = text
|
||||
.getValue()
|
||||
.trim();
|
||||
await this.saveSettings();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Advanced Section
|
||||
containerEl.createEl("h3", { text: "Advanced" });
|
||||
// Selection Prompt setting
|
||||
|
|
|
|||
Loading…
Reference in a new issue