SISTEMA DE REPUTACIÓN DE COMENTARIOS CON VALIDACIÓN DE REFERENCIAS (borrador)

ARQUITECTURA CON ANONIMIZACIÓN Y ALTA DISPONIBILIDAD

1. INTRODUCCIÓN Y OBJETIVOS

Esto es un borrador, no es saltarse pasos, es para dar un ejemplo formado y con un analisis bastante general y bien acotado para que la propuesta no se vea solo humo.

El sistema es un agregador de reputación externo que se integra con un agregador de noticias existente. Su objetivo es asignar autoridad a los comentarios basándose en:

  • El prestigio histórico del usuario que comenta (almacenado de forma anonimizada).
  • La calidad/fiabilidad de los dominios que el usuario cita como referencias (almacenados de forma anonimizada).
  • La coherencia argumentativa entre el comentario y las referencias proporcionadas (validación asíncrona en horas de baja carga).

Las referencias son opcionales, pero los comentarios que las incluyen obtienen mayor visibilidad y peso frente a los que no (los "cuñados").

1.1. Requisitos clave

  • Anonimización: Los identificadores de usuarios y dominios se almacenan con hash (SHA-256 + salt) o cifrado (AES-256) para que no se pueda asociar el peso con la identidad real, evitando manipulaciones externas.
  • Escalabilidad: Sistema diseñado para millones de peticiones al mes (cientos por segundo).
  • Rendimiento: Todo el stack en Rust para minimizar recursos y latencia.
  • Validación asíncrona: La verificación de coherencia (IA) se ejecuta en horas de baja carga, no en el momento de la publicación.
  • Alta disponibilidad: Sin punto único de fallo, con replicación y balanceo.

2. ARQUITECTURA GENERAL

⎗
✓
┌─────────────────────────────────────────────────────────────────────────────┐
│                          AGREGADOR DE NOTICIAS (Externo)                    │
│                                                                             │
│   Usuario → Comentario + Referencias (opcionales) → Formulario             │
└────────────────────────────────┬────────────────────────────────────────────┘
                                 │ HTTP POST (JSON)
                                 ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                    SERVICIO CENTRAL (API GATEWAY) — APP A                   │
│                                                                             │
│  Tecnología: Rust                              │
│  Instancias: 3-5 réplicas detrás de balanceador de carga    │
│                                                                             │
│  Funciones:                                                                 │
│  1. Recibe el comentario y valida formato                                  │
│  2. Extrae dominios de las referencias                                     │
│  3. Calcula hash(usuario) y hash(dominios) con salt                        │
│  4. Consulta BD (por hash): prestigio de dominios y del usuario           │
│  5. Asigna peso por defecto (0.3/10) a dominios no calificados            │
│  6. Calcula peso inicial del comentario (síncrono)                        │
│  7. NO persiste el comentario en BD (solo lo enriquece)                   │
│  8. Devuelve respuesta inmediata al usuario (mismo mensaje + metadatos)   │
│  9. ENCOLA tareas asíncronas en RabbitMQ (solo para mejoras)              │
└─────────────────────────────┬───────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                    COLA DE MENSAJERÍA (RabbitMQ o Kafka)                    │
│                                                                             │
│  Exchange 1: domain.ranking (direct)                                       │
│    → Queue: rank_domains (durable)                                         │
│    → Routing key: "rank"                                                   │
│                                                                             │
│  Exchange 2: content.validation (direct)                                   │
│    → Queue: validate_comments (durable)                                    │
│    → Routing key: "validate"                                               │
│                                                                             │
│  Alta disponibilidad: Cluster de 3 nodos RabbitMQ o servicio gestionado   │
│  (CloudAMQP, AWS MQ)                                                       │
└─────────────────┬─────────────────────┬─────────────────────────────────────┘
                  │                     │
                  ▼                     ▼
