diff --git a/api/server/middleware/moderateText.js b/api/server/middleware/moderateText.js index 18d370b560..7346f97ce7 100644 --- a/api/server/middleware/moderateText.js +++ b/api/server/middleware/moderateText.js @@ -1,41 +1,70 @@ -const axios = require('axios'); +const OpenAI = require('openai'); const { ErrorTypes } = require('librechat-data-provider'); +const { isEnabled } = require('~/server/utils'); const denyRequest = require('./denyRequest'); const { logger } = require('~/config'); +/** + * Middleware to moderate text content using OpenAI's moderation API + * @param {Express.Request} req - Express request object + * @param {Express.Response} res - Express response object + * @param {Express.NextFunction} next - Express next middleware function + * @returns {Promise} + */ async function moderateText(req, res, next) { - if (process.env.OPENAI_MODERATION === 'true') { - try { - const { text } = req.body; - - const response = await axios.post( - process.env.OPENAI_MODERATION_REVERSE_PROXY || 'https://api.openai.com/v1/moderations', - { - input: text, - }, - { - headers: { - 'Content-Type': 'application/json', - Authorization: `Bearer ${process.env.OPENAI_MODERATION_API_KEY}`, - }, - }, - ); - - const results = response.data.results; - const flagged = results.some((result) => result.flagged); - - if (flagged) { - const type = ErrorTypes.MODERATION; - const errorMessage = { type }; - return await denyRequest(req, res, errorMessage); - } - } catch (error) { - logger.error('Error in moderateText:', error); - const errorMessage = 'error in moderation check'; - return await denyRequest(req, res, errorMessage); - } + if (!isEnabled(process.env.OPENAI_MODERATION)) { + return next(); + } + + try { + const moderationKey = process.env.OPENAI_MODERATION_API_KEY; + + if (!moderationKey) { + logger.error('Missing OpenAI moderation API key'); + return denyRequest(req, res, { message: 'Moderation configuration error' }); + } + + const openai = new OpenAI({ + apiKey: moderationKey, + }); + + const { text } = req.body; + + if (!text || typeof text !== 'string') { + return denyRequest(req, res, { type: ErrorTypes.VALIDATION, message: 'Invalid text input' }); + } + + const response = await openai.moderations.create({ + model: 'omni-moderation-latest', + input: text, + }); + + if (!Array.isArray(response.results)) { + throw new Error('Invalid moderation API response format'); + } + + const flagged = response.results.some((result) => result.flagged); + + if (flagged) { + return denyRequest(req, res, { + type: ErrorTypes.MODERATION, + message: 'Content violates moderation policies', + }); + } + + next(); + } catch (error) { + logger.error('Moderation error:', { + error: error.message, + stack: error.stack, + status: error.response?.status, + }); + + return denyRequest(req, res, { + type: ErrorTypes.MODERATION, + message: 'Content moderation check failed', + }); } - next(); } module.exports = moderateText; diff --git a/api/server/routes/ask/gptPlugins.js b/api/server/routes/ask/gptPlugins.js index 8408e7a5d6..3adef2f82a 100644 --- a/api/server/routes/ask/gptPlugins.js +++ b/api/server/routes/ask/gptPlugins.js @@ -21,8 +21,8 @@ const { logger } = require('~/config'); const router = express.Router(); -router.use(moderateText); router.post('/abort', handleAbort()); +router.use(moderateText); router.post( '/', diff --git a/api/server/routes/ask/openAI.js b/api/server/routes/ask/openAI.js index 5083a08b10..6f8f6c9062 100644 --- a/api/server/routes/ask/openAI.js +++ b/api/server/routes/ask/openAI.js @@ -11,8 +11,8 @@ const { } = require('~/server/middleware'); const router = express.Router(); -router.use(moderateText); router.post('/abort', handleAbort()); +router.use(moderateText); router.post( '/', diff --git a/api/server/routes/edit/gptPlugins.js b/api/server/routes/edit/gptPlugins.js index cd4e575e83..77d7c81fd3 100644 --- a/api/server/routes/edit/gptPlugins.js +++ b/api/server/routes/edit/gptPlugins.js @@ -20,8 +20,8 @@ const { logger } = require('~/config'); const router = express.Router(); -router.use(moderateText); router.post('/abort', handleAbort()); +router.use(moderateText); router.post( '/', diff --git a/api/server/routes/edit/openAI.js b/api/server/routes/edit/openAI.js index ae26b235c7..67b78e773e 100644 --- a/api/server/routes/edit/openAI.js +++ b/api/server/routes/edit/openAI.js @@ -11,8 +11,8 @@ const { } = require('~/server/middleware'); const router = express.Router(); -router.use(moderateText); router.post('/abort', handleAbort()); +router.use(moderateText); router.post( '/',