| const axios = require('axios'); |
| const { HttpsProxyAgent } = require('https-proxy-agent'); |
| const { EModelEndpoint, defaultModels, CacheKeys } = require('librechat-data-provider'); |
| const { extractBaseURL, inputSchema, processModelData, logAxiosError } = require('~/utils'); |
| const { OllamaClient } = require('~/app/clients/OllamaClient'); |
| const getLogStores = require('~/cache/getLogStores'); |
|
|
| const { openAIApiKey, userProvidedOpenAI } = require('./Config/EndpointService').config; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| const fetchModels = async ({ |
| user, |
| apiKey, |
| baseURL, |
| name = 'OpenAI', |
| azure = false, |
| userIdQuery = false, |
| createTokenConfig = true, |
| tokenKey, |
| }) => { |
| let models = []; |
|
|
| if (!baseURL && !azure) { |
| return models; |
| } |
|
|
| if (!apiKey) { |
| return models; |
| } |
|
|
| if (name && name.toLowerCase().startsWith('ollama')) { |
| return await OllamaClient.fetchModels(baseURL); |
| } |
|
|
| try { |
| const options = { |
| headers: { |
| Authorization: `Bearer ${apiKey}`, |
| }, |
| }; |
|
|
| if (process.env.PROXY) { |
| options.httpsAgent = new HttpsProxyAgent(process.env.PROXY); |
| } |
|
|
| if (process.env.OPENAI_ORGANIZATION && baseURL.includes('openai')) { |
| options.headers['OpenAI-Organization'] = process.env.OPENAI_ORGANIZATION; |
| } |
|
|
| const url = new URL(`${baseURL}${azure ? '' : '/models'}`); |
| if (user && userIdQuery) { |
| url.searchParams.append('user', user); |
| } |
| const res = await axios.get(url.toString(), options); |
|
|
| |
| const input = res.data; |
|
|
| const validationResult = inputSchema.safeParse(input); |
| if (validationResult.success && createTokenConfig) { |
| const endpointTokenConfig = processModelData(input); |
| const cache = getLogStores(CacheKeys.TOKEN_CONFIG); |
| await cache.set(tokenKey ?? name, endpointTokenConfig); |
| } |
| models = input.data.map((item) => item.id); |
| } catch (error) { |
| const logMessage = `Failed to fetch models from ${azure ? 'Azure ' : ''}${name} API`; |
| logAxiosError({ message: logMessage, error }); |
| } |
|
|
| return models; |
| }; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| const fetchOpenAIModels = async (opts, _models = []) => { |
| let models = _models.slice() ?? []; |
| let apiKey = openAIApiKey; |
| const openaiBaseURL = 'https://api.openai.com/v1'; |
| let baseURL = openaiBaseURL; |
| let reverseProxyUrl = process.env.OPENAI_REVERSE_PROXY; |
|
|
| if (opts.assistants && process.env.ASSISTANTS_BASE_URL) { |
| reverseProxyUrl = process.env.ASSISTANTS_BASE_URL; |
| } else if (opts.azure) { |
| return models; |
| |
| |
| |
| |
| |
| } else if (process.env.OPENROUTER_API_KEY) { |
| reverseProxyUrl = 'https://openrouter.ai/api/v1'; |
| apiKey = process.env.OPENROUTER_API_KEY; |
| } |
|
|
| if (reverseProxyUrl) { |
| baseURL = extractBaseURL(reverseProxyUrl); |
| } |
|
|
| const modelsCache = getLogStores(CacheKeys.MODEL_QUERIES); |
|
|
| const cachedModels = await modelsCache.get(baseURL); |
| if (cachedModels) { |
| return cachedModels; |
| } |
|
|
| if (baseURL || opts.azure) { |
| models = await fetchModels({ |
| apiKey, |
| baseURL, |
| azure: opts.azure, |
| user: opts.user, |
| }); |
| } |
|
|
| if (models.length === 0) { |
| return _models; |
| } |
|
|
| if (baseURL === openaiBaseURL) { |
| const regex = /(text-davinci-003|gpt-)/; |
| models = models.filter((model) => regex.test(model)); |
| const instructModels = models.filter((model) => model.includes('instruct')); |
| const otherModels = models.filter((model) => !model.includes('instruct')); |
| models = otherModels.concat(instructModels); |
| } |
|
|
| await modelsCache.set(baseURL, models); |
| return models; |
| }; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| const getOpenAIModels = async (opts) => { |
| let models = defaultModels[EModelEndpoint.openAI]; |
|
|
| if (opts.assistants) { |
| models = defaultModels[EModelEndpoint.assistants]; |
| } else if (opts.azure) { |
| models = defaultModels[EModelEndpoint.azureAssistants]; |
| } |
|
|
| if (opts.plugins) { |
| models = models.filter( |
| (model) => |
| !model.includes('text-davinci') && |
| !model.includes('instruct') && |
| !model.includes('0613') && |
| !model.includes('0314') && |
| !model.includes('0301'), |
| ); |
| } |
|
|
| let key; |
| if (opts.assistants) { |
| key = 'ASSISTANTS_MODELS'; |
| } else if (opts.azure) { |
| key = 'AZURE_OPENAI_MODELS'; |
| } else if (opts.plugins) { |
| key = 'PLUGIN_MODELS'; |
| } else { |
| key = 'OPENAI_MODELS'; |
| } |
|
|
| if (process.env[key]) { |
| models = String(process.env[key]).split(','); |
| return models; |
| } |
|
|
| if (userProvidedOpenAI && !process.env.OPENROUTER_API_KEY) { |
| return models; |
| } |
|
|
| return await fetchOpenAIModels(opts, models); |
| }; |
|
|
| const getChatGPTBrowserModels = () => { |
| let models = ['text-davinci-002-render-sha', 'gpt-4']; |
| if (process.env.CHATGPT_MODELS) { |
| models = String(process.env.CHATGPT_MODELS).split(','); |
| } |
|
|
| return models; |
| }; |
|
|
| const getAnthropicModels = () => { |
| let models = defaultModels[EModelEndpoint.anthropic]; |
| if (process.env.ANTHROPIC_MODELS) { |
| models = String(process.env.ANTHROPIC_MODELS).split(','); |
| } |
|
|
| return models; |
| }; |
|
|
| const getGoogleModels = () => { |
| let models = defaultModels[EModelEndpoint.google]; |
| if (process.env.GOOGLE_MODELS) { |
| models = String(process.env.GOOGLE_MODELS).split(','); |
| } |
|
|
| return models; |
| }; |
|
|
| module.exports = { |
| fetchModels, |
| getOpenAIModels, |
| getChatGPTBrowserModels, |
| getAnthropicModels, |
| getGoogleModels, |
| }; |
|
|