El mapa del PLN: qué hacen spaCy, NLTK y FreeLing, y cómo lo hacemos nuestro

Tres bibliotecas cargan hoy casi todo el procesamiento del lenguaje en español del mundo: spaCy, NLTK y FreeLing. Las hemos montado como satélites para medirlas. Este ensayo es el mapa: función por función, qué hace cada una, cómo lo hace a grandes rasgos, con qué licencia, qué tenemos ya nosotros y dónde podemos hacerlo mejor —o por qué, honestamente, en algún sitio no vamos a poder. No es un plan para copiar: es un plan para rehacer la idea a nuestra manera, con datos libres y una API llana que se pueda explicar.

No necesitamos copiar; necesitamos ver la funcionalidad. Como hicimos con los diccionarios, con Molinarium y con Onoma: mirar qué resuelve cada función —su entrada, su salida, los casos que acierta y los que falla en español— y no su código. Es más que una cautela legal (el código de FreeLing es AGPL, y ahí la línea es tajante: se reimplementa la idea, nunca se copia una línea): es que el valor para un hispanohablante no está en el algoritmo ajeno, sino en tener datos propios —el diccionario, el conjugador, el silabeador, el Molino— y una salida que podamos justificar palabra por palabra.

La meta es clara: cuando lo nuestro esté, los satélites se quitan. Son andamio para medir, no producto. Y como la API es gratis y libre, todo lo que hagamos tiene que poder publicarse con licencia libre y datos libres.

Cómo lo hace cada una, en una frase

  • spaCy (código MIT; modelo es_core_news_lg MIT). Es una tubería neuronal entrenada sobre AnCora/UD: un tok2vec alimenta un etiquetador morfológico, un analizador de dependencias y un NER, todos estadísticos. Trae 500 000 vectores de palabra (dim 300). Rápida, con el modelo en memoria. Su lematización y su PoS del español fallan de maneras concretas (lo medimos abajo).
  • NLTK (código Apache 2.0; datos con licencias variadas). Es una caja de herramientas académica: tokenizadores (Punkt no supervisado, Treebank, toktok), stemmer Snowball, stopwords, n-gramas, colocaciones, concordancias, WordNet y FrameNet. Casi todo su contenido léxico-semántico es inglés; para español da sobre todo tokenización, raíces y estadística de corpus.
  • FreeLing (código AGPL; datos/treebanks tipo CC BY-SA). El más fuerte en español clásico: tokenizador y segmentador por reglas, analizador morfológico con diccionario EAGLES, PoS estadístico (HMM sobre AnCora), NER+NEC, WSD (UKB sobre WordNet), dependencias, roles semánticos, correferencia y fonética. Preciso y explicable, pero servirlo hoy es lento: relanza el binario analyze en cada petición (~9–18 s/frase en nuestro montaje).

Y lo nuestro hoy (60 endpoints en api.wordkers.com, todos algorítmicos): un motor léxico-morfológico muy completo —lematizar, morfología, silabeo, fonética, conjugación y flexión generativas, diccionario semántico con sinónimos, hiperónimos y colocaciones, refranero, niveles de dificultad y frecuencia— pero sin tokenizador de texto corrido, sin segmentador de oraciones, sin PoS/NER en contexto, sin dependencias y sin vectores. Justo el hueco que llenan los satélites.

Aviso sobre las mediciones. spaCy y FreeLing se midieron en vivo en Prepro (127.0.0.1:8022 y :8021); NLTK como librería. El core (api.wordkers.com) exige clave y este trabajo era «sin claves», así que su calidad en vivo no se mide aquí (igual que en E-465); lo que sí medimos es nuestra pieza nueva (wkpln), que no depende de claves. Para lema/PoS/NER en español, la tabla de 30 frases de E-465 (spaCy vs FreeLing) es la referencia y se cita.


El mapa función por función

Enfoque abreviado: R = reglas, L = léxico/diccionario, E = estadístico, N = red neuronal. Licencia = (código / datos).

