mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-17 17:00:15 +01:00
⚓ refactor(loadConfigModels): Stricter Default Model Fallback (#2239)
* chore: add TEndpoint type/typedef * refactor(loadConfigModels.spec): stricter default model matching (fails with current impl.) * refactor(loadConfigModels): return default models on endpoint basis and not fetch basis * refactor: rename `uniqueKeyToNameMap` to `uniqueKeyToEndpointsMap` for clarity
This commit is contained in:
parent
0a8118deed
commit
dec7879cc1
4 changed files with 36 additions and 16 deletions
|
|
@ -46,12 +46,23 @@ async function loadConfigModels(req) {
|
||||||
(endpoint.models.fetch || endpoint.models.default),
|
(endpoint.models.fetch || endpoint.models.default),
|
||||||
);
|
);
|
||||||
|
|
||||||
const fetchPromisesMap = {}; // Map for promises keyed by unique combination of baseURL and apiKey
|
/**
|
||||||
const uniqueKeyToNameMap = {}; // Map to associate unique keys with endpoint names
|
* @type {Record<string, string[]>}
|
||||||
|
* Map for promises keyed by unique combination of baseURL and apiKey */
|
||||||
|
const fetchPromisesMap = {};
|
||||||
|
/**
|
||||||
|
* @type {Record<string, string[]>}
|
||||||
|
* Map to associate unique keys with endpoint names; note: one key may can correspond to multiple endpoints */
|
||||||
|
const uniqueKeyToEndpointsMap = {};
|
||||||
|
/**
|
||||||
|
* @type {Record<string, Partial<TEndpoint>>}
|
||||||
|
* Map to associate endpoint names to their configurations */
|
||||||
|
const endpointsMap = {};
|
||||||
|
|
||||||
for (let i = 0; i < customEndpoints.length; i++) {
|
for (let i = 0; i < customEndpoints.length; i++) {
|
||||||
const endpoint = customEndpoints[i];
|
const endpoint = customEndpoints[i];
|
||||||
const { models, name, baseURL, apiKey } = endpoint;
|
const { models, name, baseURL, apiKey } = endpoint;
|
||||||
|
endpointsMap[name] = endpoint;
|
||||||
|
|
||||||
const API_KEY = extractEnvVariable(apiKey);
|
const API_KEY = extractEnvVariable(apiKey);
|
||||||
const BASE_URL = extractEnvVariable(baseURL);
|
const BASE_URL = extractEnvVariable(baseURL);
|
||||||
|
|
@ -69,11 +80,9 @@ async function loadConfigModels(req) {
|
||||||
apiKey: API_KEY,
|
apiKey: API_KEY,
|
||||||
name,
|
name,
|
||||||
userIdQuery: models.userIdQuery,
|
userIdQuery: models.userIdQuery,
|
||||||
}).then((result) => {
|
|
||||||
return !result?.length ? models.default ?? [] : result;
|
|
||||||
});
|
});
|
||||||
uniqueKeyToNameMap[uniqueKey] = uniqueKeyToNameMap[uniqueKey] || [];
|
uniqueKeyToEndpointsMap[uniqueKey] = uniqueKeyToEndpointsMap[uniqueKey] || [];
|
||||||
uniqueKeyToNameMap[uniqueKey].push(name);
|
uniqueKeyToEndpointsMap[uniqueKey].push(name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -88,10 +97,11 @@ async function loadConfigModels(req) {
|
||||||
for (let i = 0; i < fetchedData.length; i++) {
|
for (let i = 0; i < fetchedData.length; i++) {
|
||||||
const currentKey = uniqueKeys[i];
|
const currentKey = uniqueKeys[i];
|
||||||
const modelData = fetchedData[i];
|
const modelData = fetchedData[i];
|
||||||
const associatedNames = uniqueKeyToNameMap[currentKey];
|
const associatedNames = uniqueKeyToEndpointsMap[currentKey];
|
||||||
|
|
||||||
for (const name of associatedNames) {
|
for (const name of associatedNames) {
|
||||||
modelsConfig[name] = modelData;
|
const endpoint = endpointsMap[name];
|
||||||
|
modelsConfig[name] = !modelData?.length ? endpoint.models.default ?? [] : modelData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -267,6 +267,15 @@ describe('loadConfigModels', () => {
|
||||||
getCustomConfig.mockResolvedValue({
|
getCustomConfig.mockResolvedValue({
|
||||||
endpoints: {
|
endpoints: {
|
||||||
custom: [
|
custom: [
|
||||||
|
{
|
||||||
|
name: 'EndpointWithSameFetchKey',
|
||||||
|
apiKey: 'API_KEY',
|
||||||
|
baseURL: 'http://example.com',
|
||||||
|
models: {
|
||||||
|
fetch: true,
|
||||||
|
default: ['defaultModel1'],
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'EmptyFetchModel',
|
name: 'EmptyFetchModel',
|
||||||
apiKey: 'API_KEY',
|
apiKey: 'API_KEY',
|
||||||
|
|
@ -283,14 +292,7 @@ describe('loadConfigModels', () => {
|
||||||
fetchModels.mockResolvedValue([]);
|
fetchModels.mockResolvedValue([]);
|
||||||
|
|
||||||
const result = await loadConfigModels(mockRequest);
|
const result = await loadConfigModels(mockRequest);
|
||||||
|
expect(fetchModels).toHaveBeenCalledTimes(1);
|
||||||
expect(fetchModels).toHaveBeenCalledWith(
|
|
||||||
expect.objectContaining({
|
|
||||||
name: 'EmptyFetchModel',
|
|
||||||
apiKey: 'API_KEY',
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(result.EmptyFetchModel).toEqual(['defaultModel1', 'defaultModel2']);
|
expect(result.EmptyFetchModel).toEqual(['defaultModel1', 'defaultModel2']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -277,6 +277,12 @@
|
||||||
* @memberof typedefs
|
* @memberof typedefs
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @exports TEndpoint
|
||||||
|
* @typedef {import('librechat-data-provider').TEndpoint} TEndpoint
|
||||||
|
* @memberof typedefs
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @exports TEndpointsConfig
|
* @exports TEndpointsConfig
|
||||||
* @typedef {import('librechat-data-provider').TEndpointsConfig} TEndpointsConfig
|
* @typedef {import('librechat-data-provider').TEndpointsConfig} TEndpointsConfig
|
||||||
|
|
|
||||||
|
|
@ -150,6 +150,8 @@ export const endpointSchema = z.object({
|
||||||
customOrder: z.number().optional(),
|
customOrder: z.number().optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export type TEndpoint = z.infer<typeof endpointSchema>;
|
||||||
|
|
||||||
export const azureEndpointSchema = z
|
export const azureEndpointSchema = z
|
||||||
.object({
|
.object({
|
||||||
groups: azureGroupConfigsSchema,
|
groups: azureGroupConfigsSchema,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue