Классификатор опасного контента для детей

Этот проект представляет собой модель машинного обучения, предназначенную для автоматического определения потенциально опасного контента для детей в русскоязычных текстах. Модель классифицирует текст на две категории: safe (безопасный) и dangerous (опасный).

Система построена на двухкомпонентной архитектуре:

  1. Векторизация текста: Используется мощная модель Qwen/Qwen3-Embedding-4B для преобразования текста в числовые векторы (эмбеддинги), которые улавливают семантический смысл.
  2. Классификация: Поверх эмбеддингов работает простая и быстрая модель логистической регрессии, обученная различать "опасные" и "безопасные" векторы.

🎯 Назначение модели

Модель обучена выявлять следующие категории опасного контента на русском языке:

  1. Кибербуллинг и оскорбления: Прямые угрозы, унижения и травля в чатах.
  2. Опасные челленджи: Призывы к участию в рискованных для жизни и здоровья действиях.
  3. Жестокое обращение с животными: Тексты, оправдывающие или поощряющие насилие над животными.
  4. Пропаганда РПП: Контент, пропагандирующий нездоровое пищевое поведение (анорексия, булимия).
  5. Насилие и жестокость: Описание сцен насилия, нанесения увечий.

🛠️ Технический стек

  • Python 3.8+
  • PyTorch: для работы нейросетевой модели эмбеддингов.
  • Transformers (Hugging Face): для загрузки и использования модели Qwen.
  • Scikit-learn: для использования обученного классификатора логистической регрессии.
  • Joblib: для загрузки файла с классификатором.

🚀 Установка

  1. Клонируйте репозиторий:

    git clone https://huggingface.co/SlerpE/Dangerous_Content_Classifier
    cd Dangerous_Content_Classifier
    
  2. Создайте и активируйте виртуальное окружение:

    python -m venv venv
    source venv/bin/activate
    
  3. Установите зависимости:

    pip install -r requirements.txt
    
  4. Пример использования:

    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.

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support