FunciónQué hace (entrada → salida)spaCyNLTKFreeLingLo nuestro (endpoint)Veredicto de calidad en español
Tokenizartexto → palabras y signos con offsetsR+N sobre excepcionesR (Punkt/Treebank/toktok)R (reglas)**wkpln.tokenizar** (nuevo)Empate técnico: los tres y el nuestro dan F1 1.0 en 30 frases; NLTK no separa ¿/¡. Nuestro ~400× más rápido
Segmentar oracionestexto → oraciones con offsetsN (parser/senter)R+E (Punkt)R (reglas+abreviaturas)**wkpln.oraciones** (nuevo)Nuestro y spaCy/NLTK aciertan el párrafo duro (6/6); FreeLing falla uno (5/6)
Lematizarpalabra/forma → lemaN+lookup— (solo inglés)L (diccionario EAGLES)/v1/morfologia/lematizar, /lemasFreeLing y core, bien; spaCy comete errores claros (cocina→cocín, muy→mucho)
PoS / etiquetaroración → categoría por tokenN (morphologizer)E (solo si se entrena, p. ej. CESS)E (HMM sobre AnCora)(no en contexto; sí análisis léxico)FreeLing gana (EAGLES); spaCy falla con mayúscula inicial y verbos→PROPN
Morfología (rasgos)forma → género, número, tiempo…N—L+E/v1/morfologia/*, /v1/genero/*, /v1/verbo/analizarEmpate: nuestro léxico da rasgos finos por palabra suelta
NER (entidades)texto → PER/LOC/ORG con tramosN—R+E (NEC)(no)Empate de recall; spaCy tipa mejor Apple=ORG, FreeLing Barcelona=club
Dependenciasoración → árbol (cabeza+relación)N (parser)—R+E(no)spaCy gana (rápido y limpio); FreeLing lento
Chunking / sintagmasoración → SN/SV superficialesvía árbolR (RegexpParser)R (shallow)(no)Reproducible por reglas sobre PoS propio
Sinónimos / hiperónimospalabra → red léxicavectores (aprox.)WordNet (inglés; spa OMW)L (WordNet-ES)/v1/diccionario/sinonimos, /hiperonimos, /hiponimos, /relacionadasNuestro, propio y en español; WordNet-ES es CC pero indirecto
WSD (sentidos)palabra en contexto → acepción—Lesk (didáctico)E (UKB sobre WordNet)/v1/diccionario/definicion (lematiza+elige)Parcial nuestro; UKB en contexto no lo tenemos
Roles semánticos (SRL)oración → quién-hace-qué-a-quién—FrameNet (inglés)E (sobre dependencias)(no)Difícil; FrameNet es inglés. Se pospone
Vectores / similitudtexto → vector; par → cosenoN (500k vectores)——(no)spaCy gana de largo; nadie más lo ofrece de serie
Stemming (raíces)palabra → raíz cruda—R (Snowball ES)— (usa lema)(lematizar es mejor que *stem)*El stem es tosco; nuestro lema es superior para español
Stopwordslista de palabras vacíasatributo is_stoplista ES—(trivial; lista propia)Trivial; lista propia libre en minutos
n-gramassecuencia → bi/tri-gramas—R (ngrams)—*(trivial sobre wkpln)*Trivial una vez tenemos tokenizador propio
Colocacionescorpus → pares que van juntos (PMI)—E (PMI/χ²)—/v1/diccionario/colocaciones (por palabra)Nuestro por palabra; el cálculo PMI sobre corpus es reproducible
Concordancias / frecuenciascorpus → KWIC, FreqDist—R+E— (corpus)/v1/nivel/frecuenciaReproducible sobre wkpln + índice
Detección de idiomatexto → idiomaañadido externo—R (opcional)(no)Reproducible con n-gramas de caracteres (datos libres)
Silabeo / acentuaciónpalabra → sílabas, tilde, tipo———/v1/silabeo/*Solo nuestro. Los tres no lo hacen
Fonéticapalabra → IPA/SAMPA, rimas, homófonos——R (SAMPA)/v1/fonetica/*Nuestro es más rico (rimas, pares mínimos, homófonos)
Conjugación / flexiónverbo/adj → paradigma, plural, género——L (genera del diccionario)/v1/verbo/*, /v1/flexion/*, /v1/cazarSolo nuestro y generativo (conjuga hasta inventados)

Cómo lo hacen, con qué recursos (sin mirar su código)

  • spaCy aprende de treebanks UD/AnCora una red que predice etiquetas y árboles; sus vectores salen de un word2vec/fastText sobre corpus grandes. Es end-to-end estadístico: rápido y uniforme, pero opaco y con errores de español que no sabe explicar (etiqueta salta→PROPN por la mayúscula, inventa cocín).
  • NLTK es sobre todo reglas y estadística de corpus más envoltorios de recursos ajenos (WordNet, FrameNet). Su Punkt aprende abreviaturas de forma no supervisada; su Snowball es un stemmer de reglas. Poco específico del español.
  • FreeLing combina un diccionario EAGLES enorme con etiquetadores estadísticos entrenados en AnCora y desambiguación UKB sobre WordNet. Es el más fino en español, y el más caro de servir tal como está.

Dónde podemos ser mejores (honesto, función a función)

Donde ya somos mejores o iguales, y libres:

  • Silabeo, acentuación, fonética, conjugación y flexión. Los tres satélites no las hacen (o FreeLing solo SAMPA). Aquí no hay nada que sustituir: ya somos la referencia, y generativa (conjugamos e inventamos, cazamos infinitivos).
  • Sinónimos, hiperónimos, hipónimos y relacionadas en español, desde nuestro diccionario, sin depender de WordNet.
  • Lematización. Con diccionario + conjugador batimos a spaCy con claridad (E-465). El objetivo es igualar a FreeLing y quitarlo.

Donde podemos rehacerlo por reglas/léxico, con datos libres:

  • Tokenizar y segmentar oraciones. Hecho ya (ver prototipo): F1 1.0 en 30 frases, 400× más rápido que spaCy, y acierta la segmentación donde FreeLing falla.
  • PoS y morfología en contexto. Tenemos el léxico (candidatos EAGLES por palabra); falta la desambiguación en frase. Reproducible con un etiquetador propio (reglas + estadística ligera sobre AnCora, que es libre).
  • Chunking, n-gramas, colocaciones (PMI), concordancias, stopwords, detección de idioma. Todo esto es reglas o estadística de corpus sobre nuestro tokenizador: barato y publicable.

Donde honestamente no compensa (todavía) o no vamos a reproducir:

  • Vectores y similitud semántica. spaCy trae 500 000 vectores entrenados; no los vamos a reentrenar a corto plazo. Si queremos similitud, o usamos embeddings libres (fastText-es, CC BY-SA) o lo dejamos como está. Aquí spaCy gana.
  • NER y dependencias neuronales de calidad. Reproducibles por reglas hasta cierto punto, pero igualar al modelo cuesta datos y tiempo. Prioridad media-baja.
  • SRL / FrameNet. El recurso es inglés; para español habría que construirlo. Se pospone.

Plan por prioridad (tres tandas)

Estimaciones en minutos de Opus/DeepSeek. Métrica: conjunto de prueba con oro y F1 (tokenización), accuracy de frontera (oraciones), y tagging accuracy contra AnCora (PoS).

Tanda 1 — lo barato y de más valor (reglas, datos libres).

PiezaDatosMétricaEstimación
Tokenizador españolreglas + lista de abreviaturas propiaF1 vs oro (30→200 frases)hecho (prototipo)
Segmentador de oracionesreglas + abreviaturasfrontera vs orohecho (prototipo)
Stopwordslista propia libre—20 min
n-gramas + colocaciones (PMI)corpus libre + wkplnPMI reproducible60 min
Detección de idiomaperfiles de n-gramas de caracteresaccuracy60 min

Tanda 2 — el corazón léxico-gramatical (sustituir a FreeLing/spaCy en PoS).

PiezaDatosMétricaEstimación
Analizador morfológico en contexto (candidatos EAGLES por token)nuestro léxico + wkplncobertura120 min
Desambiguador PoS (reglas + HMM ligero)AnCora/UD (libres)tag accuracy vs FreeLing240 min
Lematizador de secuencia (usa PoS + conjugador)nuestroF1 de lema vs FreeLing120 min
Chunking superficial (SN/SV)reglas sobre PoS—90 min

Tanda 3 — lo caro o lo que quizá no compense.

PiezaDatosMétricaEstimación
NER por reglas + gazetteerslistas libres + MolinoF1 vs FreeLing (E-465)240 min
Dependencias (parser ligero)UD-Spanish (libre)UAS/LAS480 min+
Vectores/similitudembeddings libres (fastText-es) o descartarcosenoa decidir
SRL/FrameNet-esno hay recurso libre en español—pospuesto

Regla de oro de velocidad (Eduardo): se mide siempre tiempo por frase y por 1.000 frases del original y del nuestro; si el nuestro es más lento, no se da por bueno hasta proponer índices, precálculo, léxico compilado o caché.


Prototipo de la primera pieza: tokenizador + segmentador (apis/pln)

La pieza con mejor relación valor/coste es la que abre todas las demás: sin tokenizador y segmentador propios no hay n-gramas, ni colocaciones, ni PoS en contexto. Está hecha, en el repo nuevo **wordkers/apis/pln** (módulo wkpln, sin dependencias externas — solo librería estándar; se publica con licencia libre).

Qué hace. tokenizar(texto) y oraciones(texto), por reglas explícitas y una lista corta de abreviaturas propia, con offsets en caracteres. Decisiones documentadas: puntuación suelta, suspensivos un token, el punto de una abreviatura pegado a la palabra (Sr., etc.), números 1.234,56 / fechas 3/5/1999 / horas 12:30 / URLs enteros, contracciones del/al sin partir salvo que se pida (separar_contracciones → de+el, útil para lematizar), y clíticos enteros.

Pruebas. pytest en verde: 71 passed (sin red ni modelos).

Comparativa numérica (30 frases + párrafo duro), medida en Prepro:

MotorF1 tokenizaciónFrases exactasOraciones párrafo (oro 6)ms/frase
wkpln (nuestro)1.030/306/6 ✓0.02
spaCy (:8022)1.030/306/6 ✓7.9
NLTK (librería)0.98327/306/6 ✓7.1
FreeLing (:8021)1.030/305/6 ✗8 836

Lectura honesta. El oro es la convención Wordkers; que spaCy y FreeLing también saquen 1.0 confirma que la convención es sensata (no está trucada a nuestro favor). Las diferencias reales:

  • Velocidad. wkpln hace tokenizar+segmentar 30 000 frases en 0,68 s (~0,023 ms/frase; ~23 ms por 1.000 frases), sin cargar ningún modelo ni ocupar los ~868 MB de RAM de spaCy. Es ~400× más rápido que la llamada a spaCy y ~440 000× más rápido que FreeLing tal como se sirve hoy.
  • Segmentación. wkpln, spaCy y NLTK aciertan el párrafo duro (abreviaturas, decimales, horas, ¿?, suspensivos): 6/6. FreeLing se deja una: 5/6.
  • Español. NLTK no separa el signo de apertura ¿/¡ de la palabra (¿Cuándo como un token): 3 fallos de 30. wkpln sí lo separa.

Conclusión del prototipo. En tokenización y segmentación, lo nuestro iguala en precisión a lo mejor (spaCy/FreeLing), mejora la segmentación frente a FreeLing, evita el fallo del ¿ de NLTK, y es cientos de veces más rápido sin depender de un modelo. Es el primer satélite que podemos empezar a retirar.

En esta página