┌─────────────────────────────────┐ ┌─────────────────────────────────────────┐
│   APP B: RANKER (Workers N)     │ │   APP C: JUEZ IA (Workers N)           │
│                                 │ │                                         │
│  Tecnología: Rust + reqwest     │ │  Tecnología: Rust + ollama-rs (cliente)│
│  + scraper (HTML) + sqlx        │ │  + reqwest + trafilatura (FFI o        │
│  (PostgreSQL)                    │ │  llamado externo)                      │
│                                 │ │                                         │
│  Escalabilidad: 10-30 workers   │ │  Escalabilidad: 20-100 workers         │
│  en paralelo                    │ │  en paralelo (ejecución en horas        │
│                                 │ │  de baja carga, ej: nocturno)          │
│                                 │ │                                         │
│  Funciones:                     │ │  Funciones:                              │
│  1. Consume cola rank_domains   │ │  1. Consume cola validate_comments      │
│  2. Obtiene prestigio de        │ │     (programado para baja carga)        │
│     dominio usando fuentes      │ │  2. Extrae contenido de referencias     │
│     gratuitas (webrank,         │ │  3. Llama a IA local (Ollama)           │
│     Wikipedia, Crawly, etc.)    │ │  4. Evalúa coherencia                   │
│  3. Actualiza BD (por hash)     │ │  5. Actualiza prestigio del usuario     │
│     con resultado               │ │     (hash + incremento/decremento)     │
│  4. Dispara recalculo de        │ │  6. Guarda veredicto y log              │
│     comentarios (opcional)      │ │                                         │
└─────────────────────────────────┘ └─────────────────────────────────────────┘

3. DESCRIPCIÓN DETALLADA DE COMPONENTES

3.1. APP A: API Gateway (Servicio Central)

Tecnología: Rust + Actix Web (o Axum) + Tokio + serde + sqlx + sha2 + aes-gcm.

Instancias: 3-5 réplicas (mínimo 3 para alta disponibilidad) detrás de balanceador de carga.

Proceso Síncrono (por cada petición):

Paso Acción Detalle Técnico
1 Validar entrada Sanear texto, validar formato de URLs con crate url.
2 Extraer dominios Parsear URLs con url::Url y extraer dominio raíz usando crate domain o split manual.
3 Anonimizar identificadores Calcular SHA-256(usuario_id + salt) y SHA-256(dominio + salt) con salt rotado (guardado en variable de entorno). Almacenar en BD solo los hashes.
4 Consultar prestigio de dominios SELECT prestige_score, status FROM domain_prestige WHERE domain_hash = $1.
5 Asignar peso por defecto Si status = 'PENDING' o no existe → prestige_score = 0.3, status = 'PENDING_RANKING'.
6 Consultar prestigio del usuario SELECT prestige_score FROM users WHERE user_hash = $1. Si nuevo → 5.0.
7 Calcular peso del comentario weight = (user_prestige * 0.4) + (avg_domain_prestige * 0.6). Si no hay referencias → solo user_prestige * 0.5.
8 (NO persistir) El gateway NO guarda el comentario en BD. Solo lo procesa y enriquece.
9 Encolar tareas asíncronas (solo para mejoras) Publicar mensajes en RabbitMQ usando crate lapin o rmq con: comment_hash, user_hash, domain_hashes, text, urls.
10 Devolver respuesta JSON con el mismo mensaje original + campos añadidos: weight, domains_status (hash → status), validation_status = 'PENDING', user_prestige (anonimizado), domain_prestiges (hash → score).

Endpoints:

  • POST /api/v1/comments → Recibe comentario + referencias, devuelve el mismo comentario enriquecido con metadatos (peso, prestigios, flags). No persiste.
  • GET /api/v1/users/{user}/prestige → Obtener prestigio de un usuario (calculando hash y buscando).
  • GET /api/v1/domains/{domain}/prestige → Obtener prestigio de un dominio (calculando hash y buscando).

Seguridad :

  • El salt se genera random al lanzar la aplicación y se persiste en memoria, no en BD.
    Opcional:
    ++ incrementa costes de computacion pero aumenta la anonimización
  • El salt se rota diariamente y se almacena en memoria (no en BD). Los hashes antiguos se mantienen para auditoría y recuperación en memoria y encryptados.
  • cifrado AES-256 de los hashes si se requiere mayor anonimización.

3.2. APP B: RANKER (Mejorador de Prestigio de Dominios)

Tecnología: Rust + reqwest (cliente HTTP) + scraper (para HTML) + sqlx (PostgreSQL) + tokio (async).

Instancias: 10-30 workers en paralelo (pueden ejecutarse en máquinas diferentes). Cada worker consume de la cola rank_domains.

