Files
DLE/backend/services/ollamaConfig.js
2025-10-09 20:49:51 +03:00

289 lines
9.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Copyright (c) 2024-2025 Тарабанов Александр Викторович
* All rights reserved.
*
* This software is proprietary and confidential.
* Unauthorized copying, modification, or distribution is prohibited.
*
* For licensing inquiries: info@hb3-accelerator.com
* Website: https://hb3-accelerator.com
* GitHub: https://github.com/HB3-ACCELERATOR
*/
/**
* Конфигурационный сервис для Ollama и AI инфраструктуры
* Централизует все настройки, URL и таймауты для:
* - Ollama API
* - Vector Search
* - AI Cache
* - AI Queue
*
* ВАЖНО: Настройки берутся из таблицы ai_providers_settings (через aiProviderSettingsService)
*/
const logger = require('../utils/logger');
// Кэш для настроек из БД
let settingsCache = null;
/**
* Загружает настройки Ollama из базы данных
* @returns {Promise<Object>} Настройки Ollama провайдера
*/
async function loadSettingsFromDb() {
try {
const aiProviderSettingsService = require('./aiProviderSettingsService');
const settings = await aiProviderSettingsService.getProviderSettings('ollama');
if (settings) {
settingsCache = settings;
logger.info(`[ollamaConfig] Loaded settings from DB: model=${settings.selected_model}, base_url=${settings.base_url}`);
}
return settings;
} catch (error) {
logger.error('[ollamaConfig] Ошибка загрузки настроек Ollama из БД:', error.message);
return null;
}
}
/**
* Получает базовый URL для Ollama (синхронная версия)
* @returns {string} Базовый URL Ollama
*/
function getBaseUrl() {
// Приоритет: кэш из БД > Docker дефолт
if (settingsCache && settingsCache.base_url) {
return settingsCache.base_url;
}
// URL по умолчанию для Docker
return 'http://ollama:11434';
}
/**
* Получает базовый URL для Ollama (асинхронная версия)
* @returns {Promise<string>} Базовый URL Ollama
*/
async function getBaseUrlAsync() {
try {
if (!settingsCache) {
await loadSettingsFromDb();
}
if (settingsCache && settingsCache.base_url) {
return settingsCache.base_url;
}
} catch (error) {
logger.warn('[ollamaConfig] Failed to load base_url from DB, using default');
}
return 'http://ollama:11434';
}
/**
* Получает URL для конкретного API endpoint Ollama
* @param {string} endpoint - Endpoint API (например: 'tags', 'generate')
* @returns {string} Полный URL для API endpoint
*/
function getApiUrl(endpoint) {
const baseUrl = getBaseUrl();
return `${baseUrl}/api/${endpoint}`;
}
/**
* Получает модель по умолчанию для Ollama (синхронная версия)
* @returns {string} Название модели
*/
function getDefaultModel() {
// Приоритет: кэш из БД > дефолт
if (settingsCache && settingsCache.selected_model) {
return settingsCache.selected_model;
}
// Дефолтное значение если БД недоступна
return 'qwen2.5:7b';
}
/**
* Получает модель асинхронно из БД
* @returns {Promise<string>} Название модели из БД
*/
async function getDefaultModelAsync() {
try {
if (!settingsCache) {
await loadSettingsFromDb();
}
if (settingsCache && settingsCache.selected_model) {
logger.info(`[ollamaConfig] Using model from DB: ${settingsCache.selected_model}`);
return settingsCache.selected_model;
}
} catch (error) {
logger.warn('[ollamaConfig] Failed to load model from DB, using default');
}
return 'qwen2.5:7b';
}
/**
* Получает embedding модель асинхронно из БД
* @returns {Promise<string>} Название embedding модели из БД
*/
async function getEmbeddingModel() {
try {
if (!settingsCache) {
await loadSettingsFromDb();
}
if (settingsCache && settingsCache.embedding_model) {
logger.info(`[ollamaConfig] Using embedding model from DB: ${settingsCache.embedding_model}`);
return settingsCache.embedding_model;
}
} catch (error) {
logger.warn('[ollamaConfig] Failed to load embedding model from DB, using default');
}
return 'mxbai-embed-large:latest';
}
/**
* Централизованные таймауты для Ollama и AI сервисов
* @returns {Object} Объект с различными таймаутами
*/
function getTimeouts() {
return {
// Ollama API - таймауты запросов
ollamaChat: 180000, // 180 сек (3 мин) - генерация ответов LLM (увеличено для сложных запросов)
ollamaEmbedding: 90000, // 90 сек (1.5 мин) - генерация embeddings (увеличено)
ollamaHealth: 5000, // 5 сек - health check
ollamaTags: 10000, // 10 сек - список моделей
// Vector Search - таймауты запросов
vectorSearch: 90000, // 90 сек - поиск по векторам (увеличено для больших баз)
vectorUpsert: 90000, // 90 сек - индексация данных (увеличено)
vectorHealth: 5000, // 5 сек - health check
// AI Cache - TTL (Time To Live) для кэширования
cacheLLM: 24 * 60 * 60 * 1000, // 24 часа - LLM ответы
cacheRAG: 5 * 60 * 1000, // 5 минут - RAG результаты
cacheMax: 1000, // Максимум записей в кэше
// AI Queue - параметры очереди
queueTimeout: 180000, // 180 сек - таймаут задачи в очереди (увеличено)
queueMaxSize: 100, // Максимум задач в очереди
queueInterval: 100, // 100 мс - интервал проверки очереди
// Default для совместимости
default: 180000 // 180 сек (увеличено с 120)
};
}
/**
* Получает timeout для запросов к Ollama (обратная совместимость)
* @returns {number} Timeout в миллисекундах
*/
function getTimeout() {
return getTimeouts().ollamaChat; // 120 секунд (2 минуты) - для генерации длинных ответов
}
/**
* Получает все конфигурационные параметры Ollama (синхронная версия)
* @returns {Object} Объект с конфигурацией
*/
function getConfig() {
return {
baseUrl: getBaseUrl(),
defaultModel: getDefaultModel(),
timeout: getTimeout(),
apiUrl: {
tags: getApiUrl('tags'),
generate: getApiUrl('generate'),
chat: getApiUrl('chat'),
models: getApiUrl('models'),
show: getApiUrl('show'),
pull: getApiUrl('pull'),
push: getApiUrl('push')
}
};
}
/**
* Получает все конфигурационные параметры Ollama (асинхронная версия)
* @returns {Promise<Object>} Объект с конфигурацией
*/
async function getConfigAsync() {
const baseUrl = await getBaseUrlAsync();
const defaultModel = await getDefaultModelAsync();
const embeddingModel = await getEmbeddingModel();
return {
baseUrl,
defaultModel,
embeddingModel,
timeout: getTimeout(),
apiUrl: {
tags: `${baseUrl}/api/tags`,
generate: `${baseUrl}/api/generate`,
chat: `${baseUrl}/api/chat`,
models: `${baseUrl}/api/models`,
show: `${baseUrl}/api/show`,
pull: `${baseUrl}/api/pull`,
push: `${baseUrl}/api/push`
}
};
}
/**
* Очищает кэш настроек (для перезагрузки)
*/
function clearCache() {
settingsCache = null;
logger.info('[ollamaConfig] Settings cache cleared');
}
/**
* Проверяет доступность Ollama сервиса
* @returns {Promise<Object>} Статус здоровья сервиса
*/
async function checkHealth() {
try {
const baseUrl = getBaseUrl();
const response = await fetch(`${baseUrl}/api/tags`);
if (!response.ok) {
return {
status: 'error',
error: `Ollama вернул код ${response.status}`,
baseUrl
};
}
const data = await response.json();
return {
status: 'ok',
baseUrl,
model: getDefaultModel(),
availableModels: data.models?.length || 0
};
} catch (error) {
return {
status: 'error',
error: error.message,
baseUrl: getBaseUrl()
};
}
}
module.exports = {
getBaseUrl,
getBaseUrlAsync,
getApiUrl,
getDefaultModel,
getDefaultModelAsync,
getEmbeddingModel,
getTimeout, // Обратная совместимость (возвращает ollamaChat timeout)
getTimeouts, // ✨ НОВОЕ: Централизованные таймауты для всех сервисов
getConfig,
getConfigAsync,
loadSettingsFromDb,
clearCache,
checkHealth
};