mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-18 09:20:15 +01:00
* wip: first pass for azure endpoint schema * refactor: azure config to return groupMap and modelConfigMap * wip: naming and schema changes * refactor(errorsToString): move to data-provider * feat: rename to azureGroups, add additional tests, tests all expected outcomes, return errors * feat(AppService): load Azure groups * refactor(azure): use imported types, write `mapModelToAzureConfig` * refactor: move `extractEnvVariable` to data-provider * refactor(validateAzureGroups): throw on duplicate groups or models; feat(mapModelToAzureConfig): throw if env vars not present, add tests * refactor(AppService): ensure each model is properly configured on startup * refactor: deprecate azureOpenAI environment variables in favor of librechat.yaml config * feat: use helper functions to handle and order enabled/default endpoints; initialize azureOpenAI from config file * refactor: redefine types as well as load azureOpenAI models from config file * chore(ci): fix test description naming * feat(azureOpenAI): use validated model grouping for request authentication * chore: bump data-provider following rebase * chore: bump config file version noting significant changes * feat: add title options and switch azure configs for titling and vision requests * feat: enable azure plugins from config file * fix(ci): pass tests * chore(.env.example): mark `PLUGINS_USE_AZURE` as deprecated * fix(fetchModels): early return if apiKey not passed * chore: fix azure config typing * refactor(mapModelToAzureConfig): return baseURL and headers as well as azureOptions * feat(createLLM): use `azureOpenAIBasePath` * feat(parsers): resolveHeaders * refactor(extractBaseURL): handle invalid input * feat(OpenAIClient): handle headers and baseURL for azureConfig * fix(ci): pass `OpenAIClient` tests * chore: extract env var for azureOpenAI group config, baseURL * docs: azureOpenAI config setup docs * feat: safe check of potential conflicting env vars that map to unique placeholders * fix: reset apiKey when model switches from originally requested model (vision or title) * chore: linting * docs: CONFIG_PATH notes in custom_config.md
143 lines
4.2 KiB
JavaScript
143 lines
4.2 KiB
JavaScript
const {
|
|
Constants,
|
|
FileSources,
|
|
EModelEndpoint,
|
|
defaultSocialLogins,
|
|
validateAzureGroups,
|
|
mapModelToAzureConfig,
|
|
deprecatedAzureVariables,
|
|
conflictingAzureVariables,
|
|
} = require('librechat-data-provider');
|
|
const { initializeFirebase } = require('./Files/Firebase/initialize');
|
|
const loadCustomConfig = require('./Config/loadCustomConfig');
|
|
const handleRateLimits = require('./Config/handleRateLimits');
|
|
const { loadAndFormatTools } = require('./ToolService');
|
|
const paths = require('~/config/paths');
|
|
const { logger } = require('~/config');
|
|
|
|
/**
|
|
*
|
|
* Loads custom config and initializes app-wide variables.
|
|
* @function AppService
|
|
* @param {Express.Application} app - The Express application object.
|
|
*/
|
|
const AppService = async (app) => {
|
|
/** @type {TCustomConfig}*/
|
|
const config = (await loadCustomConfig()) ?? {};
|
|
|
|
const fileStrategy = config.fileStrategy ?? FileSources.local;
|
|
process.env.CDN_PROVIDER = fileStrategy;
|
|
|
|
if (fileStrategy === FileSources.firebase) {
|
|
initializeFirebase();
|
|
}
|
|
|
|
/** @type {Record<string, FunctionTool} */
|
|
const availableTools = loadAndFormatTools({
|
|
directory: paths.structuredTools,
|
|
filter: new Set([
|
|
'ChatTool.js',
|
|
'CodeSherpa.js',
|
|
'CodeSherpaTools.js',
|
|
'E2BTools.js',
|
|
'extractionChain.js',
|
|
]),
|
|
});
|
|
|
|
const socialLogins = config?.registration?.socialLogins ?? defaultSocialLogins;
|
|
|
|
if (!Object.keys(config).length) {
|
|
app.locals = {
|
|
availableTools,
|
|
fileStrategy,
|
|
socialLogins,
|
|
paths,
|
|
};
|
|
|
|
return;
|
|
}
|
|
|
|
if (config.version !== Constants.CONFIG_VERSION) {
|
|
logger.info(
|
|
`\nOutdated Config version: ${config.version}. Current version: ${Constants.CONFIG_VERSION}\n\nCheck out the latest config file guide for new options and features.\nhttps://docs.librechat.ai/install/configuration/custom_config.html\n\n`,
|
|
);
|
|
}
|
|
|
|
handleRateLimits(config?.rateLimits);
|
|
|
|
const endpointLocals = {};
|
|
|
|
if (config?.endpoints?.[EModelEndpoint.azureOpenAI]) {
|
|
const { groups, titleModel, titleConvo, titleMethod, plugins } =
|
|
config.endpoints[EModelEndpoint.azureOpenAI];
|
|
const { isValid, modelNames, modelGroupMap, groupMap, errors } = validateAzureGroups(groups);
|
|
|
|
if (!isValid) {
|
|
const errorString = errors.join('\n');
|
|
const errorMessage = 'Invalid Azure OpenAI configuration:\n' + errorString;
|
|
logger.error(errorMessage);
|
|
throw new Error(errorMessage);
|
|
}
|
|
|
|
for (const modelName of modelNames) {
|
|
mapModelToAzureConfig({ modelName, modelGroupMap, groupMap });
|
|
}
|
|
|
|
endpointLocals[EModelEndpoint.azureOpenAI] = {
|
|
modelNames,
|
|
modelGroupMap,
|
|
groupMap,
|
|
titleConvo,
|
|
titleMethod,
|
|
titleModel,
|
|
plugins,
|
|
};
|
|
|
|
deprecatedAzureVariables.forEach(({ key, description }) => {
|
|
if (process.env[key]) {
|
|
logger.warn(
|
|
`The \`${key}\` environment variable (related to ${description}) should not be used in combination with the \`azureOpenAI\` endpoint configuration, as you will experience conflicts and errors.`,
|
|
);
|
|
}
|
|
});
|
|
|
|
conflictingAzureVariables.forEach(({ key }) => {
|
|
if (process.env[key]) {
|
|
logger.warn(
|
|
`The \`${key}\` environment variable should not be used in combination with the \`azureOpenAI\` endpoint configuration, as you may experience with the defined placeholders for mapping to the current model grouping using the same name.`,
|
|
);
|
|
}
|
|
});
|
|
}
|
|
|
|
if (config?.endpoints?.[EModelEndpoint.assistants]) {
|
|
const { disableBuilder, pollIntervalMs, timeoutMs, supportedIds, excludedIds } =
|
|
config.endpoints[EModelEndpoint.assistants];
|
|
|
|
if (supportedIds?.length && excludedIds?.length) {
|
|
logger.warn(
|
|
`Both \`supportedIds\` and \`excludedIds\` are defined for the ${EModelEndpoint.assistants} endpoint; \`excludedIds\` field will be ignored.`,
|
|
);
|
|
}
|
|
|
|
/** @type {Partial<TAssistantEndpoint>} */
|
|
endpointLocals[EModelEndpoint.assistants] = {
|
|
disableBuilder,
|
|
pollIntervalMs,
|
|
timeoutMs,
|
|
supportedIds,
|
|
excludedIds,
|
|
};
|
|
}
|
|
|
|
app.locals = {
|
|
socialLogins,
|
|
availableTools,
|
|
fileStrategy,
|
|
fileConfig: config?.fileConfig,
|
|
paths,
|
|
...endpointLocals,
|
|
};
|
|
};
|
|
|
|
module.exports = AppService;
|