Generación de texto en ruso por plantillas

Cuando recién comenzaba a trabajar en mi juego de texto, decidí que una de sus características principales debería ser hermosas descripciones artísticas de las acciones de los personajes. En parte, quería "guardar", porque no sabía cómo programarlo. El ahorro no funcionó, pero resultó ser la biblioteca Python ( github , pypi ) para generar textos, teniendo en cuenta la dependencia de las palabras y sus características gramaticales.

Por ejemplo, de la plantilla:
[Héroe] [pasó | héroe] más allá de un patio discreto y de repente [notó | héroe] niños jugando. Corrieron con espadas de madera, bastones y máscaras de monstruos. De repente, uno de los jugadores se detuvo, puso [toy | hero.weapon | vn] [hero.weapon | vn] , gritó: “ [I | hero] [great | hero] [Hero] ! ¡Consíguelo! - Y corrió hacia la "bestia". Cayeron al suelo, saltaron de brazos y piernas, y luego se pusieron de pie, se quitaron las máscaras y se rieron. [Gruñido | héroe] y [él mismo | héroe] [Héroe] , pero no [ inicio | héroe] salieron al pequeño.
Podemos obtener el siguiente texto (las palabras cambiantes están en negrita):
Hallr pasó junto a un discreto patio y de repente notó que los niños jugaban. Corrieron con espadas de madera, bastones y máscaras de monstruos. De repente, uno de los jugadores se detuvo, sacó una espada dorada de juguete y gritó: “ ¡Soy un gran Hallr ! ¡Consíguelo! - Y corrió hacia la "bestia". Cayeron al suelo, saltaron de brazos y piernas, y luego se pusieron de pie, se quitaron las máscaras y se rieron. El propio Hallr se rió entre dientes , pero no se acercó al pequeño.
O así:
Fievara pasó junto a un discreto patio y de repente notó que los niños jugaban. Corrieron con espadas de madera, bastones y máscaras de monstruos. De repente, uno de los jugadores se detuvo, sacó un juguete de catarro y gritó: “ ¡Soy el gran Fievara ! ¡Consíguelo! - Y corrió hacia la "bestia". Cayeron al suelo, saltaron de brazos y piernas, y luego se pusieron de pie, se quitaron las máscaras y se rieron. Fievara misma gruñó , pero no se acercó al pequeño.

Reservas de pareja
Descargo de responsabilidad 1 . No soy lingüista y la biblioteca fue escrita "para trabajar", y no "para corresponder exactamente a todas las reglas del idioma". Por lo tanto, me disculpo de antemano por inexactitudes en la terminología o una interpretación incompleta de las reglas del idioma ruso.

Descargo de responsabilidad 2 . La biblioteca se desarrolló hace aproximadamente 5 años, ahora podrían aparecer medios alternativos de generación de texto (o crecer a un estado normal). Por ejemplo, algo interesante puede estar en el software para la localización.

Sobre la complejidad de la generación de texto.


El idioma ruso es complejo en muchos de sus aspectos. En particular, las palabras tienen una gran cantidad de formas morfológicas. Por ejemplo, los adjetivos pueden tener una forma completa y corta, que varía según el género, el número, el caso, la animación y el grado de comparación. La elección de una forma específica depende de otras palabras en la oración. Decimos "mujer hermosa", pero "hombre hermoso". La palabra "hermosa" en este caso depende de las palabras "hombre" / "mujer" - su forma está determinada por el género de la palabra principal.

Por lo tanto, las dificultades comienzan cuando tratamos de contactar a alguien en función de su género. Al compilar textos para sitios web, cartas, juegos, uno tiene que elaborar una redacción muy clara (evitando el género del usuario), escribir varios textos a la vez o utilizar lenguajes de marcado de diversos grados de versatilidad.

Quería algo más que una simple dependencia del género del jugador, e incluso para que los propios usuarios pudieran agregar nuevos textos (y el usuario "promedio" es bastante analfabeto, como todos sabemos :-)). Por lo tanto, al no encontrar el software adecuado, decidí hacerlo yo mismo.

Características de la biblioteca