Proceso Asíncrono (consumiendo cola):

Paso Acción Detalle Técnico
1 Consumir mensaje Obtener { "domain_hash": "abc123", "domain": "elmundo.es", "comment_hash": "..." }.
2 Verificar si ya está en proceso Usar Redis lock (crate redis-rs) para evitar duplicados.
3 Obtener prestigio del dominio Utilizar fuentes gratuitas en orden de prioridad (ver sección 3.2.1).
4 Calcular prestige_score Normalizar métricas a escala 0-10. Fórmula: (webrank * 0.3) + (wikipedia_presence * 0.2) + (age * 0.1) + (user_votes * 0.2) + (backlinks_estimate * 0.2).
5 Actualizar BD (por hash) UPDATE domain_prestige SET prestige_score = $1, status = 'RANKED', last_ranked_at = NOW(), api_data = $2 WHERE domain_hash = $3.
6 (Opcional) Recalcular comentarios Si el cambio de prestigio es significativo (>2 puntos), encolar recalculo de comentarios antiguos (cola recalculate_comments).

3.2.1. Fuentes Gratuitas para Prestigio de Dominio (Prioridad)

Prioridad Fuente Descripción Límites Implementación en Rust
1 webrank Rango de autoridad open-source (alternativa a Tranco). Sin límite, auto-hospedado. Cliente HTTP a instancia local.
2 Wikipedia API Presencia en artículos de Wikipedia. 10.000 peticiones/día. reqwest + serde_json.
3 Common Crawl + danker PageRank sobre grafo de Common Crawl. Auto-hospedado. Llamada a servicio interno.
4 Crawly API (gratuita) Domain Authority, backlinks, spam score. 100 peticiones/día. reqwest con API key.
5 Apify (gratuito) "Website Traffic & Domain Authority Checker". 1.000 peticiones/mes. reqwest con API key.
6 Scraping de herramientas gratuitas Scraping de Ahrefs/Moz gratis. Sin límite, requiere control de IPs. scraper + reqwest con rotación de User-Agent.
7 Votos de usuarios Sistema crowdsourcing. Sin límite. Consulta a BD user_votes.

Estrategia de prioridad en Rust:

⎗
✓
async fn get_domain_prestige(domain: &str) -> Result<f32, Error> {
    // 1. Webrank local
    if let Ok(prestige) = get_webrank(domain).await { return Ok(prestige); }
    // 2. Wikipedia
    if let Ok(prestige) = get_wikipedia_references(domain).await { return Ok(prestige); }
    // 3. Crawly (con límite diario)
    if let Ok(prestige) = get_crawly(domain).await { return Ok(prestige); }
    // 4. Apify
    if let Ok(prestige) = get_apify(domain).await { return Ok(prestige); }
    // 5. Scraping
    if let Ok(prestige) = scrape_ahrefs_free(domain).await { return Ok(prestige); }
    // 6. Fallback
    Ok(0.3)
}

3.3. APP C: JUEZ IA (Validador de Coherencia)

Tecnología: Rust + ollama-rs (cliente HTTP) + reqwest (scraping) + sqlx (PostgreSQL) + tokio.

Instancias: 20-100 workers en paralelo, programados para ejecutarse en horas de baja carga (ej: 00:00 - 06:00) para no saturar el sistema.

Proceso Asíncrono (consumiendo cola):

Paso Acción Detalle Técnico
1 Consumir mensaje Obtener { "comment_hash": "abc123", "user_hash": "def456", "text": "...", "urls": ["..."] }.
2 Extraer contenido de referencias Para cada URL, hacer GET con timeout (5s) usando reqwest, extraer texto limpio con trafilatura (llamada FFI o ejecutable externo) o readability (crate readability en Rust). Cachear en Redis (crate redis-rs) por URL con TTL 24h.
3 Construir prompt Utilizar el prompt detallado en sección 3.3.1.
4 Llamar a IA local (Ollama) Usar ollama-rs para POST /api/generate con modelo especializado (ej: llama3.2:3b o mistral:7b).
5 Interpretar respuesta Parsear JSON con serde_json: { "verdict": "COHERENT" | "INCOHERENT" | "UNCLEAR" | "SKIP", "confidence": 0.92, ... }.
6 Actualizar prestigio del usuario (anonimizado) Si verdict = 'COHERENT' → user_prestige += 2 (usando hash); si 'INCOHERENT' → user_prestige -= 3; si 'UNCLEAR' → sin cambios.
7 Guardar log INSERT INTO validation_logs (comment_hash, verdict, confidence, ia_model, tokens_input, tokens_output, cost, created_at) VALUES (...).
8 (Opcional) Actualizar comentario Si se persistiera, se actualizaría validation_status = 'COMPLETED'. En este diseño, no se persiste el comentario, solo el log y el prestigio del usuario.

