From 321260e3c7ef3c960b54f39a324516a96c6177c2 Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Mon, 23 Sep 2024 21:47:49 -0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=84=20refactor:=20Apply=20Config=20Pre?= =?UTF-8?q?set=20for=20Model=20Spec=20Enforcement=20(#4214)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/server/middleware/buildEndpointOption.js | 12 ++-- api/server/middleware/enforceModelSpec.js | 58 ------------------- .../middleware/enforceModelSpec.spec.js | 47 --------------- 3 files changed, 6 insertions(+), 111 deletions(-) delete mode 100644 api/server/middleware/enforceModelSpec.js delete mode 100644 api/server/middleware/enforceModelSpec.spec.js diff --git a/api/server/middleware/buildEndpointOption.js b/api/server/middleware/buildEndpointOption.js index 2b4ba40172..a85c55c06b 100644 --- a/api/server/middleware/buildEndpointOption.js +++ b/api/server/middleware/buildEndpointOption.js @@ -10,7 +10,6 @@ const openAI = require('~/server/services/Endpoints/openAI'); const agents = require('~/server/services/Endpoints/agents'); const custom = require('~/server/services/Endpoints/custom'); const google = require('~/server/services/Endpoints/google'); -const enforceModelSpec = require('./enforceModelSpec'); const { handleError } = require('~/server/utils'); const buildFunction = { @@ -28,7 +27,7 @@ const buildFunction = { async function buildEndpointOption(req, res, next) { const { endpoint, endpointType } = req.body; - const parsedBody = parseCompactConvo({ endpoint, endpointType, conversation: req.body }); + let parsedBody = parseCompactConvo({ endpoint, endpointType, conversation: req.body }); if (req.app.locals.modelSpecs?.list && req.app.locals.modelSpecs?.enforce) { /** @type {{ list: TModelSpec[] }}*/ @@ -57,10 +56,11 @@ async function buildEndpointOption(req, res, next) { }); } - const isValidModelSpec = enforceModelSpec(currentModelSpec, parsedBody); - if (!isValidModelSpec) { - return handleError(res, { text: 'Model spec mismatch' }); - } + parsedBody = parseCompactConvo({ + endpoint, + endpointType, + conversation: currentModelSpec.preset, + }); } const endpointFn = buildFunction[endpointType ?? endpoint]; diff --git a/api/server/middleware/enforceModelSpec.js b/api/server/middleware/enforceModelSpec.js deleted file mode 100644 index 17270a5cf8..0000000000 --- a/api/server/middleware/enforceModelSpec.js +++ /dev/null @@ -1,58 +0,0 @@ -const interchangeableKeys = new Map([ - ['chatGptLabel', ['modelLabel']], - ['modelLabel', ['chatGptLabel']], -]); - -/** - * Middleware to enforce the model spec for a conversation - * @param {TModelSpec} modelSpec - The model spec to enforce - * @param {TConversation} parsedBody - The parsed body of the conversation - * @returns {boolean} - Whether the model spec is enforced - */ -const enforceModelSpec = (modelSpec, parsedBody) => { - for (const [key, value] of Object.entries(modelSpec.preset)) { - if (key === 'endpoint') { - continue; - } - - if (!checkMatch(key, value, parsedBody)) { - return false; - } - } - return true; -}; - -/** - * Checks if there is a match for the given key and value in the parsed body - * or any of its interchangeable keys, including deep comparison for objects and arrays. - * @param {string} key - * @param {any} value - * @param {object} parsedBody - * @returns {boolean} - */ -const checkMatch = (key, value, parsedBody) => { - const isEqual = (a, b) => { - if (Array.isArray(a) && Array.isArray(b)) { - return a.length === b.length && a.every((val, index) => isEqual(val, b[index])); - } else if (typeof a === 'object' && typeof b === 'object' && a !== null && b !== null) { - const keysA = Object.keys(a); - const keysB = Object.keys(b); - return keysA.length === keysB.length && keysA.every((k) => isEqual(a[k], b[k])); - } - return a === b; - }; - - if (isEqual(parsedBody[key], value)) { - return true; - } - - if (interchangeableKeys.has(key)) { - return interchangeableKeys - .get(key) - .some((interchangeableKey) => isEqual(parsedBody[interchangeableKey], value)); - } - - return false; -}; - -module.exports = enforceModelSpec; diff --git a/api/server/middleware/enforceModelSpec.spec.js b/api/server/middleware/enforceModelSpec.spec.js deleted file mode 100644 index 04a8e5b35f..0000000000 --- a/api/server/middleware/enforceModelSpec.spec.js +++ /dev/null @@ -1,47 +0,0 @@ -// enforceModelSpec.test.js - -const enforceModelSpec = require('./enforceModelSpec'); - -describe('enforceModelSpec function', () => { - test('returns true when all model specs match parsed body directly', () => { - const modelSpec = { preset: { title: 'Dialog', status: 'Active' } }; - const parsedBody = { title: 'Dialog', status: 'Active' }; - expect(enforceModelSpec(modelSpec, parsedBody)).toBe(true); - }); - - test('returns true when model specs match via interchangeable keys', () => { - const modelSpec = { preset: { chatGptLabel: 'GPT-4' } }; - const parsedBody = { modelLabel: 'GPT-4' }; - expect(enforceModelSpec(modelSpec, parsedBody)).toBe(true); - }); - - test('returns false if any key value does not match', () => { - const modelSpec = { preset: { language: 'English', level: 'Advanced' } }; - const parsedBody = { language: 'Spanish', level: 'Advanced' }; - expect(enforceModelSpec(modelSpec, parsedBody)).toBe(false); - }); - - test('ignores the \'endpoint\' key in model spec', () => { - const modelSpec = { preset: { endpoint: 'ignored', feature: 'Special' } }; - const parsedBody = { feature: 'Special' }; - expect(enforceModelSpec(modelSpec, parsedBody)).toBe(true); - }); - - test('handles nested objects correctly', () => { - const modelSpec = { preset: { details: { time: 'noon', location: 'park' } } }; - const parsedBody = { details: { time: 'noon', location: 'park' } }; - expect(enforceModelSpec(modelSpec, parsedBody)).toBe(true); - }); - - test('handles arrays within objects', () => { - const modelSpec = { preset: { tags: ['urgent', 'important'] } }; - const parsedBody = { tags: ['urgent', 'important'] }; - expect(enforceModelSpec(modelSpec, parsedBody)).toBe(true); - }); - - test('fails when arrays in objects do not match', () => { - const modelSpec = { preset: { tags: ['urgent', 'important'] } }; - const parsedBody = { tags: ['important', 'urgent'] }; // Different order - expect(enforceModelSpec(modelSpec, parsedBody)).toBe(false); - }); -});