diff --git a/api/app/clients/GoogleClient.js b/api/app/clients/GoogleClient.js index 7e34a65c02..4b966646c3 100644 --- a/api/app/clients/GoogleClient.js +++ b/api/app/clients/GoogleClient.js @@ -862,6 +862,7 @@ class GoogleClient extends BaseClient { getSaveOptions() { return { + endpointType: null, artifacts: this.options.artifacts, promptPrefix: this.options.promptPrefix, modelLabel: this.options.modelLabel, diff --git a/api/server/services/AppService.js b/api/server/services/AppService.js index b4ca874aea..d194d31a6b 100644 --- a/api/server/services/AppService.js +++ b/api/server/services/AppService.js @@ -6,6 +6,7 @@ const loadCustomConfig = require('./Config/loadCustomConfig'); const handleRateLimits = require('./Config/handleRateLimits'); const { loadDefaultInterface } = require('./start/interface'); const { azureConfigSetup } = require('./start/azureOpenAI'); +const { processModelSpecs } = require('./start/modelSpecs'); const { loadAndFormatTools } = require('./ToolService'); const { agentsConfigSetup } = require('./start/agents'); const { initializeRoles } = require('~/models/Role'); @@ -122,9 +123,9 @@ const AppService = async (app) => { app.locals = { ...defaultLocals, - modelSpecs: config.modelSpecs, fileConfig: config?.fileConfig, secureImageLinks: config?.secureImageLinks, + modelSpecs: processModelSpecs(endpoints, config.modelSpecs), ...endpointLocals, }; }; diff --git a/api/server/services/start/modelSpecs.js b/api/server/services/start/modelSpecs.js new file mode 100644 index 0000000000..551f42b1cf --- /dev/null +++ b/api/server/services/start/modelSpecs.js @@ -0,0 +1,61 @@ +const { EModelEndpoint } = require('librechat-data-provider'); +const { normalizeEndpointName } = require('~/server/utils'); +const { logger } = require('~/config'); + +/** + * Sets up Model Specs from the config (`librechat.yaml`) file. + * @param {TCustomConfig['endpoints']} endpoints - The loaded custom configuration for endpoints. + * @param {TCustomConfig['modelSpecs'] | undefined} [modelSpecs] - The loaded custom configuration for model specs. + * @returns {TCustomConfig['modelSpecs'] | undefined} The processed model specs, if any. + */ +function processModelSpecs(endpoints, _modelSpecs) { + if (!_modelSpecs) { + return undefined; + } + + /** @type {TCustomConfig['modelSpecs']['list']} */ + const modelSpecs = []; + /** @type {TCustomConfig['modelSpecs']['list']} */ + const list = _modelSpecs.list; + + const customEndpoints = endpoints[EModelEndpoint.custom] ?? []; + + for (const spec of list) { + if (EModelEndpoint[spec.preset.endpoint] && spec.preset.endpoint !== EModelEndpoint.custom) { + modelSpecs.push(spec); + continue; + } else if (spec.preset.endpoint === EModelEndpoint.custom) { + logger.warn( + `Model Spec with endpoint "${spec.preset.endpoint}" is not supported. You must specify the name of the custom endpoint (case-sensitive, as defined in your config). Skipping model spec...`, + ); + continue; + } + + const normalizedName = normalizeEndpointName(spec.preset.endpoint); + const endpoint = customEndpoints.find( + (customEndpoint) => normalizedName === normalizeEndpointName(customEndpoint.name), + ); + + if (!endpoint) { + logger.warn(`Model spec with endpoint "${spec.preset.endpoint}" was skipped: Endpoint not found in configuration. The \`endpoint\` value must exactly match either a system-defined endpoint or a custom endpoint defined by the user. + +For more information, see the documentation at https://www.librechat.ai/docs/configuration/librechat_yaml/object_structure/model_specs#endpoint`); + continue; + } + + modelSpecs.push({ + ...spec, + preset: { + ...spec.preset, + endpoint: normalizedName, + }, + }); + } + + return { + ..._modelSpecs, + list: modelSpecs, + }; +} + +module.exports = { processModelSpecs }; diff --git a/client/src/components/Chat/Messages/Content/EditMessage.tsx b/client/src/components/Chat/Messages/Content/EditMessage.tsx index a098854f4a..7c86010d1d 100644 --- a/client/src/components/Chat/Messages/Content/EditMessage.tsx +++ b/client/src/components/Chat/Messages/Content/EditMessage.tsx @@ -1,6 +1,5 @@ -import { useRecoilState, useRecoilValue } from 'recoil'; -import { EModelEndpoint } from 'librechat-data-provider'; import { useRef, useEffect, useCallback } from 'react'; +import { useRecoilState, useRecoilValue } from 'recoil'; import { useForm } from 'react-hook-form'; import { useUpdateMessageMutation } from 'librechat-data-provider/react-query'; import type { TEditProps } from '~/common'; @@ -31,8 +30,6 @@ const EditMessage = ({ const textAreaRef = useRef(null); const { conversationId, parentMessageId, messageId } = message; - const { endpoint: _endpoint, endpointType } = conversation ?? { endpoint: null }; - const endpoint = endpointType ?? _endpoint; const updateMessageMutation = useUpdateMessageMutation(conversationId ?? ''); const localize = useLocalize(); @@ -181,9 +178,7 @@ const EditMessage = ({