77 lines
2.1 KiB
JavaScript
77 lines
2.1 KiB
JavaScript
/**
|
|
* Кэширование AI ответов для ускорения работы
|
|
*/
|
|
|
|
const crypto = require('crypto');
|
|
const logger = require('../utils/logger');
|
|
|
|
class AICache {
|
|
constructor() {
|
|
this.cache = new Map();
|
|
this.maxSize = 1000; // Максимальное количество кэшированных ответов
|
|
this.ttl = 24 * 60 * 60 * 1000; // 24 часа в миллисекундах
|
|
}
|
|
|
|
// Генерация ключа кэша на основе запроса
|
|
generateKey(messages, options = {}) {
|
|
const content = JSON.stringify({
|
|
messages: messages.map(m => ({ role: m.role, content: m.content })),
|
|
temperature: options.temperature || 0.3,
|
|
maxTokens: options.num_predict || 150
|
|
});
|
|
return crypto.createHash('md5').update(content).digest('hex');
|
|
}
|
|
|
|
// Получение ответа из кэша
|
|
get(key) {
|
|
const cached = this.cache.get(key);
|
|
if (!cached) return null;
|
|
|
|
// Проверяем TTL
|
|
if (Date.now() - cached.timestamp > this.ttl) {
|
|
this.cache.delete(key);
|
|
return null;
|
|
}
|
|
|
|
logger.info(`[AICache] Cache hit for key: ${key.substring(0, 8)}...`);
|
|
return cached.response;
|
|
}
|
|
|
|
// Сохранение ответа в кэш
|
|
set(key, response) {
|
|
// Очищаем старые записи если кэш переполнен
|
|
if (this.cache.size >= this.maxSize) {
|
|
const oldestKey = this.cache.keys().next().value;
|
|
this.cache.delete(oldestKey);
|
|
}
|
|
|
|
this.cache.set(key, {
|
|
response,
|
|
timestamp: Date.now()
|
|
});
|
|
|
|
logger.info(`[AICache] Cached response for key: ${key.substring(0, 8)}...`);
|
|
}
|
|
|
|
// Очистка кэша
|
|
clear() {
|
|
this.cache.clear();
|
|
logger.info('[AICache] Cache cleared');
|
|
}
|
|
|
|
// Статистика кэша
|
|
getStats() {
|
|
return {
|
|
size: this.cache.size,
|
|
maxSize: this.maxSize,
|
|
hitRate: this.calculateHitRate()
|
|
};
|
|
}
|
|
|
|
calculateHitRate() {
|
|
// Простая реализация - в реальности нужно отслеживать hits/misses
|
|
return this.cache.size / this.maxSize;
|
|
}
|
|
}
|
|
|
|
module.exports = new AICache();
|