Реализация AI-модерации контента (текст) в мобильном приложении
Текстовая модерация — обязательный компонент любого приложения с UGC: чат, комментарии, отзывы, описания. Без неё App Store Review Guideline 1.2 (User Generated Content) отклонит приложение или потребует немедленных изменений. Технически задача делится на клиентскую (базовую) и серверную (основную) модерацию.
Клиентская модерация: первая линия
На клиенте — быстрая проверка без сети. Цель: не допустить очевидные нарушения до отправки, снизить нагрузку на сервер.
Два инструмента на iOS:
-
NaturalLanguageframework сNLTaggerдля базового анализа тональности - Локальный список запрещённых слов (compiled regex)
import NaturalLanguage
class LocalTextModerator {
private let forbiddenPatterns: NSRegularExpression
init() {
// Паттерн компилируем один раз при инициализации
let patterns = ["слово1", "слово2"].joined(separator: "|")
forbiddenPatterns = try! NSRegularExpression(
pattern: "\\b(\(patterns))\\b",
options: [.caseInsensitive]
)
}
func quickCheck(_ text: String) -> ModerationResult {
let range = NSRange(text.startIndex..., in: text)
if forbiddenPatterns.firstMatch(in: text, range: range) != nil {
return .blocked(reason: .explicitContent)
}
return .passed
}
}
Список слов нельзя держать в бинарнике в открытом виде — ревьюеры Apple иногда проверяют. Лучше: зашифрованный список, расшифровывается при первом запуске, или загружается с сервера при инициализации.
Серверная модерация: основной слой
OpenAI Moderation API — бесплатный (на март 2025) и точный:
POST https://api.openai.com/v1/moderations
Authorization: Bearer <key>
{
"input": "текст для проверки",
"model": "omni-moderation-latest"
}
Ответ содержит categories и category_scores:
{
"results": [{
"flagged": false,
"categories": {
"hate": false,
"harassment": false,
"sexual": false,
"violence": false,
"self-harm": false
},
"category_scores": {
"hate": 0.0023,
"harassment": 0.0156,
"sexual": 0.0001
}
}]
}
Вызывать OpenAI Moderation с клиента нельзя — API ключ на клиенте. Всегда через backend-proxy.
Архитектура модерационного пайплайна
Пользователь вводит текст
↓
[Клиент] Локальная проверка (instant)
↓ прошёл
[Backend] OpenAI Moderation API (100–300 ms)
↓ прошёл
[Backend] Кастомные правила (regex, domain-specific)
↓ прошёл
Публикация контента
↓ параллельно
[Backend] Асинхронная повторная проверка (более дорогая модель)
Двухуровневая проверка: синхронная (для немедленного ответа) и асинхронная (для глубокого анализа). Асинхронный результат может привести к ретроактивному удалению.
Работа с пограничными случаями
OpenAI Moderation не даёт бинарный ответ — это вероятности. Нужна бизнес-логика для «серой зоны»:
// Android: обработка результатов модерации
fun evaluateModerationResult(result: ModerationResult): ContentDecision {
return when {
result.flagged -> ContentDecision.BLOCK
result.categoryScores["harassment"]!! > 0.7 -> ContentDecision.BLOCK
result.categoryScores["harassment"]!! > 0.3 -> ContentDecision.REQUIRE_REVIEW
result.categoryScores["sexual"]!! > 0.4 -> ContentDecision.REQUIRE_REVIEW
else -> ContentDecision.ALLOW
}
}
REQUIRE_REVIEW — контент попадает в очередь ручной модерации. Публикуется с задержкой или публикуется сразу, но с пониженной видимостью.
Мультиязычная модерация
OpenAI Moderation работает с русским языком, но качество на нестандартных формах (транслит, намеренные опечатки, leetspeak) — хуже. Дополнительный слой: нормализация текста перед проверкой.
func normalizeText(_ text: String) -> String {
var result = text.lowercased()
// Транслит к кириллице
let translitMap: [String: String] = ["a": "а", "e": "е", "o": "о", "p": "р", "c": "с"]
for (latin, cyrillic) in translitMap {
result = result.replacingOccurrences(of: latin, with: cyrillic)
}
// Удаляем повторяющиеся символы: "приивет" → "привет"
result = result.replacingOccurrences(of: "(.)\\1{2,}", with: "$1", options: .regularExpression)
return result
}
Проверяем как нормализованный, так и оригинальный текст.
Rate limiting и злоупотребления
Если модерация платная или дорогая — нужна защита от флуда:
- Rate limiting на backend: 20 публикаций/минуту на пользователя
- Shadowban: пользователь с историей нарушений проходит более строгую проверку автоматически
- Temporary block: при 3 нарушениях за 24 часа — временная блокировка публикаций
Логирование для аппеляций
Пользователи обжалуют блокировки. Нужно логировать: оригинальный текст, результат модерации, reason, timestamp, версию модели. Это также помогает улучшать пороги со временем.
Сроки
Backend с OpenAI Moderation + базовый клиентский фильтр — 2–3 дня. Полная система с пайплайном, ручной модерацией, нормализацией, аналитикой и аппеляциями — 2–3 недели. Стоимость рассчитывается индивидуально.







