| import { ProxyAgent } from 'undici'; |
| import { Providers } from '@librechat/agents'; |
| import { KnownEndpoints, EModelEndpoint } from 'librechat-data-provider'; |
| import type * as t from '~/types'; |
| import { getLLMConfig as getAnthropicLLMConfig } from '~/endpoints/anthropic/llm'; |
| import { getOpenAILLMConfig, extractDefaultParams } from './llm'; |
| import { getGoogleConfig } from '~/endpoints/google/llm'; |
| import { transformToOpenAIConfig } from './transform'; |
| import { constructAzureURL } from '~/utils/azure'; |
| import { createFetch } from '~/utils/generators'; |
|
|
| type Fetch = (input: string | URL | Request, init?: RequestInit) => Promise<Response>; |
|
|
| |
| |
| |
| |
| |
| |
| |
| export function getOpenAIConfig( |
| apiKey: string, |
| options: t.OpenAIConfigOptions = {}, |
| endpoint?: string | null, |
| ): t.OpenAIConfigResult { |
| const { |
| proxy, |
| addParams, |
| dropParams, |
| defaultQuery, |
| directEndpoint, |
| streaming = true, |
| modelOptions = {}, |
| reverseProxyUrl: baseURL, |
| } = options; |
|
|
| |
| const defaultParams = extractDefaultParams(options.customParams?.paramDefinitions); |
|
|
| let llmConfig: t.OAIClientOptions; |
| let tools: t.LLMConfigResult['tools']; |
| const isAnthropic = options.customParams?.defaultParamsEndpoint === EModelEndpoint.anthropic; |
| const isGoogle = options.customParams?.defaultParamsEndpoint === EModelEndpoint.google; |
|
|
| const useOpenRouter = |
| !isAnthropic && |
| !isGoogle && |
| ((baseURL && baseURL.includes(KnownEndpoints.openrouter)) || |
| (endpoint != null && endpoint.toLowerCase().includes(KnownEndpoints.openrouter))); |
| const isVercel = |
| !isAnthropic && |
| !isGoogle && |
| ((baseURL && baseURL.includes('ai-gateway.vercel.sh')) || |
| (endpoint != null && endpoint.toLowerCase().includes(KnownEndpoints.vercel))); |
|
|
| let azure = options.azure; |
| let headers = options.headers; |
| if (isAnthropic) { |
| const anthropicResult = getAnthropicLLMConfig(apiKey, { |
| modelOptions, |
| proxy: options.proxy, |
| reverseProxyUrl: baseURL, |
| addParams, |
| dropParams, |
| defaultParams, |
| }); |
| |
| const transformed = transformToOpenAIConfig({ |
| addParams, |
| dropParams, |
| llmConfig: anthropicResult.llmConfig, |
| fromEndpoint: EModelEndpoint.anthropic, |
| }); |
| llmConfig = transformed.llmConfig; |
| tools = anthropicResult.tools; |
| if (transformed.configOptions?.defaultHeaders) { |
| headers = Object.assign(headers ?? {}, transformed.configOptions?.defaultHeaders); |
| } |
| } else if (isGoogle) { |
| const googleResult = getGoogleConfig( |
| apiKey, |
| { |
| modelOptions, |
| reverseProxyUrl: baseURL ?? undefined, |
| authHeader: true, |
| addParams, |
| dropParams, |
| defaultParams, |
| }, |
| true, |
| ); |
| |
| const transformed = transformToOpenAIConfig({ |
| addParams, |
| dropParams, |
| defaultParams, |
| tools: googleResult.tools, |
| llmConfig: googleResult.llmConfig, |
| fromEndpoint: EModelEndpoint.google, |
| }); |
| llmConfig = transformed.llmConfig; |
| tools = transformed.tools; |
| } else { |
| const openaiResult = getOpenAILLMConfig({ |
| azure, |
| apiKey, |
| baseURL, |
| endpoint, |
| streaming, |
| addParams, |
| dropParams, |
| defaultParams, |
| modelOptions, |
| useOpenRouter, |
| }); |
| llmConfig = openaiResult.llmConfig; |
| azure = openaiResult.azure; |
| tools = openaiResult.tools; |
| } |
|
|
| const configOptions: t.OpenAIConfiguration = {}; |
| if (baseURL) { |
| configOptions.baseURL = baseURL; |
| } |
| if (useOpenRouter || isVercel) { |
| configOptions.defaultHeaders = Object.assign( |
| { |
| 'HTTP-Referer': 'https://librechat.ai', |
| 'X-Title': 'LibreChat', |
| }, |
| headers, |
| ); |
| } else if (headers) { |
| configOptions.defaultHeaders = headers; |
| } |
|
|
| if (defaultQuery) { |
| configOptions.defaultQuery = defaultQuery; |
| } |
|
|
| if (proxy) { |
| const proxyAgent = new ProxyAgent(proxy); |
| configOptions.fetchOptions = { |
| dispatcher: proxyAgent, |
| }; |
| } |
|
|
| if (azure && !isAnthropic) { |
| const constructAzureResponsesApi = () => { |
| if (!llmConfig.useResponsesApi || !azure) { |
| return; |
| } |
|
|
| const updatedUrl = configOptions.baseURL?.replace(/\/deployments(?:\/.*)?$/, '/v1'); |
|
|
| configOptions.baseURL = constructAzureURL({ |
| baseURL: updatedUrl || 'https://${INSTANCE_NAME}.openai.azure.com/openai/v1', |
| azureOptions: azure, |
| }); |
|
|
| configOptions.defaultHeaders = { |
| ...configOptions.defaultHeaders, |
| 'api-key': apiKey, |
| }; |
| configOptions.defaultQuery = { |
| ...configOptions.defaultQuery, |
| 'api-version': configOptions.defaultQuery?.['api-version'] ?? 'preview', |
| }; |
| }; |
|
|
| constructAzureResponsesApi(); |
| } |
|
|
| if (process.env.OPENAI_ORGANIZATION && !isAnthropic) { |
| configOptions.organization = process.env.OPENAI_ORGANIZATION; |
| } |
|
|
| if (directEndpoint === true && configOptions?.baseURL != null) { |
| configOptions.fetch = createFetch({ |
| directEndpoint: directEndpoint, |
| reverseProxyUrl: configOptions?.baseURL, |
| }) as unknown as Fetch; |
| } |
|
|
| const result: t.OpenAIConfigResult = { |
| llmConfig, |
| configOptions, |
| tools, |
| }; |
| if (useOpenRouter) { |
| result.provider = Providers.OPENROUTER; |
| } |
| return result; |
| } |
|
|