EverydayTech Platform - Developer Reference
Complete Source Code Documentation - All Applications
Loading...
Searching...
No Matches
llmCacheRateLimit.js
Go to the documentation of this file.
1/**
2 * @file LLM Caching and Rate Limiting Middleware
3 * @module middleware/llmCacheRateLimit
4 * @description
5 * Express middleware for Large Language Model (LLM) request caching and per-tenant
6 * rate limiting. Checks Redis cache for previous LLM results, enforces rate limits,
7 * and caches successful LLM responses to reduce API costs and improve performance.
8 *
9 * Features:
10 * - **Response caching**: Stores LLM outputs by (type, text) key
11 * - **Rate limiting**: Per-tenant limits using Redis counters
12 * - **Cost optimization**: Prevents redundant LLM API calls
13 * - **Performance**: Returns cached results instantly (no LLM latency)
14 * @requires llmRedis - Redis caching and rate limit logic from services/llmRedis
15 * @see {@link module:services/llmRedis} for cache storage implementation
16 */
17
18// llmCacheRateLimit.js - Express middleware for LLM caching and rate limiting
19const { getCachedLLMResult, rateLimit } = require('../services/llmRedis');
20
21/**
22 * LLM caching and rate limiting middleware.
23 *
24 * Validates request body, checks rate limits, queries cache, and either returns
25 * cached result or passes to LLM handler. Stores cache key in res.locals for
26 * response caching in route handler.
27 * @function llmCacheRateLimit
28 * @param {object} req - Express request object
29 * @param {object} req.body - Request body
30 * @param {string} req.body.text - Input text for LLM processing
31 * @param {string} req.body.type - LLM operation type (e.g., "summarize", "classify")
32 * @param {number} req.body.tenantId - Tenant ID for rate limiting
33 * @param {object} res - Express response object
34 * @param {object} res.locals - Response locals object
35 * @param {object} res.locals.llmCacheKey - Cache key {type, text} for result storage
36 * @param {Function} next - Express next middleware function
37 * @returns {void} Returns cached result or calls next() for LLM processing
38 * @throws {400} Missing required fields - text, type, or tenantId missing
39 * @throws {429} Rate limit exceeded - Tenant exceeded LLM request quota
40 * @example
41 * // Apply to LLM routes
42 * const llmCacheRateLimit = require('./middleware/llmCacheRateLimit');
43 * const { setCachedLLMResult } = require('./services/llmRedis');
44 * router.post('/ai/summarize', authenticateToken, llmCacheRateLimit, async (req, res) => {
45 * const summary = await llmService.summarize(req.body.text);
46 *
47 * // Cache result for future requests
48 * await setCachedLLMResult(res.locals.llmCacheKey.type, res.locals.llmCacheKey.text, summary);
49 *
50 * res.json({ output: summary, cached: false });
51 * });
52 * @example
53 * // Cached response
54 * {
55 * "output": "This text summarizes...",
56 * "cached": true
57 * }
58 */
59module.exports = async function llmCacheRateLimit(req, res, next) {
60 const { text, type, tenantId } = req.body;
61 if (!text || !type || !tenantId) return res.status(400).json({ error: 'Missing required fields.' });
62
63 // Rate limit per tenant
64 if (await rateLimit(tenantId)) {
65 return res.status(429).json({ error: 'Rate limit exceeded.' });
66 }
67
68 // Check cache
69 const cached = await getCachedLLMResult(type, text);
70 if (cached) {
71 return res.json({ output: cached, cached: true });
72 }
73
74 // Continue to LLM processing
75 res.locals.llmCacheKey = { type, text };
76 next();
77};