UTG (generador de texto universal - no es un nombre muy modesto) le permite crear plantillas para generar texto con lo siguiente:

  • variables (por ejemplo, nombre del personaje);
  • dependencias de palabras en variables (por ejemplo, un adjetivo en un sustantivo);
  • Dependencias de algunas variables sobre otras;
  • Propiedades explícitas de palabras y variables (por ejemplo, puede especificar que el nombre del carácter se inserte en el caso principal);

Al generar texto a partir de una plantilla:

  • Las propiedades necesarias de la palabra principal se transfieren a palabras dependientes. Por ejemplo, el género de un sustantivo se transfiere al adjetivo.
  • La forma de las palabras dependientes es consistente con los números (teniendo en cuenta la forma de las palabras dependientes).
  • Las preposiciones se modifican si es necesario (por ejemplo, sobre mí / sobre usted), el pretexto para esto debe estar marcado.

Implementado adicionalmente:

  • Un diccionario para almacenar las palabras necesarias.
  • Un repositorio de plantillas para almacenarlas por tipo y elegir las aleatorias.

La biblioteca "sabe" acerca de la existencia de sustantivos, adjetivos, pronombres, verbos, participios, números, preposiciones y "citas" (texto inmutable).

Se tienen en cuenta las siguientes propiedades de las palabras: parte del discurso, caso, animación, número, género, forma verbal, tiempo, persona, tipo, categoría de adjetivo, grado de adjetivo, categoría de pronombre, promesa, forma de preposición, forma de adjetivo, forma de participio, forma de sustantivo ( Además de la forma normal, los sustantivos tienen un contador ).

Formato de plantilla y ejemplo de uso


Veamos una plantilla simple:
Ayer [mafia] [mordida | mafia] [héroe | ext] .
Dependiendo de los valores de las variables, la plantilla puede aparecer como una frase:
Ayer, una hiena mordió a Hallre.
tal y tal:
Las luciérnagas mordieron un fantasma ayer.
Considere la plantilla con más detalle:

  • - texto plano.
  • [mob] - una variable, en lugar de la cual se sustituye el nombre del monstruo.
  • [|mob] : una palabra que depende de una variable, parte de sus propiedades cambiará dependiendo de las propiedades del nombre del monstruo (por ejemplo, un número). El generador de texto reconoce automáticamente las propiedades de la forma de la palabra e intenta guardarlas (por ejemplo, el tiempo transcurrido será reconocido y guardado, por lo que no necesita especificarlo).
  • [hero|] - una variable, en lugar de la cual se sustituye el nombre del héroe. También se indica que el nombre debe estar en el caso acusativo.

Más plantillas de muestra.
Algunos ejemplos técnicos se pueden encontrar en las pruebas .

Si está interesado en más ejemplos, puede verlos en el sitio web de juguetes. Puede encontrar un enlace a él hurgando en mi perfil o escribiendo un mensaje personal.

Las palabras variables y dependientes en la plantilla se resaltan de manera idéntica y tienen el siguiente formato:

  • [ - corchete de apertura.
  • - dependiente o identificador de variable. El generador primero verifica la presencia de una variable con este nombre; si no existe dicha variable, la palabra se busca en el diccionario.
  • | - barra vertical - separador, necesario si especificamos propiedades adicionales.
  • : la variable de la que depende la forma de la palabra puede estar ausente.
  • | - barra vertical - separador, necesario si especificamos propiedades adicionales.
  • : una descripción de la forma requerida de la palabra (caso, género, etc.). Se puede encontrar una lista de ellos en las páginas del proyecto en github y pypi.
  • ] Es el corchete de cierre.

Puede especificar las propiedades adicionales que desee, se aplicarán en el orden de definición, por ejemplo:

[ 1| 2|,| 3|,,]

En la mayoría de los casos, los siguientes formatos son suficientes:

  • [] : inserte una variable en forma normal (por ejemplo, un sustantivo en el caso nominativo del singular).
  • [|] : inserte una variable con las propiedades especificadas.
  • [|] : inserte una palabra, combinándola con una variable (por ejemplo, el adjetivo "hermoso" con un sustantivo en género y mayúscula).
  • [||] : inserte una palabra, combinándola con una variable y especificando propiedades adicionales.

