Wheewhh, it has sure been a busy few days here in Antwerpen on a computational creativity code-camp for building systems that automatically tell stories! Building a system focusing on computational creativity in a few days is a demanding task, but we (Jaws) think that groups managed to do pretty solid proof of concepts across the board. One thing that caught our attention especially was that several groups did collaboration on making the knowledge handed to us more suitable for their needs.
We, the group Jaws, started from the metaphorical point of view. We were interested in how we could use metaphors to map characters to other characters via their properties. However, what we ended up doing was completely another story… ahem.. Bad jokes aside, we may have bitten off more than we could chew with our initial idea. Making metaphors is a difficult task in its own right, and we still would have needed to create the actual stories based on the metaphors!
The system that was actually implemented on the code-camp follows mainly the generate and test approach. We start by generating a bunch of plot lines that in essence are sequences of actions, paired with characters that are taking the actions. Also, we select a location where the plot is taking the place. Then, we evaluate each generated plot (or story skeleton, the fabula) based on how well the the characters fit together, etc., and select the plot line which we evaluated to be the best. And realise the fabula in natural language by using idiomatic representations of the underlying actions.
To generate a single plot, we start by selecting a valid midpoint from the given knowledge base (consider the midpoint to be the main twist in a story). We then generate all possible paths from the list of story beginnings to the midpoint and from the midpoint to the story endings. For this we use a directed graph built from the action pairs given to us. Each action is a node in the graph, and edges denote that actions can be taken consecutively. To get the paths, we use a shortest path algorithm from source node to target node and simply discard all nodes that don’t have a valid path to the node.
After we have a sequence of actions, we need to select the characters that are suitable for this particular plot. For this, we use the exemplars of the selected midpoint. We have mapped each character in the NOC list to a set of exemplars. We have accomplished this by utilizing MetaphorMagnet to retrieve the typical properties of each character and exemplar. A detailed description of the approach can be read from another blog post. With the exemplar mapping, we have the possible character combinations for each midpoint and can select the most suitable one.
Having the sequence of the actions, and the characters we still need to realise the actual sentences for the story. For this we carried out some fairly simple sentence planning, linearisation, as well as rudimentary surface realisation (e.g. managing tenses, person reference, various forms of agreement, and the like). Essentially we made sure that we made use of established natural language generation techniques as much as possible in the available time.
We also wanted to develop our narrative by describing the characters and locations around which the story revolves. What we ended up doing was a set of templates for character and location descriptions, and selected at random the template to be used. However, we soon encountered a problem: setting description templates relies heavily on the mood (or atmosphere) of the location. So, we annotated the given locations with their basic mood: positive, neutral or negative. This allowed us to make more precise templates based on the mood of the location.
Of course, a lot of our implementation ended up half-assed as we ran out of time. However, we believe that we have an intriguing start for generating stories that have interesting character combinations, viable sequences of actions, and more developed narrative using setting and character descriptions that add flavor to the story.
The resources and the code generated during the code camp can be found from github.