3.3.1. Prompt para la IA (Versión Final)

⎗
✓
Eres un Juez de Veracidad especializado en verificar si un argumento está respaldado por sus fuentes.

### TEXTO DEL USUARIO:
{user_text}

### REFERENCIAS PROPORCIONADAS:
{references_content}

### INSTRUCCIONES:
1. Analiza si el argumento principal del usuario se corresponde con lo que dicen las fuentes.
2. Detecta si el usuario:
   - Saca de contexto frases para apoyar su tesis.
   - Omite información relevante que contradice su argumento.
   - Inventa datos que no aparecen en las fuentes.
   - Utiliza fuentes que no tienen relación con el tema.
3. Si el usuario NO ha proporcionado referencias, responde "SKIP".

### FORMATO DE RESPUESTA (JSON estricto):
{
  "verdict": "COHERENT" | "INCOHERENT" | "UNCLEAR" | "SKIP",
  "confidence": 0.0-1.0,
  "explanation": "Breve explicación de tu decisión (máx 2 frases)",
  "key_quote": "Si es INCOHERENT, cita la frase del usuario que contradice la fuente"
}

### REGLAS IMPORTANTES:
- Sé objetivo. No juzgues la opinión, solo la correspondencia con las fuentes.
- Si las fuentes son de baja calidad (blogs personales, foros), indícalo en confidence.
- Si el usuario argumenta sin fuentes, es SKIP (no penalizar).

4. ANONIMIZACIÓN Y SEGURIDAD

4.1. Almacenamiento de identificadores

  • Usuarios: user_hash = SHA-256(user_id + salt) donde salt se genera al instanciar la app y se almacena en memoria (no en BD). El user_id original nunca se guarda.
  • Dominios: domain_hash = SHA-256(domain + salt). El dominio original solo se usa para scraping (APP B), pero nunca se persiste asociado al hash.
  • Comentarios: comment_hash = SHA-256(user_hash + timestamp + nonce) para identificar de forma única el comentario en logs sin guardar el texto completo.

4.2. Protección contra manipulación

  • Salt rotatorio: Si un atacante obtiene acceso a la BD, no puede asociar pesos a dominios/usuarios sin el salt actual.
  • Auditoría: Los hashes antiguos se mantienen por 30 días para auditoría interna (sin posibilidad de desencriptar).
  • Cifrado adicional (opcional): Si se requiere mayor seguridad, los hashes pueden cifrarse con AES-256-GCM usando una clave maestra rotada anualmente.

4.3. Flujo de anonimización en la API

  1. El cliente envía user_id y domains (en claro) en la petición.
  2. El gateway calcula los hashes en memoria.
  3. La BD solo almacena y devuelve datos asociados a hashes.

5. FLUJO COMPLETO CON EJEMPLO

Escenario: Usuario "Juan" (ID real: user-123) comenta en el agregador:

"El cambio climático es el mayor desafío de nuestra era, como demuestra el último informe de la ONU."

Referencias: https://www.un.org/en/climatechange/reports

Proceso:

Paso 1: APP A (Gateway) — Síncrono

  1. Recibe petición: { user_id: "user-123", text: "...", urls: ["https://..."] }
  2. Calcula hashes:
    • user_hash = SHA-256("user-123" + salt_diario) = "abc123..."
    • domain_hash = SHA-256("un.org" + salt_diario) = "def456..."
  3. Consulta BD:
    • user_prestige para abc123 → 6.0
    • domain_prestige para def456 → no existe → 0.3, status = 'PENDING_RANKING'
  4. Calcula peso: (6.0 * 0.4) + (0.3 * 0.6) = 2.58
  5. Encola:
    • rank_domains: { "domain_hash": "def456", "domain": "un.org", "comment_hash": "xyz..." }
    • validate_comments: { "comment_hash": "xyz...", "user_hash": "abc123", "text": "...", "urls": ["..."] }
  6. Devuelve respuesta:
    ⎗
    ✓
    1
    2
    3
    4
    5
    6
    7
    {
      "text": "El cambio climático...",
      "urls": ["https://www.un.org/..."],
      "weight": 2.58,
      "domains_status": { "www.un.org": "PENDING_RANKING" },
      "validation_status": "PENDING"
    }
    

