Skip to main content

ADOLF KNOWLEDGE — Раздел 5: KB Management

Проект: Корпоративная база знаний с RAG
Модуль: Knowledge / KB Management
Версия: 1.1
Дата: Январь 2026

5.1. Управление базой знаний

Операции с документами

ОперацияОписаниеКто выполняет
ЗагрузкаДобавление документа в KBSenior, Admin
ОбновлениеЗамена версии документаSenior, Admin
УдалениеУдаление из KBAdmin
МодерацияПроверка перед публикациейSenior

Workflow загрузки


5.2. Загрузка документов

Способы загрузки

СпособОписаниеАвтоматизация
SFTP /inboxКопирование файла в папкуПолная (ETL Daemon)
Web InterfaceЗагрузка через Open WebUIПолуавтоматическая

Структура директорий

/data/
├── inbox/           # Входящие файлы
├── processing/      # В обработке
├── archive/         # Обработанные исходники
├── quarantine/      # Ошибки валидации
└── converted/       # Готовые .md файлы

ETL Daemon

ПараметрЗначение
Интервал проверки30 секунд
ОбработкаПоследовательная
УведомленияПри ошибках

5.3. Модерация документов

Трёхуровневая валидация

УровеньЧто проверяетАвтоматизация
1Формат, размер, кодировкаАвтоматически
2category, access_level, brand_idAI + правила
3Содержание, корректностьРучная (Senior)

Требования к модерации

Документы требуют модерации Senior если:
  • access_level >= senior
  • category = contract или finance
  • Автоклассификатор не уверен (confidence < 0.8)

API модерации

# Endpoints для модерации
POST /api/v1/knowledge/documents/{id}/approve  # Одобрить
POST /api/v1/knowledge/documents/{id}/reject   # Отклонить
GET  /api/v1/knowledge/documents/pending       # Список на модерацию

5.4. Метаданные в PostgreSQL

Таблица documents

-- Хранение метаданных документов
CREATE TABLE documents (
    id SERIAL PRIMARY KEY,
    filename VARCHAR(255) NOT NULL,
    title VARCHAR(255) NOT NULL,
    category VARCHAR(50) NOT NULL,
    access_level VARCHAR(20) NOT NULL,
    brand_id VARCHAR(50) NOT NULL,
    status VARCHAR(20) DEFAULT 'pending',
    kb_file_id VARCHAR(100),       -- ID в Timeweb KB
    uploaded_by INT REFERENCES users(id),
    moderated_by INT REFERENCES users(id),
    version INT DEFAULT 1,
    file_size_bytes INT,
    original_format VARCHAR(10),
    created_at TIMESTAMP DEFAULT NOW(),
    moderated_at TIMESTAMP,
    indexed_at TIMESTAMP
);

Статусы документов

СтатусОписание
pendingОжидает модерации
approvedОдобрен
rejectedОтклонён
indexedЗагружен в KB
quarantineВ карантине

5.5. Интеграция с Timeweb KB

API Timeweb KB

ОперацияEndpointМетод
Загрузка файла/api/knowledge/uploadPOST
Удаление файла/api/knowledge/files/{id}DELETE
Список файлов/api/knowledge/filesGET
Поиск/api/knowledge/searchPOST

Загрузка документа

async def upload_to_kb(file_path: str, metadata: dict) -> str:
    """Загрузка документа в Timeweb KB."""
    
    with open(file_path, 'rb') as f:
        files = {'file': (os.path.basename(file_path), f, 'text/markdown')}
        
        response = await kb_client.post(
            '/api/knowledge/upload',
            files=files,
            data={'metadata': json.dumps(metadata)}
        )
    
    return response.json()['file_id']

5.6. Версионирование

Политика версий

АспектРешение
Хранение версийТолько последняя версия в KB
ИсторияМетаданные в PostgreSQL
ОткатРучной (Admin)

Обновление документа


5.7. Карантин

Причины попадания в карантин

ПричинаДействие
Неподдерживаемый форматРучная конвертация
Размер > 50 МБРазбиение на части
Ошибка OCRРучной ввод текста
Ошибка классификацииРучная классификация
Невалидная кодировкаКонвертация кодировки

Таблица quarantine

CREATE TABLE quarantine (
    id SERIAL PRIMARY KEY,
    filename VARCHAR(255) NOT NULL,
    file_path VARCHAR(500),
    error_type VARCHAR(50),
    error_message TEXT,
    created_at TIMESTAMP DEFAULT NOW(),
    resolved_at TIMESTAMP,
    resolved_by INT REFERENCES users(id)
);

5.8. Политика хранения

Retention Policy

Тип данныхСрок хранения
Документы в KBБессрочно
Исходники в archive90 дней
Карантин30 дней
МетаданныеБессрочно

Очистка

# Celery task: cleanup_archive (еженедельно)
@shared_task
def cleanup_archive():
    """Удаление старых исходников из archive."""
    cutoff = datetime.now() - timedelta(days=90)
    
    for file in Path('/data/archive').iterdir():
        if file.stat().st_mtime < cutoff.timestamp():
            file.unlink()

5.9. Мониторинг KB

Метрики

МетрикаОписание
Количество документовВсего в KB
Документов на модерацииОжидают проверки
В карантинеТребуют внимания
Загрузок за деньАктивность

Dashboard запросы

-- Статистика по документам
SELECT 
    status,
    COUNT(*) as count
FROM documents
GROUP BY status;

-- Документы по категориям
SELECT 
    category,
    COUNT(*) as count
FROM documents
WHERE status = 'indexed'
GROUP BY category;

Документ подготовлен: Январь 2026
Версия: 1.1
Статус: Согласовано