ваше сообщение коммита
This commit is contained in:
663
docs.ru/back-docs/MULTICHAIN_GOVERNANCE_TOKEN_TRANSFER.md
Normal file
663
docs.ru/back-docs/MULTICHAIN_GOVERNANCE_TOKEN_TRANSFER.md
Normal file
@@ -0,0 +1,663 @@
|
||||
[English](../../docs.en/back-docs/MULTICHAIN_GOVERNANCE_TOKEN_TRANSFER.md) | **Русский**
|
||||
|
||||
# Мультичейн-управление переводом токенов DLE
|
||||
|
||||
## Обзор системы
|
||||
|
||||
Система мультичейн-управления DLE позволяет холдерам токенов создавать предложения по переводу токенов со своего кошелька на другой адрес (или в казну) через процесс голосования во всех сетях, где развернут контракт DLE. Каждая сеть имеет независимый кворум, но предложения координируются и отображаются как единое целое.
|
||||
|
||||
## Архитектура
|
||||
|
||||
### Мультичейн-контракты DLE
|
||||
- Один DLE может быть развернут в нескольких блокчейн-сетях (например, Sepolia, Arbitrum Sepolia, Base Sepolia)
|
||||
- Каждый контракт DLE в каждой сети работает независимо
|
||||
- Предложения создаются, голосуются и выполняются в каждой сети отдельно
|
||||
- ID предложений уникальны для каждой сети (предложение с ID=1 в Sepolia и предложение с ID=1 в Arbitrum Sepolia - это разные предложения)
|
||||
|
||||
### Группировка предложений
|
||||
- Предложения с одинаковым описанием и инициатором группируются в одну карточку
|
||||
- Карточка отображает статус предложения во всех сетях DLE
|
||||
- Каждая сеть в карточке имеет свой собственный ID предложения, состояние и результаты голосования
|
||||
|
||||
## Процесс перевода токенов
|
||||
|
||||
### Этап 1: Создание предложения
|
||||
|
||||
#### Описание процесса
|
||||
1. Пользователь заполняет форму перевода токенов:
|
||||
- **Описание предложения** - текстовое описание цели перевода
|
||||
- **Адрес получателя** - адрес кошелька или казны, на который будут переведены токены
|
||||
- **Количество токенов** - количество DLE токенов для перевода
|
||||
- **Длительность голосования** - период времени, в течение которого можно голосовать
|
||||
- **Ваш подключенный кошелек** - автоматически заполняется адресом подключенного кошелька (токены будут отправлены с этого адреса)
|
||||
|
||||
2. Система определяет все сети, где развернут контракт DLE
|
||||
|
||||
3. **Последовательное создание предложений в каждой сети:**
|
||||
- Для каждой сети DLE:
|
||||
- Переключение MetaMask на соответствующую сеть
|
||||
- Задержка 1 секунда после переключения
|
||||
- Создание предложения в контракте DLE этой сети
|
||||
- Получение уникального ID предложения для этой сети
|
||||
- Задержка 3 секунды после подтверждения транзакции (5 секунд для Base Sepolia)
|
||||
- При ошибках RPC выполняется автоматический retry с экспоненциальной задержкой (до 3 попыток)
|
||||
|
||||
4. **Подписи в MetaMask:**
|
||||
- Пользователь должен подписать транзакцию создания предложения в каждой сети DLE
|
||||
- Количество подписей = количество сетей DLE
|
||||
- Каждая подпись создает отдельное предложение в соответствующей сети
|
||||
|
||||
#### Технические детали
|
||||
- **Функция контракта:** `createProposal(description, duration, operation, targetChains, timelockDelay)`
|
||||
- **Порядок параметров:** `description`, `duration`, `operation`, `targetChains` (массив), `timelockDelay`
|
||||
- **targetChains:** Массив ID сетей, где будет выполнена операция (обычно `[chainId]` для текущей сети)
|
||||
- **Операция:** `_transferTokens(sender, recipient, amount)` - где `sender` = адрес инициатора предложения
|
||||
- **Сигнатура:** `_transferTokens(address,address,uint256)` - **все три параметра обязательны!**
|
||||
- `sender` получается автоматически из `signer.getAddress()` при создании предложения
|
||||
- **ID предложения:** Генерируется автоматически контрактом в каждой сети (начинается с 0, инкрементируется)
|
||||
- **Группировка:** Предложения с одинаковым `description` и `initiator` группируются в одну карточку
|
||||
|
||||
#### Кодирование операции
|
||||
|
||||
Операция для выполнения должна быть закодирована в формате ABI (Application Binary Interface) перед передачей в `createProposal`.
|
||||
|
||||
**Для операции перевода токенов `_transferTokens(address,address,uint256)`:**
|
||||
1. **Сигнатура функции:** `_transferTokens(address,address,uint256)`
|
||||
2. **Селектор функции:** Первые 4 байта от `keccak256(signature)`
|
||||
3. **Параметры:**
|
||||
- `sender` - адрес отправителя (инициатора предложения)
|
||||
- `recipient` - адрес получателя токенов
|
||||
- `amount` - количество токенов (в wei, т.е. количество * 10^18)
|
||||
|
||||
**Пример кодирования (JavaScript/ethers.js):**
|
||||
```javascript
|
||||
// Способ 1: Использование Interface (рекомендуется)
|
||||
const functionSignature = '_transferTokens(address,address,uint256)';
|
||||
const iface = new ethers.Interface([`function ${functionSignature}`]);
|
||||
const encodedOperation = iface.encodeFunctionData('_transferTokens', [
|
||||
senderAddress, // адрес инициатора
|
||||
recipientAddress, // адрес получателя
|
||||
ethers.parseUnits(amount.toString(), 18) // количество в wei
|
||||
]);
|
||||
|
||||
// Способ 2: Ручное кодирование
|
||||
const functionSignature = '_transferTokens(address,address,uint256)';
|
||||
const selectorBytes = ethers.keccak256(ethers.toUtf8Bytes(functionSignature));
|
||||
const selector = '0x' + selectorBytes.slice(2, 10); // первые 4 байта
|
||||
|
||||
const abiCoder = ethers.AbiCoder.defaultAbiCoder();
|
||||
const encodedParams = abiCoder.encode(
|
||||
['address', 'address', 'uint256'],
|
||||
[senderAddress, recipientAddress, ethers.parseUnits(amount.toString(), 18)]
|
||||
);
|
||||
|
||||
const encodedOperation = ethers.concat([selector, encodedParams]);
|
||||
```
|
||||
|
||||
**Важные моменты:**
|
||||
- `sender` должен совпадать с адресом инициатора предложения (проверяется в контракте при выполнении)
|
||||
- `amount` **ОБЯЗАТЕЛЬНО** передается в wei (1 токен = 10^18 wei) - используйте `ethers.parseUnits(amount.toString(), 18)`
|
||||
- **КРИТИЧЕСКИ ВАЖНО:** `sender` должен определяться из `signer.getAddress()` при создании предложения в каждой сети отдельно, а не один раз до цикла
|
||||
- Операция кодируется для каждой сети отдельно с актуальным адресом signer для этой сети
|
||||
- Контракт декодирует операцию при выполнении и проверяет соответствие `sender` и `initiator`
|
||||
|
||||
**КРИТИЧЕСКИ ВАЖНО - Правильная реализация:**
|
||||
```javascript
|
||||
// ✅ ПРАВИЛЬНО: Кодирование внутри цикла с актуальным адресом signer для каждой сети
|
||||
async function createProposalsInAllChains(allChains, formData) {
|
||||
const results = [];
|
||||
|
||||
for (let index = 0; index < allChains.length; index++) {
|
||||
const chainId = allChains[index];
|
||||
|
||||
// 1. Переключаемся на нужную сеть
|
||||
await switchToVotingNetwork(chainId.toString());
|
||||
await new Promise(resolve => setTimeout(resolve, 1000)); // Задержка после переключения
|
||||
|
||||
// 2. КРИТИЧЕСКИ ВАЖНО: Получаем адрес signer для текущей сети
|
||||
const provider = new ethers.BrowserProvider(window.ethereum);
|
||||
const signer = await provider.getSigner();
|
||||
const senderAddress = await signer.getAddress(); // Адрес инициатора из signer!
|
||||
|
||||
// 3. Кодируем операцию с актуальным адресом signer для этой сети
|
||||
const transferCallData = encodeTransferTokensCall(
|
||||
senderAddress, // адрес инициатора из signer (обязательно!)
|
||||
formData.recipient, // адрес получателя
|
||||
formData.amount // количество (будет сконвертировано в wei)
|
||||
);
|
||||
|
||||
// 4. Создаем предложение
|
||||
const proposalData = {
|
||||
description: formData.description,
|
||||
duration: formData.duration,
|
||||
operation: transferCallData,
|
||||
targetChains: [chainId],
|
||||
timelockDelay: 0
|
||||
};
|
||||
|
||||
await createProposal(contractAddress, proposalData);
|
||||
}
|
||||
}
|
||||
|
||||
function encodeTransferTokensCall(sender, recipient, amount) {
|
||||
const functionSignature = '_transferTokens(address,address,uint256)';
|
||||
const iface = new ethers.Interface([`function ${functionSignature}`]);
|
||||
|
||||
// КРИТИЧЕСКИ ВАЖНО: конвертируем amount в wei
|
||||
const amountInWei = ethers.parseUnits(amount.toString(), 18);
|
||||
|
||||
const encodedCall = iface.encodeFunctionData('_transferTokens', [
|
||||
sender, // адрес инициатора (обязательно! должен быть из signer.getAddress())
|
||||
recipient, // адрес получателя
|
||||
amountInWei // количество в wei (обязательно!)
|
||||
]);
|
||||
|
||||
return encodedCall;
|
||||
}
|
||||
|
||||
// ❌ НЕПРАВИЛЬНО: Кодирование один раз до цикла
|
||||
// const transferCallData = encodeTransferTokensCall(formData.sender, ...); // НЕПРАВИЛЬНО!
|
||||
// for (const chainId of allChains) {
|
||||
// await createProposal(contractAddress, { operation: transferCallData, ... }); // sender может не совпасть!
|
||||
// }
|
||||
|
||||
// ❌ НЕПРАВИЛЬНО: Отсутствует sender или amount не в wei
|
||||
// const transferFunctionSelector = ethers.id("_transferTokens(address,uint256)"); // НЕПРАВИЛЬНО!
|
||||
// const amount = transferData.amount; // НЕПРАВИЛЬНО! Нужна конвертация в wei
|
||||
```
|
||||
|
||||
**Другие поддерживаемые операции:**
|
||||
- `_addModule(bytes32,address)` - добавление модуля
|
||||
- `_removeModule(bytes32)` - удаление модуля
|
||||
- `_addSupportedChain(uint256)` - добавление поддерживаемой сети
|
||||
- `_removeSupportedChain(uint256)` - удаление поддерживаемой сети
|
||||
- `_updateVotingDurations(uint256,uint256)` - обновление времени голосования
|
||||
- `_updateQuorumPercentage(uint256)` - обновление процента кворума
|
||||
- `_updateDLEInfo(...)` - обновление информации DLE
|
||||
- `_setLogoURI(string)` - обновление URI логотипа
|
||||
|
||||
#### Результат
|
||||
- Создано N предложений (по одному в каждой сети DLE)
|
||||
- Каждое предложение имеет уникальный ID в своей сети
|
||||
- Все предложения отображаются как одна карточка в интерфейсе
|
||||
- Карточка показывает статус предложения в каждой сети
|
||||
|
||||
---
|
||||
|
||||
### Этап 2: Голосование
|
||||
|
||||
#### Описание процесса
|
||||
1. Пользователь видит карточку предложения с информацией о всех сетях DLE
|
||||
|
||||
2. Пользователь выбирает голос "За" или "Против"
|
||||
|
||||
3. **Последовательное голосование во всех активных сетях:**
|
||||
- Система определяет все активные цепочки (state === 0 или 'active', не выполнены, не отменены)
|
||||
- Для каждой активной сети:
|
||||
- Переключение MetaMask на соответствующую сеть
|
||||
- Задержка 1 секунда после переключения
|
||||
- **Проверка баланса токенов в этой сети** (балансы могут отличаться в разных сетях)
|
||||
- Если баланс отсутствует, сеть пропускается с предупреждением
|
||||
- Голосование продолжается в других сетях
|
||||
- Голосование с использованием **уникального ID предложения для этой сети**
|
||||
- Задержка 3 секунды после подтверждения транзакции (5 секунд для Base Sepolia)
|
||||
|
||||
4. **Подписи в MetaMask:**
|
||||
- Пользователь должен подписать транзакцию голосования в каждой активной сети DLE
|
||||
- Количество подписей = количество активных сетей DLE
|
||||
- Каждая подпись регистрирует голос в соответствующей сети
|
||||
|
||||
#### Технические детали
|
||||
- **Функция контракта:** `vote(proposalId, support)` - где `proposalId` уникален для каждой сети
|
||||
- **Проверка ID:** Система использует `chain.id` (ID предложения из конкретной сети), а не общий ID группы
|
||||
- **Проверка баланса:** Баланс токенов проверяется **в каждой сети отдельно** перед голосованием
|
||||
- В мультичейн-системе балансы могут отличаться в разных сетях
|
||||
- Если в сети нет токенов, голосование в этой сети пропускается
|
||||
- Контракт также проверяет баланс через `getPastVotes()` и вернет ошибку, если токенов нет
|
||||
- **Вес голоса:** Зависит от баланса токенов голосующего в соответствующей сети
|
||||
- **Независимые кворумы:** Каждая сеть имеет свой собственный кворум
|
||||
|
||||
#### Результат
|
||||
- Голос зарегистрирован во всех активных сетях DLE
|
||||
- Каждая сеть обновляет свои счетчики голосов (forVotes, againstVotes)
|
||||
- Карточка предложения обновляется с новыми данными голосования
|
||||
|
||||
---
|
||||
|
||||
### Этап 3: Выполнение предложения
|
||||
|
||||
#### Условия выполнения
|
||||
**КРИТИЧЕСКИ ВАЖНО:** Предложение может быть выполнено только при условии, что кворум достигнут **во всех сетях DLE**, где предложение активно.
|
||||
|
||||
Условия для каждой сети:
|
||||
- Состояние предложения: `ReadyForExecution` (state === 5)
|
||||
- Кворум достигнут: `forVotes >= quorumRequired`
|
||||
- Большинство голосов "За": `forVotes > againstVotes`
|
||||
- Предложение не выполнено: `executed === false`
|
||||
- Предложение не отменено: `canceled === false`
|
||||
- Истек период голосования (если применимо)
|
||||
- Истек период timelock (если применимо)
|
||||
|
||||
#### Описание процесса
|
||||
1. Система проверяет, что предложение готово к выполнению во всех активных сетях DLE
|
||||
|
||||
2. **Последовательное выполнение во всех готовых сетях:**
|
||||
- Для каждой сети, где предложение готово к выполнению:
|
||||
- Переключение MetaMask на соответствующую сеть
|
||||
- Задержка 1 секунда после переключения
|
||||
- Выполнение предложения с использованием **уникального ID предложения для этой сети**
|
||||
- Задержка 3 секунды после подтверждения транзакции (5 секунд для Base Sepolia)
|
||||
|
||||
3. **Подписи в MetaMask:**
|
||||
- Пользователь должен подписать транзакцию выполнения в каждой готовой сети DLE
|
||||
- Количество подписей = количество готовых сетей DLE
|
||||
- Каждая подпись выполняет перевод токенов в соответствующей сети
|
||||
|
||||
#### Технические детали
|
||||
- **Функция контракта:** `executeProposal(proposalId)` - где `proposalId` уникален для каждой сети
|
||||
- **Операция перевода:** `_transferTokens(sender, recipient, amount)`
|
||||
- `sender` = адрес инициатора предложения (проверяется в контракте)
|
||||
- `recipient` = адрес получателя из предложения
|
||||
- `amount` = количество токенов из предложения
|
||||
- **Проверка безопасности:** Контракт проверяет, что `sender` совпадает с `initiator` предложения
|
||||
- **Перевод токенов:** Токены переводятся с кошелька инициатора, а не с баланса контракта
|
||||
|
||||
#### Результат
|
||||
- Перевод токенов выполнен во всех готовых сетях DLE
|
||||
- Каждая сеть независимо выполняет перевод с кошелька инициатора
|
||||
- Карточка предложения обновляется, показывая статус "Выполнено" во всех сетях
|
||||
|
||||
---
|
||||
|
||||
## Отмена предложения
|
||||
|
||||
### Условия отмены
|
||||
- Только инициатор предложения может отменить его
|
||||
- Предложение должно быть активным (не выполнено, не отменено)
|
||||
- Отмена возможна в любой момент до выполнения
|
||||
|
||||
### Процесс отмены
|
||||
1. **Последовательная отмена во всех активных сетях:**
|
||||
- Для каждой активной сети:
|
||||
- Переключение MetaMask на соответствующую сеть
|
||||
- Задержка 1 секунда после переключения
|
||||
- Отмена предложения с использованием **уникального ID предложения для этой сети**
|
||||
- Задержка 3 секунды после подтверждения транзакции
|
||||
|
||||
2. **Подписи в MetaMask:**
|
||||
- Пользователь должен подписать транзакцию отмены в каждой активной сети DLE
|
||||
- Количество подписей = количество активных сетей DLE
|
||||
|
||||
### Технические детали
|
||||
- **Функция контракта:** `cancelProposal(proposalId, reason)`
|
||||
- **Проверка прав:** Контракт проверяет, что вызывающий является инициатором предложения
|
||||
|
||||
---
|
||||
|
||||
## Важные особенности системы
|
||||
|
||||
### 1. Уникальность ID предложений
|
||||
- **Каждая сеть имеет свой собственный счетчик предложений**
|
||||
- Предложение с ID=1 в Sepolia и предложение с ID=1 в Arbitrum Sepolia - это **разные предложения**
|
||||
- При группировке система сохраняет ID из каждой сети отдельно
|
||||
- При голосовании/выполнении/отмене используется правильный ID для каждой сети
|
||||
|
||||
### 2. Группировка предложений
|
||||
- Предложения группируются по ключу: `${description}_${initiator}`
|
||||
- Одна карточка = одно логическое предложение во всех сетях
|
||||
- Карточка отображает:
|
||||
- Общее описание
|
||||
- Инициатора
|
||||
- Список сетей с их статусами
|
||||
- Результаты голосования по каждой сети
|
||||
- Общий статус (активно/выполнено/отменено)
|
||||
|
||||
### 3. Независимые кворумы
|
||||
- **Каждая сеть имеет свой собственный кворум**
|
||||
- Кворум рассчитывается на основе общего предложения токенов в соответствующей сети
|
||||
- Голосование в одной сети не влияет на кворум в другой сети
|
||||
- Для выполнения предложения кворум должен быть достигнут **во всех сетях**
|
||||
|
||||
### 4. Последовательное выполнение операций
|
||||
- Все операции (создание, голосование, выполнение, отмена) выполняются **последовательно**, а не параллельно
|
||||
- Это необходимо, так как MetaMask может работать только с одной сетью одновременно
|
||||
- Между операциями есть задержки для стабилизации MetaMask
|
||||
- **КРИТИЧЕСКИ ВАЖНО:** Использование `Promise.all` для параллельного выполнения недопустимо и приведет к ошибкам
|
||||
|
||||
### 5. Обработка ошибок
|
||||
- **Retry для временных ошибок RPC:**
|
||||
- Автоматический retry до 3 попыток
|
||||
- Экспоненциальная задержка (2s, 4s, 8s)
|
||||
- Только для retryable ошибок (Internal JSON-RPC error, rate limiting)
|
||||
- **Ошибки в отдельных сетях:**
|
||||
- Если операция не удалась в одной сети, процесс продолжается для других сетей
|
||||
- Пользователь получает сводку успешных и неудачных операций
|
||||
- **Обработка отсутствия баланса:**
|
||||
- Перед голосованием в каждой сети проверяется баланс токенов
|
||||
- Если в сети нет токенов, голосование в этой сети пропускается с предупреждением
|
||||
- Голосование продолжается в других сетях, где баланс есть
|
||||
- Контракт также проверяет баланс и вернет ошибку `ErrNoPower`, если токенов нет
|
||||
|
||||
### 6. Безопасность
|
||||
- **Проверка инициатора:** При выполнении контракт проверяет, что `sender` совпадает с `initiator`
|
||||
- **Проверка баланса:** Перед голосованием проверяется наличие токенов **в каждой сети отдельно**
|
||||
- Балансы могут отличаться в разных сетях
|
||||
- Если в сети нет токенов, голосование в этой сети пропускается
|
||||
- Контракт также проверяет баланс через `getPastVotes()` и вернет ошибку `ErrNoPower`, если токенов нет
|
||||
- **Проверка состояния:** Перед каждой операцией проверяется актуальное состояние предложения
|
||||
- **Валидация данных:** Все данные предложения валидируются перед отправкой в контракт
|
||||
|
||||
### 7. Перевод токенов
|
||||
- **Источник токенов:** Токены переводятся с кошелька инициатора предложения, а не с баланса контракта
|
||||
- **Получатель:** Может быть любой адрес (кошелек или казна)
|
||||
- **Количество:** Указывается инициатором при создании предложения
|
||||
- **Проверка баланса:** Контракт проверяет достаточность баланса инициатора перед выполнением
|
||||
|
||||
---
|
||||
|
||||
## Пользовательский интерфейс
|
||||
|
||||
### Карточка предложения
|
||||
- **Заголовок:** Описание предложения
|
||||
- **Инициатор:** Адрес создателя предложения
|
||||
- **Список сетей:**
|
||||
- Название сети
|
||||
- Статус (Активно/Выполнено/Отменено/Истекло)
|
||||
- ID предложения в этой сети
|
||||
- Результаты голосования (За/Против)
|
||||
- Кворум (достигнут/не достигнут)
|
||||
- **Действия:**
|
||||
- Голосовать "За" / "Против" (если активно)
|
||||
- Выполнить (если готово к выполнению)
|
||||
- Отменить (если инициатор)
|
||||
|
||||
### Индикаторы статуса
|
||||
- **Активно:** Предложение открыто для голосования
|
||||
- **Готово к выполнению:** Кворум достигнут во всех сетях
|
||||
- **Выполнено:** Перевод токенов выполнен во всех сетях
|
||||
- **Отменено:** Предложение отменено инициатором
|
||||
- **Истекло:** Истек период голосования
|
||||
|
||||
---
|
||||
|
||||
## Технические детали реализации
|
||||
|
||||
### Кодирование операций
|
||||
|
||||
Подробное описание процесса кодирования операций для создания предложений см. в разделе [Кодирование операции](#кодирование-операции) (Этап 1: Создание предложения).
|
||||
|
||||
### Структура данных предложения
|
||||
```javascript
|
||||
{
|
||||
id: number, // ID группы (из первой сети)
|
||||
description: string, // Описание предложения
|
||||
initiator: address, // Адрес инициатора
|
||||
deadline: number, // Дедлайн голосования
|
||||
chains: [ // Массив данных по каждой сети
|
||||
{
|
||||
id: number, // УНИКАЛЬНЫЙ ID для этой сети
|
||||
chainId: number, // ID сети (11155111, 421614, 84532)
|
||||
networkName: string, // Название сети
|
||||
contractAddress: address, // Адрес контракта DLE в этой сети
|
||||
state: number, // Состояние (0=Active, 3=Executed, 4=Canceled, 5=ReadyForExecution)
|
||||
forVotes: bigint, // Голоса "За"
|
||||
againstVotes: bigint, // Голоса "Против"
|
||||
quorumRequired: bigint, // Требуемый кворум
|
||||
executed: boolean, // Выполнено
|
||||
canceled: boolean, // Отменено
|
||||
transactionHash: string // Хеш транзакции создания
|
||||
}
|
||||
],
|
||||
createdAt: number, // Время создания
|
||||
uniqueId: string // Уникальный ключ группировки
|
||||
}
|
||||
```
|
||||
|
||||
### Функции контракта DLE
|
||||
|
||||
#### createProposal
|
||||
```solidity
|
||||
function createProposal(
|
||||
string memory _description,
|
||||
uint256 _duration,
|
||||
bytes memory _operation,
|
||||
uint256[] memory _targetChains,
|
||||
uint256 _timelockDelay
|
||||
) public returns (uint256 proposalId)
|
||||
```
|
||||
|
||||
#### vote
|
||||
```solidity
|
||||
function vote(uint256 _proposalId, bool _support) public
|
||||
```
|
||||
|
||||
#### executeProposal
|
||||
```solidity
|
||||
function executeProposal(uint256 _proposalId) public
|
||||
```
|
||||
|
||||
#### cancelProposal
|
||||
```solidity
|
||||
function cancelProposal(uint256 _proposalId, string memory _reason) public
|
||||
```
|
||||
|
||||
#### _transferTokens (internal)
|
||||
```solidity
|
||||
function _transferTokens(
|
||||
address _sender,
|
||||
address _recipient,
|
||||
uint256 _amount
|
||||
) internal
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Примеры использования
|
||||
|
||||
### Пример 0: Кодирование операции перевода токенов
|
||||
|
||||
Перед созданием предложения необходимо закодировать операцию. **КРИТИЧЕСКИ ВАЖНО:** Используйте правильную сигнатуру и конвертируйте amount в wei.
|
||||
|
||||
```javascript
|
||||
import { ethers } from 'ethers';
|
||||
|
||||
// Получаем адрес инициатора из signer
|
||||
const signer = await provider.getSigner();
|
||||
const sender = await signer.getAddress(); // Адрес инициатора (обязательно!)
|
||||
|
||||
// Параметры перевода
|
||||
const recipient = '0x1234567890123456789012345678901234567890'; // Получатель
|
||||
const amount = 100; // 100 токенов (в обычных единицах, не в wei)
|
||||
|
||||
// Кодирование операции
|
||||
const functionSignature = '_transferTokens(address,address,uint256)';
|
||||
const iface = new ethers.Interface([`function ${functionSignature}`]);
|
||||
|
||||
// КРИТИЧЕСКИ ВАЖНО: конвертируем amount в wei
|
||||
const amountInWei = ethers.parseUnits(amount.toString(), 18); // 100 * 10^18 wei
|
||||
|
||||
const encodedOperation = iface.encodeFunctionData('_transferTokens', [
|
||||
sender, // адрес инициатора (обязательно!)
|
||||
recipient, // адрес получателя
|
||||
amountInWei // количество в wei (обязательно!)
|
||||
]);
|
||||
|
||||
// encodedOperation теперь можно использовать в createProposal
|
||||
// Результат: 0x... (селектор функции + закодированные параметры)
|
||||
|
||||
// Создание предложения с правильным порядком параметров
|
||||
const tx = await dle.createProposal(
|
||||
"Перевод 100 токенов в казну", // description
|
||||
86400, // duration (1 день в секундах)
|
||||
encodedOperation, // operation
|
||||
[chainId], // targetChains (массив!)
|
||||
0 // timelockDelay
|
||||
);
|
||||
```
|
||||
|
||||
**Результат:** Закодированная операция в формате bytes, готовая для передачи в `createProposal`.
|
||||
|
||||
**Частые ошибки:**
|
||||
- ❌ Использование `_transferTokens(address,uint256)` - неправильная сигнатура
|
||||
- ❌ Отсутствие параметра `sender` - контракт не сможет проверить инициатора
|
||||
- ❌ Передача `amount` без конвертации в wei - неправильное количество токенов
|
||||
- ❌ Неправильный порядок параметров в `createProposal` - ошибка вызова контракта
|
||||
|
||||
### Пример 1: Создание предложения в 3 сетях
|
||||
1. Пользователь создает предложение "Перевод 100 токенов в казну"
|
||||
2. Система определяет 3 сети: Sepolia, Arbitrum Sepolia, Base Sepolia
|
||||
3. Создаются 3 предложения:
|
||||
- Sepolia: ID=5
|
||||
- Arbitrum Sepolia: ID=3
|
||||
- Base Sepolia: ID=7
|
||||
4. Все 3 предложения отображаются как одна карточка
|
||||
|
||||
### Пример 2: Голосование
|
||||
1. Пользователь голосует "За" за предложение
|
||||
2. Система голосует в 3 сетях:
|
||||
- Sepolia: vote(5, true)
|
||||
- Arbitrum Sepolia: vote(3, true)
|
||||
- Base Sepolia: vote(7, true)
|
||||
3. Каждое голосование требует отдельной подписи в MetaMask
|
||||
|
||||
### Пример 3: Выполнение
|
||||
1. Кворум достигнут во всех 3 сетях
|
||||
2. Система выполняет предложение в 3 сетях:
|
||||
- Sepolia: executeProposal(5)
|
||||
- Arbitrum Sepolia: executeProposal(3)
|
||||
- Base Sepolia: executeProposal(7)
|
||||
3. В каждой сети токены переводятся с кошелька инициатора на адрес получателя
|
||||
|
||||
---
|
||||
|
||||
## Ограничения и особенности
|
||||
|
||||
### Ограничения
|
||||
- MetaMask может работать только с одной сетью одновременно
|
||||
- Операции выполняются последовательно, что может занять время при большом количестве сетей
|
||||
- Ошибки RPC могут потребовать ручного retry
|
||||
|
||||
### Особенности
|
||||
- Если предложение не создано в одной из сетей (из-за ошибки), оно все равно может быть создано в других сетях
|
||||
- Голосование возможно только в тех сетях, где предложение активно
|
||||
- Выполнение возможно только если кворум достигнут во всех активных сетях
|
||||
|
||||
---
|
||||
|
||||
## Безопасность
|
||||
|
||||
### Защита от атак
|
||||
- Проверка инициатора при выполнении
|
||||
- Проверка баланса перед переводом
|
||||
- Независимые кворумы в каждой сети
|
||||
- Валидация всех входных данных
|
||||
|
||||
### Рекомендации
|
||||
- Всегда проверяйте адрес получателя перед созданием предложения
|
||||
- Убедитесь, что у вас достаточно токенов для перевода
|
||||
- Проверяйте статус предложения перед голосованием/выполнением
|
||||
- Следите за транзакциями в каждой сети
|
||||
|
||||
---
|
||||
|
||||
## Известные проблемы и исправления
|
||||
|
||||
### Исправленные критические ошибки
|
||||
|
||||
#### 1. Отсутствие конвертации amount в wei
|
||||
**Проблема:** Параметр `amount` передавался без конвертации в wei, что приводило к неправильному количеству токенов при выполнении.
|
||||
|
||||
**Исправление:** Добавлена обязательная конвертация через `ethers.parseUnits(amount.toString(), 18)` перед кодированием операции.
|
||||
|
||||
**Файл:** `frontend/src/views/smartcontracts/TransferTokensFormView.vue`
|
||||
|
||||
**Статус:** ✅ Исправлено
|
||||
|
||||
#### 2. Неправильная сигнатура функции _transferTokens
|
||||
**Проблема:** Использовалась неправильная сигнатура `_transferTokens(address,uint256)` вместо `_transferTokens(address,address,uint256)`, что приводило к ошибкам декодирования в контракте.
|
||||
|
||||
**Исправление:** Исправлена сигнатура функции и добавлен обязательный параметр `sender` (адрес инициатора).
|
||||
|
||||
**Файл:** `frontend/src/utils/dle-contract.js` (функция `createTransferTokensProposal`)
|
||||
|
||||
**Статус:** ✅ Исправлено
|
||||
|
||||
#### 3. Неправильный порядок параметров в createProposal
|
||||
**Проблема:** В функцию `createProposal` передавался `governanceChainId` вместо `targetChains` в 4-м параметре, что нарушало сигнатуру контракта.
|
||||
|
||||
**Исправление:** Исправлен порядок параметров согласно сигнатуре контракта: `description`, `duration`, `operation`, `targetChains`, `timelockDelay`.
|
||||
|
||||
**Файл:** `frontend/src/utils/dle-contract.js` (функция `createTransferTokensProposal`)
|
||||
|
||||
**Статус:** ✅ Исправлено
|
||||
|
||||
#### 4. Неправильное кодирование операции при создании предложений (КРИТИЧЕСКАЯ)
|
||||
**Проблема:** Операция перевода токенов кодировалась один раз до цикла по сетям, используя адрес из `formData.value.sender`. По документации, `sender` должен определяться из `signer.getAddress()` при создании предложения в каждой сети, что гарантирует совпадение с инициатором предложения.
|
||||
|
||||
**Исправление:**
|
||||
- Кодирование операции перемещено внутрь цикла по сетям
|
||||
- Добавлено получение адреса signer для каждой сети через `await signer.getAddress()`
|
||||
- Добавлена проверка соответствия адреса signer адресу из формы
|
||||
- Операция теперь кодируется с актуальным адресом signer для каждой сети отдельно
|
||||
|
||||
**Файл:** `frontend/src/views/smartcontracts/TransferTokensFormView.vue` (функция `submitForm`)
|
||||
|
||||
**Статус:** ✅ Исправлено (2025-01-XX)
|
||||
|
||||
#### 5. Параллельное выполнение в executeMultichainProposal (КРИТИЧЕСКАЯ)
|
||||
**Проблема:** Функция `executeMultichainProposal` использовала `Promise.all` для параллельного выполнения операций во всех сетях одновременно. Это не работает с MetaMask, который может работать только с одной сетью одновременно.
|
||||
|
||||
**Исправление:**
|
||||
- Заменен `Promise.all` на последовательный цикл `for`
|
||||
- Добавлено переключение сетей через `switchToVotingNetwork` для каждой сети
|
||||
- Добавлены задержки после переключения сетей (1 секунда) и после подтверждения транзакций (3 секунды, 5 секунд для Base Sepolia)
|
||||
- Добавлена фильтрация только готовых к выполнению цепочек
|
||||
|
||||
**Файл:** `frontend/src/composables/useProposals.js` (функция `executeMultichainProposal`)
|
||||
|
||||
**Статус:** ✅ Исправлено (2025-01-XX)
|
||||
|
||||
#### 6. Отсутствие переключения сетей в voteOnMultichainProposal
|
||||
**Проблема:** Функция `voteOnMultichainProposal` не использовала переключение сетей и проверку баланса токенов, что требовалось по документации для корректной работы в мультичейн-среде.
|
||||
|
||||
**Исправление:**
|
||||
- Добавлено переключение сетей через `switchToVotingNetwork` для каждой сети
|
||||
- Добавлена проверка баланса токенов перед голосованием в каждой сети через `checkTokenBalance`
|
||||
- Добавлены задержки после переключения сетей (1 секунда) и после подтверждения транзакций (3 секунды, 5 секунд для Base Sepolia)
|
||||
- Добавлена фильтрация только активных цепочек
|
||||
- Добавлена обработка ошибок с пропуском сетей при отсутствии баланса
|
||||
|
||||
**Файл:** `frontend/src/composables/useProposals.js` (функция `voteOnMultichainProposal`)
|
||||
|
||||
**Статус:** ✅ Исправлено (2025-01-XX)
|
||||
|
||||
### Текущая корректная реализация
|
||||
|
||||
Все функции кодирования операций и мультичейн-операции теперь используют:
|
||||
- ✅ Правильную сигнатуру: `_transferTokens(address,address,uint256)`
|
||||
- ✅ Все три параметра: `sender`, `recipient`, `amount`
|
||||
- ✅ Конвертацию amount в wei: `ethers.parseUnits(amount.toString(), 18)`
|
||||
- ✅ Правильный порядок параметров в `createProposal`
|
||||
- ✅ Определение `sender` из `signer.getAddress()` при создании предложения в каждой сети
|
||||
- ✅ Последовательное выполнение операций во всех мультичейн-функциях (не параллельное)
|
||||
- ✅ Переключение сетей перед каждой операцией в мультичейн-функциях
|
||||
- ✅ Проверку баланса токенов перед голосованием в каждой сети
|
||||
|
||||
### Проверка корректности
|
||||
|
||||
Перед развертыванием убедитесь, что:
|
||||
1. Функция `_transferTokens` кодируется с **тремя** параметрами (sender, recipient, amount)
|
||||
2. `amount` всегда конвертируется в wei перед кодированием
|
||||
3. `sender` получается из `signer.getAddress()` при создании предложения в каждой сети и совпадает с инициатором предложения
|
||||
4. Порядок параметров в `createProposal` соответствует сигнатуре контракта
|
||||
5. Все мультичейн-операции (создание, голосование, выполнение) используют последовательное выполнение с переключением сетей
|
||||
6. При голосовании проверяется баланс токенов в каждой сети отдельно
|
||||
|
||||
---
|
||||
|
||||
## Заключение
|
||||
|
||||
Система мультичейн-управления DLE обеспечивает децентрализованное управление переводом токенов через независимые кворумы в каждой сети, при этом предоставляя единый интерфейс для управления предложениями во всех сетях одновременно.
|
||||
|
||||
**Важно:** Все критические ошибки в кодировании операций исправлены. Код соответствует документации и контракту.
|
||||
|
||||
219
docs.ru/back-docs/TASK_REQUIREMENTS.md
Normal file
219
docs.ru/back-docs/TASK_REQUIREMENTS.md
Normal file
@@ -0,0 +1,219 @@
|
||||
[English](../../docs.en/back-docs/TASK_REQUIREMENTS.md) | **Русский**
|
||||
|
||||
# Задание: Реализация мульти-чейн governance системы для DLE
|
||||
|
||||
## Статус выполнения
|
||||
- ✅ Форма создания предложения работает
|
||||
- ✅ Предложение создается во всех цепочках DLE
|
||||
- ✅ Голосование происходит отдельно в каждой цепочке
|
||||
- ✅ Кворум считается отдельно для каждой цепочки
|
||||
- ✅ Личный перевод токенов от инициатора предложения
|
||||
- ✅ Группировка предложений по description + initiator
|
||||
- ✅ Серверная координация с криптографическими доказательствами
|
||||
- ✅ Убрана хардкод цепочек - используются deployedNetworks из API
|
||||
|
||||
## Контекст
|
||||
DLE (Digital Legal Entity) - децентрализованная юридическая сущность с контрактами в нескольких блокчейн-сетях. Необходимо реализовать систему управления токенами через мульти-чейн governance, где холдеры токенов могут переводить токены через голосование с кворумом.
|
||||
|
||||
## Архитектура системы
|
||||
|
||||
### Мульти-чейн компоненты
|
||||
- **Frontend**: Vue.js приложение с Web3 интеграцией
|
||||
- **Backend**: Node.js сервер для координации и API
|
||||
- **Smart Contracts**: DLE контракты в каждой поддерживаемой сети
|
||||
- **Database**: PostgreSQL для хранения метаданных
|
||||
- **WebSocket**: Real-time синхронизация между сетями
|
||||
|
||||
### Поддерживаемые сети
|
||||
- Ethereum Sepolia (chainId: 11155111)
|
||||
- Arbitrum Sepolia (chainId: 421614)
|
||||
- Base Sepolia (chainId: 84532)
|
||||
|
||||
## Требования к функционалу
|
||||
|
||||
### 1. Форма создания предложения о переводе токенов
|
||||
**URL:** `/management/transfer-tokens?address=<DLE_ADDRESS>`
|
||||
|
||||
**Поля формы:**
|
||||
- Адрес получателя (обязательное, address)
|
||||
- Сумма перевода (обязательное, number в токенах)
|
||||
- Описание предложения (опциональное, string)
|
||||
- Время голосования (обязательное, number в днях)
|
||||
|
||||
### 2. Логика создания предложений
|
||||
1. **Определение сетей:** Получение списка `deployedNetworks` через API `/dle-v2`
|
||||
2. **Параллельное создание:** Предложения создаются одновременно во ВСЕХ сетях DLE
|
||||
3. **Кодирование операции:** `_transferTokens(address,uint256)` для перевода токенов от инициатора
|
||||
|
||||
### 3. Логика голосования
|
||||
1. **Независимое голосование:** Каждая сеть голосует отдельно
|
||||
2. **Локальный кворум:** Кворум считается по формуле `(forVotes / totalSupply) >= quorumPercentage`
|
||||
3. **Голосование токенами:** Вес голоса = баланс токенов избирателя
|
||||
|
||||
### 4. Логика исполнения
|
||||
1. **Локальное исполнение:** Каждый контракт проверяет свой локальный кворум
|
||||
2. **Серверная координация:** Backend собирает результаты кворумов из всех сетей
|
||||
3. **Криптографические доказательства:** Сервер подписывает глобальный статус кворума
|
||||
4. **Глобальное исполнение:** Контракт проверяет подпись и выполняет операцию
|
||||
|
||||
## Техническая спецификация
|
||||
|
||||
### Smart Contract (DLE.sol)
|
||||
|
||||
#### Структура Proposal
|
||||
```solidity
|
||||
struct Proposal {
|
||||
uint256 id;
|
||||
string description;
|
||||
uint256 forVotes;
|
||||
uint256 againstVotes;
|
||||
bool executed;
|
||||
bool canceled;
|
||||
uint256 deadline;
|
||||
address initiator; // Создатель предложения
|
||||
bytes operation; // Закодированная операция
|
||||
uint256[] targetChains; // Целевые сети для исполнения
|
||||
uint256 snapshotTimepoint; // Точка снимка для голосования
|
||||
mapping(address => bool) hasVoted;
|
||||
}
|
||||
```
|
||||
|
||||
#### Функция _transferTokens
|
||||
```solidity
|
||||
function _transferTokens(address _sender, address _recipient, uint256 _amount) internal {
|
||||
require(balanceOf(_sender) >= _amount, "Insufficient balance");
|
||||
_transfer(_sender, _recipient, _amount);
|
||||
emit TokensTransferredByGovernance(_recipient, _amount);
|
||||
}
|
||||
```
|
||||
|
||||
#### События
|
||||
```solidity
|
||||
event ProposalCreated(uint256 proposalId, address initiator, string description);
|
||||
event QuorumReached(uint256 proposalId, uint256 chainId);
|
||||
event ProposalExecuted(uint256 proposalId, bytes operation);
|
||||
```
|
||||
|
||||
### Backend (Node.js)
|
||||
|
||||
#### Сервис координации кворумов
|
||||
```javascript
|
||||
class QuorumCoordinator {
|
||||
// Сбор результатов голосования из всех сетей
|
||||
async collectQuorumResults(proposalId) {
|
||||
// Слушать события QuorumReached из всех сетей
|
||||
// Сохранять в базу данных
|
||||
}
|
||||
|
||||
// Генерация криптографических доказательств
|
||||
async generateGlobalQuorumProof(proposalId) {
|
||||
// Подписать глобальный статус кворума
|
||||
// Вернуть подпись для контрактов
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### API Endpoints
|
||||
- `GET /dle-v2` - получение информации о DLE и сетях
|
||||
- `POST /api/dle-proposals/get-proposals` - получение списка предложений
|
||||
- `POST /api/dle-proposals/create-proposal` - создание предложения
|
||||
- `POST /api/dle-proposals/vote-proposal` - голосование
|
||||
- `POST /api/dle-proposals/execute-proposal` - исполнение
|
||||
|
||||
### Frontend (Vue.js)
|
||||
|
||||
#### Компонент TransferTokensFormView
|
||||
- Валидация формы
|
||||
- Кодирование операции перевода
|
||||
- Параллельное создание предложений во всех сетях
|
||||
- Обработка ошибок и отображение результатов
|
||||
|
||||
#### Компонент DleProposalsView
|
||||
- Группировка предложений по `description + initiator`
|
||||
- Отображение статуса по каждой сети
|
||||
- Кнопки голосования для каждой активной сети
|
||||
- Кнопка исполнения при глобальном кворуме
|
||||
|
||||
## Алгоритм работы
|
||||
|
||||
### Сценарий использования
|
||||
|
||||
1. **Пользователь открывает форму** `/management/transfer-tokens?address=0xdD27...9386`
|
||||
2. **Вводит данные:**
|
||||
- Получатель: `0x123...abc`
|
||||
- Сумма: `1000` токенов
|
||||
- Описание: `"Перевод средств подрядчику"`
|
||||
- Время: `7` дней
|
||||
3. **Нажимает "Создать"**
|
||||
4. **Система:**
|
||||
- Определяет сети: Sepolia, Arbitrum Sepolia, Base Sepolia
|
||||
- Создает предложения в каждой сети параллельно
|
||||
- Кодирует `_transferTokens(инициатор, получатель, сумма)`
|
||||
|
||||
5. **На странице предложений** появляется одна карточка с статусом по сетям
|
||||
6. **Пользователи голосуют** в каждой сети отдельно
|
||||
7. **При локальном кворуме** контракт эмитирует `QuorumReached`
|
||||
8. **Backend собирает** результаты из всех сетей
|
||||
9. **При глобальном кворуме** сервер подписывает доказательство
|
||||
10. **Пользователь вызывает** `executeWithGlobalQuorum()` с подписью
|
||||
11. **Контракт проверяет** подпись и выполняет перевод
|
||||
|
||||
## Безопасность
|
||||
|
||||
### Уровни защиты
|
||||
1. **On-chain проверки:** Баланс токенов, сроки голосования, кворум
|
||||
2. **Криптографические доказательства:** Подпись сервера для глобального кворума
|
||||
3. **Многоуровневая валидация:** Локальный + глобальный кворум
|
||||
4. **Отказоустойчивость:** Graceful degradation при недоступности сетей
|
||||
|
||||
### Риски и mitigation
|
||||
- **Сервер скомпрометирован:** Проверка подписи предотвращает подделку
|
||||
- **Сеть недоступна:** Локальное голосование работает независимо
|
||||
- **Replay attacks:** Проверка ID предложения и chainId
|
||||
- **Front-running:** Использование commit-reveal схемы при необходимости
|
||||
|
||||
## Тестирование
|
||||
|
||||
### Критерии приемки
|
||||
- [x] Форма создания предложения работает
|
||||
- [x] Предложение создается во всех цепочках DLE
|
||||
- [x] Голосование происходит отдельно в каждой цепочке
|
||||
- [x] Кворум считается отдельно для каждой цепочки
|
||||
- [x] Перевод токенов происходит от инициатора предложения
|
||||
- [x] Серверная координация с криптографическими доказательствами
|
||||
- [x] Группировка предложений в интерфейсе
|
||||
- [x] Обработка ошибок и edge cases
|
||||
|
||||
### Test cases
|
||||
1. Создание предложения в мульти-чейн среде
|
||||
2. Голосование в одной сети при недоступности других
|
||||
3. Исполнение при глобальном кворуме
|
||||
4. Исполнение при частичном кворуме (должен fail)
|
||||
5. Перевод токенов от инициатора с достаточным балансом
|
||||
6. Попытка перевода с недостаточным балансом (должен fail)
|
||||
|
||||
## Развертывание
|
||||
|
||||
### Требования к инфраструктуре
|
||||
- **Backend сервер** с доступом к RPC всех сетей
|
||||
- **Database** для хранения метаданных предложений
|
||||
- **SSL сертификаты** для безопасной коммуникации
|
||||
- **Monitoring** для отслеживания состояния сетей
|
||||
|
||||
### Переменные окружения
|
||||
```bash
|
||||
# RPC URLs
|
||||
SEPOLIA_RPC_URL=https://1rpc.io/sepolia
|
||||
ARBITRUM_SEPOLIA_RPC_URL=https://sepolia-rollup.arbitrum.io/rpc
|
||||
BASE_SEPOLIA_RPC_URL=https://sepolia.base.org
|
||||
|
||||
# Database
|
||||
DATABASE_URL=postgresql://user:pass@localhost:5432/dle
|
||||
|
||||
# Server keys for signing
|
||||
SERVER_PRIVATE_KEY=0x...
|
||||
```
|
||||
|
||||
## Заключение
|
||||
|
||||
Реализована полнофункциональная мульти-чейн governance система для управления токенами DLE. Система обеспечивает децентрализованное принятие решений с координацией через trusted server с криптографическими доказательствами, обеспечивая баланс между удобством использования и безопасностью.
|
||||
1051
docs.ru/back-docs/blockchain-integration-technical.md
Normal file
1051
docs.ru/back-docs/blockchain-integration-technical.md
Normal file
File diff suppressed because it is too large
Load Diff
418
docs.ru/back-docs/multi-agent-architecture.md
Normal file
418
docs.ru/back-docs/multi-agent-architecture.md
Normal file
@@ -0,0 +1,418 @@
|
||||
[English](../../docs.en/back-docs/multi-agent-architecture.md) | **Русский**
|
||||
|
||||
# 🏗️ Архитектура множественных ИИ-агентов в DLE
|
||||
|
||||
> **Концепция**: Создание отдельных специализированных агентов для разных задач, использующих одну локальную модель Ollama, но с разными системными промптами, правилами и интерфейсами.
|
||||
|
||||
---
|
||||
|
||||
## 📋 Содержание
|
||||
|
||||
1. [Концепция архитектуры](#концепция-архитектуры)
|
||||
2. [Типы агентов](#типы-агентов)
|
||||
3. [Архитектура системы](#архитектура-системы)
|
||||
4. [Настройка агентов](#настройка-агентов)
|
||||
5. [Интерфейсы агентов](#интерфейсы-агентов)
|
||||
6. [База знаний для агентов](#база-знаний-для-агентов)
|
||||
7. [Процесс работы агентов](#процесс-работы-агентов)
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Концепция архитектуры
|
||||
|
||||
### Основные принципы
|
||||
|
||||
1. **Одна модель, множество агентов**
|
||||
- Все агенты используют одну локальную модель Ollama (qwen2.5:7b)
|
||||
- Различие между агентами — в системных промптах и правилах
|
||||
- Каждый агент имеет свою специализацию и роль
|
||||
|
||||
2. **Изоляция агентов**
|
||||
- Каждый агент имеет свои настройки (системный промпт, правила, RAG таблицы)
|
||||
- Агенты не влияют друг на друга
|
||||
- Можно создавать, редактировать и удалять агентов независимо
|
||||
|
||||
3. **Специализация по задачам**
|
||||
- Агент поддержки — отвечает на вопросы пользователей
|
||||
- Агент-редактор — создает контент по запросу
|
||||
- Возможность создания дополнительных агентов (аналитик, переводчик и т.д.)
|
||||
|
||||
4. **Отдельные интерфейсы**
|
||||
- Каждый агент имеет свой интерфейс доступа
|
||||
- Интерфейсы адаптированы под задачи агента
|
||||
- Разные права доступа для разных агентов
|
||||
|
||||
---
|
||||
|
||||
## 🤖 Типы агентов
|
||||
|
||||
### 1. Агент поддержки (Support Agent)
|
||||
|
||||
**Роль**: Отвечать на сообщения пользователей
|
||||
|
||||
**Задачи**:
|
||||
- Обработка входящих сообщений от пользователей
|
||||
- Поиск ответов в базе знаний (FAQ, документация)
|
||||
- Генерация ответов на основе найденной информации
|
||||
- Эскалация сложных вопросов к операторам
|
||||
|
||||
**Характеристики**:
|
||||
- Использует RAG для поиска в FAQ и документах
|
||||
- Системный промпт: "Вы — профессиональный ассистент службы поддержки"
|
||||
- Правила: строгий режим (только из базы знаний, минимум генерации)
|
||||
- Интерфейс: встроен в чат (web, telegram, email)
|
||||
|
||||
**База знаний**:
|
||||
- FAQ таблицы
|
||||
- Документация продукта
|
||||
- База знаний для клиентов
|
||||
|
||||
---
|
||||
|
||||
### 2. Агент-редактор (Content Editor Agent)
|
||||
|
||||
**Роль**: Создавать контент по запросу пользователя
|
||||
|
||||
**Задачи**:
|
||||
- Создание постов для социальных сетей
|
||||
- Написание статей для блога
|
||||
- Генерация email-рассылок
|
||||
- Создание рекламных текстов
|
||||
|
||||
**Характеристики**:
|
||||
- Использует RAG для поиска инструкций платформ и стиля компании
|
||||
- Системный промпт: "Вы — профессиональный контент-маркетолог и редактор"
|
||||
- Правила: креативный режим (больше генерации, использование примеров)
|
||||
- Интерфейс: отдельная страница "Редактор контента"
|
||||
|
||||
**База знаний**:
|
||||
- Инструкции платформ (ВК, Telegram, Instagram и т.д.)
|
||||
- Стиль компании (tone of voice, запрещенные слова)
|
||||
- Примеры контента (референсы)
|
||||
- Ключевые слова и хэштеги
|
||||
- CTA блоки
|
||||
|
||||
---
|
||||
|
||||
### 3. Потенциальные дополнительные агенты
|
||||
|
||||
**Агент-аналитик**:
|
||||
- Анализ данных и создание отчетов
|
||||
- Выявление трендов
|
||||
- Прогнозирование
|
||||
|
||||
**Агент-переводчик**:
|
||||
- Перевод контента на разные языки
|
||||
- Локализация материалов
|
||||
- Адаптация под культурные особенности
|
||||
|
||||
**Агент-закупщик**:
|
||||
- Поиск поставщиков
|
||||
- Анализ условий
|
||||
- Рекомендации по выбору
|
||||
|
||||
---
|
||||
|
||||
## 🏛️ Архитектура системы
|
||||
|
||||
### Компоненты системы
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ Единая модель Ollama │
|
||||
│ (qwen2.5:7b) │
|
||||
└────────────────┬────────────────────────────────────────┘
|
||||
│
|
||||
├─────────────────┬───────────────────────┐
|
||||
│ │ │
|
||||
↓ ↓ ↓
|
||||
┌────────────────────┐ ┌──────────────────┐ ┌──────────────┐
|
||||
│ Агент поддержки │ │ Агент-редактор │ │ Другие агенты│
|
||||
│ │ │ │ │ │
|
||||
│ • Системный промпт │ │ • Системный │ │ • Свои │
|
||||
│ • Правила (строгие)│ │ промпт │ │ настройки │
|
||||
│ • RAG: FAQ │ │ • Правила │ │ │
|
||||
│ • Интерфейс: чат │ │ (креативные) │ │ │
|
||||
│ │ │ • RAG: инструкции │ │ │
|
||||
│ │ │ • Интерфейс: │ │ │
|
||||
│ │ │ редактор │ │ │
|
||||
└────────────────────┘ └──────────────────┘ └──────────────┘
|
||||
```
|
||||
|
||||
### Хранение настроек агентов
|
||||
|
||||
**Таблица `ai_agents`**:
|
||||
- `id` — уникальный идентификатор агента
|
||||
- `name` — название агента (например, "Агент поддержки", "Агент-редактор")
|
||||
- `role` — роль агента (support, content_editor, analyst и т.д.)
|
||||
- `description` — описание назначения агента
|
||||
- `system_prompt_encrypted` — системный промпт (зашифрован)
|
||||
- `rules_id` — ссылка на правила агента (из таблицы `ai_assistant_rules`)
|
||||
- `selected_rag_tables` — массив ID таблиц для RAG поиска
|
||||
- `enabled_channels` — на каких каналах активен (web, telegram, email)
|
||||
- `interface_route` — маршрут для интерфейса агента
|
||||
- `permissions_required` — требуемые права доступа
|
||||
- `is_active` — активен ли агент
|
||||
- `created_at`, `updated_at` — даты создания и обновления
|
||||
|
||||
**Связь с правилами**:
|
||||
- Каждый агент может использовать набор правил из `ai_assistant_rules`
|
||||
- Правила определяют поведение: temperature, maxTokens, searchRagFirst и т.д.
|
||||
- Можно создавать правила специально для каждого агента
|
||||
|
||||
**Связь с RAG таблицами**:
|
||||
- Каждый агент может использовать свои RAG таблицы
|
||||
- Агент поддержки: FAQ, документация
|
||||
- Агент-редактор: инструкции платформ, стиль компании, примеры
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ Настройка агентов
|
||||
|
||||
### Создание нового агента
|
||||
|
||||
**Шаг 1: Базовая информация**
|
||||
- Название агента
|
||||
- Роль (support, content_editor и т.д.)
|
||||
- Описание назначения
|
||||
|
||||
**Шаг 2: Системный промпт**
|
||||
- Определяет роль и поведение агента
|
||||
- Указывает, как агент должен работать
|
||||
- Содержит контекст о компании и стиле
|
||||
|
||||
**Шаг 3: Правила (Rules)**
|
||||
- Создание или выбор существующих правил
|
||||
- Настройка параметров генерации (temperature, maxTokens)
|
||||
- Настройка поведения RAG (searchRagFirst, generateIfNoRag)
|
||||
|
||||
**Шаг 4: База знаний (RAG таблицы)**
|
||||
- Выбор таблиц для поиска информации
|
||||
- Агент поддержки: FAQ, документация
|
||||
- Агент-редактор: инструкции, стиль, примеры
|
||||
|
||||
**Шаг 5: Интерфейс**
|
||||
- Определение маршрута для доступа к агенту
|
||||
- Настройка прав доступа
|
||||
- Выбор каналов (web, telegram, email)
|
||||
|
||||
**Шаг 6: Активация**
|
||||
- Включение/выключение агента
|
||||
- Тестирование работы агента
|
||||
|
||||
### Примеры настроек
|
||||
|
||||
**Агент поддержки**:
|
||||
- Системный промпт: "Вы — профессиональный ассистент службы поддержки..."
|
||||
- Правила: строгий режим (temperature: 0.3, searchRagFirst: true, generateIfNoRag: false)
|
||||
- RAG таблицы: FAQ, Документация продукта
|
||||
- Интерфейс: встроен в чат
|
||||
- Каналы: web, telegram, email
|
||||
|
||||
**Агент-редактор**:
|
||||
- Системный промпт: "Вы — профессиональный контент-маркетолог и редактор..."
|
||||
- Правила: креативный режим (temperature: 0.7, searchRagFirst: true, generateIfNoRag: true)
|
||||
- RAG таблицы: Инструкции платформ, Стиль компании, Примеры контента
|
||||
- Интерфейс: отдельная страница /content-editor
|
||||
- Каналы: только web (для редакторов)
|
||||
|
||||
---
|
||||
|
||||
## 🖥️ Интерфейсы агентов
|
||||
|
||||
### Агент поддержки — интерфейс чата
|
||||
|
||||
**Расположение**: Встроен в основной чат (HomeView)
|
||||
|
||||
**Особенности**:
|
||||
- Автоматическая активация при получении сообщения от пользователя
|
||||
- Показ статуса генерации ответа
|
||||
- Возможность отключения AI для конкретного сообщения
|
||||
- История диалога с контекстом
|
||||
|
||||
**Права доступа**:
|
||||
- Доступен всем пользователям
|
||||
- Автоматически отвечает на сообщения
|
||||
|
||||
---
|
||||
|
||||
### Агент-редактор — интерфейс редактора
|
||||
|
||||
**Расположение**: Отдельная страница `/content-editor`
|
||||
|
||||
**Особенности**:
|
||||
- Поле для ввода запроса на создание контента
|
||||
- Выбор типа контента (пост ВК, статья блога, email и т.д.)
|
||||
- Выбор платформы (ВКонтакте, Telegram, Instagram и т.д.)
|
||||
- Показ процесса генерации
|
||||
- Редактирование сгенерированного контента
|
||||
- Сохранение готового контента
|
||||
- История созданного контента
|
||||
|
||||
**Права доступа**:
|
||||
- Только для пользователей с ролью Editor
|
||||
- Требуется авторизация
|
||||
|
||||
**Функционал интерфейса**:
|
||||
1. **Форма запроса**:
|
||||
- Текстовое поле для описания задачи
|
||||
- Выбор типа контента (выпадающий список)
|
||||
- Выбор платформы (чекбоксы или выпадающий список)
|
||||
- Дополнительные параметры (тон, длина, ключевые слова)
|
||||
|
||||
2. **Процесс генерации**:
|
||||
- Индикатор загрузки
|
||||
- Показ найденных инструкций
|
||||
- Показ процесса генерации
|
||||
|
||||
3. **Результат**:
|
||||
- Готовый контент в редактируемом поле
|
||||
- Кнопка "Сохранить"
|
||||
- Кнопка "Перегенерировать"
|
||||
- Кнопка "Экспортировать" (копировать, скачать)
|
||||
|
||||
4. **История**:
|
||||
- Список созданного контента
|
||||
- Фильтры по типу, платформе, дате
|
||||
- Возможность редактирования и удаления
|
||||
|
||||
---
|
||||
|
||||
## 📚 База знаний для агентов
|
||||
|
||||
### Структура базы знаний
|
||||
|
||||
**Для агента поддержки**:
|
||||
- Таблица "FAQ" — часто задаваемые вопросы
|
||||
- Таблица "Документация" — описание функций продукта
|
||||
- Таблица "База знаний для клиентов" — расширенная информация
|
||||
|
||||
**Для агента-редактора**:
|
||||
- Таблица "Инструкции платформ" — правила размещения контента
|
||||
- Таблица "Стиль компании" — tone of voice, запрещенные слова
|
||||
- Таблица "Примеры контента" — референсы для разных типов контента
|
||||
- Таблица "Ключевые слова" — семантическое ядро, хэштеги
|
||||
- Таблица "CTA блоки" — призывы к действию
|
||||
|
||||
### Как агенты используют базу знаний
|
||||
|
||||
1. **RAG поиск**:
|
||||
- Пользователь задает вопрос/запрос
|
||||
- Агент выполняет векторный поиск в своих RAG таблицах
|
||||
- Находит релевантную информацию
|
||||
|
||||
2. **Контекст для генерации**:
|
||||
- Найденная информация передается в LLM как контекст
|
||||
- LLM генерирует ответ/контент на основе контекста
|
||||
- Системный промпт направляет, как использовать контекст
|
||||
|
||||
3. **Фильтрация по роли**:
|
||||
- Агент поддержки ищет только в FAQ и документации
|
||||
- Агент-редактор ищет только в инструкциях и примерах
|
||||
- Изоляция данных между агентами
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Процесс работы агентов
|
||||
|
||||
### Агент поддержки — процесс ответа
|
||||
|
||||
1. **Получение сообщения**:
|
||||
- Пользователь отправляет сообщение в чат
|
||||
- Система определяет, что нужно использовать агента поддержки
|
||||
|
||||
2. **RAG поиск**:
|
||||
- Агент ищет ответ в своих RAG таблицах (FAQ, документация)
|
||||
- Использует векторный поиск для семантического поиска
|
||||
|
||||
3. **Генерация ответа**:
|
||||
- Если найден ответ в базе знаний → использует его
|
||||
- Если не найден → в строгом режиме предлагает связаться с оператором
|
||||
- Генерирует ответ с учетом системного промпта и правил
|
||||
|
||||
4. **Отправка ответа**:
|
||||
- Ответ отправляется пользователю в чат
|
||||
- Сохраняется в истории диалога
|
||||
|
||||
---
|
||||
|
||||
### Агент-редактор — процесс создания контента
|
||||
|
||||
1. **Получение запроса**:
|
||||
- Редактор открывает интерфейс `/content-editor`
|
||||
- Вводит запрос: "Создай пост для ВКонтакте о новой функции"
|
||||
- Выбирает тип контента и платформу
|
||||
|
||||
2. **RAG поиск инструкций**:
|
||||
- Агент ищет инструкции для выбранной платформы
|
||||
- Ищет стиль компании
|
||||
- Ищет примеры похожего контента
|
||||
- Ищет релевантные ключевые слова
|
||||
|
||||
3. **Генерация контента**:
|
||||
- Агент генерирует контент на основе:
|
||||
- Системного промпта (роль редактора)
|
||||
- Найденных инструкций платформы
|
||||
- Стиля компании
|
||||
- Примеров контента
|
||||
- Ключевых слов
|
||||
|
||||
4. **Результат**:
|
||||
- Готовый контент показывается в интерфейсе
|
||||
- Редактор может редактировать контент
|
||||
- Сохранить или экспортировать
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Преимущества архитектуры
|
||||
|
||||
### 1. Специализация
|
||||
- Каждый агент решает свою задачу оптимально
|
||||
- Не нужно жертвовать качеством для универсальности
|
||||
|
||||
### 2. Гибкость
|
||||
- Легко создавать новых агентов для новых задач
|
||||
- Можно настраивать каждого агента независимо
|
||||
|
||||
### 3. Изоляция
|
||||
- Агенты не мешают друг другу
|
||||
- Можно тестировать и обновлять агентов независимо
|
||||
|
||||
### 4. Масштабируемость
|
||||
- Легко добавлять новых агентов
|
||||
- Каждый агент использует одну модель, нет перегрузки
|
||||
|
||||
### 5. Контроль
|
||||
- Четкое разделение ответственности
|
||||
- Легко отслеживать, какой агент что делает
|
||||
|
||||
---
|
||||
|
||||
## 📊 Сравнение с единым агентом
|
||||
|
||||
| Характеристика | Единый агент | Множественные агенты |
|
||||
|----------------|--------------|----------------------|
|
||||
| **Специализация** | Универсальный, но менее точный | Специализированный, более точный |
|
||||
| **Настройка** | Один набор настроек для всех задач | Отдельные настройки для каждой задачи |
|
||||
| **База знаний** | Все таблицы для всех задач | Изолированные таблицы для каждой задачи |
|
||||
| **Интерфейс** | Один интерфейс | Отдельные интерфейсы для каждой задачи |
|
||||
| **Гибкость** | Сложно адаптировать под разные задачи | Легко создавать новых агентов |
|
||||
| **Производительность** | Одна модель для всех | Одна модель, но разные промпты |
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Следующие шаги
|
||||
|
||||
1. **Создание таблицы `ai_agents`** в базе данных
|
||||
2. **Создание сервиса для управления агентами**
|
||||
3. **Модификация AI Assistant для работы с несколькими агентами**
|
||||
4. **Создание интерфейса для агента-редактора**
|
||||
5. **Настройка агента поддержки (уже существует, нужно адаптировать)**
|
||||
6. **Создание базы знаний для агента-редактора**
|
||||
7. **Тестирование работы обоих агентов**
|
||||
|
||||
---
|
||||
|
||||
**© 2024-2025 Тарабанов Александр Викторович. Все права защищены.**
|
||||
|
||||
**Последнее обновление**: Январь 2026
|
||||
931
docs.ru/back-docs/setup-ai-assistant.md
Normal file
931
docs.ru/back-docs/setup-ai-assistant.md
Normal file
@@ -0,0 +1,931 @@
|
||||
[English](../../docs.en/back-docs/setup-ai-assistant.md) | **Русский**
|
||||
|
||||
# Инструкция по настройке AI Ассистента с векторным поиском
|
||||
|
||||
## 🤖 Полное руководство по запуску интеллектуального помощника
|
||||
|
||||
Этот документ описывает пошаговый процесс настройки AI ассистента для решения бизнес-задач через электронные таблицы и векторный поиск.
|
||||
|
||||
---
|
||||
|
||||
## 📚 Что вы настроите
|
||||
|
||||
После выполнения инструкции у вас будет:
|
||||
|
||||
✅ Работающий AI ассистент с локальной моделью (Ollama)
|
||||
✅ База знаний для ответов клиентам (FAQ)
|
||||
✅ Автоматизация работы с поставщиками
|
||||
✅ Система обучения персонала
|
||||
✅ Векторный поиск по вашим данным
|
||||
✅ Значительная экономия времени и ресурсов
|
||||
|
||||
> 💡 **Экономический эффект**: См. [ИИ-агенты DLE](../ai-assistant.md) — архитектура, примеры агентов и расчёты экономии.
|
||||
|
||||
---
|
||||
|
||||
## ⏱️ Время настройки
|
||||
|
||||
- **Быстрая настройка**: 20-30 минут (базовый FAQ)
|
||||
- **Полная настройка**: 1-2 часа (все возможности)
|
||||
|
||||
---
|
||||
|
||||
## Шаг 1: Установка и запуск Ollama
|
||||
|
||||
### 1.1 Проверка статуса Ollama
|
||||
|
||||
1. Перейдите в **Настройки** → вкладка **Интеграции**
|
||||
2. Найдите блок **"Ollama"** и нажмите **"Подробнее"**
|
||||
3. Проверьте статус подключения:
|
||||
- ✅ **"Ollama is running"** — все готово, переходите к шагу 1.3
|
||||
- ❌ **"Ollama API not responding"** — переходите к шагу 1.2
|
||||
|
||||
### 1.2 Запуск Ollama (если не запущен)
|
||||
|
||||
Если Ollama не запущен, выполните в терминале:
|
||||
|
||||
```bash
|
||||
# Для Docker (рекомендуется)
|
||||
docker-compose up -d ollama
|
||||
|
||||
# Или локально
|
||||
ollama serve
|
||||
```
|
||||
|
||||
Обновите страницу и проверьте статус снова.
|
||||
|
||||
### 1.3 Установка модели для AI
|
||||
|
||||
1. В разделе **Ollama** нажмите **"Установить модель"**
|
||||
2. Выберите модель:
|
||||
- **qwen2.5:7b** (рекомендуется) — для русского языка, 4.7 GB
|
||||
- **llama2:7b** — для английского, 3.8 GB
|
||||
- **mistral:7b** — универсальная, 4.1 GB
|
||||
3. Нажмите **"Установить"**
|
||||
4. Дождитесь завершения загрузки (5-10 минут в зависимости от скорости интернета)
|
||||
|
||||
> 💡 **Подсказка**: Модель скачивается один раз и хранится локально
|
||||
|
||||
### 1.4 Установка Embedding модели
|
||||
|
||||
1. В том же разделе найдите **"Установить Embedding модель"**
|
||||
2. Выберите модель:
|
||||
- **mxbai-embed-large:latest** (рекомендуется) — 670 MB
|
||||
- **nomic-embed-text:latest** — альтернатива, 274 MB
|
||||
3. Нажмите **"Установить"**
|
||||
|
||||
> ⚠️ **Важно**: Embedding модель нужна для векторного поиска (RAG)
|
||||
|
||||
---
|
||||
|
||||
## Шаг 2: Создание базы знаний (электронные таблицы)
|
||||
|
||||
### 2.1 Создание таблицы FAQ
|
||||
|
||||
1. Перейдите в **Таблицы** (в главном меню)
|
||||
2. Нажмите **"+ Создать таблицу"**
|
||||
3. Заполните:
|
||||
- **Название**: `FAQ - Часто задаваемые вопросы`
|
||||
- **Описание**: `База знаний для AI ассистента по работе с клиентами`
|
||||
4. Нажмите **"Создать"**
|
||||
|
||||
### 2.2 Настройка столбцов таблицы
|
||||
|
||||
Добавьте следующие столбцы:
|
||||
|
||||
#### Столбец 1: Вопрос (обязательный для RAG)
|
||||
|
||||
1. Нажмите **"+ Добавить столбец"**
|
||||
2. Заполните:
|
||||
- **Название**: `Вопрос`
|
||||
- **Тип**: `Текст`
|
||||
- **Назначение**: Выберите `Вопрос для AI` ⭐
|
||||
3. Нажмите **"Сохранить"**
|
||||
|
||||
> ⚠️ **Критично**: Обязательно выберите назначение "Вопрос для AI" — это поле будет индексироваться для векторного поиска
|
||||
|
||||
#### Столбец 2: Ответ (обязательный для RAG)
|
||||
|
||||
1. Нажмите **"+ Добавить столбец"**
|
||||
2. Заполните:
|
||||
- **Название**: `Ответ`
|
||||
- **Тип**: `Текст`
|
||||
- **Назначение**: Выберите `Ответ AI` ⭐
|
||||
3. Нажмите **"Сохранить"**
|
||||
|
||||
#### Столбец 3: Продукт (опционально, для фильтрации)
|
||||
|
||||
1. Нажмите **"+ Добавить столбец"**
|
||||
2. Заполните:
|
||||
- **Название**: `Продукт`
|
||||
- **Тип**: `Множественный выбор`
|
||||
- **Варианты**: `Базовый`, `Премиум`, `Корпоративный`
|
||||
- **Назначение**: Выберите `Фильтр по продукту`
|
||||
3. Нажмите **"Сохранить"**
|
||||
|
||||
#### Столбец 4: Теги (опционально, для категоризации)
|
||||
|
||||
1. Нажмите **"+ Добавить столбец"**
|
||||
2. Заполните:
|
||||
- **Название**: `Теги`
|
||||
- **Тип**: `Множественный выбор`
|
||||
- **Варианты**: `Оплата`, `Доставка`, `Возврат`, `Гарантия`, `Техподдержка`
|
||||
- **Назначение**: Выберите `Теги пользователя`
|
||||
3. Нажмите **"Сохранить"**
|
||||
|
||||
#### Столбец 5: Приоритет (опционально)
|
||||
|
||||
1. Нажмите **"+ Добавить столбец"**
|
||||
2. Заполните:
|
||||
- **Название**: `Приоритет`
|
||||
- **Тип**: `Число`
|
||||
- **Назначение**: Выберите `Приоритет`
|
||||
3. Нажмите **"Сохранить"**
|
||||
|
||||
> 💡 **Подсказка**: Вопросы с более высоким приоритетом будут показываться AI первыми
|
||||
|
||||
### 2.3 Заполнение базы знаний
|
||||
|
||||
Добавьте типовые вопросы и ответы:
|
||||
|
||||
**Пример 1: Оплата**
|
||||
|
||||
| Вопрос | Ответ | Продукт | Теги | Приоритет |
|
||||
|--------|-------|---------|------|-----------|
|
||||
| Как оплатить заказ? | Мы принимаем оплату банковской картой, через PayPal, или банковским переводом. Выберите удобный способ при оформлении заказа. | Все | Оплата | 10 |
|
||||
| Можно ли оплатить частями? | Да, для заказов от 50,000₽ доступна рассрочка на 3, 6 или 12 месяцев без переплаты. | Премиум, Корпоративный | Оплата | 8 |
|
||||
|
||||
**Пример 2: Доставка**
|
||||
|
||||
| Вопрос | Ответ | Продукт | Теги | Приоритет |
|
||||
|--------|-------|---------|------|-----------|
|
||||
| Сколько времени занимает доставка? | Стандартная доставка: 3-5 рабочих дней по России. Экспресс-доставка: 1-2 дня в крупных городах. | Все | Доставка | 10 |
|
||||
| Сколько стоит доставка? | Бесплатная доставка при заказе от 5,000₽. Для заказов менее 5,000₽ стоимость доставки 300₽. | Все | Доставка | 9 |
|
||||
|
||||
**Пример 3: Возврат**
|
||||
|
||||
| Вопрос | Ответ | Продукт | Теги | Приоритет |
|
||||
|--------|-------|---------|------|-----------|
|
||||
| Как вернуть товар? | Возврат возможен в течение 14 дней с момента получения. Товар должен быть в оригинальной упаковке, с сохранением товарного вида. Свяжитесь с поддержкой для оформления возврата. | Все | Возврат | 10 |
|
||||
| Когда вернут деньги? | Возврат денежных средств производится в течение 5-10 рабочих дней после получения товара на наш склад. | Все | Возврат | 8 |
|
||||
|
||||
> 💡 **Рекомендация**: Добавьте минимум 20-30 вопросов для качественной работы AI. Чем больше вопросов, тем точнее ответы!
|
||||
|
||||
### 2.4 Активация таблицы как источника для AI
|
||||
|
||||
1. В правом верхнем углу таблицы найдите **⚙️ Настройки таблицы**
|
||||
2. Включите переключатель **"Использовать как источник для AI"** ✅
|
||||
3. Нажмите **"Сохранить"**
|
||||
|
||||
> ✅ **Готово!** Таблица теперь индексируется для векторного поиска
|
||||
|
||||
---
|
||||
|
||||
## Шаг 3: Настройка AI провайдера (Ollama)
|
||||
|
||||
### 3.1 Открытие настроек Ollama
|
||||
|
||||
1. Перейдите в **Настройки** → **Интеграции**
|
||||
2. Найдите блок **"Ollama"** и нажмите **"Подробнее"**
|
||||
|
||||
### 3.2 Проверка Base URL
|
||||
|
||||
1. Проверьте поле **Base URL**:
|
||||
- Для Docker: `http://ollama:11434` ✅
|
||||
- Для локального: `http://localhost:11434`
|
||||
2. Если URL неверный, исправьте и нажмите **"Сохранить"**
|
||||
|
||||
### 3.3 Выбор модели
|
||||
|
||||
1. В поле **"Модель (LLM)"** выберите установленную модель:
|
||||
- `qwen2.5:7b` (рекомендуется для русского)
|
||||
2. В поле **"Embeddings-модель"** выберите:
|
||||
- `mxbai-embed-large:latest`
|
||||
3. Нажмите **"Сохранить"**
|
||||
|
||||
---
|
||||
|
||||
## Шаг 4: Настройка AI Ассистента
|
||||
|
||||
### 4.1 Открытие настроек ассистента
|
||||
|
||||
1. Перейдите в **Настройки** → **Интеграции**
|
||||
2. Найдите блок **"ИИ-ассистент"** и нажмите **"Подробнее"**
|
||||
|
||||
### 4.2 Настройка системного промта
|
||||
|
||||
В поле **"Системный промт"** введите инструкции для AI:
|
||||
|
||||
**Базовый промт (для начала)**:
|
||||
|
||||
```
|
||||
Вы — профессиональный ассистент службы поддержки компании.
|
||||
|
||||
Правила:
|
||||
1. Отвечайте вежливо и профессионально
|
||||
2. Используйте информацию из базы знаний
|
||||
3. Если информации нет — предложите связаться с оператором
|
||||
4. Отвечайте кратко и по существу
|
||||
5. Всегда заканчивайте вопросом "Чем еще могу помочь?"
|
||||
```
|
||||
|
||||
**Продвинутый промт (с персонализацией)**:
|
||||
|
||||
```
|
||||
Вы — профессиональный ассистент службы поддержки компании "Название вашей компании".
|
||||
|
||||
О компании:
|
||||
- Мы занимаемся [краткое описание бизнеса]
|
||||
- Наши ценности: качество, надежность, клиентоориентированность
|
||||
|
||||
Стиль общения:
|
||||
- Дружелюбный, но профессиональный
|
||||
- Обращайтесь к клиенту на "Вы"
|
||||
- Используйте эмодзи умеренно (1-2 на сообщение)
|
||||
|
||||
Правила ответа:
|
||||
1. ОБЯЗАТЕЛЬНО: Отвечайте ТОЛЬКО на русском языке. Все вопросы и ответы должны быть на русском языке
|
||||
2. Сначала ищите ответ в базе знаний (RAG)
|
||||
3. Если нашли — отвечайте на основе найденной информации
|
||||
4. Если не нашли — честно скажите и предложите помощь оператора
|
||||
5. Не придумывайте информацию о ценах, сроках, условиях
|
||||
6. При сложных вопросах предлагайте связаться с менеджером
|
||||
|
||||
Всегда заканчивайте: "Чем еще могу помочь? 😊"
|
||||
```
|
||||
|
||||
### 4.3 Выбор моделей
|
||||
|
||||
1. **LLM-модель**: Выберите `qwen2.5:7b (ollama)`
|
||||
2. **Embedding-модель**: Выберите `mxbai-embed-large:latest (ollama)`
|
||||
|
||||
> 💡 **Подсказка**: Модели автоматически подтянутся из настроек Ollama
|
||||
|
||||
> 📊 **Размер контекстного окна**:
|
||||
> - **Qwen2.5:7b**: Базовый контекст = **32,768 токенов** (~24,000 русских слов)
|
||||
> - Всего данных, отправляемых в модель:
|
||||
> - Системный промпт: ~500-2000 символов (~300-1200 токенов)
|
||||
> - История диалога: до 20 сообщений (~100-500 токенов на сообщение = ~2000-10000 токенов)
|
||||
> - RAG контекст: ~500-2000 токенов (из найденных данных)
|
||||
> - Текущий вопрос: ~50-200 токенов
|
||||
> - **Итого**: примерно 3,000-15,000 токенов (запас достаточен)
|
||||
> - Если нужен больший контекст → используйте Qwen3 с YaRN (до 131K токенов)
|
||||
|
||||
### 4.4 Выбор RAG-таблицы
|
||||
|
||||
1. В поле **"Выбранные RAG-таблицы"** выберите созданную таблицу:
|
||||
- `FAQ - Часто задаваемые вопросы`
|
||||
2. Нажмите **"Сохранить"**
|
||||
|
||||
### 4.5 Настройка правил AI (Rules)
|
||||
|
||||
Создайте набор правил для управления поведением AI:
|
||||
|
||||
1. Нажмите кнопку **"Создать"** рядом с полем "Набор правил"
|
||||
2. В модальном окне заполните:
|
||||
|
||||
**Название**: `Гибридный режим (RAG + генерация)`
|
||||
|
||||
**Описание**: `AI сначала ищет в базе знаний, если не находит — генерирует ответ`
|
||||
|
||||
**Правила (JSON)**:
|
||||
```json
|
||||
{
|
||||
"checkUserTags": true,
|
||||
"searchRagFirst": true,
|
||||
"generateIfNoRag": true,
|
||||
"temperature": 0.7,
|
||||
"maxTokens": 500
|
||||
}
|
||||
```
|
||||
|
||||
3. Нажмите **"Сохранить"**
|
||||
4. Выберите созданное правило в выпадающем списке
|
||||
|
||||
> 💡 **Что означают параметры**:
|
||||
> - `checkUserTags: true` — учитывать теги пользователя при поиске
|
||||
> - `searchRagFirst: true` — сначала искать в базе знаний
|
||||
> - `generateIfNoRag: true` — генерировать ответ, если ничего не найдено
|
||||
> - `temperature: 0.7` — баланс между точностью и креативностью (0.0-1.0)
|
||||
> - `maxTokens: 500` — максимальная длина ответа
|
||||
|
||||
### 4.6 Настройки RAG поиска
|
||||
|
||||
Разверните раздел **"🔍 Настройки RAG поиска"**:
|
||||
|
||||
**Базовые настройки:**
|
||||
1. **Метод поиска**: Выберите `Гибридный поиск` (рекомендуется)
|
||||
2. **Максимальное количество результатов**: `5`
|
||||
3. **Порог релевантности**: `0.1` (от 0.01 до 1.0)
|
||||
|
||||
**Извлечение ключевых слов:**
|
||||
1. ✅ **Включить извлечение ключевых слов**
|
||||
2. **Минимальная длина слова**: `3`
|
||||
3. **Максимальное количество ключевых слов**: `10`
|
||||
4. ✅ **Удалять стоп-слова**
|
||||
|
||||
**Веса поиска (для гибридного):**
|
||||
1. **Семантический поиск**: `70%` (точность)
|
||||
2. **Поиск по ключевым словам**: `30%` (скорость)
|
||||
|
||||
**Дополнительные настройки:**
|
||||
1. ✅ **Нечеткий поиск** (для опечаток)
|
||||
2. ✅ **Стемминг слов** (находит разные формы слова)
|
||||
3. ☐ **Поиск синонимов** (пока отключен)
|
||||
|
||||
### 4.7 Сохранение настроек
|
||||
|
||||
Нажмите кнопку **"Сохранить"** внизу формы.
|
||||
|
||||
---
|
||||
|
||||
## Шаг 5: Тестирование AI Ассистента
|
||||
|
||||
### 5.1 Использование встроенного тестера
|
||||
|
||||
1. На странице настроек AI ассистента прокрутите вниз до блока **"🔍 Мониторинг системы"**
|
||||
2. В разделе **"🧠 Тест RAG-функциональности"**:
|
||||
- Убедитесь, что выбрана таблица `FAQ - Часто задаваемые вопросы`
|
||||
- Введите тестовый вопрос: `Как оплатить заказ?`
|
||||
- Нажмите **"Тестировать RAG"**
|
||||
3. Наблюдайте за процессом:
|
||||
- 🔍 Ищем ответ в базе знаний... (векторный поиск)
|
||||
- 🤖 Генерируем ответ с помощью ИИ... (LLM генерация)
|
||||
- ✅ Готово!
|
||||
4. Проверьте результат:
|
||||
- Должен отобразиться ответ из вашей таблицы
|
||||
- Score (оценка близости): чем ближе к 0, тем лучше
|
||||
|
||||
> 💡 **Хороший Score**: от -300 до 0 (ответ найден)
|
||||
> ⚠️ **Плохой Score**: больше 300 (ответ не найден, AI придумает свой)
|
||||
|
||||
### 5.2 Тестирование через Web Chat
|
||||
|
||||
1. Перейдите на главную страницу приложения
|
||||
2. Найдите виджет **"💬 Чат с AI"** (обычно справа внизу)
|
||||
3. Нажмите на виджет, чтобы открыть чат
|
||||
4. Введите вопрос: `Сколько стоит доставка?`
|
||||
5. Проверьте ответ AI
|
||||
|
||||
**Ожидаемый результат:**
|
||||
```
|
||||
🤖 AI Ассистент:
|
||||
Бесплатная доставка при заказе от 5,000₽.
|
||||
Для заказов менее 5,000₽ стоимость доставки 300₽.
|
||||
|
||||
Чем еще могу помочь? 😊
|
||||
```
|
||||
|
||||
### 5.3 Тестирование разных сценариев
|
||||
|
||||
Попробуйте задать различные вопросы:
|
||||
|
||||
**✅ Вопрос из базы знаний:**
|
||||
```
|
||||
Пользователь: "Как вернуть товар?"
|
||||
AI: [Ответ из таблицы FAQ]
|
||||
```
|
||||
|
||||
**⚠️ Вопрос НЕ из базы знаний:**
|
||||
```
|
||||
Пользователь: "Какая погода сегодня?"
|
||||
AI: "Извините, я специализируюсь на вопросах о нашей компании и продуктах.
|
||||
По вопросам погоды обратитесь к специализированным сервисам.
|
||||
Чем еще могу помочь?"
|
||||
```
|
||||
|
||||
**🎯 Вопрос с опечаткой:**
|
||||
```
|
||||
Пользователь: "Как аплатить заказ?" (опечатка)
|
||||
AI: [Найдет правильный ответ благодаря нечеткому поиску]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Шаг 6: Расширенные возможности (опционально)
|
||||
|
||||
### 6.1 Создание таблицы для работы с поставщиками
|
||||
|
||||
#### Структура таблицы "База поставщиков"
|
||||
|
||||
1. Создайте новую таблицу: `База поставщиков`
|
||||
2. Добавьте столбцы:
|
||||
|
||||
| Столбец | Тип | Описание |
|
||||
|---------|-----|----------|
|
||||
| Название компании | Текст | Наименование поставщика |
|
||||
| Категория товаров | Множественный выбор | Электроника, Мебель, Одежда, и т.д. |
|
||||
| Контактное лицо | Текст | ФИО менеджера |
|
||||
| Email | Текст | Электронная почта |
|
||||
| Телефон | Текст | Контактный телефон |
|
||||
| Цены | Текст | Прайс-лист (краткое описание) |
|
||||
| Условия оплаты | Текст | Отсрочка, предоплата, и т.д. |
|
||||
| Минимальный заказ | Число | Минимальная сумма заказа |
|
||||
| Срок доставки | Текст | Сроки поставки |
|
||||
| Рейтинг | Число | Оценка от 1 до 10 |
|
||||
| Примечания | Текст | Дополнительная информация |
|
||||
|
||||
3. Активируйте как источник для AI
|
||||
4. Заполните данными о ваших поставщиках
|
||||
|
||||
#### Промт для AI закупщика
|
||||
|
||||
Добавьте в системный промт:
|
||||
|
||||
```
|
||||
ДОПОЛНИТЕЛЬНО - Работа с поставщиками:
|
||||
|
||||
Когда пользователь спрашивает о поставщиках:
|
||||
1. Ищите в базе "База поставщиков"
|
||||
2. Фильтруйте по категории товаров
|
||||
3. Сортируйте по рейтингу и условиям
|
||||
4. Предоставьте ТОП-3 рекомендации
|
||||
|
||||
Формат ответа:
|
||||
🏆 TOP-3 поставщика по запросу "[категория]":
|
||||
|
||||
1. [Название] ⭐ [Рейтинг]/10
|
||||
📧 [Email] | 📞 [Телефон]
|
||||
💰 Условия: [Условия оплаты]
|
||||
🚚 Доставка: [Срок доставки]
|
||||
📦 Минимум: [Минимальный заказ]₽
|
||||
|
||||
2. ...
|
||||
3. ...
|
||||
|
||||
Рекомендую связаться с [Название первого поставщика] — лучшие условия.
|
||||
```
|
||||
|
||||
### 6.2 Создание таблицы для обучения персонала
|
||||
|
||||
#### Структура таблицы "База знаний для сотрудников"
|
||||
|
||||
1. Создайте новую таблицу: `База знаний для сотрудников`
|
||||
2. Добавьте столбцы:
|
||||
|
||||
| Столбец | Тип | Описание |
|
||||
|---------|-----|----------|
|
||||
| Вопрос | Текст | Вопрос сотрудника (назначение: Вопрос для AI) |
|
||||
| Ответ | Текст | Подробный ответ (назначение: Ответ AI) |
|
||||
| Категория | Множественный выбор | Продажи, HR, Финансы, IT, Маркетинг |
|
||||
| Отдел | Множественный выбор | Для какого отдела актуально |
|
||||
| Сложность | Число | От 1 (простой) до 5 (сложный) |
|
||||
| Инструкции | Текст | Пошаговые инструкции (если есть) |
|
||||
| Ссылки | Текст | Ссылки на документы/видео |
|
||||
| Дата обновления | Дата | Когда информация обновлялась |
|
||||
|
||||
3. Примеры вопросов:
|
||||
|
||||
**Категория "Продажи":**
|
||||
- "Как оформить возврат клиенту?"
|
||||
- "Какие скидки можно давать постоянным клиентам?"
|
||||
- "Как работать с корпоративными клиентами?"
|
||||
|
||||
**Категория "HR":**
|
||||
- "Как оформить отпуск?"
|
||||
- "Куда обращаться по больничному?"
|
||||
- "Как происходит адаптация новых сотрудников?"
|
||||
|
||||
**Категория "IT":**
|
||||
- "Как получить доступ к корпоративной почте?"
|
||||
- "Что делать при проблемах с VPN?"
|
||||
- "Как создать заявку в техподдержку?"
|
||||
|
||||
### 6.3 Создание связей между таблицами
|
||||
|
||||
#### Пример: Связь "Клиенты" → "Заказы"
|
||||
|
||||
1. Создайте таблицу **"Клиенты"**:
|
||||
- Название, Email, Телефон, Статус (VIP/Обычный)
|
||||
|
||||
2. Создайте таблицу **"Заказы"**:
|
||||
- Номер заказа, Дата, Сумма
|
||||
|
||||
3. В таблице "Заказы" добавьте столбец:
|
||||
- **Название**: `Клиент`
|
||||
- **Тип**: `Связь (Relation)`
|
||||
- **Связанная таблица**: выберите `Клиенты`
|
||||
- **Показывать поле**: выберите `Название`
|
||||
|
||||
4. Добавьте еще один столбец в "Заказы":
|
||||
- **Название**: `Email клиента`
|
||||
- **Тип**: `Lookup (Подстановка)`
|
||||
- **Связь через**: выберите столбец `Клиент`
|
||||
- **Подставлять поле**: выберите `Email`
|
||||
|
||||
**Результат**: При выборе клиента автоматически подставится его Email!
|
||||
|
||||
#### Использование AI с связанными таблицами
|
||||
|
||||
AI автоматически понимает связи и может отвечать на вопросы:
|
||||
|
||||
```
|
||||
Пользователь: "Покажи все заказы клиента Иванов"
|
||||
AI: [Ищет в таблице Заказы, фильтрует по клиенту Иванов]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Шаг 7: Интеграция с Telegram и Email (опционально)
|
||||
|
||||
### 7.1 Настройка Telegram бота
|
||||
|
||||
1. Перейдите в **Настройки** → **Интеграции** → **Telegram**
|
||||
2. Создайте бота через [@BotFather](https://t.me/botfather) в Telegram:
|
||||
- Отправьте `/newbot`
|
||||
- Выберите имя и username бота
|
||||
- Скопируйте **Bot Token**
|
||||
3. В настройках DLE введите:
|
||||
- **Bot Token**: вставьте токен от BotFather
|
||||
- **Bot Username**: username вашего бота (например, `@mycompany_bot`)
|
||||
4. Нажмите **"Сохранить"**
|
||||
5. В настройках AI ассистента выберите этот Telegram бот в поле **"Telegram-бот"**
|
||||
|
||||
**Результат**: AI будет отвечать на сообщения в Telegram!
|
||||
|
||||
### 7.2 Настройка Email интеграции
|
||||
|
||||
1. Перейдите в **Настройки** → **Интеграции** → **Email**
|
||||
2. Заполните IMAP настройки (для получения писем):
|
||||
- **IMAP Host**: `imap.gmail.com` (для Gmail)
|
||||
- **IMAP Port**: `993`
|
||||
- **IMAP User**: ваш email
|
||||
- **IMAP Password**: пароль приложения (не основной пароль!)
|
||||
3. Заполните SMTP настройки (для отправки писем):
|
||||
- **SMTP Host**: `smtp.gmail.com`
|
||||
- **SMTP Port**: `587`
|
||||
- **SMTP User**: ваш email
|
||||
- **SMTP Password**: пароль приложения
|
||||
- **From Email**: email для отправки
|
||||
4. Нажмите **"Тест IMAP"** и **"Тест SMTP"** для проверки
|
||||
5. Нажмите **"Сохранить"**
|
||||
6. В настройках AI ассистента выберите этот Email в поле **"Email для связи"**
|
||||
|
||||
> ⚠️ **Важно для Gmail**: Создайте "Пароль приложения" в настройках безопасности Google
|
||||
|
||||
**Результат**: AI будет отвечать на входящие email автоматически!
|
||||
|
||||
---
|
||||
|
||||
## Шаг 8: Мониторинг и оптимизация
|
||||
|
||||
### 8.1 Проверка статуса сервисов
|
||||
|
||||
1. Перейдите в **Настройки** → **Интеграции** → **ИИ-ассистент**
|
||||
2. Прокрутите вниз до **"🔍 Мониторинг системы"**
|
||||
3. Нажмите **"🔄 Обновить статус"**
|
||||
4. Проверьте статусы:
|
||||
- 🟢 **Backend**: должен быть "Работает"
|
||||
- 🟢 **Postgres**: должен быть "Работает"
|
||||
- 🟢 **Ollama**: должен показывать количество моделей
|
||||
- 🟢 **Vector Search**: должен быть "Работает"
|
||||
|
||||
> ⚠️ Если что-то красное (🔴) — см. раздел "Решение проблем" ниже
|
||||
|
||||
### 8.2 Анализ качества ответов
|
||||
|
||||
Регулярно проверяйте качество ответов AI:
|
||||
|
||||
1. **Score в тестере RAG**:
|
||||
- **-300 до 0** ✅ — отличное совпадение
|
||||
- **0 до 300** ⚠️ — среднее совпадение
|
||||
- **>300** ❌ — совпадение не найдено
|
||||
|
||||
2. **Если Score плохой**:
|
||||
- Добавьте больше похожих вопросов в таблицу
|
||||
- Используйте разные формулировки одного вопроса
|
||||
- Увеличьте порог релевантности (например, до 0.2)
|
||||
|
||||
### 8.3 Оптимизация настроек RAG
|
||||
|
||||
Экспериментируйте с настройками для улучшения результатов:
|
||||
|
||||
**Для более точных ответов:**
|
||||
```
|
||||
Метод поиска: Семантический
|
||||
Порог релевантности: 0.05 (ниже = строже)
|
||||
Веса: Семантический 100% / Ключевые слова 0%
|
||||
```
|
||||
|
||||
**Для более быстрых ответов:**
|
||||
```
|
||||
Метод поиска: Поиск по ключевым словам
|
||||
Максимальное количество результатов: 3
|
||||
```
|
||||
|
||||
**Для баланса (рекомендуется):**
|
||||
```
|
||||
Метод поиска: Гибридный
|
||||
Веса: Семантический 70% / Ключевые слова 30%
|
||||
Порог релевантности: 0.1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ AI Ассистент готов к работе!
|
||||
|
||||
### Что у вас теперь есть
|
||||
|
||||
✅ **Локальный AI ассистент** без зависимости от облака
|
||||
✅ **База знаний FAQ** для ответов клиентам
|
||||
✅ **Векторный поиск** для точных ответов
|
||||
✅ **Настроенные правила** поведения AI
|
||||
✅ **Система мониторинга** для контроля качества
|
||||
|
||||
### Экономический эффект
|
||||
|
||||
При правильной настройке AI ассистента вы получите:
|
||||
|
||||
✅ **Автоматизацию рутинных задач** - высвобождение времени для стратегии
|
||||
✅ **Повышение качества обслуживания** - AI работает 24/7 без усталости
|
||||
✅ **Снижение операционных расходов** - меньше персонала на рутинных задачах
|
||||
✅ **Ускорение принятия решений** - мгновенный доступ к информации
|
||||
|
||||
> 💡 **Подробная информация**: См. [ИИ-агенты DLE](../ai-assistant.md#экономический-эффект) — архитектура, примеры агентов и расчёты экономии.
|
||||
|
||||
---
|
||||
|
||||
## 📚 Следующие шаги
|
||||
|
||||
### Расширьте возможности AI
|
||||
|
||||
1. **Добавьте больше таблиц**:
|
||||
- База знаний для партнеров
|
||||
- Инструкции для персонала
|
||||
- Каталог продуктов
|
||||
- База контактов
|
||||
|
||||
2. **Создайте правила для разных сценариев**:
|
||||
- Строгий режим (только RAG) — для финансов
|
||||
- Креативный режим (больше генерации) — для маркетинга
|
||||
- Гибридный режим (баланс) — для поддержки
|
||||
|
||||
3. **Интегрируйте с другими системами**:
|
||||
- CRM (синхронизация клиентов)
|
||||
- Складская система (остатки товаров)
|
||||
- Бухгалтерия (счета и оплаты)
|
||||
|
||||
### Обучите команду
|
||||
|
||||
1. Покажите сотрудникам, как работает AI
|
||||
2. Объясните, как добавлять новые вопросы в базу
|
||||
3. Установите процесс регулярного обновления базы знаний
|
||||
4. Назначьте ответственного за качество ответов AI
|
||||
|
||||
---
|
||||
|
||||
## 🆘 Решение проблем
|
||||
|
||||
### Проблема: Ollama не запускается
|
||||
|
||||
**Симптомы**: Статус "Ollama API not responding"
|
||||
|
||||
**Решение**:
|
||||
```bash
|
||||
# Проверить контейнер
|
||||
docker ps | grep ollama
|
||||
|
||||
# Перезапустить
|
||||
docker-compose restart ollama
|
||||
|
||||
# Проверить логи
|
||||
docker-compose logs ollama
|
||||
```
|
||||
|
||||
### Проблема: AI отвечает неточно
|
||||
|
||||
**Симптомы**: Ответы не соответствуют базе знаний
|
||||
|
||||
**Решение**:
|
||||
1. Проверьте Score в тестере (должен быть < 300)
|
||||
2. Добавьте больше вариантов вопросов в таблицу
|
||||
3. Уменьшите порог релевантности (например, до 0.05)
|
||||
4. Проверьте, что столбцы имеют правильные назначения ("Вопрос для AI", "Ответ AI")
|
||||
|
||||
### Проблема: Vector Search не работает
|
||||
|
||||
**Симптомы**: Статус Vector Search показывает ошибку
|
||||
|
||||
**Решение**:
|
||||
1. Проверьте, установлена ли Embedding модель
|
||||
2. Пересоберите индекс: на странице таблицы нажмите **"🔄 Пересобрать индекс"**
|
||||
3. Проверьте, что таблица активирована как источник для AI
|
||||
|
||||
### Проблема: AI отвечает на неправильном языке
|
||||
|
||||
**Симптомы**: Ответы на английском вместо русского
|
||||
|
||||
**Решение**:
|
||||
1. Измените системный промт, добавив в начало: `ВСЕГДА отвечай на русском языке.`
|
||||
2. Используйте модель `qwen2.5:7b` вместо `llama2:7b`
|
||||
3. В правилах AI установите `"language": "ru"`
|
||||
|
||||
### Проблема: Медленные ответы
|
||||
|
||||
**Симптомы**: AI отвечает дольше 5-10 секунд
|
||||
|
||||
**Решение**:
|
||||
1. Используйте меньшую модель (`mistral:7b` вместо `qwen2.5:14b`)
|
||||
2. Уменьшите `maxResults` в настройках RAG (например, до 3)
|
||||
3. Отключите "Поиск синонимов" в дополнительных настройках
|
||||
4. Используйте SSD для хранения моделей
|
||||
|
||||
---
|
||||
|
||||
## 📖 Дополнительная документация
|
||||
|
||||
### Изучите возможности AI
|
||||
|
||||
- 🤖 **[ИИ-агенты DLE](../ai-assistant.md)** — архитектура, примеры агентов и экономический эффект
|
||||
- 📊 **[Система электронных таблиц](./tables-system.md)** - техническое описание таблиц
|
||||
- ⚙️ **[Конфигурация AI](./setup-ai-assistant.md#техническая-документация-для-разработчиков)** - технические детали настройки
|
||||
|
||||
### Общая документация
|
||||
|
||||
- 🛡️ **[Безопасность](../security.md)** - как AI защищает ваши данные
|
||||
- 💼 **[Блокчейн для бизнеса](../blockchain-for-business.md)** - интеграция AI с блокчейном
|
||||
- 📋 **[FAQ](../FAQ.md)** - часто задаваемые вопросы
|
||||
|
||||
### Поддержка
|
||||
|
||||
- 💬 **Чат поддержки**: https://hb3-accelerator.com/
|
||||
- 📧 **Email**: info@hb3-accelerator.com
|
||||
- 📚 **База знаний**: https://hb3-accelerator.com
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Техническая документация (для разработчиков)
|
||||
|
||||
### Архитектура системы AI
|
||||
|
||||
```
|
||||
┌───────────────────────────────────────────────────────────┐
|
||||
│ Настройка 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-функциональности │
|
||||
│ └── Отслеживание прогресса │
|
||||
│ │
|
||||
└───────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### База данных
|
||||
|
||||
#### Таблица: `ai_providers_settings`
|
||||
|
||||
```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()
|
||||
);
|
||||
```
|
||||
|
||||
#### Таблица: `ai_assistant_settings`
|
||||
|
||||
```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 поиска
|
||||
updated_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_by INTEGER
|
||||
);
|
||||
```
|
||||
|
||||
#### Таблица: `ai_assistant_rules`
|
||||
|
||||
```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, -- Зашифрованная версия правил
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
```
|
||||
|
||||
### Backend API
|
||||
|
||||
#### Настройки AI провайдеров
|
||||
|
||||
- **GET** `/settings/ai-settings/:provider` — Получить настройки провайдера
|
||||
- **PUT** `/settings/ai-settings/:provider` — Сохранить настройки провайдера
|
||||
- **DELETE** `/settings/ai-settings/:provider` — Удалить настройки провайдера
|
||||
- **GET** `/settings/ai-settings/:provider/models` — Получить список моделей
|
||||
- **POST** `/settings/ai-settings/:provider/verify` — Проверить API ключ
|
||||
|
||||
#### Настройки AI ассистента
|
||||
|
||||
- **GET** `/settings/ai-assistant` — Получить настройки ассистента
|
||||
- **PUT** `/settings/ai-assistant` — Сохранить настройки ассистента
|
||||
|
||||
#### Правила AI
|
||||
|
||||
- **GET** `/settings/ai-assistant-rules` — Получить все правила
|
||||
- **GET** `/settings/ai-assistant-rules/:id` — Получить правило по ID
|
||||
- **POST** `/settings/ai-assistant-rules` — Создать правило
|
||||
- **PUT** `/settings/ai-assistant-rules/:id` — Обновить правило
|
||||
- **DELETE** `/settings/ai-assistant-rules/:id` — Удалить правило
|
||||
|
||||
#### Ollama (локальные модели)
|
||||
|
||||
- **GET** `/ollama/status` — Проверить статус Ollama
|
||||
- **GET** `/ollama/models` — Получить список моделей
|
||||
- **POST** `/ollama/install` — Установить модель
|
||||
- **DELETE** `/ollama/models/:modelName` — Удалить модель
|
||||
|
||||
### Frontend страницы
|
||||
|
||||
- **`/settings/ai`** — Главная страница интеграций
|
||||
- **`/settings/ai/:provider`** — Настройки AI провайдера
|
||||
- **`/settings/ai/assistant`** — Настройки AI ассистента
|
||||
|
||||
### Процесс обработки сообщения
|
||||
|
||||
```
|
||||
1. Пользователь → Сообщение
|
||||
↓
|
||||
2. UnifiedMessageProcessor
|
||||
↓
|
||||
3. Проверка языка (только русский)
|
||||
↓
|
||||
4. Дедупликация (хеш сообщения)
|
||||
↓
|
||||
5. Загрузка настроек (aiAssistantSettingsService)
|
||||
↓
|
||||
6. Загрузка правил (aiAssistantRulesService)
|
||||
↓
|
||||
7. RAG поиск (ragService)
|
||||
├── Семантический поиск (vector search)
|
||||
├── Поиск по ключевым словам
|
||||
└── Гибридный поиск
|
||||
↓
|
||||
8. Генерация ответа (generateLLMResponse)
|
||||
├── System Prompt
|
||||
├── История разговора
|
||||
├── Контекст из RAG
|
||||
└── Правила
|
||||
↓
|
||||
9. Ответ → Пользователь
|
||||
```
|
||||
|
||||
### Безопасность
|
||||
|
||||
- **Шифрование**: Все чувствительные поля зашифрованы с помощью AES-256
|
||||
- **Права доступа**: Только администраторы могут изменять настройки
|
||||
- **Валидация**: Проверка всех входных данных и API ключей
|
||||
|
||||
---
|
||||
|
||||
**© 2024-2025 Тарабанов Александр Викторович. Все права защищены.**
|
||||
|
||||
**Версия документа**: 1.0.0
|
||||
**Дата создания**: October 25, 2025
|
||||
|
||||
197
docs.ru/back-docs/setup-instruction.md
Normal file
197
docs.ru/back-docs/setup-instruction.md
Normal file
@@ -0,0 +1,197 @@
|
||||
<!--
|
||||
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/VC-HB3-Accelerator
|
||||
-->
|
||||
|
||||
[English](../../docs.en/back-docs/setup-instruction.md) | **Русский**
|
||||
|
||||
# Инструкция по настройке приложения Digital Legal Entity
|
||||
|
||||
## 🚀 Полный процесс инициализации системы
|
||||
|
||||
Этот документ описывает полный процесс подготовки приложения к работе с поддержкой блокчейна, смарт-контрактов и системы управления доступом.
|
||||
|
||||
---
|
||||
|
||||
## Шаг 1: Установка софта
|
||||
|
||||
1. Клонируйте репозиторий проекта на ваше локальное устройство
|
||||
2. Запустите приложение через Docker Compose или локально в зависимости от конфигурации
|
||||
3. Откройте веб-приложение в браузере: `http://localhost:9000` (production) или `http://localhost:5173` (dev режим)
|
||||
|
||||
---
|
||||
|
||||
## Шаг 2: Подключение крипто кошелька
|
||||
|
||||
1. Убедитесь, что у вас установлен браузерный кошелек (MetaMask, WalletConnect или аналог)
|
||||
2. В кошельке создайте или импортируйте аккаунт с токеном управления
|
||||
3. В веб-приложении нажмите на кнопку **"Подключить кошелек"**
|
||||
4. Выберите тип кошелька и подтвердите подключение
|
||||
5. После успешного подключения вы увидите адрес вашего аккаунта в верхнем углу
|
||||
|
||||
---
|
||||
|
||||
## Шаг 3: Добавление RPC провайдеров (Безопасность → RPC провайдеры)
|
||||
|
||||
1. Перейдите в **Настройки** → вкладка **Безопасность**
|
||||
2. Найдите раздел **"RPC провайдеры"**
|
||||
3. Нажмите кнопку **"Добавить"**
|
||||
4. Заполните форму для каждой блокчейн сети, которую хотите использовать:
|
||||
- **Название сети** (например: Ethereum, Polygon, BSC)
|
||||
- **RPC URL** (ссылка для подключения, пример: `https://eth-mainnet.g.alchemy.com/v2/YOUR-API-KEY`)
|
||||
- **ID сети** (Chain ID)
|
||||
5. Нажмите **"Сохранить"** для каждого провайдера
|
||||
6. Система автоматически проверит корректность подключения
|
||||
|
||||
> ⚠️ **Важно**: Получите API ключи от провайдеров (Alchemy, Infura, Quicknode и т.д.) перед добавлением
|
||||
|
||||
---
|
||||
|
||||
## Шаг 4: Настройка мультидеплоя смарт контрактов
|
||||
|
||||
1. Перейдите в **Настройки** → вкладка **Блокчейн**
|
||||
2. Заполните форму
|
||||
3. Нажмите **"Запустить деплой"**
|
||||
|
||||
---
|
||||
|
||||
## Шаг 5: Завершение деплоя и сохранение адреса контракта
|
||||
|
||||
1. Ожидайте завершения деплоя (зависит от сети, обычно 30-120 секунд)
|
||||
2. После успешного завершения откроется страница **"Управление контрактами"**
|
||||
3. **Копируйте адрес развернутого контракта** (обычно он выглядит как: `0x742d35Cc6634C0532925a3b844Bc...`)
|
||||
|
||||
---
|
||||
|
||||
## Шаг 6: Настройка аутентификации через смарт контракт
|
||||
|
||||
1. Вернитесь в **Настройки** → вкладка **Аутентификация**
|
||||
2. В поле **"Адрес смарт контракта"** вставьте адрес, скопированный на шаге 5
|
||||
3. Установите пороги для управления доступом:
|
||||
- **Минимальное количество токенов для редактирования** (например: 100 токенов)
|
||||
- **Минимальное количество токенов для просмотра** (например: 1 токен)
|
||||
|
||||
---
|
||||
|
||||
## Шаг 7: Настройка ИИ и базы данных
|
||||
|
||||
1. Перейдите в **Настройки** → вкладка **ИИ**
|
||||
2. Откройте подраздел **"База данных"**
|
||||
3. Замените дефолтные пароли
|
||||
4. Нажмите **"Сгенерировать новый ключ шифрования"**
|
||||
- Система автоматически создаст криптографический ключ
|
||||
- **Сохраните ключ в безопасном месте** (он понадобится для восстановления данных)
|
||||
|
||||
---
|
||||
|
||||
## Шаг 8: Настройка доступа через интернет (опционально)
|
||||
|
||||
**Если вам нужен доступ к веб приложению извне через интернет:**
|
||||
|
||||
1. Перейдите в **Настройки** → вкладка **Сервер**
|
||||
2. На странице **Сервер** выберите **WEB SSH** или иной подходящий сервис
|
||||
3. Заполните форму для миграции локального приложения на виртуальное устройство с:
|
||||
- **Публичным IP адресом**
|
||||
- **Подключением к вашему доменному имени**
|
||||
4. Нажмите **"Опубликовать"**
|
||||
5. Дождитесь завершения процесса миграции
|
||||
|
||||
> ℹ️ **Примечание**: Этот шаг требует наличия зарегистрированного доменного имени и доступа к DNS настройкам
|
||||
|
||||
---
|
||||
|
||||
## Шаг 9: Настройка юридических документов для работы с персональными данными
|
||||
|
||||
### 9.1 Заполнение юридической информации о компании
|
||||
|
||||
1. Перейдите в **CRM** → раздел **Контент**
|
||||
2. Найдите и откройте форму **"Юридическая информация компании"**
|
||||
3. Заполните все необходимые поля:
|
||||
- **Полное наименование организации** (юридическое название)
|
||||
- **Краткое наименование**
|
||||
- **Организационно-правовая форма** (ООО, ИП, АО и т.д.)
|
||||
- **Юридический адрес**
|
||||
- **Фактический адрес** (если отличается)
|
||||
- **ИНН / ОГРН / КПП** (регистрационные данные)
|
||||
- **Контактные данные** (телефон, email, сайт)
|
||||
- **Ответственное лицо за обработку персональных данных** (ФИО, должность)
|
||||
- **Применимая юрисдикция** (GDPR, CCPA, российское законодательство и т.д.)
|
||||
4. Нажмите **"Сохранить"**
|
||||
|
||||
> 💡 **Подсказка**: Все введенные данные автоматически подставятся во все шаблоны юридических документов
|
||||
|
||||
### 9.2 Работа с шаблонами документов
|
||||
|
||||
1. В разделе **Контент** перейдите в подраздел **"Шаблоны"**
|
||||
2. Выберите необходимые шаблоны документов, требуемые регуляторами:
|
||||
- **Политика конфиденциальности**
|
||||
- **Пользовательское соглашение**
|
||||
- **Согласие на обработку персональных данных**
|
||||
- **Политика использования cookies**
|
||||
3. Для каждого шаблона:
|
||||
- Нажмите **"Предварительный просмотр"** для проверки автоматически заполненных данных
|
||||
- При необходимости отредактируйте специфичные параметры обработки данных
|
||||
- Выберите действие:
|
||||
- **"Опубликовать для публичного использования"** — документ будет доступен на сайте
|
||||
- **"Опубликовать для внутреннего использования"** — документ доступен только внутри CRM
|
||||
- **"Распечатать"** — экспорт в PDF для печати или подписания
|
||||
4. Подтвердите публикацию
|
||||
5. Система автоматически добавит документы на соответствующие страницы приложения
|
||||
|
||||
> ⚠️ **Важно**: Рекомендуется проконсультироваться с юристом перед публикацией документов для обеспечения полного соответствия требованиям законодательства
|
||||
|
||||
---
|
||||
|
||||
## ✅ Приложение готово к работе!
|
||||
|
||||
После завершения всех шагов ваше приложение полностью сконфигурировано и готово к использованию.
|
||||
|
||||
**Следующие этапы:**
|
||||
- 📖 Настройка AI ассистента (см. документ: `setup-ai-assistant.md`)
|
||||
- 🔐 Управление смарт контрактами (см. документ: `manage-smart-contracts.md`)
|
||||
|
||||
---
|
||||
|
||||
## 🆘 Рекомендации по безопасности
|
||||
|
||||
✓ Сохраняйте адреса контрактов и ключи шифрования в безопасном месте
|
||||
✓ Используйте мощные пароли для БД
|
||||
✓ Регулярно создавайте резервные копии конфигурации
|
||||
✓ Никогда не делитесь приватными ключами кошелька
|
||||
✓ Используйте HTTPS для доступа к приложению в продакшене
|
||||
|
||||
---
|
||||
|
||||
## 📝 Что дальше?
|
||||
|
||||
После завершения базовой настройки вы можете:
|
||||
1. Добавлять пользователей и управлять их разрешениями
|
||||
2. Создавать группы для совместной работы
|
||||
3. Настраивать AI ассистента для автоматизации задач
|
||||
4. Управлять смарт контрактами для расширения функциональности
|
||||
5. Интегрировать внешние сервисы и боты
|
||||
|
||||
---
|
||||
|
||||
## 📚 Дополнительная документация
|
||||
|
||||
### Изучите возможности DLE
|
||||
- 🤖 **[ИИ-агенты](../ai-assistant.md)** — система создания специализированных агентов под бизнес-процессы
|
||||
- 💼 **[Блокчейн для бизнеса](../blockchain-for-business.md)** - как токенизация активов решает бизнес-задачи
|
||||
- 🛡️ **[Безопасность](../security.md)** - многоуровневая защита вашего бизнеса
|
||||
|
||||
### Техническая информация
|
||||
- 🔗 **[Техническая документация по блокчейну](./blockchain-integration-technical.md)** - для разработчиков
|
||||
- 📋 **[FAQ](../FAQ.md)** - часто задаваемые вопросы
|
||||
- 📝 **[Описание приложения](../application-description.md)** - обзор функциональности
|
||||
|
||||
### Поддержка
|
||||
- 💬 **Чат поддержки**: https://hb3-accelerator.com/
|
||||
- 📧 **Email**: info@hb3-accelerator.com
|
||||
134
docs.ru/back-docs/system-messages-management.md
Normal file
134
docs.ru/back-docs/system-messages-management.md
Normal file
@@ -0,0 +1,134 @@
|
||||
[English](../../docs.en/back-docs/system-messages-management.md) | **Русский**
|
||||
|
||||
# Техническое задание: управление системными сообщениями
|
||||
|
||||
## 1. Цель и контекст
|
||||
- Обеспечить управляемое отображение системных сообщений на главной странице (`/`, компонент `HomeView.vue`) и добавить административный интерфейс для их создания и модерации в разделе контента (`/content`, компонент `ContentListView.vue`).
|
||||
- Системные сообщения должны поддерживать статусы «черновик» и «опубликовано», храниться в базе данных и быть доступны через REST API.
|
||||
|
||||
## 2. Актуальное состояние
|
||||
- Главная страница строится компонентом `HomeView.vue` и отображает чат ассистента (`ChatInterface.vue`), в котором выделены системные сообщения (`Message.vue`) по признаку `message.role === 'system'`.
|
||||
- Раздел контента (`ContentListView.vue`) содержит карточки переходов: «Создать страницу», «Шаблоны», «Публичные», «Настройка», «Внутренние». Карточки ведут на существующие маршруты `content-create`, `content-templates`, `content-published`, `content-settings`, `content-internal`.
|
||||
- В проекте отсутствуют сущности и API для системных сообщений; текущий `pagesService.js` работает только со страницами (`/pages`).
|
||||
|
||||
## 3. Новые пользовательские сценарии
|
||||
- **Просмотр системных сообщений (главная, `/`):**
|
||||
- Опубликованные системные сообщения подгружаются в чат ассистента и отображаются в виде свернутых карточек с кликабельным заголовком.
|
||||
- При клике на заголовок сообщение раскрывается: в ленте чата отображается полный текст сообщения **или** отправляется предзаготовленный ответ от ИИ ассистента (контент «ответа» хранится вместе с сообщением и выбирается по флагу `reply_type`).
|
||||
- Сообщения должны явно маркироваться как системные (цвет, иконка). При повторном открытии пользователь видит последнее состояние раскрытия; возможно локальное запоминание «прочитано».
|
||||
- **Раздел «Системные сообщения» (`/content`):**
|
||||
- На странице `/content` появляется новая карточка «Системные сообщения» с кнопкой «Подробнее». Переход ведёт на страницу с пользовательской таблицей (`/content/system-messages/table`), построенной на уже существующих компонентах таблиц (см. `UserTablesList.vue`), без отдельного дэшборда карточек.
|
||||
- Таблица отображает системные сообщения построчно, с возможностью множественного выбора через чекбоксы; доступные массовые действия: публикация, снятие с публикации, перевод в черновики, удаление.
|
||||
- Для каждого сообщения по клику «Подробнее» (внутри строки) открывается просмотр/редактирование с формой (см. ниже).
|
||||
- **Создание/редактирование (`/content/system-messages/create`, `/content/system-messages/:id/edit`):**
|
||||
- Форма с полями: заголовок, краткое описание, основной текст (Markdown/HTML), тип ответа (`inline` — показывать контент, `assistant_reply` — отправлять подготовленный ответ от ассистента), поле «Ответ ассистента» (активно при `assistant_reply`), тег важности (info/warning/danger), дата начала публикации (опционально), дата окончания (опционально), флаг отображения гостям.
|
||||
- Кнопки: «Сохранить как черновик», «Опубликовать». При редактировании — «Обновить», «Снять с публикации», «Удалить».
|
||||
- Проверки: обязательность заголовка и основного текста (или ответа ассистента в соответствующем режиме); валидация дат (окончание ≥ начало).
|
||||
- **Работа с таблицей системных сообщений:**
|
||||
- Колонки: чекбокс выбора, заголовок (кликабелен), статус, тип ответа, период действия, целевая аудитория (гости/авторизованные/все), дата создания, автор.
|
||||
- Массовые действия выполняются для выбранных строк; одиночные действия доступны через контекстное меню/кнопки в строке (редактировать, опубликовать, снять с публикации, удалить).
|
||||
|
||||
## 4. Требования к интерфейсу
|
||||
- В `ContentListView.vue` в сетку `management-blocks` добавить карточку «Системные сообщения» с кнопкой `Подробнее`. По дизайну карточка должна соответствовать существующим блокам (заголовок, описание, кнопка).
|
||||
- Страница с таблицей системных сообщений:
|
||||
- Использовать `BaseLayout` и локальные стили (`scoped`).
|
||||
- Таблица поддерживает сортировку, фильтрацию по статусам и поиск по заголовку.
|
||||
- Чекбоксы в шапке и строках для массового выбора; панель действий появляется при наличии выбора.
|
||||
- Кнопка «Создать сообщение» открывает форму создания.
|
||||
- Форма создания/редактирования:
|
||||
- Rich-text (минимум Markdown) с предпросмотром и счётчиками символов/слов.
|
||||
- Переключатель режима показа (`inline`/`assistant_reply`) с условным отображением поля «Ответ ассистента» (можно использовать `<transition>`).
|
||||
- Поле для выбора иконки/цвета по `severity` (статические пресеты).
|
||||
- Главная страница:
|
||||
- Системные сообщения отображаются в блоке чата как свернутые карточки (`system-message-collapsed`). При клике заголовок разворачивает карточку (`system-message-expanded`) или инициирует отправку ассистента (UI показывает «сообщение от ассистента»).
|
||||
- Для развёрнутых сообщений предусмотреть кнопку «Свернуть» и (опционально) «Отметить как прочитанное». Состояние хранить в `localStorage`.
|
||||
|
||||
## 5. Маршрутизация и компоненты
|
||||
- Добавить маршруты в `router/index.js`:
|
||||
- - `/content/system-messages/table` → `SystemMessagesTableView.vue`
|
||||
- - `/content/system-messages/create` → `SystemMessageCreateView.vue`
|
||||
- - `/content/system-messages/:id` → `SystemMessageDetailsView.vue` (просмотр)
|
||||
- - `/content/system-messages/:id/edit` → `SystemMessageEditView.vue`
|
||||
- При необходимости для модальных/вложенных маршрутов можно использовать дочерние маршруты или именованные вью.
|
||||
- Создать соответствующие Vue-компоненты в `src/views/content/system-messages/` и общий набор переиспользуемых элементов (таблица, форма, фильтры, массовые действия) в `src/components/system-messages/`.
|
||||
- Создать сервис `src/services/systemMessagesService.js` с методами для нового API.
|
||||
|
||||
## 6. Требования к API и данным
|
||||
- **Новая таблица** `system_messages` (PostgreSQL):
|
||||
- `id` (uuid, pk)
|
||||
- `title` (text, not null)
|
||||
- `summary` (text, nullable)
|
||||
- `content` (text, not null)
|
||||
- `reply_type` (enum: inline, assistant_reply; default inline)
|
||||
- `assistant_reply_content` (text, nullable; требуется при `reply_type = assistant_reply`)
|
||||
- `severity` (enum: info, warning, danger; default info)
|
||||
- `status` (enum: draft, published; not null)
|
||||
- `visible_for` (enum: all, authenticated, guests; default all)
|
||||
- `publish_at` (timestamp, nullable)
|
||||
- `expire_at` (timestamp, nullable)
|
||||
- `created_at`, `updated_at`
|
||||
- `created_by`, `updated_by` (references users/identities, nullable)
|
||||
- `slug` (text, уникальный, для адресации по ссылке при необходимости)
|
||||
- **REST API (Express):**
|
||||
- `GET /system-messages` (пагинация, фильтры по статусу, поиску)
|
||||
- `GET /system-messages/published` (фильтрация по дате/аудитории; публичная)
|
||||
- `GET /system-messages/:id` (доступ только авторизованным редакторам)
|
||||
- `POST /system-messages` (создание; права `MANAGE_LEGAL_DOCS`)
|
||||
- `PATCH /system-messages/:id` (редактирование; проверка статусов)
|
||||
- `DELETE /system-messages/:id` (мягкое удаление или физическое)
|
||||
- `POST /system-messages/:id/publish` и `POST /system-messages/:id/unpublish` (опционально, если не использовать PATCH)
|
||||
- Все защищённые эндпоинты должны требовать авторизацию и права (см. `permissions.js`, `usePermissions`).
|
||||
- Добавить новую миграцию (`backend/scripts/run-migrations.js`) и ORM/SQL-файлы в существующем формате проекта.
|
||||
- Обновить логирование и обработку ошибок `winston`, добавить валидацию входных данных (например, `Joi` или кастомную).
|
||||
|
||||
## 7. Логика отображения на фронтенде
|
||||
- `HomeView.vue`:
|
||||
- При инициализации запрашивать опубликованные системные сообщения (учитывая текущую аудиторию) через `systemMessagesService.getPublished({ includeExpired: false })`.
|
||||
- Кэшировать ответ в сторе или локальном состоянии; при подписке на WebSocket можно предусмотреть `system_message_updated` событие.
|
||||
- Добавить обработчик раскрытия: по клику на заголовок либо подставлять полный текст сообщения (`inline`), либо инициировать цепочку отправки `assistant_reply_content` в чат (без участия пользователя).
|
||||
- Добавить обработчик скрытия сообщения, сохраняющий идентификатор в `localStorage` и фильтрующий локально.
|
||||
- `ContentListView.vue`:
|
||||
- Добавить новую карточку «Системные сообщения» в сетку `management-blocks`, не нарушая адаптивную сетку (обновить `grid-template-columns` при необходимости).
|
||||
- Страницы списков:
|
||||
- Реализовать пагинацию (lazy loading или обычная), сортировку по дате.
|
||||
- Для статусов использовать цветовые бейджи (info/warning/danger).
|
||||
- Форма создания:
|
||||
- Поддерживать сабмит через `yarn lint`-friendly код; валидация на клиенте (например, с использованием `computed`/`watch`).
|
||||
- При успешной публикации перенаправлять на список опубликованных; при сохранении черновика — оставаться на странице с уведомлением.
|
||||
|
||||
## 8. Требования к безопасности и доступу
|
||||
- Сценарии создания/изменения доступны только ролям с `PERMISSIONS.MANAGE_LEGAL_DOCS`.
|
||||
- Публичный список (`GET /system-messages/published`) фильтрует по:
|
||||
- `status === 'published'`.
|
||||
- `publish_at <= now()` (или null).
|
||||
- `expire_at > now()` (или null).
|
||||
- `visible_for` проверяется на основе контекста (гость/авторизованный).
|
||||
- При выдаче через чат скрывать поля `created_by`, `updated_by`, внутренние метки.
|
||||
- Учитывать CSRF, CORS, rate-limit (перенять конфиг из существующих роутов).
|
||||
|
||||
## 9. Тестирование
|
||||
- **Backend:**
|
||||
- Юнит-тесты для CRUD в `tests/system-messages/*.test.js` (Mocha).
|
||||
- Проверка фильтров publish/expire и доступа по ролям.
|
||||
- Тест миграции (откат/применение).
|
||||
- **Frontend:**
|
||||
- Юнит-тесты Vue (если настроены) для основных компонентов (форма, список).
|
||||
- E2E (при наличии) — сценарий: создание черновика → публикация → отображение на главной.
|
||||
- **Регрессионные проверки:**
|
||||
- Убедиться, что существующий список контента и чат ассистента продолжают работать без ошибок (`yarn lint`, `yarn test`).
|
||||
|
||||
## 10. Интеграция и DevOps
|
||||
- Обновить `docker-compose.yml` при необходимости (например, добавить миграции в стартовый процесс).
|
||||
- Убедиться, что новые переменные окружения (если будут, например, лимиты количества сообщений) документированы в `README.md` и `setup-instruction.md`.
|
||||
- Добавить скрипт seeding (опционально) для тестовых системных сообщений.
|
||||
|
||||
## 11. Открытые вопросы
|
||||
- Нужно ли хранить историю публикаций (auditing)? Если да — предусмотреть таблицу `system_messages_history`.
|
||||
- Требуется ли поддержка многоязычности? (При отсутствии — ограничение на один язык, RU).
|
||||
- Нужно ли уведомление по WebSocket при появлении новых сообщений? (Если да — добавить событие в `wsHub.js`).
|
||||
|
||||
## 12. Итоговые артефакты
|
||||
- Backend: новые маршруты, контроллеры, сервис, миграция.
|
||||
- Frontend: новые страницы и сервис, обновлённые маршруты и компоненты `HomeView`, `ContentListView`.
|
||||
- Документация: обновление `README.md` (раздел запуск), `application-description.md` или `tables-system.md` при изменении схем, настоящая спецификация.
|
||||
|
||||
1641
docs.ru/back-docs/tables-system.md
Normal file
1641
docs.ru/back-docs/tables-system.md
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user