Paso 2: APP B (Ranker) — Worker 3 (asíncrono, tras segundos/minutos)

  1. Consume rank_domains → obtiene domain = "un.org", domain_hash = "def456".
  2. Obtiene prestigio:
    • Webrank: no disponible.
    • Wikipedia API: 150 referencias → prestige = 8.2.
  3. Actualiza BD: def456 → prestige_score = 8.2, status = 'RANKED'.

Paso 3: APP C (Juez IA) — Worker 7 (ejecutado en baja carga, ej: 03:00)

  1. Consume validate_comments → obtiene comment_hash, user_hash, text, urls.
  2. Extrae contenido de https://www.un.org/... → 2000 palabras.
  3. Llama a Ollama con modelo llama3.2:3b.
  4. IA responde: { "verdict": "COHERENT", "confidence": 0.92, "explanation": "..." }
  5. Actualiza prestigio de usuario: user_prestige = 6.0 + 2.0 = 8.0 (para hash abc123).
  6. Guarda log en validation_logs.

Nota: El comentario en sí no se persiste. Solo se actualizan los prestigios en BD (usuarios y dominios). El peso original (2.58) se devolvió al agregador en el momento de la publicación, pero si se quiere recalcular, el agregador puede consultar nuevamente la API con los mismos hashes.


6. ESCALABILIDAD Y ALTA DISPONIBILIDAD

6.1. Componentes y escalado

Componente Escalabilidad Estrategia
APP A (Gateway) Horizontal (3-5 réplicas) Balanceador de carga (Nginx/HAProxy) distribuye peticiones. Estado compartido en BD/Redis.
APP B (Ranker) Horizontal (10-30 workers) Cada worker consume de la misma cola RabbitMQ. Auto-escalado basado en longitud de cola.
APP C (Juez IA) Horizontal (20-100 workers) Workers activos solo en horas de baja carga (programación con cron o Kubernetes cronjob).
RabbitMQ Cluster de 3 nodos Alta disponibilidad con mirroring de colas.
PostgreSQL Primario + réplicas (lectura) Escrituras en primario, lecturas en réplicas. Pool de conexiones (PgBouncer).
Redis (cache) Cluster de 3 nodos Para cacheo de contenido de referencias y locks distribuidos.

6.2. Auto-escalado de workers (APP B y C)

Usar KEDA (Kubernetes Event-Driven Autoscaling) para escalar workers basado en:

  • Longitud de cola RabbitMQ (rabbitmq_queue_length).
  • CPU/Memoria de los pods.

Ejemplo (APP B):

⎗
✓
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: ranker-worker-scaler
spec:
  scaleTargetRef:
    name: ranker-worker
  minReplicaCount: 10
  maxReplicaCount: 30
  triggers:
    - type: rabbitmq
      metadata:
        queueName: rank_domains
        queueLength: "50"   # Por cada 50 mensajes, escala +1 pod

7. CUELLOS DE BOTELLA Y PUNTOS CRÍTICOS

7.1. Cuellos de botella identificados

Cuello de botella Impacto Solución Coste adicional estimado
Scraping de referencias (APP C) Lento si muchas URLs nuevas (1-3s por URL). Cachear contenido en Redis (TTL 24h). Usar reqwest con timeout de 3s. Bajo (Redis)
IA (Ollama) en APP C Inferencia lenta (1-5s por petición). Ejecutar solo en baja carga. Programar workers nocturnos. Usar modelos más pequeños (3B en lugar de 7B). Bajo (GPU)
RabbitMQ Backlog si consumo < producción. Auto-escalar workers (KEDA). Monitorizar longitud de cola. Medio (infraestructura)
PostgreSQL (escrituras) Múltiples UPDATEs concurrentes en domain_prestige y users. Usar conexiones pooling (PgBouncer). Réplicas de lectura para consultas. Particionamiento. Medio (RDS)
APP A (Gateway) Latencia si todas las peticiones consultan BD síncronamente. Cachear prestigios en Redis (TTL 1h). Múltiples réplicas. Bajo (Redis)
Anonimización (hash) Cálculo de SHA-256 por petición (muy rápido, no es cuello). Ninguno. Cero

