El análisis de sentimiento de Apple cree que ‘borra el fichero temporal’ es una amenaza de muerte

| Última modificación: 4 de mayo de 2026 | Tiempo de Lectura: 6 minutos
Premios Blog KeepCoding 2025

Co-Fundador de KeepCoding

NLTagger es la API de Apple para análisis de sentimiento. Está integrada en iOS y macOS, corre on-device, no necesita servidor, y está a tres líneas de código de distancia. Es lo primero que encuentras cuando buscas «sentiment analysis Swift».

Esto es lo que devuelve para texto que cualquier desarrollador escribiría en un día normal:

Mensaje NLTagger Realidad
«delete the temp file» -0.8 Instrucción neutra
«ok» -0.8 Confirmación neutra
«run make test» -0.6 Instrucción neutra
«commit and push» -0.4 Instrucción neutra
«great job, thanks!» +1.0 Positivo (correcto)
«this is fucking broken» -1.0 Negativo (correcto)

La escala va de -1.0 (muy negativo) a +1.0 (muy positivo). Según Apple, «delete the temp file» tiene casi la misma carga emocional que «this is fucking broken». Y «ok» — la respuesta más neutra del idioma inglés — puntúa -0.8.

Estos no son números inventados. Son resultados reproducibles en cualquier Mac con macOS 14+.

Cómo reproducirlo

import NaturalLanguage

let tagger = NLTagger(tagSchemes: [.sentimentScore])
tagger.string = "delete the temp file"
let (tag, _) = tagger.tag(
    at: tagger.string!.startIndex,
    unit: .paragraph,
    scheme: .sentimentScore
)
print(tag?.rawValue ?? "nil")
// "-0.8"

Ocho líneas de Swift. El resultado es determinista: el mismo texto produce el mismo score en cada ejecución, en cada dispositivo. No es un error aleatorio. Es un sesgo sistemático.

Por qué ocurre

NLTagger usa un modelo entrenado con texto de consumo: reviews de productos, comentarios de redes sociales, opiniones sobre restaurantes. En ese dominio, funciona razonablemente bien. «This product is terrible» puntúa -0.9 y «I love this app» puntúa +0.9. Correcto en ambos casos.

El problema es que el vocabulario técnico comparte palabras con el vocabulario emocional, pero con significados completamente distintos:

  • kill, terminate, abort — operaciones normales sobre procesos
  • fatal, critical, panic — niveles de log
  • crash, dead, zombie — estados del sistema
  • delete, destroy, drop — operaciones de datos
  • reject, deny, block — control de acceso

Para un modelo entrenado con reviews de Amazon, «delete» es destructivo, «kill» es violento, y «fatal» es catastrófico. No tiene contexto para saber que «kill the background process» es tan emocional como «cierra la puerta al salir».

Esto se llama lexical bias: el modelo asigna polaridad a palabras individuales sin entender el dominio. Es el equivalente a que un traductor automático interprete «I’m killing it» como un homicidio en curso.

Nadie se ha dado cuenta

Y aquí está lo interesante: este sesgo no aparece en ningún paper académico. Hay cientos de artículos sobre sentiment analysis en software engineering — análisis de code reviews, detección de toxicidad en commits, clasificación de issues — pero ninguno menciona NLTagger. La comunidad de NLP lo ignora completamente.

La razón es simple: nadie usa NLTagger para producción. Los investigadores usan modelos de Hugging Face. Las empresas usan APIs de OpenAI o Google. NLTagger es lo que usa el desarrollador indie que busca una solución rápida para su app de iOS, la implementa en una tarde, y nunca valida los resultados contra datos reales.

Eso significa que hay un número desconocido de apps en la App Store que están clasificando texto técnico con un modelo que cree que «ok» es casi tan negativo como un insulto explícito. Y ninguna de ellas lo sabe.

Un caso real: monitorización de sesiones de código

El problema no es teórico. Construí Tokamak, una app de macOS que monitoriza sesiones de Claude Code. Una de las funcionalidades que quería añadir era detección de frustración: si llevas dos horas peleándote con un bug, la app debería poder detectarlo por el tono de tus mensajes.

El enfoque obvio era NLTagger. Tres líneas de código, cero dependencias, corre on-device. El prototipo funcionó en 20 minutos.

Y clasificó «borra el fichero temporal y ejecuta los tests» como -0.7. Una instrucción completamente neutra que le darías a un asistente de código. Según NLTagger, estaba al borde de una crisis emocional.

Cómo lo resolvimos: capas deterministas primero

La solución no es «usar un modelo mejor» (aunque eso también ayuda). La solución es no depender de un único modelo opaco para todo.

SentimentKit es la librería que escribí para resolver esto. Usa un pipeline de 4 capas donde el análisis determinista corre primero y el ML solo interviene cuando hay ambigüedad:

Mensaje
  │
  ├─ Capa 1: Detector de keywords (determinista, ~20KB)
  │  Diccionarios curados de profanidad, frustración y expresiones positivas.
  │  8 idiomas (ES, EN, PT, DE, FR, ZH, JA, KO).
  │
  ├─ Capa 2: Reglas VADER (determinista, ~500KB)
  │  Negación ("not good"), intensificadores ("very bad"),
  │  MAYÚSCULAS, puntuación.
  │
  ├─ Capa 3: CoreML DistilBERT (opcional)
  │  Solo para mensajes largos y ambiguos.
  │
  └─ Capa 4: LLM scorer (opcional, requiere API)
     Solo para casos que las capas anteriores no resuelven.

