Conceptual Storytelling

A fable of semantic primitives

August 16, 2018
nanogenmo nlg narrative

While on holiday I finally have the energy to do a bit more work on my NaNoGenMo project, which of course is far too ambitious for a single month. At the moment I’m doing a bit more work on generating natural language text from an internal formal representation, conceptual dependency. Here you have a set of semantic primitives that are turned into English (or any other language, eventually). The idea is that the computer manipulates a simulated world, producing a list of such statements, which are then rendered into text.

To practice working above sentence level I have tried encoding a fable (The Ant and the Dove) in the right format. Not too tricky after a bit of thought: you need to first rephrase the sentences as a set of simple propositions using the primitives, and then translation is not too hard. Also, replace the picture producers (ie noun groups) by a set of entities that can be easily referred to by id value throughout.

Here is the original fable:

The Ant and the Dove

AN ANT went to the bank of a river to quench its thirst, and being carried away by the rush of the stream, was on the point of drowning. A Dove sitting on a tree overhanging the water plucked a leaf and let it fall into the stream close to her. The Ant climbed onto it and floated in safety to the bank. Shortly afterwards a birdcatcher came and stood under the tree, and laid his lime-twigs for the Dove, which sat in the branches. The Ant, perceiving his design, stung him in the foot. In pain the birdcatcher threw down the twigs, and the noise made the Dove take wing.

One good turn deserves another

And, after some (minor) simplification, this is the fable in conceptual dependency format – a list of Lisp/Scheme expressions with the semantic primitives and their arguments:

((pp (class being)
     (label "ant")
     (id 0)
     (features animal)
     (type "ant"))
 (pp (class location) (label "river bank") (id 1))
 (pp (class location) (label "river") (id 2))
 (pp (class being)
     (label "dove")
     (id 3)
     (features animal can-fly)
     (type "dove"))
 (pp (class object)
     (label "leaf")
     (id 4)
     (features plant)
     (type "leaf"))
 (pp (class being)
     (label "bird catcher")
     (id 5)
     (features human)
     (type "human"))
 (pp (class location) (label "tree") (id 6))
 (pp (class object)
     (label "trap")
     (id 7)
     (type "trap"))
 (pp (class object)
     (label "water")
     (features liquid edible)
     (id 9))
 (thirsty (actor (pp (id 0))))
 (plan (actor (pp (id 0)))
       (object
         (ingest (actor (pp (id 0))) (object (pp (id 9))))))
 (ptrans
   (actor (pp (id 0)))
   (object (pp (id 0)))
   (to (pp (id 1))))
 (ptrans
   (actor gravity)
   (object (pp (id 0)))
   (from (pp (id 1)))
   (to (pp (id 2))))
 (loc (actor (pp (id 0))) (val (pp (id 2))))
 (loc (actor (pp (id 3))) (val (pp (id 6))))
 (loc (actor (pp (id 6)))
      (val (above (pp (id 2)))))
 (loc (actor (pp (id 4))) (val (pp (id 6))))
 (grasp (actor (pp (id 3))) (object (pp (id 4))))
 (grasp (actor (pp (id 3)))
        (object (pp (id 4)))
        (mode (tf)))
 (ptrans
   (actor gravity)
   (object (pp (id 4)))
   (from (pp (id 6)))
   (to (pp (id 2))))
 (loc (actor (pp (id 4))) (val (pp (id 2))))
 (ptrans
   (actor (pp (id 0)))
   (object (pp (id 0)))
   (from (pp (id 2)))
   (to (pp (id 4))))
 (ptrans
   (object (pp (id 4)))
   (from (pp (id 2)))
   (to (pp (id 1))))
 (ptrans
   (actor (pp (id 0)))
   (object (pp (id 0)))
   (from (pp (id 4)))
   (to (pp (id 1))))
 (like (actor (pp (id 0))) (to (pp (id 3))))
 (loc (actor (pp (id 5))) (val (pp (id 1))))
 (loc (actor (pp (id 3))) (val (pp (id 6))))
 (plan (actor (pp (id 5)))
       (object
         (grasp (actor (pp (id 5))) (object (pp (id 3))))))
 (grasp (actor (pp (id 5))) (object (pp (id 7))))
 (mtrans
   (actor (pp (id 0)))
   (object (pp (id 5)))
   (from eye)
   (to memory))
 (mloc (actor (pp (id 0)))
       (object
         (plan (actor (pp (id 5)))
               (object
                 (grasp (actor (pp (id 5))) (object (pp (id 3))))))))
 (like (actor (pp (id 0)))
       (to (pp (id 5)))
       (mode (neg)))
 (propel (actor (pp (id 0))) (to (pp (id 5))))
 (health (actor (pp (id 5))) (val 3))
 (grasp (actor (pp (id 5)))
        (object (pp (id 7)))
        (mode (tf)))
 (mtrans
   (actor (pp (id 3)))
   (object
     (grasp (actor (pp (id 5)))
            (object (pp (id 7)))
            (mode (tf))))
   (from ear)
   (to memory))
 (mloc (actor (pp (id 3)))
       (object
         (plan (actor (pp (id 5)))
               (object
                 (grasp (actor (pp (id 5))) (object (pp (id 3))))))))
 (ptrans
   (actor (pp (id 3)))
   (object (pp (id 3)))
   (from (pp (id 6)))))

The most common primitive is ptrans, which is a physical transfer, either moving or going, depending on whether the actor and the object are the same thing. Then, loc describes the location of something, and mloc is about thinking.

So, what do we do with this? The first step is to put this back into (English) prose. This is done with a program based on an old module called mumble. It takes as input a list of CD structures (as above) and puts out English sentences. Depending on the primitive and certain features of the actor and object, an appropriate verb and sentence structure is chosen. After some minor tweaking we get the following output:

The ant is thirsty. The ant plans to drink water. The ant goes to the river bank. The ant falls from the river bank into the river. The ant is in the river. The dove is in a tree. A tree is in the river. A leaf is in a tree. The dove picks up a leaf. The dove lets go of a leaf. A leaf falls from a tree into the river. A leaf is in the river. The ant goes to a leaf. A leaf goes to the river bank. The ant goes to the river bank. The ant likes the dove. The bird catcher is on the river bank. The dove is in a tree. The bird catcher plans to pick up the dove. The bird catcher picks up a trap. The ant sees the bird catcher. The ant thinks that the bird catcher plans to pick up the dove. The ant does not like the bird catcher. The ant strikes the bird catcher. The bird catcher is somewhat ill. The bird catcher lets go of a trap. The dove hears that the bird catcher lets go of a trap. The dove thinks that the bird catcher plans to pick up the dove. The dove leaves from a tree.

END

There are several ways to make this more ‘natural’ and less computery. At first we need to look at definite/indefinite: we always say the ant, and the dove, as if there was only one. Ideally we would want an ant and a dove, at least until they have been mentioned once. After that we switch to the definite article to refer back to the particular animal. And pronouns would be good.

Still lots of scope for improvement!