7.2. Puntos críticos que requerirían aumento de presupuesto

Punto crítico Situación Presupuesto adicional Alternativa gratuita
APIs de prestigio de pago Si las fuentes gratuitas no son suficientes (precisión baja). $200-500/mes (Moz/Ahrefs). Usar solo webrank + Wikipedia + votos de usuarios.
GPU para Ollama Si se necesita inferencia en tiempo real (no en baja carga). $1.000-5.000 (hardware) o $200-500/mes (nube GPU). Usar solo en baja carga (no se necesita GPU potente).
PostgreSQL gestionado Si el equipo no quiere administrar BD. $200-800/mes (AWS RDS/Aurora). Self-hosted en las mismas máquinas (gratis).
RabbitMQ gestionado Si se requiere alta disponibilidad garantizada. $150-500/mes (CloudAMQP). Self-hosted cluster de 3 nodos.
Balanceador de carga Si se necesita alta disponibilidad del gateway. $50-150/mes (AWS ALB/NLB). Nginx/HAProxy self-hosted en las mismas máquinas.
Redis gestionado Para cacheo y locks distribuidos. $50-200/mes (AWS ElastiCache). Self-hosted en las mismas máquinas.

7.3. Estrategia de minimización de costes (ampliada)

  1. Usar infraestructura self-hosted en máquinas dedicadas (on-premise o nube con reservas).
  2. Aprovechar al máximo las fuentes gratuitas (webrank, Wikipedia, Crawly 100/día, Apify 1000/mes).
  3. Ejecutar APP C solo en horas de baja carga (no se necesita infraestructura adicional).
  4. Cachear todo lo posible (Redis) para reducir consultas a BD y scraping.
  5. Usar Rust para reducir el número de instancias necesarias (menos máquinas = menos coste).
  6. Aprovechar APIs de IA con capas gratuitas para la validación de coherencia (APP C), reduciendo o eliminando la necesidad de hardware GPU propio.
  7. Optimizar la validación: solo procesar comentarios de usuarios con baja reputación o bajo demanda (validación selectiva), en lugar de analizar todos los comentarios.

7.3.1. APIs de IA con capas gratuitas para APP C (Validador de coherencia)

Existen múltiples opciones para ejecutar la validación de coherencia sin coste, con diferentes compromisos entre límites, latencia y calidad:

Proveedor Capa gratuita Límites Modelos destacados Ideal para
Groq Permanente, sin tarjeta 30 RPM / 1.000 RPD por modelo Llama 3.3 70B Baja latencia, validaciones rápidas
OpenRouter Permanente, sin tarjeta 20 RPM / 50 RPD 30+ modelos gratuitos Agregador, probar múltiples modelos
Google Gemini (AI Studio) Permanente, sin tarjeta ~30 prompts/día o hasta 1M token/min Gemini 2.5 Flash, Flash-Lite Alto volumen, calidad media-alta
Puter.js Ilimitada, sin API key Sin límites conocidos Gemini, OpenAI, Claude Volumen masivo, sin restricciones
Hugging Face Inference Créditos gratuitos/mes Limitado por créditos Miles de modelos open-source Modelos específicos, investigación
Agnes AI Ilimitada, permanente Sin límite de llamadas Modelos propios (texto, imagen, vídeo) Volumen masivo, casos de uso variados

Recomendación para el proyecto:

  • Para volumen moderado: Usar Groq (Llama 3.3 70B) con 1.000 validaciones/día gratis, suficiente para millones de peticiones al mes si se combina con validación selectiva.
  • Para volumen alto sin coste: Puter.js ofrece acceso ilimitado a Gemini y OpenAI sin necesidad de API key, ideal para escalar sin preocuparse por límites.
  • Como respaldo: Google AI Studio con Gemini 2.5 Flash, que en algunos casos ofrece hasta 1M tokens/minuto gratis.
  • Para pruebas y desarrollo: OpenRouter con sus 30+ modelos gratuitos permite comparar y elegir el mejor modelo para el prompt de validación.

