From 9f94295d15aa0ed42a7089f97988ff6f758aa76e Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 4 Sep 2025 13:24:53 +0300 Subject: [PATCH] =?UTF-8?q?=D0=B2=D0=B0=D1=88=D0=B5=20=D1=81=D0=BE=D0=BE?= =?UTF-8?q?=D0=B1=D1=89=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BA=D0=BE=D0=BC=D0=BC?= =?UTF-8?q?=D0=B8=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile.ollama | 10 +++++ backend/app.js | 1 - backend/scripts/warmup-model.js | 66 -------------------------------- backend/server.js | 4 -- backend/services/ai-assistant.js | 3 +- docker-compose.yml | 10 ++--- docs/RAG_TASKS.md | 56 ++++++++++++++++++++++++++- entrypoint.sh | 47 +++++++++++++++++++++++ 8 files changed, 118 insertions(+), 79 deletions(-) create mode 100644 Dockerfile.ollama delete mode 100644 backend/scripts/warmup-model.js create mode 100644 entrypoint.sh diff --git a/Dockerfile.ollama b/Dockerfile.ollama new file mode 100644 index 0000000..bde7d63 --- /dev/null +++ b/Dockerfile.ollama @@ -0,0 +1,10 @@ +FROM ollama/ollama:latest + +# Устанавливаем curl для API запросов +RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/* + +# Копируем entrypoint скрипт +COPY entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh + +ENTRYPOINT ["/entrypoint.sh"] diff --git a/backend/app.js b/backend/app.js index a1b4061..217ad5e 100644 --- a/backend/app.js +++ b/backend/app.js @@ -21,7 +21,6 @@ const errorHandler = require('./middleware/errorHandler'); // const { version } = require('./package.json'); // Закомментировано, так как не используется const db = require('./db'); // Добавляем импорт db const aiAssistant = require('./services/ai-assistant'); // Добавляем импорт aiAssistant -const { warmupModel } = require('./scripts/warmup-model'); // Добавляем импорт разогрева модели const fs = require('fs'); const path = require('path'); const messagesRoutes = require('./routes/messages'); diff --git a/backend/scripts/warmup-model.js b/backend/scripts/warmup-model.js deleted file mode 100644 index aede95e..0000000 --- a/backend/scripts/warmup-model.js +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env node - -/** - * Скрипт для разогрева модели Ollama - * Запускается при старте backend для ускорения первых запросов - */ - -const fetch = require('node-fetch'); - -const OLLAMA_URL = process.env.OLLAMA_URL || 'http://ollama:11434'; -const MODEL_NAME = process.env.OLLAMA_MODEL || 'qwen2.5:7b'; - -async function warmupModel() { - // console.log('🔥 Разогрев модели Ollama...'); - - try { - // Проверяем доступность Ollama - const healthResponse = await fetch(`${OLLAMA_URL}/api/tags`); - if (!healthResponse.ok) { - throw new Error(`Ollama недоступен: ${healthResponse.status}`); - } - - // console.log('✅ Ollama доступен'); - - // Отправляем простой запрос для разогрева (корректный эндпоинт) - const warmupResponse = await fetch(`${OLLAMA_URL}/api/chat`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - model: MODEL_NAME, - messages: [ - { role: 'system', content: 'Ты полезный ассистент.' }, - { role: 'user', content: 'Привет! Как дела?' } - ], - stream: false, - options: { - temperature: 0.2, - num_predict: 64, - num_ctx: 1024, - num_thread: 4, - num_gpu: 1, - repeat_penalty: 1.1, - top_k: 30, - top_p: 0.9 - } - }), - }); - - if (!warmupResponse.ok) { - throw new Error(`Ошибка разогрева: ${warmupResponse.status}`); - } - - const data = await warmupResponse.json(); - // console.log('✅ Модель разогрета успешно'); - // console.log(`📝 Ответ модели: ${(data.message?.content || data.response || '').substring(0, 100)}...`); - - } catch (error) { - // console.error('❌ Ошибка разогрева модели:', error.message); - // Не прерываем запуск приложения - } -} - -// Запускаем разогрев с задержкой -setTimeout(warmupModel, 5000); - -module.exports = { warmupModel }; \ No newline at end of file diff --git a/backend/server.js b/backend/server.js index 2f49651..dc1d5b9 100644 --- a/backend/server.js +++ b/backend/server.js @@ -18,7 +18,6 @@ const logger = require('./utils/logger'); const { getBot } = require('./services/telegramBot'); const EmailBotService = require('./services/emailBot'); const { initDbPool, seedAIAssistantSettings } = require('./db'); -const { warmupModel } = require('./scripts/warmup-model'); // Добавляем импорт разогрева модели const memoryMonitor = require('./utils/memoryMonitor'); const PORT = process.env.PORT || 8000; @@ -72,9 +71,6 @@ async function startServer() { // Разогрев модели Ollama // console.log('🔥 Запуск разогрева модели...'); setTimeout(() => { - warmupModel().catch(err => { - // console.error('❌ Ошибка разогрева модели:', err.message); - }); }, 10000); // Задержка 10 секунд для полной инициализации await initServices(); // Только теперь запускать сервисы diff --git a/backend/services/ai-assistant.js b/backend/services/ai-assistant.js index 7b97ed5..7ec1598 100644 --- a/backend/services/ai-assistant.js +++ b/backend/services/ai-assistant.js @@ -352,8 +352,7 @@ class AIAssistant { model, messages: finalMessages, stream: false, - options: ollamaOptions, - keep_alive: '3m' + options: ollamaOptions }) }); logger.info(`[AIAssistant] Ollama API ответил: status=${response.status}`); diff --git a/docker-compose.yml b/docker-compose.yml index 1b320ef..aace7ac 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -30,7 +30,9 @@ services: timeout: 5s retries: 5 ollama: - image: ollama/ollama:latest + build: + context: . + dockerfile: Dockerfile.ollama container_name: dapp-ollama restart: unless-stopped logging: @@ -53,11 +55,11 @@ services: environment: - OLLAMA_HOST=0.0.0.0 - OLLAMA_ORIGINS=* - - OLLAMA_NUM_PARALLEL=1 + - OLLAMA_NUM_PARALLEL=2 - OLLAMA_NUM_GPU=0 - OLLAMA_KEEP_ALIVE=86400 - OLLAMA_MODEL_TIMEOUT=0 - - OLLAMA_MAX_LOADED_MODELS=1 + - OLLAMA_MAX_LOADED_MODELS=2 - OLLAMA_FLASH_ATTENTION=0 - OLLAMA_LLM_LIBRARY=auto healthcheck: @@ -66,8 +68,6 @@ services: timeout: 10s retries: 5 start_period: 120s - # Предзагружаем модель при запуске контейнера с keepalive - entrypoint: ["/bin/sh", "-c", "ollama serve & sleep 15 && ollama run --keepalive 24h qwen2.5:7b 'test' && tail -f /dev/null"] vector-search: build: context: ./vector-search diff --git a/docs/RAG_TASKS.md b/docs/RAG_TASKS.md index cc1a9af..63ae0cc 100644 --- a/docs/RAG_TASKS.md +++ b/docs/RAG_TASKS.md @@ -134,6 +134,36 @@ - Генерация мультимодальных ответов - **Результат:** Контекст из медиафайлов +#### 9. Агент "Саммари беседы" +- **Задача:** Создание краткого саммари истории беседы +- **Функции:** + - Анализирует последние 10-20 сообщений из истории + - Создает краткое саммари через AI (вместо передачи полной истории) + - Кэширует результат для повторного использования + - Обновляет саммари при поступлении новых сообщений + - Оптимизирует количество токенов в промпте +- **Результат:** Оптимизированный контекст беседы для AI + +#### 10. Агент "Анализ контакта" +- **Задача:** Извлечение и анализ данных пользователя из профиля +- **Функции:** + - Получает данные из профиля контакта (имя, теги, язык, роль) + - Анализирует предпочтения и историю взаимодействий + - Кэширует анализ для быстрого доступа + - Обновляет при изменении профиля пользователя + - Определяет стиль общения и приоритет +- **Результат:** Персонализированный контекст для ответа + +#### 11. Агент "Кэширование бесед" +- **Задача:** Управление кэшем бесед и контекста +- **Функции:** + - Кэширует саммари беседы + анализ контакта + - Управляет TTL (Time To Live) для автоматической очистки + - Проверяет актуальность кэша при новых сообщениях + - Оптимизирует производительность системы + - Предотвращает повторные вычисления +- **Результат:** Быстрый доступ к контексту без пересчета + ### ⚙️ Логика работы многоагентной системы #### Шаг 1: Получение сообщения @@ -148,6 +178,9 @@ - Агент "Контекст" → анализирует историю - Агент "Мультиязычность" → определяет язык - Агент "Мультимодальность" → обрабатывает медиа +- Агент "Саммари беседы" → создает краткое саммари истории +- Агент "Анализ контакта" → извлекает данные из профиля +- Агент "Кэширование бесед" → проверяет и обновляет кэш #### Шаг 3: Сбор и анализ результатов - Координатор собирает данные от всех агентов @@ -163,6 +196,8 @@ - Обновляет профиль пользователя - Сохраняет контекст беседы - Логирует использованные знания +- Обновляет кэш саммари и анализа контакта +- Сохраняет оптимизированный контекст для будущих запросов ### 🎨 Преимущества многоагентной архитектуры @@ -172,6 +207,9 @@ 4. **Гибкость:** Разные комбинации агентов для разных ситуаций 5. **Персонализация:** Глубокое понимание каждого пользователя 6. **Качество:** Специализированная обработка каждого аспекта +7. **Оптимизация:** Саммари бесед снижает количество токенов +8. **Кэширование:** Быстрый доступ к контексту без пересчета +9. **Производительность:** Уменьшение времени ответа и нагрузки на AI --- @@ -251,10 +289,17 @@ - Агент "Контекст беседы" - Агент "Детализация" - Агент "Персонализация ответа" + - Агент "Саммари беседы" (новый) + - Агент "Анализ контакта" (новый) + - Агент "Кэширование бесед" (новый) 3. **Интеграция с существующей системой:** - Подключение агентов к текущему pipeline - Настройка логирования и мониторинга - Тестирование взаимодействия агентов +4. **Реализация оптимизаций:** + - Создание сервиса саммари бесед + - Интеграция анализа контактов для персонализации + - Настройка кэширования для повышения производительности --- @@ -262,8 +307,12 @@ 1. **Модификация логики ответа ассистента:** - При получении сообщения пользователя — искать релевантные знания и включать их в prompt LLM. - Обеспечить мультиязычность поиска и генерации ответа. + - Интегрировать саммари беседы вместо передачи полной истории. + - Использовать анализ контактов для персонализации ответов. 2. **Логирование и трассировка:** - Сохранять, какие знания были использованы для ответа. + - Логировать использование саммари и кэширования. + - Отслеживать производительность оптимизаций. --- @@ -287,7 +336,9 @@ ## Этап 7. Тестирование и оптимизация 1. **Покрытие тестами ключевых сценариев (unit, интеграционные).** 2. **Оптимизация скорости поиска и генерации.** -3. **Документация для команды.** +3. **Тестирование производительности саммари и кэширования.** +4. **Оптимизация использования токенов и времени ответа.** +5. **Документация для команды.** --- @@ -308,6 +359,9 @@ - При обработке запроса пользователя RAG-ассистент определяет его теги (по связям в таблице тегов). - Для генерации ответа ассистент использует только те знания (вопросы/ответы), которые соответствуют тегам пользователя. - Администратор может добавлять новые теги, связывать их с пользователями, а также создавать и редактировать знания для каждой группы. +- **Оптимизация через саммари:** Вместо передачи полной истории беседы (10 сообщений), система создает краткое саммари через AI. +- **Персонализация через контакты:** Ассистент использует данные из профиля контакта (имя, язык, теги) для персонализации ответов. +- **Кэширование контекста:** Саммари беседы и анализ контактов кэшируются для быстрого доступа без пересчета. ### 4. UI/UX требования - В интерфейсе создания/редактирования пользовательских таблиц должен быть доступен тип столбца "relation" (связь с users). diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000..f4f70b7 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +# Запускаем Ollama сервер в фоне +ollama serve & + +# Ждем запуска сервера +echo "Ждем запуска Ollama сервера..." +sleep 20 + +# Проверяем готовность сервера +echo "Проверяем готовность сервера..." +while ! curl -s http://localhost:11434/api/tags > /dev/null; do + echo "Сервер еще не готов, ждем..." + sleep 5 +done +echo "Сервер готов!" + +# Загружаем чат-модель через API с keepalive 24h +echo "Загружаем чат-модель qwen2.5:7b через API..." +curl -X POST http://localhost:11434/api/chat \ + -H "Content-Type: application/json" \ + -d '{ + "model": "qwen2.5:7b", + "messages": [{"role": "user", "content": "hi"}], + "keep_alive": "24h" + }' > /dev/null 2>&1 + +echo "Чат-модель qwen2.5:7b загружена!" + +# Скачиваем модель эмбеддингов +echo "Скачиваем модель эмбеддингов mxbai-embed-large:latest..." +ollama pull mxbai-embed-large:latest + +# Загружаем модель эмбеддингов через API с keepalive 24h +echo "Загружаем модель эмбеддингов в память на 24 часа..." +curl -X POST http://localhost:11434/api/embed \ + -H "Content-Type: application/json" \ + -d '{ + "model": "mxbai-embed-large:latest", + "input": "test", + "keep_alive": "24h" + }' + +echo "Все модели загружены! Система готова к работе." + +# Держим контейнер запущенным +tail -f /dev/null