Por favor tenga en cuenta:

  • La especificación de propiedades para palabras y variables es válida solo en el lugar de inserción, por lo tanto, para obtener la frase "héroe hermoso" debemos indicar el caso acusativo explícitamente para dos palabras: [|hero|] [hero|] .
  • El generador de texto puede "adivinar" las propiedades de la palabra por su forma, por ejemplo, en la frase [hero] [|hero] puede omitir el tiempo del verbo.
  • Las propiedades especificadas más adelante sobrescriben las propiedades especificadas anteriormente. Por ejemplo, en la frase [|hero] [hero|] , no se establecerá el acusativo del adjetivo, ya que será reemplazado por el caso nominativo del héroe variable.
  • Se puede encontrar una lista de propiedades de palabras en las páginas de la biblioteca en github y pypi.

Ejemplo de código
Python 3 requerido

Instalación

 pip install utg python -m unittest discover utg 

Código

 from utg import relations as r from utg import dictionary from utg import words from utg import templates from utg import constructors ####################################### #     ####################################### coins_forms = [#   '', '', '', '', '', '', #   '', '', '', '', '', '', #   (  , #     autofill_missed_forms) '', '', '', '', '', ''] # : ,   coins_properties = words.Properties(r.ANIMALITY.INANIMATE, r.GENDER.FEMININE) #      ,    coins_word = words.Word(type=r.WORD_TYPE.NOUN, forms=coins_forms, properties=coins_properties) #        . #      , #          : # - utg.data.WORDS_CACHES # - utg.data.INVERTED_WORDS_CACHES ############################## #     ############################## #       # (     utg.data.WORDS_CACHES[r.WORD_TYPE.VERB]) action_forms = (['', '', '', '', ''] + [''] * 15) # : ,   action_properties = words.Properties(r.ASPECT.PERFECTIVE, r.VOICE.DIRECT) action_word = words.Word(type=r.WORD_TYPE.VERB, forms=action_forms, properties=action_properties) #       (  ) action_word.autofill_missed_forms() ############################################## #       ############################################## test_dictionary = dictionary.Dictionary(words=[coins_word, action_word]) ################ #   ################ template = templates.Template() # externals —  ,      template.parse('[Npc] [|npc] [hero|] [coins] [|coins|].', externals=('hero', 'npc', 'coins')) ############################## #    ############################## hero_forms = ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''] # : ,   hero_properties = words.Properties(r.ANIMALITY.ANIMATE, r.GENDER.MASCULINE) hero = words.WordForm(words.Word(type=r.WORD_TYPE.NOUN, forms=hero_forms, properties=hero_properties)) npc_forms = ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''] # : ,   npc_properties = words.Properties(r.ANIMALITY.ANIMATE, r.GENDER.FEMININE) npc = words.WordForm(words.Word(type=r.WORD_TYPE.NOUN, forms=npc_forms, properties=npc_properties)) ########################## #   ########################## result = template.substitute(externals={'hero': hero, 'npc': npc, 'coins': constructors.construct_integer(125)}, dictionary=test_dictionary) ########################## #  ########################## result == '   125 .' 

Sobre los diccionarios


Como habrás notado, UTG requiere la formación de un diccionario. Esto se hace "a mano" ya que en el momento del desarrollo:

  • No encontré ningún diccionario morfológico cualitativo generalmente accesible.
  • La biblioteca de pymorphy seguía siendo la primera versión y, con frecuencia, entrecerraba los ojos (especialmente con el caso acusativo), por lo que tuve que abandonarla.

Si desea usar un generador con muchas palabras, antes de conducirlas manualmente, intente usar pymorphy2, o busque un diccionario listo y exporte desde él.

Total


Espero que la biblioteca sea útil.

Si tiene ideas para su desarrollo (o mejor aún, un deseo de participar en él), escriba un mensaje personal, haga solicitudes de extracción, publique errores en el github.

Source: https://habr.com/ru/post/471278/


All Articles