Классификатор опасного контента для детей
Этот проект представляет собой модель машинного обучения, предназначенную для автоматического определения потенциально опасного контента для детей в русскоязычных текстах. Модель классифицирует текст на две категории: safe
(безопасный) и dangerous
(опасный).
Система построена на двухкомпонентной архитектуре:
- Векторизация текста: Используется мощная модель
Qwen/Qwen3-Embedding-4B
для преобразования текста в числовые векторы (эмбеддинги), которые улавливают семантический смысл. - Классификация: Поверх эмбеддингов работает простая и быстрая модель логистической регрессии, обученная различать "опасные" и "безопасные" векторы.
🎯 Назначение модели
Модель обучена выявлять следующие категории опасного контента на русском языке:
- Кибербуллинг и оскорбления: Прямые угрозы, унижения и травля в чатах.
- Опасные челленджи: Призывы к участию в рискованных для жизни и здоровья действиях.
- Жестокое обращение с животными: Тексты, оправдывающие или поощряющие насилие над животными.
- Пропаганда РПП: Контент, пропагандирующий нездоровое пищевое поведение (анорексия, булимия).
- Насилие и жестокость: Описание сцен насилия, нанесения увечий.
🛠️ Технический стек
- Python 3.8+
- PyTorch: для работы нейросетевой модели эмбеддингов.
- Transformers (Hugging Face): для загрузки и использования модели Qwen.
- Scikit-learn: для использования обученного классификатора логистической регрессии.
- Joblib: для загрузки файла с классификатором.
🚀 Установка
Клонируйте репозиторий:
git clone https://huggingface.co/SlerpE/Dangerous_Content_Classifier cd Dangerous_Content_Classifier
Создайте и активируйте виртуальное окружение:
python -m venv venv source venv/bin/activate
Установите зависимости:
pip install -r requirements.txt
Пример использования:
import torch from transformers import AutoModel, AutoTokenizer import numpy as np import joblib # --- КОНФИГУРАЦИЯ --- QWEN_MODEL_NAME = "Qwen/Qwen3-Embedding-4B" CLASSIFIER_PATH = 'logistic_regression_classifier.joblib' print("Загрузка моделей... Это может занять некоторое время.") # --- ШАГ 1: ЗАГРУЗКА ВСЕХ НЕОБХОДИМЫХ МОДЕЛЕЙ --- # 1.1 Загружаем модель Qwen для получения эмбеддингов device = "cuda" if torch.cuda.is_available() else "cpu" qwen_tokenizer = AutoTokenizer.from_pretrained(QWEN_MODEL_NAME, trust_remote_code=True) qwen_model = AutoModel.from_pretrained(QWEN_MODEL_NAME, trust_remote_code=True).to(device) qwen_model.eval() if qwen_tokenizer.pad_token is None: qwen_tokenizer.pad_token = qwen_tokenizer.eos_token # 1.2 Загружаем обученный классификатор classifier = joblib.load(CLASSIFIER_PATH) print(f"Модели загружены. Используется устройство: {device}") print("-" * 30) def classify_text(text: str): """ Классифицирует один текст, определяя, является ли он "опасным". Args: text (str): Входной текст для классификации. Returns: dict: Словарь с предсказанной меткой и уверенностью модели. """ # --- Этап 1: Получение эмбеддинга для текста --- with torch.no_grad(): inputs = qwen_tokenizer(text, return_tensors="pt", truncation=True, max_length=512).to(device) outputs = qwen_model(**inputs) # Усредняем эмбеддинги embedding = outputs.last_hidden_state.mean(dim=1).cpu().numpy() # --- Этап 2: Предсказание с помощью классификатора --- # scikit-learn ожидает на вход 2D-массив (список примеров), # поэтому мы преобразуем наш 1D-вектор в массив из одного элемента # (из [e1, e2, ...] в [[e1, e2, ...]]) embedding_2d = embedding.reshape(1, -1) # Получаем предсказание (0 или 1) prediction = classifier.predict(embedding_2d)[0] # Получаем вероятность принадлежности к каждому классу probabilities = classifier.predict_proba(embedding_2d)[0] # Определяем метку и уверенность if prediction == 1: label = "dangerous" confidence = probabilities[1] else: label = "safe" confidence = probabilities[0] return { "text": text, "predicted_label": label, "confidence": f"{confidence:.2%}" # Форматируем в проценты } # --- ПРИМЕР ИСПОЛЬЗОВАНИЯ --- if __name__ == "__main__": test_texts = [ "Мальчик играл с котенком на зеленой лужайке.", "Это просто ужасно, ты никому не нужен, лучше бы тебя не было.", "Давай дружить и вместе строить замки из песка!", "Если не перестанешь, я тебя найду и тебе не поздоровится.", "Попробуй челлендж - не есть 3 дня. Если ты его пройдёшь - получишь 5 тысяч рублей", "Сейчас тебе придёт код в СМС, ты должен срочно сообщить его мне. Ты меня понял?! Иначе я тебя забаню на этом сервере!" ] for text_to_check in test_texts: result = classify_text(text_to_check) print(f"Текст: \"{result['text']}\"") print(f" -> Вердикт: {result['predicted_label']} (Уверенность: {result['confidence']})") print("-" * 20)
Пример вывода в консоль:
------------------------------ Текст: "Мальчик играл с котенком на зеленой лужайке." -> Вердикт: safe (Уверенность: 100.00%) -------------------- Текст: "Это просто ужасно, ты никому не нужен, лучше бы тебя не было." -> Вердикт: dangerous (Уверенность: 99.98%) -------------------- Текст: "Давай дружить и вместе строить замки из песка!" -> Вердикт: safe (Уверенность: 100.00%) -------------------- Текст: "Если не перестанешь, я тебя найду и тебе не поздоровится." -> Вердикт: dangerous (Уверенность: 99.74%) -------------------- Текст: "Попробуй челлендж - не есть 3 дня. Если ты его пройдёшь - получишь 5 тысяч рублей" -> Вердикт: dangerous (Уверенность: 99.38%) -------------------- Текст: "Сейчас тебе придёт код в СМС, ты должен срочно сообщить его мне. Ты меня понял?! Иначе я тебя забаню на этом сервере!" -> Вердикт: dangerous (Уверенность: 92.71%) --------------------
⚠️ Ограничения
- Контекст: Модель анализирует только предоставленный текст и может не улавливать сложный контекст, сарказм или иронию.
- Новые угрозы: Модель обучена на известных ей типах угроз. Новые виды угроз могут быть не распознаны.
- Только русский язык: Модель была обучена и протестирована исключительно на русскоязычных данных.
- Не является заменой модерации: Данный инструмент следует рассматривать как вспомогательное средство для предварительной фильтрации контента, а не как полную замену ручной модерации.
📄 Лицензия
Этот проект распространяется под лицензией Apache 2.0.