1119 lines
50 KiB
Markdown
1119 lines
50 KiB
Markdown
# Настройка AI Ассистента в DLE
|
||
|
||
> **Временный документ для внутреннего анализа**
|
||
|
||
---
|
||
|
||
## 📋 Содержание
|
||
|
||
1. [Обзор системы](#обзор-системы)
|
||
2. [Архитектура настроек](#архитектура-настроек)
|
||
3. [База данных](#база-данных)
|
||
4. [Backend API](#backend-api)
|
||
5. [Frontend страницы](#frontend-страницы)
|
||
6. [Настройка AI провайдеров](#настройка-ai-провайдеров)
|
||
7. [Настройка AI ассистента](#настройка-ai-ассистента)
|
||
8. [Правила AI (Rules)](#правила-ai-rules)
|
||
9. [Интеграции (Email, Telegram)](#интеграции-email-telegram)
|
||
10. [RAG конфигурация](#rag-конфигурация)
|
||
11. [Мониторинг системы](#мониторинг-системы)
|
||
|
||
---
|
||
|
||
## Обзор системы
|
||
|
||
### Что это?
|
||
|
||
Система настройки AI ассистента в DLE — это **модульная конфигурация** для управления поведением искусственного интеллекта, интеграциями с провайдерами LLM, базами знаний (RAG), и каналами связи.
|
||
|
||
### Ключевые компоненты
|
||
|
||
```
|
||
┌───────────────────────────────────────────────────────────┐
|
||
│ Настройка AI Ассистента в DLE │
|
||
├───────────────────────────────────────────────────────────┤
|
||
│ │
|
||
│ 🤖 AI Провайдеры: │
|
||
│ ├── OpenAI (GPT-4, GPT-3.5) │
|
||
│ ├── Anthropic (Claude) │
|
||
│ ├── Google (Gemini) │
|
||
│ └── Ollama (локальные модели) │
|
||
│ │
|
||
│ ⚙️ Настройки AI: │
|
||
│ ├── System Prompt │
|
||
│ ├── Выбор LLM модели │
|
||
│ ├── Выбор Embedding модели │
|
||
│ ├── Выбор RAG-таблиц │
|
||
│ ├── Правила (Rules) │
|
||
│ └── Настройки RAG поиска │
|
||
│ │
|
||
│ 📋 Правила (Rules): │
|
||
│ ├── JSON конфигурация поведения │
|
||
│ ├── Создание/редактирование/удаление │
|
||
│ └── Привязка к AI ассистенту │
|
||
│ │
|
||
│ 🔗 Интеграции: │
|
||
│ ├── Email (IMAP + SMTP) │
|
||
│ └── Telegram Bot │
|
||
│ │
|
||
│ 🔍 RAG: │
|
||
│ ├── Выбор таблиц для поиска │
|
||
│ ├── Настройки поиска (гибридный/семантический) │
|
||
│ ├── Порог релевантности │
|
||
│ └── Извлечение ключевых слов │
|
||
│ │
|
||
│ 📊 Мониторинг: │
|
||
│ ├── Статус сервисов (Backend, Ollama, Postgres) │
|
||
│ ├── Тест RAG-функциональности │
|
||
│ └── Отслеживание прогресса │
|
||
│ │
|
||
└───────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## Архитектура настроек
|
||
|
||
### Иерархия настроек
|
||
|
||
```
|
||
Уровень 1: AI Провайдеры (ai_providers_settings)
|
||
├── OpenAI (API Key, Base URL, модели)
|
||
├── Anthropic (API Key, модели)
|
||
├── Google (API Key, модели)
|
||
└── Ollama (Base URL, локальные модели)
|
||
|
||
Уровень 2: AI Ассистент (ai_assistant_settings)
|
||
├── System Prompt
|
||
├── Выбранная LLM модель
|
||
├── Выбранная Embedding модель
|
||
├── Выбранные RAG-таблицы
|
||
├── Правила (Rules ID)
|
||
├── Telegram Bot ID
|
||
├── Email Settings ID
|
||
└── Настройки RAG поиска
|
||
|
||
Уровень 3: Правила AI (ai_assistant_rules)
|
||
├── Название
|
||
├── Описание
|
||
└── JSON конфигурация
|
||
```
|
||
|
||
### Процесс обработки сообщения
|
||
|
||
```
|
||
1. Пользователь → Сообщение
|
||
↓
|
||
2. UnifiedMessageProcessor
|
||
↓
|
||
3. Проверка языка (только русский)
|
||
↓
|
||
4. Дедупликация (хеш сообщения)
|
||
↓
|
||
5. Загрузка настроек (aiAssistantSettingsService)
|
||
↓
|
||
6. Загрузка правил (aiAssistantRulesService)
|
||
↓
|
||
7. RAG поиск (ragService)
|
||
├── Семантический поиск (vector search)
|
||
├── Поиск по ключевым словам
|
||
└── Гибридный поиск
|
||
↓
|
||
8. Генерация ответа (generateLLMResponse)
|
||
├── System Prompt
|
||
├── История разговора
|
||
├── Контекст из RAG
|
||
└── Правила
|
||
↓
|
||
9. Ответ → Пользователь
|
||
```
|
||
|
||
---
|
||
|
||
## База данных
|
||
|
||
### Таблица: `ai_providers_settings`
|
||
|
||
**Назначение**: Хранение настроек для AI провайдеров (OpenAI, Anthropic, Google, Ollama).
|
||
|
||
```sql
|
||
CREATE TABLE IF NOT EXISTS ai_providers_settings (
|
||
id SERIAL PRIMARY KEY,
|
||
provider_encrypted TEXT, -- Провайдер: openai, anthropic, google, ollama
|
||
api_key_encrypted TEXT, -- API ключ (зашифрован)
|
||
base_url_encrypted TEXT, -- Base URL для API
|
||
selected_model_encrypted TEXT, -- Выбранная LLM модель
|
||
embedding_model_encrypted TEXT, -- Выбранная Embedding модель
|
||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
|
||
);
|
||
```
|
||
|
||
**Шифрование**: Все чувствительные поля (`provider`, `api_key`, `base_url`, `selected_model`, `embedding_model`) зашифрованы с помощью AES-256.
|
||
|
||
**Примеры записей**:
|
||
|
||
```json
|
||
[
|
||
{
|
||
"id": 1,
|
||
"provider": "ollama",
|
||
"base_url": "http://ollama:11434",
|
||
"selected_model": "qwen2.5:7b",
|
||
"embedding_model": "mxbai-embed-large:latest"
|
||
},
|
||
{
|
||
"id": 2,
|
||
"provider": "openai",
|
||
"api_key": "sk-...",
|
||
"base_url": "https://api.openai.com/v1",
|
||
"selected_model": "gpt-4",
|
||
"embedding_model": "text-embedding-ada-002"
|
||
}
|
||
]
|
||
```
|
||
|
||
### Таблица: `ai_assistant_settings`
|
||
|
||
**Назначение**: Глобальные настройки AI ассистента.
|
||
|
||
```sql
|
||
CREATE TABLE IF NOT EXISTS ai_assistant_settings (
|
||
id SERIAL PRIMARY KEY,
|
||
system_prompt_encrypted TEXT, -- Системный промт
|
||
selected_rag_tables INTEGER[], -- Массив ID RAG-таблиц
|
||
languages TEXT[], -- Массив поддерживаемых языков
|
||
model_encrypted TEXT, -- Выбранная LLM модель
|
||
embedding_model_encrypted TEXT, -- Выбранная Embedding модель
|
||
rules JSONB, -- Правила (DEPRECATED)
|
||
rules_id INTEGER REFERENCES ai_assistant_rules(id), -- Ссылка на правило
|
||
telegram_settings_id INTEGER, -- Ссылка на Telegram бота
|
||
email_settings_id INTEGER, -- Ссылка на Email настройки
|
||
rag_settings JSONB, -- Настройки RAG поиска (NEW)
|
||
updated_at TIMESTAMP DEFAULT NOW(),
|
||
updated_by INTEGER
|
||
);
|
||
```
|
||
|
||
**Новое поле**: `rag_settings` (JSONB)
|
||
|
||
```json
|
||
{
|
||
"searchMethod": "hybrid", // "semantic", "keyword", "hybrid"
|
||
"maxResults": 5, // Максимальное количество результатов
|
||
"relevanceThreshold": 0.1, // Порог релевантности
|
||
"keywordExtraction": {
|
||
"enabled": true, // Включить извлечение ключевых слов
|
||
"minWordLength": 3, // Минимальная длина слова
|
||
"maxKeywords": 10, // Максимальное количество ключевых слов
|
||
"removeStopWords": true, // Удалять стоп-слова
|
||
"language": "ru"
|
||
},
|
||
"searchWeights": {
|
||
"semantic": 70, // Вес семантического поиска (%)
|
||
"keyword": 30 // Вес поиска по ключевым словам (%)
|
||
},
|
||
"advanced": {
|
||
"enableFuzzySearch": true, // Нечеткий поиск
|
||
"enableStemming": true, // Стемминг слов
|
||
"enableSynonyms": false // Поиск синонимов
|
||
}
|
||
}
|
||
```
|
||
|
||
**Пример записи**:
|
||
|
||
```json
|
||
{
|
||
"id": 1,
|
||
"system_prompt": "Вы — полезный ассистент. Отвечайте на русском языке.",
|
||
"selected_rag_tables": [1, 3],
|
||
"languages": ["ru"],
|
||
"model": "qwen2.5:7b",
|
||
"embedding_model": "mxbai-embed-large:latest",
|
||
"rules_id": 2,
|
||
"telegram_settings_id": 1,
|
||
"email_settings_id": 1,
|
||
"rag_settings": { /* см. выше */ }
|
||
}
|
||
```
|
||
|
||
### Таблица: `ai_assistant_rules`
|
||
|
||
**Назначение**: Наборы правил для управления поведением AI.
|
||
|
||
```sql
|
||
CREATE TABLE IF NOT EXISTS ai_assistant_rules (
|
||
id SERIAL PRIMARY KEY,
|
||
name TEXT NOT NULL, -- Название набора правил
|
||
description TEXT, -- Описание правила
|
||
rules JSONB NOT NULL, -- JSON конфигурация
|
||
rules_encrypted TEXT, -- Зашифрованная версия правил (NEW)
|
||
created_at TIMESTAMP DEFAULT NOW(),
|
||
updated_at TIMESTAMP DEFAULT NOW()
|
||
);
|
||
```
|
||
|
||
**Формат правил** (JSON):
|
||
|
||
```json
|
||
{
|
||
"checkUserTags": true, // Проверять теги пользователя
|
||
"searchRagFirst": true, // Искать в RAG сначала
|
||
"generateIfNoRag": true, // Генерировать ответ, если нет RAG
|
||
"requireAdminApproval": false, // Требовать одобрения админа
|
||
"maxTokens": 500, // Максимальное количество токенов
|
||
"temperature": 0.7, // Температура генерации
|
||
"customInstructions": "..." // Дополнительные инструкции
|
||
}
|
||
```
|
||
|
||
**Примеры правил**:
|
||
|
||
```json
|
||
[
|
||
{
|
||
"id": 1,
|
||
"name": "Строгий режим",
|
||
"description": "Только ответы из базы знаний, без генерации",
|
||
"rules": {
|
||
"checkUserTags": true,
|
||
"searchRagFirst": true,
|
||
"generateIfNoRag": false
|
||
}
|
||
},
|
||
{
|
||
"id": 2,
|
||
"name": "Гибридный режим",
|
||
"description": "RAG + генерация при необходимости",
|
||
"rules": {
|
||
"checkUserTags": true,
|
||
"searchRagFirst": true,
|
||
"generateIfNoRag": true,
|
||
"temperature": 0.7
|
||
}
|
||
}
|
||
]
|
||
```
|
||
|
||
---
|
||
|
||
## Backend API
|
||
|
||
### 1. Настройки AI провайдеров
|
||
|
||
#### GET `/settings/ai-settings/:provider`
|
||
|
||
Получить настройки провайдера (openai, anthropic, google, ollama).
|
||
|
||
**Требования**: Авторизация + Admin права
|
||
|
||
**Ответ**:
|
||
```json
|
||
{
|
||
"success": true,
|
||
"settings": {
|
||
"provider": "ollama",
|
||
"api_key": null,
|
||
"base_url": "http://ollama:11434",
|
||
"selected_model": "qwen2.5:7b",
|
||
"embedding_model": "mxbai-embed-large:latest"
|
||
}
|
||
}
|
||
```
|
||
|
||
#### PUT `/settings/ai-settings/:provider`
|
||
|
||
Сохранить/обновить настройки провайдера.
|
||
|
||
**Требования**: Admin права (`requireAdmin`)
|
||
|
||
**Тело запроса**:
|
||
```json
|
||
{
|
||
"api_key": "sk-...",
|
||
"base_url": "https://api.openai.com/v1",
|
||
"selected_model": "gpt-4",
|
||
"embedding_model": "text-embedding-ada-002"
|
||
}
|
||
```
|
||
|
||
#### DELETE `/settings/ai-settings/:provider`
|
||
|
||
Удалить настройки провайдера.
|
||
|
||
**Требования**: Admin права
|
||
|
||
#### GET `/settings/ai-settings/:provider/models`
|
||
|
||
Получить список доступных моделей для провайдера.
|
||
|
||
**Требования**: Admin права
|
||
|
||
**Ответ**:
|
||
```json
|
||
{
|
||
"success": true,
|
||
"models": [
|
||
{ "id": "gpt-4", "name": "GPT-4" },
|
||
{ "id": "gpt-3.5-turbo", "name": "GPT-3.5 Turbo" }
|
||
]
|
||
}
|
||
```
|
||
|
||
#### POST `/settings/ai-settings/:provider/verify`
|
||
|
||
Проверить валидность API ключа.
|
||
|
||
**Требования**: Admin права
|
||
|
||
**Тело запроса**:
|
||
```json
|
||
{
|
||
"api_key": "sk-...",
|
||
"base_url": "https://api.openai.com/v1"
|
||
}
|
||
```
|
||
|
||
**Ответ**:
|
||
```json
|
||
{
|
||
"success": true
|
||
}
|
||
```
|
||
|
||
### 2. Настройки AI ассистента
|
||
|
||
#### GET `/settings/ai-assistant`
|
||
|
||
Получить настройки AI ассистента.
|
||
|
||
**Требования**: Admin права
|
||
|
||
**Ответ**:
|
||
```json
|
||
{
|
||
"success": true,
|
||
"settings": {
|
||
"id": 1,
|
||
"system_prompt": "Вы — полезный ассистент.",
|
||
"selected_rag_tables": [1, 3],
|
||
"model": "qwen2.5:7b",
|
||
"embedding_model": "mxbai-embed-large:latest",
|
||
"rules_id": 2,
|
||
"telegram_settings_id": 1,
|
||
"email_settings_id": 1,
|
||
"ragSettings": {
|
||
"searchMethod": "hybrid",
|
||
"maxResults": 5
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
#### PUT `/settings/ai-assistant`
|
||
|
||
Сохранить/обновить настройки AI ассистента.
|
||
|
||
**Требования**: Admin права
|
||
|
||
**Тело запроса**:
|
||
```json
|
||
{
|
||
"system_prompt": "Вы — полезный ассистент.",
|
||
"selected_rag_tables": [1],
|
||
"model": "qwen2.5:7b",
|
||
"embedding_model": "mxbai-embed-large:latest",
|
||
"rules_id": 2,
|
||
"telegram_settings_id": 1,
|
||
"email_settings_id": 1,
|
||
"ragSettings": {
|
||
"searchMethod": "hybrid",
|
||
"maxResults": 5,
|
||
"relevanceThreshold": 0.1
|
||
}
|
||
}
|
||
```
|
||
|
||
**Обработка на Backend**:
|
||
|
||
```javascript
|
||
// Преобразование selected_rag_tables в массив
|
||
let { selected_rag_tables, ...rest } = req.body;
|
||
|
||
if (typeof selected_rag_tables === 'string') {
|
||
try {
|
||
selected_rag_tables = JSON.parse(selected_rag_tables);
|
||
} catch {
|
||
selected_rag_tables = [Number(selected_rag_tables)];
|
||
}
|
||
}
|
||
|
||
if (!Array.isArray(selected_rag_tables)) {
|
||
selected_rag_tables = [Number(selected_rag_tables)];
|
||
}
|
||
|
||
selected_rag_tables = selected_rag_tables.map(Number);
|
||
```
|
||
|
||
### 3. Правила AI
|
||
|
||
#### GET `/settings/ai-assistant-rules`
|
||
|
||
Получить все наборы правил.
|
||
|
||
**Требования**: Admin права
|
||
|
||
**Ответ**:
|
||
```json
|
||
{
|
||
"success": true,
|
||
"rules": [
|
||
{
|
||
"id": 1,
|
||
"name": "Строгий режим",
|
||
"description": "Только ответы из базы знаний",
|
||
"rules": { "checkUserTags": true, "generateIfNoRag": false },
|
||
"created_at": "2025-01-15T10:00:00Z",
|
||
"updated_at": "2025-01-15T10:00:00Z"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
#### GET `/settings/ai-assistant-rules/:id`
|
||
|
||
Получить правило по ID.
|
||
|
||
**Требования**: Admin права
|
||
|
||
#### POST `/settings/ai-assistant-rules`
|
||
|
||
Создать новое правило.
|
||
|
||
**Требования**: Admin права
|
||
|
||
**Тело запроса**:
|
||
```json
|
||
{
|
||
"name": "Новое правило",
|
||
"description": "Описание правила",
|
||
"rules": {
|
||
"checkUserTags": true,
|
||
"searchRagFirst": true,
|
||
"generateIfNoRag": true
|
||
}
|
||
}
|
||
```
|
||
|
||
#### PUT `/settings/ai-assistant-rules/:id`
|
||
|
||
Обновить правило.
|
||
|
||
**Требования**: Admin права
|
||
|
||
#### DELETE `/settings/ai-assistant-rules/:id`
|
||
|
||
Удалить правило.
|
||
|
||
**Требования**: Admin права
|
||
|
||
### 4. Ollama (локальные модели)
|
||
|
||
#### GET `/ollama/status`
|
||
|
||
Проверить статус Ollama.
|
||
|
||
**Требования**: Авторизация
|
||
|
||
**Ответ**:
|
||
```json
|
||
{
|
||
"connected": true,
|
||
"message": "Ollama is running",
|
||
"models": 3,
|
||
"availableModels": ["qwen2.5:7b", "llama2:7b", "mistral:7b"]
|
||
}
|
||
```
|
||
|
||
#### GET `/ollama/models`
|
||
|
||
Получить список установленных моделей.
|
||
|
||
**Требования**: Авторизация
|
||
|
||
**Ответ**:
|
||
```json
|
||
{
|
||
"models": [
|
||
{
|
||
"name": "qwen2.5:7b",
|
||
"id": "qwen2.5:7b",
|
||
"size": 4500000000,
|
||
"modified": "2025-01-15T10:00:00Z"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
#### POST `/ollama/install`
|
||
|
||
Установить модель.
|
||
|
||
**Требования**: Авторизация
|
||
|
||
**Тело запроса**:
|
||
```json
|
||
{
|
||
"model": "llama2:7b"
|
||
}
|
||
```
|
||
|
||
**Ответ** (немедленный):
|
||
```json
|
||
{
|
||
"success": true,
|
||
"message": "Installation of llama2:7b started",
|
||
"processId": 12345
|
||
}
|
||
```
|
||
|
||
**Примечание**: Установка происходит в фоне, не блокирует запрос.
|
||
|
||
#### DELETE `/ollama/models/:modelName`
|
||
|
||
Удалить модель.
|
||
|
||
**Требования**: Авторизация
|
||
|
||
### 5. Интеграции
|
||
|
||
#### Email
|
||
|
||
**GET** `/settings/email-settings` — Получить настройки Email
|
||
**PUT** `/settings/email-settings` — Обновить настройки Email
|
||
**DELETE** `/settings/email-settings` — Удалить настройки Email
|
||
**POST** `/settings/email-settings/test-smtp` — Тест SMTP
|
||
**POST** `/settings/email-settings/test-imap` — Тест IMAP
|
||
**GET** `/settings/email-settings/list` — Список всех Email настроек
|
||
|
||
#### Telegram
|
||
|
||
**GET** `/settings/telegram-settings` — Получить настройки Telegram
|
||
**PUT** `/settings/telegram-settings` — Обновить настройки Telegram
|
||
**DELETE** `/settings/telegram-settings` — Удалить настройки Telegram
|
||
**GET** `/settings/telegram-settings/list` — Список всех Telegram ботов
|
||
|
||
---
|
||
|
||
## Frontend страницы
|
||
|
||
### 1. Главная страница интеграций
|
||
|
||
**Путь**: `/settings/ai`
|
||
**Компонент**: `AiSettingsView.vue`
|
||
|
||
**Блоки интеграций**:
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────┐
|
||
│ Интеграции │
|
||
├─────────────────────────────────────────────────────┤
|
||
│ │
|
||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐│
|
||
│ │ OpenAI │ │ Ollama │ │ Telegram ││
|
||
│ │ │ │ │ │ ││
|
||
│ │ [Подробнее]│ │ [Подробнее]│ │ [Подробнее]││
|
||
│ └─────────────┘ └─────────────┘ └─────────────┘│
|
||
│ │
|
||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐│
|
||
│ │ Email │ │База данных │ │ИИ-ассистент ││
|
||
│ │ │ │ │ │ ││
|
||
│ │ [Подробнее]│ │ [Подробнее]│ │ [Подробнее]││
|
||
│ └─────────────┘ └─────────────┘ └─────────────┘│
|
||
│ │
|
||
└─────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
**Навигация**:
|
||
- `/settings/ai/openai` → Настройки OpenAI
|
||
- `/settings/ai/ollama` → Настройки Ollama
|
||
- `/settings/ai/telegram` → Настройки Telegram
|
||
- `/settings/ai/email` → Настройки Email
|
||
- `/settings/ai/database` → Настройки БД
|
||
- `/settings/ai/assistant` → Настройки AI ассистента
|
||
|
||
### 2. Настройки AI провайдера
|
||
|
||
**Путь**: `/settings/ai/:provider`
|
||
**Компонент**: `AIProviderSettings.vue`
|
||
|
||
**Форма настроек**:
|
||
|
||
```
|
||
┌──────────────────────────────────────────────────────────┐
|
||
│ OpenAI [×] │
|
||
├──────────────────────────────────────────────────────────┤
|
||
│ │
|
||
│ Введите OpenAI API Key и (опционально) Base URL. │
|
||
│ │
|
||
│ API Key: │
|
||
│ ┌────────────────────────────────────────────────────┐ │
|
||
│ │ sk-... │ │
|
||
│ └────────────────────────────────────────────────────┘ │
|
||
│ [Verify] ✔️ │
|
||
│ │
|
||
│ Base URL: │
|
||
│ ┌────────────────────────────────────────────────────┐ │
|
||
│ │ https://api.openai.com/v1 │ │
|
||
│ └────────────────────────────────────────────────────┘ │
|
||
│ │
|
||
│ Модель (LLM): │
|
||
│ ┌────────────────────────────────────────────────────┐ │
|
||
│ │ gpt-4 ▼ │ │
|
||
│ └────────────────────────────────────────────────────┘ │
|
||
│ │
|
||
│ Embeddings-модель: │
|
||
│ ┌────────────────────────────────────────────────────┐ │
|
||
│ │ text-embedding-ada-002 ▼ │ │
|
||
│ └────────────────────────────────────────────────────┘ │
|
||
│ │
|
||
│ [Сохранить] [Удалить ключ] [Закрыть] │
|
||
│ │
|
||
│ ✅ Сохранено! │
|
||
└──────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
**Логика работы**:
|
||
|
||
1. **Загрузка настроек**: При монтировании компонента загружаются сохраненные настройки через `GET /settings/ai-settings/:provider`.
|
||
|
||
2. **Verify**: Проверка валидности API ключа через `POST /settings/ai-settings/:provider/verify`.
|
||
|
||
3. **Загрузка моделей**: После успешной верификации загружаются доступные модели через `GET /settings/ai-settings/:provider/models` или `/ollama/models` (для Ollama).
|
||
|
||
4. **Сохранение**: Сохранение настроек через `PUT /settings/ai-settings/:provider`.
|
||
|
||
5. **Удаление**: Удаление настроек через `DELETE /settings/ai-settings/:provider`.
|
||
|
||
**Особенности Ollama**:
|
||
- Не требуется API Key
|
||
- Только Base URL
|
||
- Модели загружаются через `/ollama/models`
|
||
|
||
### 3. Настройки AI ассистента
|
||
|
||
**Путь**: `/settings/ai/assistant`
|
||
**Компонент**: `AiAssistantSettings.vue`
|
||
|
||
**Основная форма настроек**:
|
||
|
||
```
|
||
┌──────────────────────────────────────────────────────────┐
|
||
│ ИИ-ассистент: интеграция и настройки [×] │
|
||
├──────────────────────────────────────────────────────────┤
|
||
│ │
|
||
│ Системный промт │
|
||
│ ┌────────────────────────────────────────────────────┐ │
|
||
│ │ Вы — полезный ассистент. Отвечайте на русском. │ │
|
||
│ └────────────────────────────────────────────────────┘ │
|
||
│ │
|
||
│ 📋 Плейсхолдеры пользовательских таблиц │
|
||
│ ┌────────────────────────────────────────────────────┐ │
|
||
│ │ Плейсхолдер | Столбец | Таблица │ │
|
||
│ ├────────────────────────────────────────────────────┤ │
|
||
│ │ { email } | Email | Контакты [Ред.] │ │
|
||
│ │ { phone } | Телефон | Контакты [Ред.] │ │
|
||
│ └────────────────────────────────────────────────────┘ │
|
||
│ │
|
||
│ LLM-модель │
|
||
│ ┌────────────────────────────────────────────────────┐ │
|
||
│ │ qwen2.5:7b (ollama) ▼ │ │
|
||
│ └────────────────────────────────────────────────────┘ │
|
||
│ │
|
||
│ Embedding-модель │
|
||
│ ┌────────────────────────────────────────────────────┐ │
|
||
│ │ mxbai-embed-large:latest (ollama) ▼ │ │
|
||
│ └────────────────────────────────────────────────────┘ │
|
||
│ │
|
||
│ Выбранные RAG-таблицы │
|
||
│ ┌────────────────────────────────────────────────────┐ │
|
||
│ │ FAQ (ID: 1) ▼ │ │
|
||
│ └────────────────────────────────────────────────────┘ │
|
||
│ │
|
||
│ Набор правил │
|
||
│ ┌────────────────────────────────────────────────────┐ │
|
||
│ │ Гибридный режим ▼ │ │
|
||
│ └────────────────────────────────────────────────────┘ │
|
||
│ [Создать] [Редактировать] [Удалить] │
|
||
│ │
|
||
│ Описание: RAG + генерация при необходимости │
|
||
│ ┌────────────────────────────────────────────────────┐ │
|
||
│ │ { │ │
|
||
│ │ "checkUserTags": true, │ │
|
||
│ │ "searchRagFirst": true, │ │
|
||
│ │ "generateIfNoRag": true │ │
|
||
│ │ } │ │
|
||
│ └────────────────────────────────────────────────────┘ │
|
||
│ │
|
||
│ Telegram-бот │
|
||
│ ┌────────────────────────────────────────────────────┐ │
|
||
│ │ @mybot ▼ │ │
|
||
│ └────────────────────────────────────────────────────┘ │
|
||
│ │
|
||
│ Email для связи │
|
||
│ ┌────────────────────────────────────────────────────┐ │
|
||
│ │ support@example.com ▼ │ │
|
||
│ └────────────────────────────────────────────────────┘ │
|
||
│ │
|
||
│ 🔍 Настройки RAG поиска │
|
||
│ (см. ниже) │
|
||
│ │
|
||
│ [Сохранить] [Отмена] │
|
||
└──────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## Настройки RAG поиска
|
||
|
||
**Блок в форме AI ассистента**:
|
||
|
||
```
|
||
┌──────────────────────────────────────────────────────────┐
|
||
│ 🔍 Настройки RAG поиска │
|
||
├──────────────────────────────────────────────────────────┤
|
||
│ │
|
||
│ Метод поиска │
|
||
│ ┌────────────────────────────────────────────────────┐ │
|
||
│ │ Гибридный поиск ▼ │ │
|
||
│ └────────────────────────────────────────────────────┘ │
|
||
│ │
|
||
│ Максимальное количество результатов поиска │
|
||
│ ┌─────┐ │
|
||
│ │ 5 │ │
|
||
│ └─────┘ │
|
||
│ │
|
||
│ Порог релевантности (0.1) │
|
||
│ ├───────────●──────────────────────────────────────┤ │
|
||
│ 0.01 1.0 │
|
||
│ │
|
||
│ 🔑 Извлечение ключевых слов │
|
||
│ ☑ Включить извлечение ключевых слов │
|
||
│ │
|
||
│ Минимальная длина слова: 3 │
|
||
│ Максимальное количество ключевых слов: 10 │
|
||
│ ☑ Удалять стоп-слова │
|
||
│ │
|
||
│ ⚖️ Веса поиска (для гибридного) │
|
||
│ Семантический поиск: 70% │
|
||
│ ├───────────────●────────────────────────────────┤ │
|
||
│ │
|
||
│ Поиск по ключевым словам: 30% │
|
||
│ ├───────●────────────────────────────────────────┤ │
|
||
│ │
|
||
│ ⚙️ Дополнительные настройки │
|
||
│ ☑ Нечеткий поиск │
|
||
│ ☑ Стемминг слов │
|
||
│ ☐ Поиск синонимов │
|
||
│ │
|
||
└──────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
**Параметры RAG настроек**:
|
||
|
||
| Параметр | Тип | Значение по умолчанию | Описание |
|
||
|----------|-----|-----------------------|----------|
|
||
| `searchMethod` | `string` | `"hybrid"` | Метод поиска: `semantic`, `keyword`, `hybrid` |
|
||
| `maxResults` | `number` | `5` | Максимальное количество результатов (1-20) |
|
||
| `relevanceThreshold` | `number` | `0.1` | Порог релевантности (0.01-1.0) |
|
||
| `keywordExtraction.enabled` | `boolean` | `true` | Включить извлечение ключевых слов |
|
||
| `keywordExtraction.minWordLength` | `number` | `3` | Минимальная длина слова (2-10) |
|
||
| `keywordExtraction.maxKeywords` | `number` | `10` | Максимальное количество ключевых слов (5-20) |
|
||
| `keywordExtraction.removeStopWords` | `boolean` | `true` | Удалять стоп-слова |
|
||
| `searchWeights.semantic` | `number` | `70` | Вес семантического поиска (%) |
|
||
| `searchWeights.keyword` | `number` | `30` | Вес поиска по ключевым словам (%) |
|
||
| `advanced.enableFuzzySearch` | `boolean` | `true` | Нечеткий поиск |
|
||
| `advanced.enableStemming` | `boolean` | `true` | Стемминг слов |
|
||
| `advanced.enableSynonyms` | `boolean` | `false` | Поиск синонимов |
|
||
|
||
**Сохранение на Backend**:
|
||
|
||
```javascript
|
||
const settingsToSave = { ...settings.value };
|
||
settingsToSave.ragSettings = ragSettings.value;
|
||
|
||
await axios.put('/settings/ai-assistant', settingsToSave);
|
||
```
|
||
|
||
---
|
||
|
||
## Правила AI (Rules)
|
||
|
||
### Редактор правил
|
||
|
||
**Компонент**: `RuleEditor.vue`
|
||
|
||
**Модальное окно**:
|
||
|
||
```
|
||
┌──────────────────────────────────────────────────────────┐
|
||
│ Создать набор правил │
|
||
├──────────────────────────────────────────────────────────┤
|
||
│ │
|
||
│ Название │
|
||
│ ┌────────────────────────────────────────────────────┐ │
|
||
│ │ Строгий режим │ │
|
||
│ └────────────────────────────────────────────────────┘ │
|
||
│ │
|
||
│ Описание │
|
||
│ ┌────────────────────────────────────────────────────┐ │
|
||
│ │ Только ответы из базы знаний, без генерации │ │
|
||
│ └────────────────────────────────────────────────────┘ │
|
||
│ │
|
||
│ Правила (JSON) │
|
||
│ ┌────────────────────────────────────────────────────┐ │
|
||
│ │ { │ │
|
||
│ │ "checkUserTags": true, │ │
|
||
│ │ "searchRagFirst": true, │ │
|
||
│ │ "generateIfNoRag": false │ │
|
||
│ │ } │ │
|
||
│ └────────────────────────────────────────────────────┘ │
|
||
│ │
|
||
│ [Сохранить] [Отмена] │
|
||
└──────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
**Логика работы**:
|
||
|
||
1. **Создание**: `POST /settings/ai-assistant-rules` с `{ name, description, rules }`
|
||
2. **Редактирование**: `PUT /settings/ai-assistant-rules/:id` с `{ name, description, rules }`
|
||
3. **Валидация**: Проверка JSON перед сохранением
|
||
|
||
```javascript
|
||
async function save() {
|
||
let rules;
|
||
try {
|
||
rules = JSON.parse(rulesJson.value);
|
||
} catch (e) {
|
||
error.value = 'Ошибка в формате JSON!';
|
||
return;
|
||
}
|
||
|
||
if (props.rule && props.rule.id) {
|
||
await axios.put(`/settings/ai-assistant-rules/${props.rule.id}`, { name, description, rules });
|
||
} else {
|
||
await axios.post('/settings/ai-assistant-rules', { name, description, rules });
|
||
}
|
||
|
||
emit('close', true);
|
||
}
|
||
```
|
||
|
||
### Примеры правил
|
||
|
||
#### 1. Строгий режим (только RAG)
|
||
|
||
```json
|
||
{
|
||
"checkUserTags": true,
|
||
"searchRagFirst": true,
|
||
"generateIfNoRag": false,
|
||
"maxTokens": 300
|
||
}
|
||
```
|
||
|
||
**Применение**: Когда нужны только точные ответы из базы знаний.
|
||
|
||
#### 2. Гибридный режим (RAG + генерация)
|
||
|
||
```json
|
||
{
|
||
"checkUserTags": true,
|
||
"searchRagFirst": true,
|
||
"generateIfNoRag": true,
|
||
"temperature": 0.7,
|
||
"maxTokens": 500
|
||
}
|
||
```
|
||
|
||
**Применение**: Баланс между точностью и гибкостью.
|
||
|
||
#### 3. Креативный режим
|
||
|
||
```json
|
||
{
|
||
"checkUserTags": false,
|
||
"searchRagFirst": false,
|
||
"generateIfNoRag": true,
|
||
"temperature": 0.9,
|
||
"maxTokens": 1000,
|
||
"customInstructions": "Будьте креативны и дружелюбны"
|
||
}
|
||
```
|
||
|
||
**Применение**: Для общения с пользователями, когда нужна более свободная генерация.
|
||
|
||
---
|
||
|
||
## Мониторинг системы
|
||
|
||
**Компонент**: `SystemMonitoring.vue`
|
||
|
||
**Интерфейс мониторинга**:
|
||
|
||
```
|
||
┌──────────────────────────────────────────────────────────┐
|
||
│ 🔍 Мониторинг системы │
|
||
│ [🔄 Обновить статус] Последнее обновление: 12:34:56 │
|
||
├──────────────────────────────────────────────────────────┤
|
||
│ │
|
||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||
│ │ ● Backend │ │ ● Postgres │ │ ● Ollama │ │
|
||
│ │ │ │ │ │ │ │
|
||
│ │ Статус: │ │ Статус: │ │ Статус: │ │
|
||
│ │ Работает │ │ Работает │ │ Работает │ │
|
||
│ │ │ │ │ │ Модели: 3 │ │
|
||
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
||
│ │
|
||
│ ┌──────────────┐ │
|
||
│ │ ● Vector │ │
|
||
│ │ Search │ │
|
||
│ │ │ │
|
||
│ │ Статус: │ │
|
||
│ │ Работает │ │
|
||
│ └──────────────┘ │
|
||
│ │
|
||
│ 🧠 Тест RAG-функциональности │
|
||
│ ┌────────────────────────────────────────────────────┐ │
|
||
│ │ Выберите RAG-таблицу: │ │
|
||
│ │ FAQ (ID: 1) ▼ [🔄] │ │
|
||
│ └────────────────────────────────────────────────────┘ │
|
||
│ │
|
||
│ ┌────────────────────────────────────────────────────┐ │
|
||
│ │ Как работает ИИ-ассистент? │ │
|
||
│ └────────────────────────────────────────────────────┘ │
|
||
│ [Тестировать RAG] │
|
||
│ │
|
||
│ 🔍 Ищем ответ в базе знаний... │
|
||
│ ├──────────────────────────●───────────────────────┤ │
|
||
│ 75% │
|
||
│ │
|
||
│ ✅ Успешно! │
|
||
│ Таблица: FAQ │
|
||
│ Вопрос: "Как работает ИИ-ассистент?" │
|
||
│ Ответ: "ИИ-ассистент использует..." │
|
||
│ Score: -120 │
|
||
│ │
|
||
└──────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### Статусы сервисов
|
||
|
||
**Backend**: `GET /monitoring`
|
||
|
||
```json
|
||
{
|
||
"services": {
|
||
"backend": {
|
||
"status": "ok"
|
||
},
|
||
"postgres": {
|
||
"status": "ok"
|
||
},
|
||
"ollama": {
|
||
"status": "ok",
|
||
"models": 3
|
||
},
|
||
"vectorSearch": {
|
||
"status": "ok"
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
**Цвета статусов**:
|
||
- 🟢 `ok` / `healthy` — Зеленый
|
||
- 🟡 `warning` — Желтый
|
||
- 🔴 `error` — Красный
|
||
- ⚫ `unknown` — Серый
|
||
|
||
### Тест RAG
|
||
|
||
**Логика теста**:
|
||
|
||
1. **Выбор таблицы**: Загружаются все таблицы с `is_rag_source_id === 1`
|
||
2. **Ввод вопроса**: Пользователь вводит тестовый вопрос
|
||
3. **Запрос**: `POST /rag/answer` с `{ tableId, question, product: null }`
|
||
4. **Прогресс-бар**: Симуляция прогресса для UX
|
||
5. **Результат**: Отображение ответа и score
|
||
|
||
```javascript
|
||
const testRAG = async () => {
|
||
ragTesting.value = true;
|
||
ragResult.value = null;
|
||
ragProgress.value = 0;
|
||
ragStatus.value = '🔍 Ищем ответ в базе знаний...';
|
||
|
||
const progressInterval = setInterval(() => {
|
||
if (ragProgress.value < 90) {
|
||
ragProgress.value += Math.random() * 15;
|
||
}
|
||
}, 1000);
|
||
|
||
try {
|
||
ragStatus.value = '🤖 Генерируем ответ с помощью ИИ...';
|
||
|
||
const response = await axios.post('/rag/answer', {
|
||
tableId: selectedRagTable.value,
|
||
question: ragQuestion.value,
|
||
product: null
|
||
});
|
||
|
||
clearInterval(progressInterval);
|
||
ragProgress.value = 100;
|
||
ragStatus.value = '✅ Готово!';
|
||
|
||
ragResult.value = {
|
||
success: true,
|
||
answer: response.data.answer,
|
||
score: response.data.score
|
||
};
|
||
} catch (error) {
|
||
clearInterval(progressInterval);
|
||
ragProgress.value = 0;
|
||
|
||
ragResult.value = {
|
||
success: false,
|
||
error: error.response?.data?.error || error.message
|
||
};
|
||
}
|
||
|
||
ragTesting.value = false;
|
||
};
|
||
```
|
||
|
||
---
|
||
|
||
## Заключение
|
||
|
||
Система настройки AI ассистента в DLE — это **комплексная платформа** для управления:
|
||
|
||
✅ **AI провайдерами** (OpenAI, Anthropic, Google, Ollama)
|
||
✅ **Настройками ассистента** (промты, модели, RAG-таблицы)
|
||
✅ **Правилами поведения** (JSON конфигурация)
|
||
✅ **Интеграциями** (Email, Telegram)
|
||
✅ **RAG конфигурацией** (гибридный поиск, ключевые слова)
|
||
✅ **Мониторингом** (статусы сервисов, тестирование)
|
||
|
||
Все настройки **зашифрованы** (AES-256), имеют **детальные права доступа** (только админы), и предоставляют **гибкую конфигурацию** для различных сценариев использования.
|
||
|
||
---
|
||
|
||
**© 2024-2025 Тарабанов Александр Викторович. Все права защищены.**
|
||
|
||
**Версия документа**: 1.0.0
|
||
**Дата создания**: October 25, 2025
|
||
**Статус**: Временный (для внутреннего использования)
|
||
|