const { ChatOllama } = require('@langchain/ollama'); const { HNSWLib } = require('@langchain/community/vectorstores/hnswlib'); const { OpenAIEmbeddings } = require('@langchain/openai'); const logger = require('../utils/logger'); const fetch = require('node-fetch'); class AIAssistant { constructor() { this.baseUrl = process.env.OLLAMA_BASE_URL || 'http://localhost:11434'; this.defaultModel = process.env.OLLAMA_MODEL || 'qwen2.5'; } // Создание экземпляра ChatOllama с нужными параметрами createChat(language = 'ru') { const systemPrompt = language === 'ru' ? 'Вы - полезный ассистент. Отвечайте на русском языке.' : 'You are a helpful assistant. Respond in English.'; return new ChatOllama({ baseUrl: this.baseUrl, model: this.defaultModel, system: systemPrompt, temperature: 0.7, maxTokens: 1000, timeout: 30000, // 30 секунд таймаут }); } // Определение языка сообщения detectLanguage(message) { const cyrillicPattern = /[а-яА-ЯёЁ]/; return cyrillicPattern.test(message) ? 'ru' : 'en'; } // Основной метод для получения ответа async getResponse(message, language = 'auto') { try { console.log('getResponse called with:', { message, language }); // Определяем язык, если не указан явно const detectedLanguage = language === 'auto' ? this.detectLanguage(message) : language; console.log('Detected language:', detectedLanguage); // Сначала пробуем прямой API запрос try { console.log('Trying direct API request...'); const response = await this.fallbackRequest(message, detectedLanguage); console.log('Direct API response received:', response); return response; } catch (error) { console.error('Error in direct API request:', error); } // Если прямой запрос не удался, пробуем через ChatOllama const chat = this.createChat(detectedLanguage); try { console.log('Sending request to ChatOllama...'); const response = await chat.invoke(message); console.log('ChatOllama response:', response); return response.content; } catch (error) { console.error('Error using ChatOllama:', error); throw error; } } catch (error) { console.error('Error in getResponse:', error); return 'Извините, я не смог обработать ваш запрос. Пожалуйста, попробуйте позже.'; } } // Альтернативный метод запроса через прямой API async fallbackRequest(message, language) { try { console.log('Using fallback request method with:', { message, language }); const systemPrompt = language === 'ru' ? 'Вы - полезный ассистент. Отвечайте на русском языке.' : 'You are a helpful assistant. Respond in English.'; console.log('Sending request to Ollama API...'); const response = await fetch(`${this.baseUrl}/api/generate`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ model: this.defaultModel, prompt: message, system: systemPrompt, stream: false, options: { temperature: 0.7, num_predict: 1000, }, }), }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); console.log('Ollama API response:', data); return data.response; } catch (error) { console.error('Error in fallback request:', error); throw error; } } // Получение списка доступных моделей async getAvailableModels() { try { const response = await fetch(`${this.baseUrl}/api/tags`); const data = await response.json(); return data.models || []; } catch (error) { logger.error('Error getting available models:', error); return []; } } // Добавляем методы из vectorStore.js async initVectorStore() { // ... код инициализации ... } async findSimilarDocuments(query, k = 3) { // ... код поиска документов ... } } // Создаем и экспортируем единственный экземпляр const aiAssistant = new AIAssistant(); module.exports = aiAssistant;