Большие языковые модели вроде DeepSeek, GPT-4 или Claude отлично справляются с общей задачей определения токсичности. Но когда речь заходит о специфике конкретной компании — внутреннем сленге, корпоративных нормах, контексте звонков клиентам — универсальные модели начинают ошибаться.
Представьте: оператор говорит клиенту «вы не правы» — это токсично или нет? В одной компании это допустимая прямота, в другой — нарушение стандартов. Универсальная модель не знает ваших стандартов. А маленькая специализированная модель на 0.5–1.5B параметров, обученная на ваших данных, — знает.
Ключевая идея: не нужно обучать модель с нуля. Достаточно взять готовую компактную модель и дообучить её на нескольких тысячах примеров из вашей компании. Это быстро, дёшево и точно.
Ваша идея с оператором, который нажимает «верно / не верно» — это классический паттерн Human-in-the-Loop (HITL) и Active Learning. Вот как выглядит полная схема:
DeepSeek выступает в роли «учителя» (teacher model) — он размечает данные автоматически. Ваша маленькая модель — «ученик» (student model) — учится на этих данных. Оператор исправляет ошибки, и цикл повторяется. Это называется knowledge distillation + active learning.
| Компонент | Инструмент | Зачем |
|---|---|---|
| Распознавание речи | Whisper / Vosk |
Перевод звонков в текст |
| Учитель | DeepSeek-V3 / GPT-4o |
Автоматическая разметка |
| Базовая модель | Qwen2.5-0.5B |
Основа для дообучения |
| Метод обучения | LoRA / QLoRA |
Экономия GPU-памяти |
| Библиотека | Unsloth / TRL |
Ускорение обучения в 2–5× |
| Деплой | vLLM / Ollama |
Инференс в продакшене |
Минимум 500–1000 записей для пилота. Идеально — 3000–5000 для стабильного результата. Записи должны покрывать разные сценарии: жалобы, конфликты, обычные разговоры.
Используйте openai/whisper-large-v3 или faster-whisper для локального запуска. Разбивайте длинные звонки на чанки по 30–60 секунд.
Промпт для учителя должен возвращать структурированный JSON с меткой и объяснением.
PROMPT = """Ты — эксперт по анализу токсичности в телефонных разговорах.
Оцени следующий фрагмент звонка оператора колл-центра.
Критерии токсичности:
- оскорбления, грубость, угрозы
- пассивная агрессия, унижение
- нарушение корпоративной этики
Верни JSON:
{{"toxic": true/false, "score": 0.0-1.0, "reason": "..."}}
Текст: {transcript}
"""
Важно: разметка от DeepSeek не идеальна. Именно поэтому в схеме есть оператор, который верифицирует спорные случаи. Не используйте авторазметку без проверки.
Для задачи классификации токсичности не нужна модель на 32B. Вот оптимальные варианты:
| Модель | Параметры | GPU для обучения | Комментарий |
|---|---|---|---|
Qwen2.5-0.5B |
0.5B | RTX 3090 / T4 | Лучший старт, очень быстрая |
Qwen2.5-1.5B |
1.5B | RTX 4090 / A10G | Баланс качества и скорости |
DeepSeek-R1-Distill-Qwen-1.5B |
1.5B | RTX 4090 / A10G | Уже умеет reasoning |
Llama-3.2-1B |
1B | RTX 3090 | Хорошая мультиязычность |
Рекомендация: начните с Qwen2.5-0.5B. Она обучается за минуты на одной GPU и уже показывает отличные результаты на узких задачах.
LoRA (Low-Rank Adaptation) — метод, который замораживает основные веса модели и обучает лишь небольшие дополнительные матрицы. Это снижает требования к памяти в 10–20 раз.
from unsloth import FastLanguageModel
import torch
# 1. Загружаем базовую модель
model, tokenizer = FastLanguageModel.from_pretrained(
model_name="Qwen/Qwen2.5-0.5B-Instruct",
max_seq_length=2048,
load_in_4bit=True, # QLoRA — ещё экономнее
)
# 2. Настраиваем LoRA
model = FastLanguageModel.get_peft_model(
model,
r=16, # ранг адаптера
lora_alpha=32,
lora_dropout=0.05,
target_modules=["q_proj", "k_proj", "v_proj", "o_proj"],
bias="none",
)
# 3. Тренировка
from trl import SFTTrainer
from transformers import TrainingArguments
trainer = SFTTrainer(
model=model,
tokenizer=tokenizer,
train_dataset=dataset, # ваш датасет
args=TrainingArguments(
per_device_train_batch_size=4,
gradient_accumulation_steps=4,
num_train_epochs=3,
learning_rate=2e-4,
fp16=not torch.cuda.is_bf16_supported(),
bf16=torch.cuda.is_bf16_supported(),
logging_steps=10,
output_dir="outputs",
),
)
trainer.train()
model.save_pretrained("toxic-classifier-lora")
Обучение на 1000 примеров займёт ~10–15 минут на NVIDIA T4 (бесплатно в Google Colab) или ~3–5 минут на RTX 4090.
[
{
"instruction": "Оцени токсичность звонка оператора.",
"input": "Клиент: Я жду уже 20 минут! Оператор: Успокойтесь, я вам не обязан помогать.",
"output": "{\"toxic\": true, \"score\": 0.85, \"reason\": \"Грубость и отказ в помощи\"}"
},
{
"instruction": "Оцени токсичность звонка оператора.",
"input": "Клиент: Спасибо за помощь! Оператор: Рад был помочь, хорошего дня!",
"output": "{\"toxic\": false, \"score\": 0.02, \"reason\": \"Вежливое завершение\"}"
}
]
Это самая ценная часть вашей идеи. Вместо того чтобы размечать тысячи случайных звонков, вы показываете оператору только те, где модель сомневается.
score близок к 0.5 — модель не уверена.┌─────────────────────────────────────────────┐
│ 🎧 Звонок #4821 [ 02:14 / 05:30 ] │
├─────────────────────────────────────────────┤
│ Транскрипт: │
│ "Клиент: Это уже третий раз! Оператор: │
│ Ну так обратитесь в другой отдел." │
├─────────────────────────────────────────────┤
│ 🤖 Модель: ТОКСИЧНО (score: 0.62) │
│ 💬 Причина: уклонение от помощи │
├─────────────────────────────────────────────┤
│ Ваша оценка: │
│ [ ✅ Верно ] [ ❌ Неверно ] │
│ │
│ Если неверно — выберите метку: │
│ ○ Токсично ○ Не токсично │
└─────────────────────────────────────────────┘
Эффект: active learning позволяет достичь 90%+ точности, используя всего 5–10% данных от того объёма, который понадобился бы при случайной разметке.
Для продакшена используйте vLLM — он даёт в 10–20 раз большую пропускную способность, чем стандартный HuggingFace pipeline.
# Запуск vLLM с LoRA-адаптером
python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen2.5-0.5B-Instruct \
--enable-lora \
--lora-modules toxic-classifier=./toxic-classifier-lora \
--port 8000
Теперь у вас есть OpenAI-совместимый API. Ваш бэкенд может отправлять транскрипты и получать JSON с оценкой токсичности.
| Метрика | Что показывает | Целевое значение |
|---|---|---|
| Precision | Точность срабатываний | > 0.85 |
| Recall | Полнота обнаружения | > 0.80 |
| F1-score | Баланс precision/recall | > 0.82 |
| Latency p95 | Скорость инференса | < 200 мс |
| Agreement с оператором | Совпадение с ручной оценкой | > 90% |
| Этап | Время | Ресурсы |
|---|---|---|
| Сбор 1000 звонков + ASR | 1–2 дня | Whisper на 1 GPU |
| Авторазметка через DeepSeek | 3–4 часа | API ~$10–20 |
| Первое дообучение LoRA | 15 минут | Google Colab T4 (free) |
| Настройка UI для оператора | 2–3 дня | Frontend-разработчик |
| Цикл active learning (2 недели) | 14 дней | Оператор 1–2 ч/день |
| Итого до MVP | ~3 недели | 1 GPU + 1 оператор |
Главный вывод: вам не нужны 32B параметров и кластер GPU. Маленькая модель 0.5B + 1000 качественных примеров + оператор в цикле = рабочее решение за 3 недели и минимальный бюджет.
Комментарии
Пока нет комментариев. Будьте первым!