Skip to main content
Documentación
CENTRO DE APRENDIZAJE

Domina la moderación de contenido con guías completas, tutoriales y documentación de API

Enlaces rápidos

Configuración de los umbrales de detección

Los umbrales de detección establecen el nivel de confianza con el que Discuse marca contenido, equilibrando los falsos positivos frente a los falsos negativos. En Discuse, estos umbrales son ajustes del proyecto configurados en el panel de control (o mediante la API de ajustes), y la solicitud de la API solo activa o desactiva las comprobaciones que se ejecutan; no incluye umbrales numéricos. Esta guía explica cómo funciona este equilibrio y cómo elegir valores adecuados para tu plataforma.

Cómo funcionan los umbrales de Discuse

Cada comprobación devuelve una puntuación de confianza de 0.0 a 1.0 y una marca hit. La marca hit se activa cuando la puntuación alcanza o supera el umbral que configuraste para esa categoría en tu proyecto. Los umbrales configurables son:

Umbral (configuración del proyecto) Se aplica a
threshold_sentiment Límite general para sentimiento negativo
threshold_toxicity Texto tóxico
threshold_profanity Lenguaje ofensivo
threshold_threat Amenazas
threshold_insult Insultos
threshold_spam Confianza del clasificador de spam
threshold_images Imágenes explícitas (general)
threshold_images_porn Imágenes pornográficas
threshold_images_sexual Imágenes sexualmente sugerentes

Estos son los nombres expuestos por la API de configuración del proyecto; el objeto settings de cada solicitud solo contiene interruptores check_* de activación/desactivación, además de expected_language. Los umbrales se cambian en el panel de control, no en cada solicitud.

El equilibrio

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

Visualización del equilibrio

                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

¿Qué umbrales convienen a cada plataforma?

Los valores siguientes son puntos de partida expresados con los nombres de umbral de Discuse (threshold_toxicity, threshold_images_porn, etc.). Tómalos como una referencia inicial que debes ajustar según tus propios datos de falsos positivos, no como cifras garantizadas. Un umbral más bajo marca contenido de forma más agresiva.

Plataformas de redes sociales

Las plataformas sociales de uso general necesitan una moderación equilibrada:

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
};

Plataformas profesionales / empresariales

Los contextos empresariales suelen requerir una moderación más estricta:

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
};

Comunidades de videojuegos

Las plataformas de videojuegos pueden tolerar más bromas y piques, sin dejar de ser estrictas con las amenazas reales:

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
};

Plataformas infantiles

Las plataformas para menores requieren la configuración más estricta:

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
};

¿Puedo variar los umbrales de forma dinámica?

Discuse almacena un conjunto de umbrales por proyecto, por lo que la variación por usuario o por contexto debe gestionarse en tu aplicación. Los patrones siguientes calculan un umbral efectivo de tu lado; luego puedes dirigir el contenido a distintos proyectos (cada uno con sus propios umbrales configurados) o aplicar tú mismo la comparación con las puntuaciones que devuelve Discuse.

Niveles de confianza del usuario

Ajusta los umbrales efectivos según la reputación del usuario:

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)
    ])
  );
}

Umbrales basados en el contexto

Los distintos tipos de contenido pueden necesitar umbrales diferentes:

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;
}

Ajustes basados en el tiempo

Ajusta los umbrales durante períodos de alto riesgo:

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);
}

Implementación de la configuración de umbrales

Configuración centralizada

// 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
  }
};

Actualizaciones de umbrales en tiempo de ejecución

Permite ajustar los umbrales sin volver a desplegar:

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);
  }
}

Medición de la eficacia de los umbrales

Métricas clave

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'
};

Umbrales de pruebas A/B

Prueba los cambios de umbral en un subconjunto del tráfico:

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;
}

Análisis de resultados

-- 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;

Flujo de ajuste de umbrales

Paso 1: Establecer una referencia inicial

// Start with conservative thresholds
const INITIAL_THRESHOLDS = {
  threshold_toxicity: 0.5,
  threshold_profanity: 0.5,
  threshold_spam: 0.6
};

Paso 2: Recopilar datos

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()
  });
}

Paso 3: Analizar las tasas de error

Revisa el contenido bloqueado y las apelaciones de los usuarios para identificar:

  • Falsos positivos: contenido seguro bloqueado incorrectamente
  • Falsos negativos: contenido dañino que no se detectó

Paso 4: Ajustar e iterar

// 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
};

Paso 5: Supervisar de forma continua

Configura alertas para la eficacia de los umbrales:

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');
  }
}

Resumen de buenas prácticas

  1. Empieza de forma conservadora: comienza con umbrales más estrictos y flexibilízalos según los datos.
  2. Usa el contexto: distintas superficies (publicaciones públicas, mensajes directos, perfiles) justifican umbrales diferentes.
  3. Los niveles de confianza importan: ajusta el umbral efectivo según la reputación del usuario en tu app.
  4. Mídelo todo: haz seguimiento de la precisión, la exhaustividad y el impacto en los usuarios.
  5. Itera continuamente: la moderación nunca está "terminada".
  6. Documenta las decisiones: lleva un registro de por qué cambiaron los umbrales.
  7. Ten alternativas: deriva los casos límite a revisión humana.

Recuerda: en Discuse, estos umbrales son ajustes del proyecto. Cámbialos en el panel de control o mediante la API de ajustes; el objeto settings por solicitud solo activa o desactiva qué check_* se ejecutan.

Próximos pasos

Escrito por Equipo de Discuse · Última actualización June 2026

Artículos relacionados

Guía de moderación de contenido con AI

Cómo el aprendizaje automático impulsa los sistemas modernos de moderación de contenido

Escalado de la moderación de contenido

Patrones de arquitectura para moderación de contenido de alto volumen