-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
🔉 feat: TTS/STT rate limiters (#2925)
* fix: remove double initialization of speech routes * refactor(useMessageHelpers): more consistent latestMessage updates based on unique textKey and early returns when setting * feat: TTS/STT rate limiters * chore: remove console log * fix: make modular chat true by default
- Loading branch information
1 parent
cd1dd62
commit bbb8771
Showing
12 changed files
with
264 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
const createTTSLimiters = require('./ttsLimiters'); | ||
const createSTTLimiters = require('./sttLimiters'); | ||
|
||
module.exports = { | ||
createTTSLimiters, | ||
createSTTLimiters, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
const rateLimit = require('express-rate-limit'); | ||
const { ViolationTypes } = require('librechat-data-provider'); | ||
const logViolation = require('~/cache/logViolation'); | ||
|
||
const getEnvironmentVariables = () => { | ||
const STT_IP_MAX = parseInt(process.env.STT_IP_MAX) || 100; | ||
const STT_IP_WINDOW = parseInt(process.env.STT_IP_WINDOW) || 1; | ||
const STT_USER_MAX = parseInt(process.env.STT_USER_MAX) || 50; | ||
const STT_USER_WINDOW = parseInt(process.env.STT_USER_WINDOW) || 1; | ||
|
||
const sttIpWindowMs = STT_IP_WINDOW * 60 * 1000; | ||
const sttIpMax = STT_IP_MAX; | ||
const sttIpWindowInMinutes = sttIpWindowMs / 60000; | ||
|
||
const sttUserWindowMs = STT_USER_WINDOW * 60 * 1000; | ||
const sttUserMax = STT_USER_MAX; | ||
const sttUserWindowInMinutes = sttUserWindowMs / 60000; | ||
|
||
return { | ||
sttIpWindowMs, | ||
sttIpMax, | ||
sttIpWindowInMinutes, | ||
sttUserWindowMs, | ||
sttUserMax, | ||
sttUserWindowInMinutes, | ||
}; | ||
}; | ||
|
||
const createSTTHandler = (ip = true) => { | ||
const { sttIpMax, sttIpWindowInMinutes, sttUserMax, sttUserWindowInMinutes } = | ||
getEnvironmentVariables(); | ||
|
||
return async (req, res) => { | ||
const type = ViolationTypes.STT_LIMIT; | ||
const errorMessage = { | ||
type, | ||
max: ip ? sttIpMax : sttUserMax, | ||
limiter: ip ? 'ip' : 'user', | ||
windowInMinutes: ip ? sttIpWindowInMinutes : sttUserWindowInMinutes, | ||
}; | ||
|
||
await logViolation(req, res, type, errorMessage); | ||
res.status(429).json({ message: 'Too many STT requests. Try again later' }); | ||
}; | ||
}; | ||
|
||
const createSTTLimiters = () => { | ||
const { sttIpWindowMs, sttIpMax, sttUserWindowMs, sttUserMax } = getEnvironmentVariables(); | ||
|
||
const sttIpLimiter = rateLimit({ | ||
windowMs: sttIpWindowMs, | ||
max: sttIpMax, | ||
handler: createSTTHandler(), | ||
}); | ||
|
||
const sttUserLimiter = rateLimit({ | ||
windowMs: sttUserWindowMs, | ||
max: sttUserMax, | ||
handler: createSTTHandler(false), | ||
keyGenerator: function (req) { | ||
return req.user?.id; // Use the user ID or NULL if not available | ||
}, | ||
}); | ||
|
||
return { sttIpLimiter, sttUserLimiter }; | ||
}; | ||
|
||
module.exports = createSTTLimiters; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
const rateLimit = require('express-rate-limit'); | ||
const { ViolationTypes } = require('librechat-data-provider'); | ||
const logViolation = require('~/cache/logViolation'); | ||
|
||
const getEnvironmentVariables = () => { | ||
const TTS_IP_MAX = parseInt(process.env.TTS_IP_MAX) || 100; | ||
const TTS_IP_WINDOW = parseInt(process.env.TTS_IP_WINDOW) || 1; | ||
const TTS_USER_MAX = parseInt(process.env.TTS_USER_MAX) || 50; | ||
const TTS_USER_WINDOW = parseInt(process.env.TTS_USER_WINDOW) || 1; | ||
|
||
const ttsIpWindowMs = TTS_IP_WINDOW * 60 * 1000; | ||
const ttsIpMax = TTS_IP_MAX; | ||
const ttsIpWindowInMinutes = ttsIpWindowMs / 60000; | ||
|
||
const ttsUserWindowMs = TTS_USER_WINDOW * 60 * 1000; | ||
const ttsUserMax = TTS_USER_MAX; | ||
const ttsUserWindowInMinutes = ttsUserWindowMs / 60000; | ||
|
||
return { | ||
ttsIpWindowMs, | ||
ttsIpMax, | ||
ttsIpWindowInMinutes, | ||
ttsUserWindowMs, | ||
ttsUserMax, | ||
ttsUserWindowInMinutes, | ||
}; | ||
}; | ||
|
||
const createTTSHandler = (ip = true) => { | ||
const { ttsIpMax, ttsIpWindowInMinutes, ttsUserMax, ttsUserWindowInMinutes } = | ||
getEnvironmentVariables(); | ||
|
||
return async (req, res) => { | ||
const type = ViolationTypes.TTS_LIMIT; | ||
const errorMessage = { | ||
type, | ||
max: ip ? ttsIpMax : ttsUserMax, | ||
limiter: ip ? 'ip' : 'user', | ||
windowInMinutes: ip ? ttsIpWindowInMinutes : ttsUserWindowInMinutes, | ||
}; | ||
|
||
await logViolation(req, res, type, errorMessage); | ||
res.status(429).json({ message: 'Too many TTS requests. Try again later' }); | ||
}; | ||
}; | ||
|
||
const createTTSLimiters = () => { | ||
const { ttsIpWindowMs, ttsIpMax, ttsUserWindowMs, ttsUserMax } = getEnvironmentVariables(); | ||
|
||
const ttsIpLimiter = rateLimit({ | ||
windowMs: ttsIpWindowMs, | ||
max: ttsIpMax, | ||
handler: createTTSHandler(), | ||
}); | ||
|
||
const ttsUserLimiter = rateLimit({ | ||
windowMs: ttsUserWindowMs, | ||
max: ttsUserMax, | ||
handler: createTTSHandler(false), | ||
keyGenerator: function (req) { | ||
return req.user?.id; // Use the user ID or NULL if not available | ||
}, | ||
}); | ||
|
||
return { ttsIpLimiter, ttsUserLimiter }; | ||
}; | ||
|
||
module.exports = createTTSLimiters; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { ContentTypes } from 'librechat-data-provider'; | ||
import type { TMessage } from 'librechat-data-provider'; | ||
|
||
export const getLengthAndFirstFiveChars = (str?: string) => { | ||
const length = str ? str.length : 0; | ||
const firstFiveChars = str ? str.substring(0, 5) : ''; | ||
return `${length}${firstFiveChars}`; | ||
}; | ||
|
||
export const getLatestText = (message?: TMessage | null) => { | ||
if (!message) { | ||
return ''; | ||
} | ||
if (message.text) { | ||
return message.text; | ||
} | ||
if (message.content?.length) { | ||
for (let i = message.content.length - 1; i >= 0; i--) { | ||
const part = message.content[i]; | ||
if (part.type === ContentTypes.TEXT && part[ContentTypes.TEXT]?.value?.length > 0) { | ||
return part[ContentTypes.TEXT].value; | ||
} | ||
} | ||
} | ||
return ''; | ||
}; |
Oops, something went wrong.