Настройка порогов обнаружения
Пороги обнаружения задают уровень уверенности, при котором Discuse помечает контент, позволяя найти баланс между ложными срабатываниями и пропущенными нарушениями. В Discuse эти пороги являются настройками проекта, которые задаются в панели управления (или через API настроек), а запрос к API только включает или отключает нужные проверки — числовые значения порогов в нём не передаются. В этом руководстве объясняется, как работает этот компромисс и как выбрать подходящие значения для вашей платформы.
Как работают пороги Discuse
Каждая проверка возвращает оценку уверенности от 0.0 до 1.0 и флаг hit. Флаг hit устанавливается, когда оценка достигает порога, заданного для этой категории в вашем проекте, или превышает его. Настраиваемые пороги:
| Порог (настройка проекта) | К чему применяется |
|---|---|
threshold_sentiment |
Общая граница негативной тональности |
threshold_toxicity |
Токсичный текст |
threshold_profanity |
Нецензурная лексика |
threshold_threat |
Угрозы |
threshold_insult |
Оскорбления |
threshold_spam |
Уверенность классификатора спама |
threshold_images |
Откровенные изображения (в целом) |
threshold_images_porn |
Порнографические изображения |
threshold_images_sexual |
Изображения сексуального характера |
Именно эти названия доступны через API настроек проекта; объект settings в отдельном запросе содержит только переключатели включения/выключения check_*, а также expected_language. Пороги меняются в панели управления, а не для каждого запроса отдельно.
Компромисс
Lower Threshold = More Strict
├── More content flagged
├── Higher false positive rate
├── Fewer harmful posts slip through
└── More user friction
Higher Threshold = More Permissive
├── Less content flagged
├── Lower false positive rate
├── More harmful posts may slip through
└── Better user experience
Визуализация компромисса
False Positives ─────────────────────────►
Few Many
┌─────────────────────────────────────────┐
False Few │ ◄─── Ideal Zone │
Negatives │ (High threshold, │
│ low false rates) │
│ │ │
│ │ Your platform's │
│ │ optimal point → ● │
▼ │ │
Many │ Too permissive ──►│
└─────────────────────────────────────────┘
Threshold: 0.3 0.5 0.7 0.9
Какие пороги подходят для разных платформ?
Значения ниже — это отправные точки, выраженные через названия порогов в Discuse (threshold_toxicity, threshold_images_porn и так далее). Используйте их как базовый ориентир для дальнейшей настройки на основе собственных данных о ложных срабатываниях, а не как гарантированно точные значения. Чем ниже порог, тем строже срабатывает проверка.
Социальные платформы
Универсальным социальным платформам нужна сбалансированная модерация:
const SOCIAL_MEDIA_THRESHOLDS = {
threshold_toxicity: 0.7,
threshold_profanity: 0.6,
threshold_threat: 0.5, // Lower (stricter) for threats
threshold_insult: 0.7,
threshold_spam: 0.75,
threshold_images_porn: 0.6,
threshold_images_sexual: 0.8 // More permissive for suggestive content
};
Профессиональные и бизнес-платформы
В деловой среде обычно требуется более строгая модерация:
const PROFESSIONAL_THRESHOLDS = {
threshold_toxicity: 0.5,
threshold_profanity: 0.4,
threshold_threat: 0.3,
threshold_insult: 0.5,
threshold_spam: 0.6,
threshold_images_porn: 0.3,
threshold_images_sexual: 0.5
};
Игровые сообщества
Игровые платформы могут допускать больше дружеских подколов, но при этом должны строго реагировать на реальные угрозы:
const GAMING_THRESHOLDS = {
threshold_toxicity: 0.8,
threshold_profanity: 0.85, // Banter allowed
threshold_threat: 0.5, // Still strict on real threats
threshold_insult: 0.8,
threshold_spam: 0.8,
threshold_images_porn: 0.6,
threshold_images_sexual: 0.9
};
Детские платформы
Платформам для несовершеннолетних нужны самые строгие настройки:
const CHILDRENS_THRESHOLDS = {
threshold_toxicity: 0.3,
threshold_profanity: 0.2,
threshold_threat: 0.2,
threshold_insult: 0.3,
threshold_spam: 0.5,
threshold_images_porn: 0.1, // Maximum strictness
threshold_images_sexual: 0.2
};
Можно ли динамически менять пороги?
Discuse хранит один набор порогов для каждого проекта, поэтому вариативность по пользователям или контексту должна обрабатываться в вашем приложении. В приведённых ниже шаблонах эффективный порог рассчитывается на вашей стороне; затем вы либо направляете запросы в разные проекты (у каждого из которых настроены свои пороги), либо самостоятельно выполняете сравнение с оценками, которые возвращает Discuse.
Уровни доверия пользователей
Настраивайте эффективные пороги с учётом репутации пользователя:
function getThresholds(user) {
const baseThresholds = PLATFORM_THRESHOLDS;
const trustMultipliers = {
new_user: 0.8, // Stricter (lower effective threshold)
basic_user: 1.0, // Standard
verified_user: 1.15, // Slightly more permissive
trusted_user: 1.3, // More permissive
moderator: 1.5 // Most permissive
};
const multiplier = trustMultipliers[user.trustLevel] || 1.0;
return Object.fromEntries(
Object.entries(baseThresholds).map(([key, value]) => [
key,
typeof value === 'number'
? Math.min(value * multiplier, 0.95)
: adjustNestedThresholds(value, multiplier)
])
);
}
Пороги с учётом контекста
Для разных типов контента могут потребоваться разные пороги:
const CONTEXT_THRESHOLDS = {
// Public posts visible to everyone
public_post: {
toxic: 0.6,
profanity: 0.5
},
// Direct messages between users
direct_message: {
toxic: 0.7, // Slightly more permissive
profanity: 0.6
},
// Comments on public content
comment: {
toxic: 0.55, // Stricter than posts
profanity: 0.5
},
// Profile information
profile: {
toxic: 0.5, // Strict for public-facing content
profanity: 0.4
}
};
function getContextThresholds(contentType) {
return CONTEXT_THRESHOLDS[contentType] || CONTEXT_THRESHOLDS.public_post;
}
Корректировки по времени
Корректируйте пороги в периоды повышенного риска:
function getTimeAdjustedThresholds(baseThresholds) {
const hour = new Date().getHours();
const dayOfWeek = new Date().getDay();
// Stricter during off-hours when fewer moderators available
const isOffHours = hour < 6 || hour > 22;
const isWeekend = dayOfWeek === 0 || dayOfWeek === 6;
let multiplier = 1.0;
if (isOffHours) multiplier *= 0.85;
if (isWeekend) multiplier *= 0.9;
return adjustThresholds(baseThresholds, multiplier);
}
Реализация настройки порогов
Централизованная конфигурация
// config/moderation.js — mirrors your Discuse project thresholds so app-side
// routing stays in sync with the values configured in the dashboard.
export const ModerationConfig = {
thresholds: {
threshold_toxicity: parseFloat(process.env.THRESHOLD_TOXICITY || '0.7'),
threshold_profanity: parseFloat(process.env.THRESHOLD_PROFANITY || '0.6'),
threshold_threat: parseFloat(process.env.THRESHOLD_THREAT || '0.5'),
threshold_insult: parseFloat(process.env.THRESHOLD_INSULT || '0.7'),
threshold_spam: parseFloat(process.env.THRESHOLD_SPAM || '0.75'),
threshold_images_porn: parseFloat(process.env.THRESHOLD_IMAGES_PORN || '0.6'),
threshold_images_sexual: parseFloat(process.env.THRESHOLD_IMAGES_SEXUAL || '0.8')
},
actions: {
high_confidence: 'auto_block', // score > 0.95
medium_confidence: 'human_review', // 0.7 - 0.95
low_confidence: 'allow_with_flag' // threshold - 0.7
}
};
Обновление порогов во время выполнения
Разрешите изменять пороги без повторного развертывания:
class ModerationService {
constructor() {
this.thresholds = defaultThresholds;
this.loadRemoteConfig();
}
async loadRemoteConfig() {
try {
const config = await fetch('/api/admin/moderation-config');
const data = await config.json();
this.thresholds = data.thresholds;
console.log('Loaded remote moderation config');
} catch (error) {
console.warn('Using default thresholds:', error);
}
}
async checkContent(content, context) {
const result = await callModerationAPI(content);
const thresholds = this.getThresholdsForContext(context);
return this.applyThresholds(result, thresholds);
}
}
Оценка эффективности пороговых значений
Ключевые метрики
const MODERATION_METRICS = {
// Accuracy
precision: 'True positives / (True positives + False positives)',
recall: 'True positives / (True positives + False negatives)',
f1_score: 'Harmonic mean of precision and recall',
// User impact
block_rate: 'Content blocked / Total content',
appeal_rate: 'Appeals filed / Content blocked',
appeal_success: 'Appeals won / Appeals filed',
// Operational
review_queue_size: 'Items waiting for human review',
review_time: 'Average time to human decision'
};
A/B-тестирование пороговых значений
Проверяйте изменения порогов на части трафика:
async function moderateWithExperiment(content, userId) {
const experiment = getExperiment(userId, 'threshold_test');
const thresholds = experiment === 'control'
? CURRENT_THRESHOLDS
: EXPERIMENTAL_THRESHOLDS;
const result = await checkContent(content);
const decision = applyThresholds(result, thresholds);
// Log for analysis
await logExperiment({
experiment: 'threshold_test',
variant: experiment,
content_id: content.id,
scores: result,
decision: decision,
timestamp: Date.now()
});
return decision;
}
Анализ результатов
-- Calculate precision and recall for each threshold variant
SELECT
variant,
COUNT(*) as total_decisions,
SUM(CASE WHEN blocked AND actually_harmful THEN 1 ELSE 0 END) as true_positives,
SUM(CASE WHEN blocked AND NOT actually_harmful THEN 1 ELSE 0 END) as false_positives,
SUM(CASE WHEN NOT blocked AND actually_harmful THEN 1 ELSE 0 END) as false_negatives,
SUM(CASE WHEN blocked AND actually_harmful THEN 1 ELSE 0 END) * 1.0 /
NULLIF(SUM(CASE WHEN blocked THEN 1 ELSE 0 END), 0) as precision,
SUM(CASE WHEN blocked AND actually_harmful THEN 1 ELSE 0 END) * 1.0 /
NULLIF(SUM(CASE WHEN actually_harmful THEN 1 ELSE 0 END), 0) as recall
FROM moderation_decisions
WHERE experiment = 'threshold_test'
GROUP BY variant;
Рабочий процесс настройки порогов
Шаг 1: Задайте базовые значения
// Start with conservative thresholds
const INITIAL_THRESHOLDS = {
threshold_toxicity: 0.5,
threshold_profanity: 0.5,
threshold_spam: 0.6
};
Шаг 2: Соберите данные
async function logModerationDecision(content, result, decision) {
await db.insert('moderation_log', {
content_id: content.id,
content_hash: hashContent(content.text),
scores: result.results,
thresholds_used: currentThresholds,
decision: decision,
user_trust_level: content.author.trustLevel,
created_at: Date.now()
});
}
Шаг 3: Проанализируйте долю ошибок
Просмотрите заблокированный контент и обращения пользователей, чтобы выявить:
- Ложные срабатывания: безопасный контент был ошибочно заблокирован
- Пропуски: вредоносный контент, который не удалось обнаружить
Шаг 4: Скорректируйте настройки и повторите
// Based on analysis, raise thresholds that fire too often
const ADJUSTED_THRESHOLDS = {
threshold_toxicity: 0.65, // Raised after false positives
threshold_profanity: 0.55,
threshold_spam: 0.7
};
Шаг 5: Ведите постоянный мониторинг
Настройте оповещения об эффективности порогов:
async function checkModerationHealth() {
const stats = await getModerationStats(last24Hours);
// Alert if false positive rate too high
if (stats.appealSuccessRate > 0.3) {
alert('High appeal success rate - thresholds may be too strict');
}
// Alert if harmful content is getting through
if (stats.reportedAfterApproval > threshold) {
alert('Increase in reported content - thresholds may be too permissive');
}
}
Краткое изложение лучших практик
- Начинайте консервативно: сперва задайте более строгие пороги и ослабляйте их на основе данных.
- Учитывайте контекст: разные поверхности (публичные публикации, личные сообщения, профили) требуют разных порогов.
- Уровни доверия важны: корректируйте фактический порог с учетом репутации пользователя в вашем приложении.
- Измеряйте всё: отслеживайте точность, полноту и влияние на пользователей.
- Постоянно улучшайте: модерация никогда не бывает «завершена».
- Документируйте решения: ведите записи о том, почему менялись пороги.
- Предусмотрите запасные варианты: направляйте пограничные случаи на проверку модератором.
Помните: в Discuse эти пороги задаются в настройках проекта. Изменяйте их в панели управления или через API настроек; объект settings в отдельном запросе лишь включает или отключает выполнение проверок check_*.
Следующие шаги
- Руководство по модерации контента с помощью AI - Как работает AI-модерация
- Масштабирование модерации контента - Реализация при больших объёмах
- Анализ текста - Подробности модерации текста