Skip to content

added support for azure openai #102

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ COPY --from=builder /app/config.json ./
COPY --from=builder /app/dist ./dist

# Set environment variables (Recommended to set at runtime, avoid hardcoding)
ENV AZURE_OPENAI_RESOURCE_NAME=${AZURE_OPENAI_RESOURCE_NAME}
ENV AZURE_OPENAI_API_KEY=${AZURE_OPENAI_API_KEY}
ENV AZURE_OPENAI_API_VERSION=${AZURE_OPENAI_API_VERSION}
ENV GEMINI_API_KEY=${GEMINI_API_KEY}
ENV OPENAI_API_KEY=${OPENAI_API_KEY}
ENV JINA_API_KEY=${JINA_API_KEY}
Expand Down
27 changes: 26 additions & 1 deletion config.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
"JINA_API_KEY": "",
"BRAVE_API_KEY": "",
"SERPER_API_KEY": "",
"DEFAULT_MODEL_NAME": ""
"DEFAULT_MODEL_NAME": "",
"AZURE_OPENAI_RESOURCE_NAME": "",
"AZURE_OPENAI_API_KEY": "",
"AZURE_OPENAI_API_VERSION": ""
},
"defaults": {
"search_provider": "jina",
Expand All @@ -23,6 +26,9 @@
"clientConfig": {
"compatibility": "strict"
}
},
"azure":{
"createClient": "createAzure"
}
},
"models": {
Expand Down Expand Up @@ -61,6 +67,25 @@
"agentBeastMode": { "temperature": 0.7 },
"fallback": { "temperature": 0 }
}
},
"azure":{
"default": {
"model": "gpt-4o",
"temperature": 0,
"maxTokens": 10000
},
"tools": {
"coder": { "temperature": 0.7 },
"searchGrounding": { "temperature": 0 },
"dedup": { "temperature": 0.1 },
"evaluator": {},
"errorAnalyzer": {},
"queryRewriter": { "temperature": 0.1 },
"agent": { "temperature": 0.7 },
"agentBeastMode": { "temperature": 0.7 },
"fallback": { "temperature": 0 }
}

}
}
}
3 changes: 3 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ services:
context: .
dockerfile: Dockerfile
environment:
- AZURE_OPENAI_RESOURCE_NAME=${AZURE_OPENAI_RESOURCE_NAME}
- AZURE_OPENAI_API_KEY=${AZURE_OPENAI_API_KEY}
- AZURE_OPENAI_API_VERSION=${AZURE_OPENAI_API_VERSION}
- GEMINI_API_KEY=${GEMINI_API_KEY}
- OPENAI_API_KEY=${OPENAI_API_KEY}
- JINA_API_KEY=${JINA_API_KEY}
Expand Down
86 changes: 81 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"dependencies": {
"@ai-sdk/google": "^1.0.0",
"@ai-sdk/openai": "^1.1.9",
"@ai-sdk/azure": "^1.3.16",
"@types/jsdom": "^21.1.7",
"ai": "^4.1.26",
"axios": "^1.7.9",
Expand Down
86 changes: 68 additions & 18 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import dotenv from 'dotenv';
import { ProxyAgent, setGlobalDispatcher } from 'undici';
import { createGoogleGenerativeAI } from '@ai-sdk/google';
import { createOpenAI, OpenAIProviderSettings } from '@ai-sdk/openai';
import { createAzure, AzureOpenAIProviderSettings } from '@ai-sdk/azure'
import configJson from '../config.json';
// Load environment variables
dotenv.config();

// Types
export type LLMProvider = 'openai' | 'gemini' | 'vertex';
export type LLMProvider = 'openai' | 'gemini' | 'vertex' | 'azure';
export type ToolName = keyof typeof configJson.models.gemini.tools;

// Type definitions for our config structure
Expand Down Expand Up @@ -46,6 +47,9 @@ export const BRAVE_API_KEY = env.BRAVE_API_KEY;
export const SERPER_API_KEY = env.SERPER_API_KEY;
export const SEARCH_PROVIDER = configJson.defaults.search_provider;
export const STEP_SLEEP = configJson.defaults.step_sleep;
export const AZURE_OPENAI_RESOURCE_NAME = env.AZURE_OPENAI_RESOURCE_NAME;
export const AZURE_OPENAI_API_KEY = env.AZURE_OPENAI_API_KEY;
export const AZURE_OPENAI_API_VERSION = env.AZURE_OPENAI_API_VERSION;

// Determine LLM provider
export const LLM_PROVIDER: LLMProvider = (() => {
Expand All @@ -57,7 +61,7 @@ export const LLM_PROVIDER: LLMProvider = (() => {
})();

function isValidProvider(provider: string): provider is LLMProvider {
return provider === 'openai' || provider === 'gemini' || provider === 'vertex';
return provider === 'openai' || provider === 'gemini' || provider === 'vertex' || provider === 'azure';
}

interface ToolConfig {
Expand Down Expand Up @@ -92,6 +96,27 @@ export function getMaxTokens(toolName: ToolName): number {
export function getModel(toolName: ToolName) {
const config = getToolConfig(toolName);
const providerConfig = (configJson.providers as Record<string, ProviderConfig | undefined>)[LLM_PROVIDER];
if (LLM_PROVIDER === 'azure') {
if (!AZURE_OPENAI_API_KEY) {
throw new Error('AZURE_OPENAI_API_KEY not found');
}

if (!AZURE_OPENAI_RESOURCE_NAME) {
throw new Error('AZURE_OPENAI_RESOURCE_NAME not found');
}

if (!AZURE_OPENAI_API_VERSION) {
throw new Error('AZURE_OPENAI_API_VERSION not found');
}

const opt: AzureOpenAIProviderSettings = {
apiKey: AZURE_OPENAI_API_KEY,
resourceName: AZURE_OPENAI_RESOURCE_NAME,
apiVersion: AZURE_OPENAI_API_VERSION
};

return createAzure(opt)(config.model);
}

if (LLM_PROVIDER === 'openai') {
if (!OPENAI_API_KEY) {
Expand Down Expand Up @@ -131,29 +156,54 @@ export function getModel(toolName: ToolName) {
// Validate required environment variables
if (LLM_PROVIDER === 'gemini' && !GEMINI_API_KEY) throw new Error("GEMINI_API_KEY not found");
if (LLM_PROVIDER === 'openai' && !OPENAI_API_KEY) throw new Error("OPENAI_API_KEY not found");
if (LLM_PROVIDER === 'azure' && !AZURE_OPENAI_API_KEY) throw new Error("AZURE_OPENAI_API_KEY not found");
if (LLM_PROVIDER === 'azure' && !AZURE_OPENAI_RESOURCE_NAME) throw new Error("AZURE_OPENAI_RESOURCE_NAME not found");
if (LLM_PROVIDER === 'azure' && !AZURE_OPENAI_API_VERSION) throw new Error("AZURE_OPENAI_API_VERSION not found");
if (!JINA_API_KEY) throw new Error("JINA_API_KEY not found");

// Log all configurations
const providerModels: Record<LLMProvider, string> = {
openai : configJson.models.openai.default.model,
gemini : configJson.models.gemini.default.model,
vertex : configJson.models.gemini.default.model, // vertex uses Gemini models
azure : configJson.models.azure.default.model,
};

const providerExtras: Record<LLMProvider, Record<string, unknown>> = {
openai : { baseUrl: OPENAI_BASE_URL },
azure : { resourceName: AZURE_OPENAI_RESOURCE_NAME, apiVersion: AZURE_OPENAI_API_VERSION },
gemini : {},
vertex : {},
};

const providerNameForTools: Record<LLMProvider, keyof typeof configJson.models> = {
openai : 'openai',
gemini : 'gemini',
vertex : 'gemini', // vertex shares the Gemini tool settings
azure : 'azure',
};

const configSummary = {
provider: {
name: LLM_PROVIDER,
model: LLM_PROVIDER === 'openai'
? configJson.models.openai.default.model
: configJson.models.gemini.default.model,
...(LLM_PROVIDER === 'openai' && { baseUrl: OPENAI_BASE_URL })
},
search: {
provider: SEARCH_PROVIDER
name : LLM_PROVIDER,
model: providerModels[LLM_PROVIDER],
...providerExtras[LLM_PROVIDER], // adds baseUrl / endpoint when present
},

search: { provider: SEARCH_PROVIDER },

tools: Object.fromEntries(
Object.keys(configJson.models[LLM_PROVIDER === 'vertex' ? 'gemini' : LLM_PROVIDER].tools).map(name => [
Object.keys(
configJson.models[providerNameForTools[LLM_PROVIDER]].tools
).map(name => [
name,
getToolConfig(name as ToolName)
])
getToolConfig(name as ToolName),
]),
),
defaults: {
stepSleep: STEP_SLEEP
}

defaults: { stepSleep: STEP_SLEEP },
};

console.log('Configuration Summary:', JSON.stringify(configSummary, null, 2));
console.log(
'Configuration Summary:',
JSON.stringify(configSummary, null, 2),
);