From 5221a98f96326fbedfd42f0ce602dc61ef3f4522 Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Wed, 22 Nov 2023 12:32:06 -0500 Subject: [PATCH 1/3] fix: endpoint will not be select if disabled --- client/src/utils/getDefaultEndpoint.ts | 16 +++------------- client/src/utils/mapEndpoints.ts | 2 +- packages/data-provider/src/schemas.ts | 11 +++++++++++ 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/client/src/utils/getDefaultEndpoint.ts b/client/src/utils/getDefaultEndpoint.ts index ec26f5f5e0f..bdfb7b6470b 100644 --- a/client/src/utils/getDefaultEndpoint.ts +++ b/client/src/utils/getDefaultEndpoint.ts @@ -1,22 +1,11 @@ import type { TConversation, TPreset, TEndpointsConfig } from 'librechat-data-provider'; -import { EModelEndpoint } from 'librechat-data-provider'; import getLocalStorageItems from './getLocalStorageItems'; +import mapEndpoints from './mapEndpoints'; type TConvoSetup = Partial | Partial; type TDefaultEndpoint = { convoSetup: TConvoSetup; endpointsConfig: TEndpointsConfig }; -export const defaultEndpoints: EModelEndpoint[] = [ - EModelEndpoint.openAI, - EModelEndpoint.assistant, - EModelEndpoint.azureOpenAI, - EModelEndpoint.bingAI, - EModelEndpoint.chatGPTBrowser, - EModelEndpoint.gptPlugins, - EModelEndpoint.google, - EModelEndpoint.anthropic, -]; - const getEndpointFromSetup = (convoSetup: TConvoSetup, endpointsConfig: TEndpointsConfig) => { const { endpoint: targetEndpoint } = convoSetup || {}; if (targetEndpoint && endpointsConfig?.[targetEndpoint]) { @@ -49,7 +38,8 @@ const getEndpointFromLocalStorage = (endpointsConfig: TEndpointsConfig) => { }; const getDefinedEndpoint = (endpointsConfig: TEndpointsConfig) => { - return defaultEndpoints.find((e) => Object.hasOwn(endpointsConfig ?? {}, e)) ?? 'openAI'; + const endpoints = mapEndpoints(endpointsConfig); + return endpoints.find((e) => Object.hasOwn(endpointsConfig ?? {}, e)); }; const getDefaultEndpoint = ({ convoSetup, endpointsConfig }: TDefaultEndpoint) => { diff --git a/client/src/utils/mapEndpoints.ts b/client/src/utils/mapEndpoints.ts index b224c3bf4e9..8bb91ac7bc2 100644 --- a/client/src/utils/mapEndpoints.ts +++ b/client/src/utils/mapEndpoints.ts @@ -1,5 +1,5 @@ +import { defaultEndpoints } from 'librechat-data-provider'; import type { TEndpointsConfig } from 'librechat-data-provider'; -import { defaultEndpoints } from './getDefaultEndpoint'; const getEndpointsFilter = (config: TEndpointsConfig) => { const filter: Record = {}; diff --git a/packages/data-provider/src/schemas.ts b/packages/data-provider/src/schemas.ts index 139e13dbe39..38ccad17d86 100644 --- a/packages/data-provider/src/schemas.ts +++ b/packages/data-provider/src/schemas.ts @@ -11,6 +11,17 @@ export enum EModelEndpoint { assistant = 'assistant', } +export const defaultEndpoints: EModelEndpoint[] = [ + EModelEndpoint.openAI, + EModelEndpoint.assistant, + EModelEndpoint.azureOpenAI, + EModelEndpoint.bingAI, + EModelEndpoint.chatGPTBrowser, + EModelEndpoint.gptPlugins, + EModelEndpoint.google, + EModelEndpoint.anthropic, +]; + export const alternateName = { [EModelEndpoint.openAI]: 'OpenAI', [EModelEndpoint.assistant]: 'Assistants', From b5e71108443622101e4044b2547b38d31beb89eb Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Wed, 22 Nov 2023 13:22:27 -0500 Subject: [PATCH 2/3] feat: order and disable endpoints with ENDPOINTS env var --- .env.example | 7 +++ api/server/controllers/EndpointController.js | 59 ++++++++++++++------ client/src/utils/mapEndpoints.ts | 2 +- packages/data-provider/src/types.ts | 3 +- 4 files changed, 52 insertions(+), 19 deletions(-) diff --git a/.env.example b/.env.example index 86d529fde5f..e6d298e42a0 100644 --- a/.env.example +++ b/.env.example @@ -8,6 +8,13 @@ APP_TITLE=LibreChat # Uncomment and make empty "" to remove the footer. # CUSTOM_FOOTER="My custom footer" +# Uncomment the `ENDPOINTS` variable to determine which endpoints are available. +# Listed here are the only accepted values, which are all enabled if an authentication +# option is provided, whether user provided or admin provided in this .env file. +# Note: the first value is considered the default value. + +# ENDPOINTS=openAI,azureOpenAI,bingAI,chatGPTBrowser,google,gptPlugins,anthropic + # The server will listen to localhost:3080 by default. You can change the target IP as you want. # If you want to make this server available externally, for example to share the server with others # or expose this from a Docker container, set host to 0.0.0.0 or your external IP interface. diff --git a/api/server/controllers/EndpointController.js b/api/server/controllers/EndpointController.js index 11501d84913..c52f3650836 100644 --- a/api/server/controllers/EndpointController.js +++ b/api/server/controllers/EndpointController.js @@ -1,6 +1,6 @@ -const { EModelEndpoint } = require('../routes/endpoints/schemas'); -const { availableTools } = require('../../app/clients/tools'); -const { addOpenAPISpecs } = require('../../app/clients/tools/util/addOpenAPISpecs'); +const { EModelEndpoint } = require('~/server/routes/endpoints/schemas'); +const { availableTools } = require('~/app/clients/tools'); +const { addOpenAPISpecs } = require('~/app/clients/tools/util/addOpenAPISpecs'); const { openAIApiKey, azureOpenAIApiKey, @@ -13,13 +13,13 @@ const { bingAI, chatGPTBrowser, anthropic, -} = require('../services/EndpointService').config; +} = require('~/server/services/EndpointService').config; let i = 0; async function endpointController(req, res) { let key, palmUser; try { - key = require('../../data/auth.json'); + key = require('~/data/auth.json'); } catch (e) { if (i === 0) { i++; @@ -54,18 +54,43 @@ async function endpointController(req, res) { } : false; - res.send( - JSON.stringify({ - [EModelEndpoint.openAI]: openAI, - // [EModelEndpoint.assistant]: assistant, - [EModelEndpoint.azureOpenAI]: azureOpenAI, - [EModelEndpoint.google]: google, - [EModelEndpoint.bingAI]: bingAI, - [EModelEndpoint.chatGPTBrowser]: chatGPTBrowser, - [EModelEndpoint.gptPlugins]: gptPlugins, - [EModelEndpoint.anthropic]: anthropic, - }), - ); + let enabledEndpoints = [ + EModelEndpoint.openAI, + EModelEndpoint.azureOpenAI, + EModelEndpoint.google, + EModelEndpoint.bingAI, + EModelEndpoint.chatGPTBrowser, + EModelEndpoint.gptPlugins, + EModelEndpoint.anthropic, + ]; + + const endpointsEnv = process.env.ENDPOINTS || ''; + if (endpointsEnv) { + console.log(`Using endpoints from environment variable ENDPOINTS=${endpointsEnv}`); + enabledEndpoints = endpointsEnv + .split(',') + .filter((endpoint) => endpoint?.trim()) + .map((endpoint) => endpoint.trim()); + } + + const endpointConfig = { + [EModelEndpoint.openAI]: openAI, + [EModelEndpoint.azureOpenAI]: azureOpenAI, + [EModelEndpoint.google]: google, + [EModelEndpoint.bingAI]: bingAI, + [EModelEndpoint.chatGPTBrowser]: chatGPTBrowser, + [EModelEndpoint.gptPlugins]: gptPlugins, + [EModelEndpoint.anthropic]: anthropic, + }; + + const orderedAndFilteredEndpoints = enabledEndpoints.reduce((config, key, index) => { + if (endpointConfig[key]) { + config[key] = { ...(endpointConfig[key] ?? {}), order: index }; + } + return config; + }, {}); + + res.send(JSON.stringify(orderedAndFilteredEndpoints)); } module.exports = endpointController; diff --git a/client/src/utils/mapEndpoints.ts b/client/src/utils/mapEndpoints.ts index 8bb91ac7bc2..1902971a01d 100644 --- a/client/src/utils/mapEndpoints.ts +++ b/client/src/utils/mapEndpoints.ts @@ -16,5 +16,5 @@ const getAvailableEndpoints = (filter: Record) => { export default function mapEndpoints(config: TEndpointsConfig) { const filter = getEndpointsFilter(config); - return getAvailableEndpoints(filter); + return getAvailableEndpoints(filter).sort((a, b) => config[a].order - config[b].order); } diff --git a/packages/data-provider/src/types.ts b/packages/data-provider/src/types.ts index bf66f212a2c..8b914b36f33 100644 --- a/packages/data-provider/src/types.ts +++ b/packages/data-provider/src/types.ts @@ -122,11 +122,12 @@ export type TConfig = { availableTools?: []; plugins?: Record; azure?: boolean; + order: number; }; export type TModelsConfig = Record; -export type TEndpointsConfig = Record; +export type TEndpointsConfig = Record; export type TUpdateTokenCountResponse = { count: number; From 6292d77360053011991e53f2a753b7b4b59f2f87 Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Wed, 22 Nov 2023 13:25:22 -0500 Subject: [PATCH 3/3] chore: remove console.log --- api/server/controllers/EndpointController.js | 1 - 1 file changed, 1 deletion(-) diff --git a/api/server/controllers/EndpointController.js b/api/server/controllers/EndpointController.js index c52f3650836..7ace52510a3 100644 --- a/api/server/controllers/EndpointController.js +++ b/api/server/controllers/EndpointController.js @@ -66,7 +66,6 @@ async function endpointController(req, res) { const endpointsEnv = process.env.ENDPOINTS || ''; if (endpointsEnv) { - console.log(`Using endpoints from environment variable ENDPOINTS=${endpointsEnv}`); enabledEndpoints = endpointsEnv .split(',') .filter((endpoint) => endpoint?.trim())