La clave es que las capas 1 y 2 son deterministas. Producen el mismo resultado cada vez. No hay modelo opaco. Puedes auditar cada diccionario, cada regla. Y lo más importante: los comandos técnicos neutros puntúan 0.0, no -0.8.

import SentimentKit

let analyzer = SentimentAnalyzer()

let result = analyzer.analyze("delete the temp file and run make test")
// result.score = 0.0 -- neutro, como debe ser

let angry = analyzer.analyze("qué coño es esto, no funciona una mierda")
// angry.score = -2.0 -- dos hits de profanidad detectados

VADER: la herramienta que debería ser más conocida

Las reglas de la capa 2 están inspiradas en VADER (Valence Aware Dictionary and sEntiment Reasoner), un sistema creado por C.J. Hutto y Eric Gilbert en Georgia Tech en 2014. VADER es un analizador de sentimiento basado en reglas, no en ML, que usa un diccionario de ~7500 palabras anotadas por humanos con scores de valencia.

Lo interesante de VADER es que maneja modificadores lingüísticos que los modelos basados en bag of words ignoran:

  • Negación: «not good» invierte la polaridad
  • Intensificadores: «very good» amplifica el score
  • Mayúsculas: «GOOD» puntúa más que «good»
  • Pero: «the food was great BUT the service was terrible» — el but da más peso a la segunda cláusula

VADER tiene limitaciones (no entiende sarcasmo, funciona mejor en inglés), pero su transparencia es su mayor virtud. Cuando VADER clasifica algo mal, puedes abrir el diccionario, encontrar la entrada, y corregirla. Con NLTagger, solo puedes encogerte de hombros.

La ironía: Apple creó el problema y la solución

Desde macOS 26 / iOS 26, Apple ofrece el framework Foundation Models, un LLM de ~3B parámetros que corre on-device. Es incomparablemente mejor que NLTagger para análisis de sentimiento porque entiende contexto, no solo palabras sueltas.

El mismo Apple que te vendió un clasificador que cree que «ok» es negativo, ahora te ofrece un modelo de lenguaje que entiende que «kill the process» es una instrucción técnica. La solución correcta existía dentro del mismo ecosistema; solo llegó una década tarde.

SentimentKit puede usar Foundation Models como capa 4 (LLM scorer). La ironía de usar Apple Intelligence para corregir los errores de NLTagger no se me escapa.

Cómo detecta frustración Anthropic (spoiler: regex)

Un dato curioso. En el código de Claude Code (el CLI de Anthropic para Claude), la detección de frustración del usuario se implementa con expresiones regulares. No con NLTagger. No con un modelo de ML. Con regex que buscan patrones como «this is broken», «doesn’t work», «what the».

Es un enfoque crudo pero efectivo: sin falsos positivos en comandos técnicos, porque los patrones son explícitos. Anthropic, la empresa detrás de uno de los LLMs más avanzados del mundo, usa regex para detectar frustración. Si eso no te dice algo sobre el estado del análisis de sentimiento en producción, nada lo hará.

Golden tests: 144 fixtures y contando

SentimentKit incluye 144 golden messages con aserciones exactas: 35 en español, 35 en inglés, 20 en portugués, 19 en alemán, 20 en francés y 15 en chino. Los datos provienen de datasets publicados (cardiffnlp/tweet_sentiment_multilingual, sepidmnorozy/Chinese_sentiment) y de code reviews reales de repositorios públicos.

Cada fixture tiene un rango esperado de score, las expresiones que deben detectarse, y las que no. El sistema de tests incluye detección PHANTOM (entradas del diccionario que nunca coinciden con datos reales) y detección UNCONSUMED (expresiones reales que faltan en los diccionarios). Es el mismo enfoque que uso en Tokamak para validar DTOs contra datos de producción: si el LLM inventó un dato, el test falla.

Pruébalo

git clone https://github.com/frr149/SentimentKit
cd SentimentKit
swift test

O como dependencia Swift Package Manager:

.package(url: "https://github.com/frr149/SentimentKit.git", from: "1.0.0")

El paquete funciona sin CoreML y sin conexión a internet. Las capas deterministas (keywords + VADER) son suficientes para la mayoría de los casos de uso en texto técnico.

La lección

Si usas NLTagger para cualquier texto que no sean reviews de productos, estás obteniendo datos basura con dos decimales de falsa precisión. El modelo no está roto; está fuera de dominio. Y la API no te avisa.

La comunidad NLP lo ignora. Apple no lo documenta como limitación. Y los desarrolladores que lo usan en producción nunca validan los resultados, porque un Double entre -1.0 y 1.0 parece riguroso aunque no signifique nada.

Antes de confiar en un score de sentimiento, hay que preguntarse: «ok» debería ser -0.8? Si tu herramienta dice que sí, el problema no está en el usuario. Está en la herramienta.


Read this article in English.

Noticias recientes del mundo tech


¡CONVOCATORIA ABIERTA!

Desarrollo de apps móviles ios & Android

Full Stack Bootcamp

Clases en Directo | Profesores en Activo | Temario 100% actualizado

Descárgate también el informe de tendencias en el mercado laboral 2026.

Fórmate con planes adaptados a tus objetivos y logra resultados en tiempo récord.
KeepCoding Bootcamps
Resumen de privacidad

Esta web utiliza cookies para que podamos ofrecerte la mejor experiencia de usuario posible. La información de las cookies se almacena en tu navegador y realiza funciones tales como reconocerte cuando vuelves a nuestra web o ayudar a nuestro equipo a comprender qué secciones de la web encuentras más interesantes y útiles.