From ff057152e2a1183b70670c41ed664b708bf30b79 Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Thu, 8 Feb 2024 10:06:58 -0500 Subject: [PATCH] =?UTF-8?q?=F0=9F=91=A4=20feat:=20User=20ID=20in=20Model?= =?UTF-8?q?=20Query;=20chore:=20cleanup=20ModelService=20(#1753)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: send the LibreChat user ID as a query param when fetching the list of models * chore: update bun * chore: change bun command for building data-provider * refactor: prefer use of `getCustomConfig` to access custom config, also move to `server/services/Config` * refactor: make endpoints/custom option for the config optional, add userIdQuery, and use modelQueries log store in ModelService * refactor(ModelService): use env variables at runtime, use default models from data-provider, and add tests * docs: add `userIdQuery` * fix(ci): import changed --- api/cache/getLogStores.js | 5 + api/server/controllers/ModelController.js | 4 +- api/server/services/AuthService.js | 2 +- api/server/services/AuthService.spec.js | 4 +- .../services/Config}/getCustomConfig.js | 4 +- api/server/services/Config/index.js | 2 + .../services/Config/loadConfigEndpoints.js | 12 +- .../services/Config/loadConfigModels.js | 27 ++- .../services/Config/loadCustomConfig.js | 3 +- .../services/Config/loadDefaultModels.js | 18 +- .../Endpoints/custom/initializeClient.js | 2 +- api/server/services/ModelService.js | 112 +++++---- api/server/services/ModelService.spec.js | 212 ++++++++++++++++++ bun.lockb | Bin 857707 -> 859049 bytes docs/install/configuration/custom_config.md | 3 + package.json | 4 +- packages/data-provider/src/config.ts | 8 +- 17 files changed, 339 insertions(+), 83 deletions(-) rename api/{cache => server/services/Config}/getCustomConfig.js (80%) create mode 100644 api/server/services/ModelService.spec.js diff --git a/api/cache/getLogStores.js b/api/cache/getLogStores.js index 7f759e5f3..894edd216 100644 --- a/api/cache/getLogStores.js +++ b/api/cache/getLogStores.js @@ -31,6 +31,10 @@ const genTitle = isEnabled(USE_REDIS) // ttl: 2 minutes ? new Keyv({ store: keyvRedis, ttl: 120000 }) : new Keyv({ namespace: CacheKeys.GEN_TITLE, ttl: 120000 }); +const modelQueries = isEnabled(process.env.USE_REDIS) + ? new Keyv({ store: keyvRedis }) + : new Keyv({ namespace: 'models' }); + const namespaces = { [CacheKeys.CONFIG_STORE]: config, pending_req, @@ -44,6 +48,7 @@ const namespaces = { logins: createViolationInstance('logins'), [CacheKeys.TOKEN_CONFIG]: tokenConfig, [CacheKeys.GEN_TITLE]: genTitle, + [CacheKeys.MODEL_QUERIES]: modelQueries, }; /** diff --git a/api/server/controllers/ModelController.js b/api/server/controllers/ModelController.js index 2d23961e1..0025ef910 100644 --- a/api/server/controllers/ModelController.js +++ b/api/server/controllers/ModelController.js @@ -9,8 +9,8 @@ async function modelController(req, res) { res.send(cachedModelsConfig); return; } - const defaultModelsConfig = await loadDefaultModels(); - const customModelsConfig = await loadConfigModels(); + const defaultModelsConfig = await loadDefaultModels(req); + const customModelsConfig = await loadConfigModels(req); const modelConfig = { ...defaultModelsConfig, ...customModelsConfig }; diff --git a/api/server/services/AuthService.js b/api/server/services/AuthService.js index 62e3ee839..0811b10fa 100644 --- a/api/server/services/AuthService.js +++ b/api/server/services/AuthService.js @@ -1,7 +1,7 @@ const crypto = require('crypto'); const bcrypt = require('bcryptjs'); const { registerSchema, errorsToString } = require('~/strategies/validators'); -const getCustomConfig = require('~/cache/getCustomConfig'); +const getCustomConfig = require('~/server/services/Config/getCustomConfig'); const Token = require('~/models/schema/tokenSchema'); const { sendEmail } = require('~/server/utils'); const Session = require('~/models/Session'); diff --git a/api/server/services/AuthService.spec.js b/api/server/services/AuthService.spec.js index 23aad21d3..fb5d8e253 100644 --- a/api/server/services/AuthService.spec.js +++ b/api/server/services/AuthService.spec.js @@ -1,7 +1,7 @@ -const getCustomConfig = require('~/cache/getCustomConfig'); +const getCustomConfig = require('~/server/services/Config/getCustomConfig'); const { isDomainAllowed } = require('./AuthService'); -jest.mock('~/cache/getCustomConfig', () => jest.fn()); +jest.mock('~/server/services/Config/getCustomConfig', () => jest.fn()); describe('isDomainAllowed', () => { it('should allow domain when customConfig is not available', async () => { diff --git a/api/cache/getCustomConfig.js b/api/server/services/Config/getCustomConfig.js similarity index 80% rename from api/cache/getCustomConfig.js rename to api/server/services/Config/getCustomConfig.js index 6d5cf8f27..a479ca37b 100644 --- a/api/cache/getCustomConfig.js +++ b/api/server/services/Config/getCustomConfig.js @@ -1,6 +1,6 @@ const { CacheKeys } = require('librechat-data-provider'); -const loadCustomConfig = require('~/server/services/Config/loadCustomConfig'); -const getLogStores = require('./getLogStores'); +const loadCustomConfig = require('./loadCustomConfig'); +const getLogStores = require('~/cache/getLogStores'); /** * Retrieves the configuration object diff --git a/api/server/services/Config/index.js b/api/server/services/Config/index.js index 57a00bf51..2e8ccb143 100644 --- a/api/server/services/Config/index.js +++ b/api/server/services/Config/index.js @@ -1,4 +1,5 @@ const { config } = require('./EndpointService'); +const getCustomConfig = require('./getCustomConfig'); const loadCustomConfig = require('./loadCustomConfig'); const loadConfigModels = require('./loadConfigModels'); const loadDefaultModels = require('./loadDefaultModels'); @@ -9,6 +10,7 @@ const loadDefaultEndpointsConfig = require('./loadDefaultEConfig'); module.exports = { config, + getCustomConfig, loadCustomConfig, loadConfigModels, loadDefaultModels, diff --git a/api/server/services/Config/loadConfigEndpoints.js b/api/server/services/Config/loadConfigEndpoints.js index 1b435e144..156688b05 100644 --- a/api/server/services/Config/loadConfigEndpoints.js +++ b/api/server/services/Config/loadConfigEndpoints.js @@ -1,18 +1,12 @@ -const { CacheKeys, EModelEndpoint } = require('librechat-data-provider'); +const { EModelEndpoint } = require('librechat-data-provider'); const { isUserProvided, extractEnvVariable } = require('~/server/utils'); -const loadCustomConfig = require('./loadCustomConfig'); -const { getLogStores } = require('~/cache'); +const getCustomConfig = require('./getCustomConfig'); /** * Load config endpoints from the cached configuration object * @function loadConfigEndpoints */ async function loadConfigEndpoints() { - const cache = getLogStores(CacheKeys.CONFIG_STORE); - let customConfig = await cache.get(CacheKeys.CUSTOM_CONFIG); - - if (!customConfig) { - customConfig = await loadCustomConfig(); - } + const customConfig = await getCustomConfig(); if (!customConfig) { return {}; diff --git a/api/server/services/Config/loadConfigModels.js b/api/server/services/Config/loadConfigModels.js index aff861493..d78ad5950 100644 --- a/api/server/services/Config/loadConfigModels.js +++ b/api/server/services/Config/loadConfigModels.js @@ -1,19 +1,15 @@ -const { CacheKeys, EModelEndpoint } = require('librechat-data-provider'); +const { EModelEndpoint } = require('librechat-data-provider'); const { isUserProvided, extractEnvVariable } = require('~/server/utils'); const { fetchModels } = require('~/server/services/ModelService'); -const loadCustomConfig = require('./loadCustomConfig'); -const { getLogStores } = require('~/cache'); +const getCustomConfig = require('./getCustomConfig'); /** * Load config endpoints from the cached configuration object - * @function loadConfigModels */ -async function loadConfigModels() { - const cache = getLogStores(CacheKeys.CONFIG_STORE); - let customConfig = await cache.get(CacheKeys.CUSTOM_CONFIG); - - if (!customConfig) { - customConfig = await loadCustomConfig(); - } + * @function loadConfigModels + * @param {Express.Request} req - The Express request object. + */ +async function loadConfigModels(req) { + const customConfig = await getCustomConfig(); if (!customConfig) { return {}; @@ -49,7 +45,14 @@ async function loadConfigModels() { if (models.fetch && !isUserProvided(API_KEY) && !isUserProvided(BASE_URL)) { fetchPromisesMap[BASE_URL] = - fetchPromisesMap[BASE_URL] || fetchModels({ baseURL: BASE_URL, apiKey: API_KEY, name }); + fetchPromisesMap[BASE_URL] || + fetchModels({ + user: req.user.id, + baseURL: BASE_URL, + apiKey: API_KEY, + name, + userIdQuery: models.userIdQuery, + }); baseUrlToNameMap[BASE_URL] = baseUrlToNameMap[BASE_URL] || []; baseUrlToNameMap[BASE_URL].push(name); continue; diff --git a/api/server/services/Config/loadCustomConfig.js b/api/server/services/Config/loadCustomConfig.js index ab99f2aa7..a90083b2f 100644 --- a/api/server/services/Config/loadCustomConfig.js +++ b/api/server/services/Config/loadCustomConfig.js @@ -17,6 +17,7 @@ const configPath = path.resolve(projectRoot, 'librechat.yaml'); async function loadCustomConfig() { const customConfig = loadYaml(configPath); if (!customConfig) { + logger.info('Custom config file missing or YAML format invalid.'); return null; } @@ -25,7 +26,7 @@ async function loadCustomConfig() { logger.error(`Invalid custom config file at ${configPath}`, result.error); return null; } else { - logger.info('Loaded custom config file:'); + logger.info('Custom config file loaded:'); logger.info(JSON.stringify(customConfig, null, 2)); } diff --git a/api/server/services/Config/loadDefaultModels.js b/api/server/services/Config/loadDefaultModels.js index 665aa7147..e22a9b276 100644 --- a/api/server/services/Config/loadDefaultModels.js +++ b/api/server/services/Config/loadDefaultModels.js @@ -11,13 +11,23 @@ const fitlerAssistantModels = (str) => { return /gpt-4|gpt-3\\.5/i.test(str) && !/vision|instruct/i.test(str); }; -async function loadDefaultModels() { +/** + * Loads the default models for the application. + * @async + * @function + * @param {Express.Request} req - The Express request object. + */ +async function loadDefaultModels(req) { const google = getGoogleModels(); - const openAI = await getOpenAIModels(); + const openAI = await getOpenAIModels({ user: req.user.id }); const anthropic = getAnthropicModels(); const chatGPTBrowser = getChatGPTBrowserModels(); - const azureOpenAI = await getOpenAIModels({ azure: true }); - const gptPlugins = await getOpenAIModels({ azure: useAzurePlugins, plugins: true }); + const azureOpenAI = await getOpenAIModels({ user: req.user.id, azure: true }); + const gptPlugins = await getOpenAIModels({ + user: req.user.id, + azure: useAzurePlugins, + plugins: true, + }); return { [EModelEndpoint.openAI]: openAI, diff --git a/api/server/services/Endpoints/custom/initializeClient.js b/api/server/services/Endpoints/custom/initializeClient.js index e5c9a62e8..c308bd6a7 100644 --- a/api/server/services/Endpoints/custom/initializeClient.js +++ b/api/server/services/Endpoints/custom/initializeClient.js @@ -1,8 +1,8 @@ const { EModelEndpoint, CacheKeys } = require('librechat-data-provider'); const { getUserKey, checkUserKeyExpiry } = require('~/server/services/UserService'); +const getCustomConfig = require('~/server/services/Config/getCustomConfig'); const { isUserProvided, extractEnvVariable } = require('~/server/utils'); const { fetchModels } = require('~/server/services/ModelService'); -const getCustomConfig = require('~/cache/getCustomConfig'); const getLogStores = require('~/cache/getLogStores'); const { OpenAIClient } = require('~/app'); diff --git a/api/server/services/ModelService.js b/api/server/services/ModelService.js index 9a9f5238f..45ae11aa1 100644 --- a/api/server/services/ModelService.js +++ b/api/server/services/ModelService.js @@ -1,47 +1,35 @@ -const Keyv = require('keyv'); const axios = require('axios'); -const HttpsProxyAgent = require('https-proxy-agent'); +const { HttpsProxyAgent } = require('https-proxy-agent'); const { EModelEndpoint, defaultModels, CacheKeys } = require('librechat-data-provider'); const { extractBaseURL, inputSchema, processModelData } = require('~/utils'); const getLogStores = require('~/cache/getLogStores'); -const { isEnabled } = require('~/server/utils'); -const keyvRedis = require('~/cache/keyvRedis'); const { logger } = require('~/config'); // const { getAzureCredentials, genAzureChatCompletion } = require('~/utils/'); const { openAIApiKey, userProvidedOpenAI } = require('./Config/EndpointService').config; -const modelsCache = isEnabled(process.env.USE_REDIS) - ? new Keyv({ store: keyvRedis }) - : new Keyv({ namespace: 'models' }); - -const { - OPENROUTER_API_KEY, - OPENAI_REVERSE_PROXY, - CHATGPT_MODELS, - ANTHROPIC_MODELS, - GOOGLE_MODELS, - PROXY, -} = process.env ?? {}; - /** * Fetches OpenAI models from the specified base API path or Azure, based on the provided configuration. * * @param {Object} params - The parameters for fetching the models. + * @param {Object} params.user - The user ID to send to the API. * @param {string} params.apiKey - The API key for authentication with the API. * @param {string} params.baseURL - The base path URL for the API. * @param {string} [params.name='OpenAI'] - The name of the API; defaults to 'OpenAI'. * @param {boolean} [params.azure=false] - Whether to fetch models from Azure. + * @param {boolean} [params.userIdQuery=false] - Whether to send the user ID as a query parameter. * @param {boolean} [params.createTokenConfig=true] - Whether to create a token configuration from the API response. * @returns {Promise} A promise that resolves to an array of model identifiers. * @async */ const fetchModels = async ({ + user, apiKey, baseURL, name = 'OpenAI', azure = false, + userIdQuery = false, createTokenConfig = true, }) => { let models = []; @@ -51,21 +39,26 @@ const fetchModels = async ({ } try { - const payload = { + const options = { headers: { Authorization: `Bearer ${apiKey}`, }, }; - if (PROXY) { - payload.httpsAgent = new HttpsProxyAgent(PROXY); + if (process.env.PROXY) { + options.httpsAgent = new HttpsProxyAgent(process.env.PROXY); } if (process.env.OPENAI_ORGANIZATION && baseURL.includes('openai')) { - payload.headers['OpenAI-Organization'] = process.env.OPENAI_ORGANIZATION; + options.headers['OpenAI-Organization'] = process.env.OPENAI_ORGANIZATION; } - const res = await axios.get(`${baseURL}${azure ? '' : '/models'}`, payload); + const url = new URL(`${baseURL}${azure ? '' : '/models'}`); + if (user && userIdQuery) { + url.searchParams.append('user', user); + } + const res = await axios.get(url.toString(), options); + /** @type {z.infer} */ const input = res.data; @@ -83,11 +76,22 @@ const fetchModels = async ({ return models; }; -const fetchOpenAIModels = async (opts = { azure: false, plugins: false }, _models = []) => { +/** + * Fetches models from the specified API path or Azure, based on the provided options. + * @async + * @function + * @param {object} opts - The options for fetching the models. + * @param {string} opts.user - The user ID to send to the API. + * @param {boolean} [opts.azure=false] - Whether to fetch models from Azure. + * @param {boolean} [opts.plugins=false] - Whether to fetch models from the plugins. + * @param {string[]} [_models=[]] - The models to use as a fallback. + */ +const fetchOpenAIModels = async (opts, _models = []) => { let models = _models.slice() ?? []; let apiKey = openAIApiKey; - let baseURL = 'https://api.openai.com/v1'; - let reverseProxyUrl = OPENAI_REVERSE_PROXY; + const openaiBaseURL = 'https://api.openai.com/v1'; + let baseURL = openaiBaseURL; + let reverseProxyUrl = process.env.OPENAI_REVERSE_PROXY; if (opts.azure) { return models; // const azure = getAzureCredentials(); @@ -95,15 +99,17 @@ const fetchOpenAIModels = async (opts = { azure: false, plugins: false }, _model // .split('/deployments')[0] // .concat(`/models?api-version=${azure.azureOpenAIApiVersion}`); // apiKey = azureOpenAIApiKey; - } else if (OPENROUTER_API_KEY) { + } else if (process.env.OPENROUTER_API_KEY) { reverseProxyUrl = 'https://openrouter.ai/api/v1'; - apiKey = OPENROUTER_API_KEY; + 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; @@ -114,10 +120,15 @@ const fetchOpenAIModels = async (opts = { azure: false, plugins: false }, _model apiKey, baseURL, azure: opts.azure, + user: opts.user, }); } - if (!reverseProxyUrl) { + if (models.length === 0) { + return _models; + } + + if (baseURL === openaiBaseURL) { const regex = /(text-davinci-003|gpt-)/; models = models.filter((model) => regex.test(model)); } @@ -126,18 +137,27 @@ const fetchOpenAIModels = async (opts = { azure: false, plugins: false }, _model return models; }; -const getOpenAIModels = async (opts = { azure: false, plugins: false }) => { - let models = [ - 'gpt-4', - 'gpt-4-0613', - 'gpt-3.5-turbo', - 'gpt-3.5-turbo-16k', - 'gpt-3.5-turbo-0613', - 'gpt-3.5-turbo-0301', - ]; +/** + * Loads the default models for the application. + * @async + * @function + * @param {object} opts - The options for fetching the models. + * @param {string} opts.user - The user ID to send to the API. + * @param {boolean} [opts.azure=false] - Whether to fetch models from Azure. + * @param {boolean} [opts.plugins=false] - Whether to fetch models from the plugins. + */ +const getOpenAIModels = async (opts) => { + let models = defaultModels.openAI; - if (!opts.plugins) { - models.push('text-davinci-003'); + 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; @@ -154,7 +174,7 @@ const getOpenAIModels = async (opts = { azure: false, plugins: false }) => { return models; } - if (userProvidedOpenAI && !OPENROUTER_API_KEY) { + if (userProvidedOpenAI && !process.env.OPENROUTER_API_KEY) { return models; } @@ -163,8 +183,8 @@ const getOpenAIModels = async (opts = { azure: false, plugins: false }) => { const getChatGPTBrowserModels = () => { let models = ['text-davinci-002-render-sha', 'gpt-4']; - if (CHATGPT_MODELS) { - models = String(CHATGPT_MODELS).split(','); + if (process.env.CHATGPT_MODELS) { + models = String(process.env.CHATGPT_MODELS).split(','); } return models; @@ -172,8 +192,8 @@ const getChatGPTBrowserModels = () => { const getAnthropicModels = () => { let models = defaultModels[EModelEndpoint.anthropic]; - if (ANTHROPIC_MODELS) { - models = String(ANTHROPIC_MODELS).split(','); + if (process.env.ANTHROPIC_MODELS) { + models = String(process.env.ANTHROPIC_MODELS).split(','); } return models; @@ -181,8 +201,8 @@ const getAnthropicModels = () => { const getGoogleModels = () => { let models = defaultModels[EModelEndpoint.google]; - if (GOOGLE_MODELS) { - models = String(GOOGLE_MODELS).split(','); + if (process.env.GOOGLE_MODELS) { + models = String(process.env.GOOGLE_MODELS).split(','); } return models; diff --git a/api/server/services/ModelService.spec.js b/api/server/services/ModelService.spec.js new file mode 100644 index 000000000..19fa407ce --- /dev/null +++ b/api/server/services/ModelService.spec.js @@ -0,0 +1,212 @@ +const axios = require('axios'); + +const { fetchModels, getOpenAIModels } = require('./ModelService'); +jest.mock('~/utils', () => { + const originalUtils = jest.requireActual('~/utils'); + return { + ...originalUtils, + processModelData: jest.fn((...args) => { + return originalUtils.processModelData(...args); + }), + }; +}); + +jest.mock('axios'); +jest.mock('~/cache/getLogStores', () => + jest.fn().mockImplementation(() => ({ + get: jest.fn().mockResolvedValue(undefined), + set: jest.fn().mockResolvedValue(true), + })), +); +jest.mock('~/config', () => ({ + logger: { + error: jest.fn(), + }, +})); +jest.mock('./Config/EndpointService', () => ({ + config: { + openAIApiKey: 'mockedApiKey', + userProvidedOpenAI: false, + }, +})); + +axios.get.mockResolvedValue({ + data: { + data: [{ id: 'model-1' }, { id: 'model-2' }], + }, +}); + +describe('fetchModels', () => { + it('fetches models successfully from the API', async () => { + const models = await fetchModels({ + user: 'user123', + apiKey: 'testApiKey', + baseURL: 'https://api.test.com', + name: 'TestAPI', + }); + + expect(models).toEqual(['model-1', 'model-2']); + expect(axios.get).toHaveBeenCalledWith( + expect.stringContaining('https://api.test.com/models'), + expect.any(Object), + ); + }); + + it('adds the user ID to the models query when option and ID are passed', async () => { + const models = await fetchModels({ + user: 'user123', + apiKey: 'testApiKey', + baseURL: 'https://api.test.com', + userIdQuery: true, + name: 'TestAPI', + }); + + expect(models).toEqual(['model-1', 'model-2']); + expect(axios.get).toHaveBeenCalledWith( + expect.stringContaining('https://api.test.com/models?user=user123'), + expect.any(Object), + ); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); +}); + +describe('fetchModels with createTokenConfig true', () => { + const data = { + data: [ + { + id: 'model-1', + pricing: { + prompt: '0.002', + completion: '0.001', + }, + context_length: 1024, + }, + { + id: 'model-2', + pricing: { + prompt: '0.003', + completion: '0.0015', + }, + context_length: 2048, + }, + ], + }; + + beforeEach(() => { + // Clears the mock's history before each test + const _utils = require('~/utils'); + axios.get.mockResolvedValue({ data }); + }); + + it('creates and stores token configuration if createTokenConfig is true', async () => { + await fetchModels({ + user: 'user123', + apiKey: 'testApiKey', + baseURL: 'https://api.test.com', + createTokenConfig: true, + }); + + const { processModelData } = require('~/utils'); + expect(processModelData).toHaveBeenCalled(); + expect(processModelData).toHaveBeenCalledWith(data); + }); +}); + +describe('getOpenAIModels', () => { + let originalEnv; + + beforeEach(() => { + originalEnv = { ...process.env }; + axios.get.mockRejectedValue(new Error('Network error')); + }); + + afterEach(() => { + process.env = originalEnv; + axios.get.mockReset(); + }); + + it('returns default models when no environment configurations are provided (and fetch fails)', async () => { + const models = await getOpenAIModels({ user: 'user456' }); + expect(models).toContain('gpt-4'); + }); + + it('returns `AZURE_OPENAI_MODELS` with `azure` flag (and fetch fails)', async () => { + process.env.AZURE_OPENAI_MODELS = 'azure-model,azure-model-2'; + const models = await getOpenAIModels({ azure: true }); + expect(models).toEqual(expect.arrayContaining(['azure-model', 'azure-model-2'])); + }); + + it('returns `PLUGIN_MODELS` with `plugins` flag (and fetch fails)', async () => { + process.env.PLUGIN_MODELS = 'plugins-model,plugins-model-2'; + const models = await getOpenAIModels({ plugins: true }); + expect(models).toEqual(expect.arrayContaining(['plugins-model', 'plugins-model-2'])); + }); + + it('returns `OPENAI_MODELS` with no flags (and fetch fails)', async () => { + process.env.OPENAI_MODELS = 'openai-model,openai-model-2'; + const models = await getOpenAIModels({}); + expect(models).toEqual(expect.arrayContaining(['openai-model', 'openai-model-2'])); + }); + + it('attempts to use OPENROUTER_API_KEY if set', async () => { + process.env.OPENROUTER_API_KEY = 'test-router-key'; + const expectedModels = ['model-router-1', 'model-router-2']; + + axios.get.mockResolvedValue({ + data: { + data: expectedModels.map((id) => ({ id })), + }, + }); + + const models = await getOpenAIModels({ user: 'user456' }); + + expect(models).toEqual(expect.arrayContaining(expectedModels)); + expect(axios.get).toHaveBeenCalled(); + }); + + it('utilizes proxy configuration when PROXY is set', async () => { + axios.get.mockResolvedValue({ + data: { + data: [], + }, + }); + process.env.PROXY = 'http://localhost:8888'; + await getOpenAIModels({ user: 'user456' }); + + expect(axios.get).toHaveBeenCalledWith( + expect.any(String), + expect.objectContaining({ + httpsAgent: expect.anything(), + }), + ); + }); +}); + +describe('getOpenAIModels with mocked config', () => { + it('uses alternative behavior when userProvidedOpenAI is true', async () => { + jest.mock('./Config/EndpointService', () => ({ + config: { + openAIApiKey: 'mockedApiKey', + userProvidedOpenAI: true, + }, + })); + jest.mock('librechat-data-provider', () => { + const original = jest.requireActual('librechat-data-provider'); + return { + ...original, + defaultModels: { + [original.EModelEndpoint.openAI]: ['some-default-model'], + }, + }; + }); + + jest.resetModules(); + const { getOpenAIModels } = require('./ModelService'); + + const models = await getOpenAIModels({ user: 'user456' }); + expect(models).toContain('some-default-model'); + }); +}); diff --git a/bun.lockb b/bun.lockb index 9fd1d656d17158b9cfed1922ac169d1286a47eda..c97b3970475ab4d5e71b8b9a2ef987fcc85fdc89 100755 GIT binary patch delta 85237 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≀%ce+dWuT=5P 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 asU8-M?-lLiAHT;gTi)pLkK?Dx{(k`W&ecZ% diff --git a/docs/install/configuration/custom_config.md b/docs/install/configuration/custom_config.md index a45cd69a4..fde2cccc8 100644 --- a/docs/install/configuration/custom_config.md +++ b/docs/install/configuration/custom_config.md @@ -242,6 +242,9 @@ endpoints: - Type: Boolean - Example: `fetch: true` - **Note**: May cause slowdowns during initial use of the app if the response is delayed. Defaults to `false`. + - **userIdQuery**: When set to `true`, adds the LibreChat user ID as a query parameter to the API models request. + - Type: Boolean + - Example: `userIdQuery: true` ### **titleConvo**: diff --git a/package.json b/package.json index 526a6d289..48209877b 100644 --- a/package.json +++ b/package.json @@ -50,8 +50,8 @@ "format": "prettier-eslint --write \"{,!(node_modules)/**/}*.{js,jsx,ts,tsx}\"", "b:api": "NODE_ENV=production bun run api/server/index.js", "b:api:dev": "NODE_ENV=production bun run --watch api/server/index.js", - "b:data-provider": "cd packages/data-provider && bun run b:build", - "b:client": "bun --bun run b:data-provider && cd client && bun --bun run b:build", + "b:data": "cd packages/data-provider && bun run b:build", + "b:client": "bun --bun run b:data && cd client && bun --bun run b:build", "b:client:dev": "cd client && bun run b:dev", "b:test:client": "cd client && bun run b:test", "b:test:api": "cd api && bun run b:test", diff --git a/packages/data-provider/src/config.ts b/packages/data-provider/src/config.ts index 44c0a260b..753b35bb8 100644 --- a/packages/data-provider/src/config.ts +++ b/packages/data-provider/src/config.ts @@ -15,6 +15,7 @@ export const endpointSchema = z.object({ models: z.object({ default: z.array(z.string()).min(1), fetch: z.boolean().optional(), + userIdQuery: z.boolean().optional(), }), titleConvo: z.boolean().optional(), titleMethod: z.union([z.literal('completion'), z.literal('functions')]).optional(), @@ -40,7 +41,8 @@ export const configSchema = z.object({ .object({ custom: z.array(endpointSchema.partial()), }) - .strict(), + .strict() + .optional(), }); export type TCustomConfig = z.infer; @@ -177,6 +179,10 @@ export enum CacheKeys { * Key for the model config cache. */ MODELS_CONFIG = 'modelsConfig', + /** + * Key for the model queries cache. + */ + MODEL_QUERIES = 'modelQueries', /** * Key for the default endpoint config cache. */