Coste estimado con APIs gratuitas: $0/mes para APP C, eliminando la necesidad del nodo GPU (ahorro de ~$378/mes en la opción de nube).


7.3.2. Validación selectiva: solo procesar comentarios bajo demanda o de usuarios con baja reputación

En lugar de validar todos los comentarios con IA (APP C), se puede implementar un sistema de validación selectiva que reduzca drásticamente el volumen de procesamiento:

Estrategias de selección:

Estrategia Descripción Reducción estimada
Validación por umbral de reputación Solo se validan comentarios de usuarios con prestige < 7.0 (los nuevos o con baja reputación). Los usuarios con alta reputación (>7.0) se consideran "confiables" y sus comentarios no necesitan validación inmediata. 60-80%
Validación por demanda de la app principal La app principal puede enviar un flag validate: true en la petición para solicitar validación solo para comentarios destacados o sospechosos. Variable (según criterio de la app)
Validación muestral (sampling) Validar aleatoriamente un porcentaje de comentarios (ej: 10%) para mantener la calidad sin procesar todo el volumen. 90%
Validación por keywords Solo validar comentarios que contengan palabras clave de controversia (ej: "política", "vacunas", "cambio climático"). 70-90%
Validación por longitud Solo validar comentarios largos (>200 palabras) que son más propensos a contener argumentos que necesitan verificación. 50-70%
Validación por número de referencias Solo validar comentarios con 3 o más referencias (los más complejos). 60-80%

Flujo de validación selectiva:

  1. La APP A recibe el comentario y lo enriquece con el peso inicial (síncrono).
  2. Decide si encolar para validación según las reglas configuradas (reputación del usuario, flag de la app, muestreo, etc.).
  3. Si no se valida, el comentario se marca como validation_status = 'SKIPPED' y se devuelve sin procesamiento de IA.
  4. Solo los comentarios seleccionados pasan por APP C (IA), reduciendo el coste y la carga.

Ejemplo de configuración en Rust:

⎗
✓
fn should_validate(comment: &Comment, user_prestige: f32, app_flags: &AppFlags) -> bool {
    // 1. Si la app principal lo solicita explícitamente
    if app_flags.force_validation { return true; }

    // 2. Usuarios con alta reputación (>7.0) no se validan (son confiables)
    if user_prestige > 7.0 { return false; }

    // 3. Muestreo aleatorio: 10% de los comentarios
    if rand::random::<f32>() < 0.1 { return true; }

    // 4. Comentarios con muchas referencias (>2) se validan
    if comment.urls.len() > 2 { return true; }

    // 5. Por defecto, no validar
    false
}

Impacto en costes:

  • Con una estrategia combinada (umbral de reputación + muestreo 10%), se puede reducir el volumen de validaciones de IA en un 80-90%.
  • Para un sistema con 1 millón de comentarios/mes, solo se procesarían 100.000-200.000 con IA, quedando dentro de los límites de las capas gratuitas (ej: Groq: 1.000 RPD → 30.000/mes, combinado con Puter.js ilimitado para el resto).
  • Ahorro estimado: Eliminación completa del coste de GPU/infraestructura para IA, manteniendo la calidad mediante validación focalizada.

8. RESUMEN Y PRÓXIMOS PASOS

8.1. Resumen de la arquitectura

  • APP A (Gateway): Rust + Actix Web, 3-5 réplicas, recibe comentarios, anonimiza, calcula peso síncrono, devuelve metadatos, encola mejoras.
  • APP B (Ranker): Rust + reqwest, 10-30 workers, obtiene prestigio de dominios de fuentes gratuitas, actualiza BD anonimizada.
  • APP C (Juez IA): Rust + ollama-rs, 20-100 workers programados en baja carga, valida coherencia con IA local, actualiza prestigio del usuario.
  • Anonimización: SHA-256 + salt rotatorio para usuarios y dominios. No se persisten identificadores reales.
  • Escalabilidad: Todo horizontal, con auto-escalado basado en colas y caché Redis.
  • Costes: Opción gratuita (self-hosted) o ~$550-900/mes en nube.
Edit

Pub: 04 Sep 2026 08:16 UTC

Views: 114