2024-11-26 19:16:31 +01:00
|
|
|
const OpenAI = require('openai');
|
2024-04-21 08:31:54 -04:00
|
|
|
const { ErrorTypes } = require('librechat-data-provider');
|
2024-11-26 19:16:31 +01:00
|
|
|
const { isEnabled } = require('~/server/utils');
|
2024-01-01 21:08:02 +01:00
|
|
|
const denyRequest = require('./denyRequest');
|
2024-03-29 08:23:38 -04:00
|
|
|
const { logger } = require('~/config');
|
2024-01-01 21:08:02 +01:00
|
|
|
|
2024-11-26 19:16:31 +01:00
|
|
|
/**
|
|
|
|
|
* 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<void>}
|
|
|
|
|
*/
|
2024-01-01 21:08:02 +01:00
|
|
|
async function moderateText(req, res, next) {
|
2024-11-26 19:16:31 +01:00
|
|
|
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' });
|
2024-01-01 21:08:02 +01:00
|
|
|
}
|
2024-11-26 19:16:31 +01:00
|
|
|
|
|
|
|
|
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',
|
|
|
|
|
});
|
2024-01-01 21:08:02 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
module.exports = moderateText;
|