- El tratamiento de la declinación de nombres personales en islandés cambia a 4 formas según el contexto
- Se desarrolló una librería de JavaScript basada en datos con capacidad de devolver el caso gramatical adecuado para el nombre ingresado
- Guardar todos los nombres directamente generaba aumento de tamaño y faltantes de datos, por lo que se resolvió usando una estructura trie y técnicas de compresión
- Gracias a la compresión trie, es posible inferir automáticamente a partir de patrones comunes y se alcanzó una base de datos muy pequeña que cubre más del 80% de los datos
- En situaciones normales muestra más de 74% de precisión, y para el sector público y casos donde se requiere precisión se ofrece una versión strict aparte
Antecedentes del problema
- En las interfaces en islandés, mostrar nombres personales presenta dificultades debido a la declinación
- En islandés, los nombres cambian de forma según los casos gramaticales nominativo, acusativo, dativo y genitivo
- La base de datos suele guardar normalmente los nombres en forma nominativa, y surgen dificultades cuando se requiere otro caso según el contexto
- Si no se usa la forma correcta, suena poco natural o forzado para un hablante nativo
Recolección y limpieza de datos
- Islandia dispone de los datos abiertos DIM (Database of Icelandic Morphology) administrados por Árnastofnun
- Los datos de declinación de nombres pueden prepararse como CSV en Kristín’s Format (formato K)
- Aunque el conjunto completo DIM tiene 7 millones de filas y es excesivamente grande, se filtran 4,500 nombres personales oficialmente aprobados, y se pueden obtener datos de declinación para poco más de 3.600
- Para cada nombre se puede construir una matriz con las formas desde nominativo hasta genitivo
Estructura base de la librería
- La implementación inicial comenzó con una función applyCase para retornar la forma adecuada a partir del arreglo nombre-formas de caso
- Sin embargo, la carga mediante simple lectura de arreglo ocupaba 30kB gzipped
- Tiene la limitación de que no responde para nombres que no están incluidos en los datos
Eliminación de duplicados y extracción de patrones
- Se extrajeron prefijos comunes entre las 4 formas de cada nombre y se almacenaron solo los conjuntos de sufijos (suffix encoding) para minimizar duplicados
- Se observó que hay muchos nombres que comparten el mismo patrón de declinación
Introducción de trie para coincidencia de patrones
- Se optimiza la asignación de valores para grupos de nombres que comparten patrones mediante una estructura trie (inserción inversa por sufijo)
- Se almacena la información de declinación solo una vez bajo patrones comunes de terminación (name endings), manteniendo alta capacidad de predicción para nombres nuevos
Compresión y optimización del trie
- Cuando los valores son iguales en cada hoja del subárbol, se asigna el valor al nodo padre y se eliminan los hijos para comprimir el árbol
- Esto redujo el número de nodos hasta un 15,4%, y el tamaño bajó a 4.01kB
- Una compresión de segundo nivel que fusiona hojas hermanas con valores idénticos en un solo nodo llevó a 3.27kB
Rendimiento y generalización del trie
- Al ingresar un nombre nuevo, es posible declinar automáticamente usando patrones similares
- En la práctica, con nombres no conocidos mostró 74% de declinación correcta y 26% de error; la tasa de error para usuarios reales fue solo 0.34%
- Cuanto mayor es la regularidad y la exhaustividad de los datos, mayor es el beneficio de la compresión y la precisión de inferencia automática
Librería real y aplicación
- Finalmente se distribuyó la librería comprimida con trie beygla
- Se ofrece un tamaño mínimo de 4.46kB y un módulo strict más estricto y completo de 15kB
- En contextos que requieren 100% de precisión, como documentos públicos, se puede elegir la versión strict; en aplicaciones web comunes, elegir la versión ligera
Conclusiones y potencial de expansión
- La compresión de datos de patrones de declinación de lenguas con trie puede aplicarse a la automatización de nombres, direcciones y otros sustantivos en otras lenguas flexivas, además del islandés
- La combinación de datos con alta regularidad y compresión trie es una forma de maximizar la eficiencia de datos y rendimiento en la automatización de la flexión morfológica
Agradecimientos
- En el desarrollo de beygla hubo retroalimentación de diversos expertos y optimizaciones
- Una compresión adicional del trie redujo el tamaño de 3.43kB a 3.27kB
Resumen
- Presenta un caso de automatización de la declinación de nombres islandeses mediante la miniaturización automática basada en patrones con una estructura trie
- Sugiere una estrategia práctica de procesamiento de datos con un equilibrio de tamaño-precisión bien planteado
1 comentarios
Comentarios de Hacker News
Cuando aprendí español por primera vez en la secundaria, usé software para Windows que te lanzaba infinitivos y tiempos verbales en serie, y uno tenía que escribir la conjugación correspondiente. Gracias a esa práctica, las reglas gramaticales se me quedaron grabadas y terminé adquiriendo soltura. Pero cuando aprendí ruso, los casos de repente se volvieron difíciles, y por más que busqué una app que explicara o permitiera practicar patrones similares, no encontré ninguna. Me pregunto si alguien conoce una app para esto (web o macOS/iOS)
En Anki hay un mazo de tarjetas que usa un método llamado "KOFI (Konjugation First)". KOFI significa aprender primero todos los patrones de conjugación antes de estudiar el idioma. Después de estudiar francés, me di cuenta de que me faltaba soltura con las conjugaciones y luego probé este método; aunque hablar con errores gramaticales no impide la comunicación cotidiana, no era el nivel que yo quería. La idea de este método es aprender en poco tiempo todos los patrones de conjugación antes de estudiar el idioma. Algún día me gustaría aplicarlo en serio a un idioma nuevo. Perdí interés en el francés y lo dejé a medio camino. Enlace al mazo de Anki relacionado
Mientras aprendía ruso, una vez hice un script que combinaba el módulo de Python spaCy con un módulo grande para ruso para hacer lematización contextual y extraer etiquetas gramaticales. Pero en la práctica, cuando mi ruso empezó a mejorar, me resultó mucho más efectivo dejar de intentar descomponer lógicamente las flexiones y, en cambio, acumular en la cabeza una biblioteca de patrones (incluyendo excepciones) mediante la experiencia de uso y la repetición. Por cierto, aquí "contexto" significa el sentido dentro de la oración
Cuando aprendía español por mi cuenta hace 25 años, usé un diccionario español/inglés. A los infinitivos se les agregaba un índice numérico para clasificarlos en grupos con el mismo patrón de conjugación. Al principio del diccionario había una tabla con la conjugación completa en todos los tiempos de un verbo representativo de cada grupo. Los verbos irregulares tenían un índice aparte y, del mismo modo, los verbos irregulares parecidos se agrupaban juntos (por ejemplo: tener, detener). Todos los verbos quedaban ordenados limpiamente en unas cuantas decenas de patrones únicos. Pensé en hacer un software de cuestionarios aprovechando este sistema, pero al final no lo hice. Me pregunto si el patrón de reverse-string trie mencionado en el artículo podría servir también para este tipo de clasificación
Para aprender la declinación de casos en ruso, tuve la idea de crear tarjetas con combinaciones de preposición + adjetivo + sustantivo para acelerar la memorización. Antes había aprendido latín, y con la declinación latina no esperaba memorizarla rápido (a menos que uno sea monje, quizá), pero con el ruso sí quería avanzar rápido. Al final, el proyecto no llegó a concretarse
Estoy usando ConjuGato para iOS para practicar conjugaciones en español. En el modo de juego te dan el infinitivo / tiempo / persona y tienes que pensar en la forma conjugada. También puedes practicar solo los verbos irregulares, así que sirve mucho para aprender las excepciones
En el caso de los 800 nombres cuya información de declinación falta en la base de datos, la solución más directa parece ser asignarles manualmente las declinaciones. Un hablante nativo podría terminarlo en unas pocas horas, e incluso con nombres totalmente desconocidos al menos podría estimar una forma que no resulte claramente extraña. O también podría pedírsele a un LLM y saldría muy barato. Sigue siendo buena idea codificar el resultado y distribuirlo en una estructura trie como esta. Solo que no hace falta usar el trie también como estimador de declinaciones
Lo ideal sería cubrir más nombres; en DIM esto sigue siendo un área que debe completarse continuamente. En Islandia se agregan con frecuencia nuevos nombres a la lista de nombres permitidos, así que siempre habrá huecos. Yo no tenía suficiente confianza como para agregar datos por mi cuenta, y cada vez que revisaba resultados de 100 nombres no verificados, a menudo había casos en que pensaba: "¿de verdad será así?". Varias veces busqué nombres parecidos en DIM y pensé: "yo no los declinaría así". Por eso tomo los datos de DIM como la "fuente de verdad" mantenida por especialistas en la lengua
El trabajo manual está bien, pero sigue teniendo limitaciones con nombres que no están en la lista oficial (por ejemplo, nombres extranjeros). Yo también vivo en un país con una lista centralizada de nombres, pero se pueden pedir excepciones, y puede haber personas nacidas antes de que existiera la lista o inmigrantes cuyos nombres no estén en ella. En todas esas situaciones combinadas, una función de "predicción de una declinación más o menos adecuada" sigue siendo útil
No he visto evidencia para decir que un LLM prediga mejor las declinaciones que un trie (si el ejemplo real no está en los datos de entrenamiento del LLM, probablemente buscar en la web sería mejor)
Me da curiosidad si los LLM actuales ya habrán aprendido este tipo de patrones
No estoy seguro de si Rails resuelve esto automáticamente, pero antes era muy bueno para este tipo de magia. Hace tiempo vi el código fuente de
pluralise, y hasta tenía codificadas las reglas irregulares de plural en galésUna idea de optimización sería que, en vez de que el trie apunte directamente a la cadena del sufijo, se cree un arreglo de sufijos únicos y el trie apunte al índice dentro de ese arreglo. Por ejemplo:
y luego referenciar el índice así:
Lo probé yo mismo con Claude Code y, con gzip, en realidad aumentó 100 bytes (3456 -> 3556), y solo el tamaño sin comprimir se redujo 20%. Parece que gzip ya está bastante bien optimizado para patrones repetidos
Dando un paso más, también se podría meter el propio sufijo dentro del trie e identificar subárboles iguales para deduplicarlos. Si se puede usar gzip, seguro debe haber alguna optimización inteligente aprovechando el arreglo de sufijos. Tal vez un formato binario optimizado funcione mejor
Personalmente sigo sintiendo que debe existir alguna solución mágica para resolverlo en <1kb sin comprimir. ¿Tal vez una lista minimizada de expresiones regulares que clasifique los nombres con 100% de precisión? ¿Un bloom filter enorme? ¿O quizá usar características especializadas en vez de un hash general?
Parece una pregunta de entrevista de pesadilla. Usar un trie invertido (en orden inverso) es de esas cosas que en toda la vida quizá solo usas una vez, pero cuando la usas pareces mago
En vez de hacer esto en JS, quizá podría hacerse desde la base de datos devolviendo todas las combinaciones name-case y, al momento de mostrar, elegir solo la necesaria. O sea, resolverlo en la capa de localización. Me pregunto cómo funcionaría en situaciones multilingües. Cuando una UI en islandés maneja un nombre francés, supongo que usaría siempre el nominativo, y lo mismo pasaría cuando una UI en inglés maneja un nombre islandés. Al final, probablemente solo se vuelve realmente necesario en contextos donde se designa o se llama directamente al usuario, o en paneles de administración ("el usuario x respondió al usuario y"), etc.
Hay hasta 88 nombres con cierto patrón de declinación que terminan en "idur", "tur" o "ður", pero el mismo sufijo no siempre sigue el mismo patrón de declinación. El problema parece una regla simple, pero en realidad es muy interesante. ¿Tendrá el patrón del sufijo relación con la pronunciación de la sílaba anterior? Si uno quisiera manejar mejor nombres desconocidos, me pregunto si haría falta extraer con NLP una representación fonética del nombre y consultarla con un trie o algo similar, en vez de basarse solo en letras
Hay que tener cuidado, porque pensar en esto puede terminar llevándote a discusiones sobre Dependent Types
Es una idea aguda. De hecho, incluso nombres con la misma pronunciación pueden tener patrones de declinación distintos. Por ejemplo:
En el caso de beygla/strict, perfect hashing podría considerarse como alternativa
Me sorprende que la flexión de casos de los nombres islandeses sea lo bastante simple y tenga patrones lo bastante deterministas como para que este enfoque funcione tan bien. El lenguaje normalmente suele ser bastante complejo