Template-Based Text Generation

Written by on September 28, 2020 in LISP, Natural Language Processing, Programming with 0 Comments

I had written earlier about natural language generation using my iLangGen framework. I used a “template” text file which was instantiated dynamically based on predefined “grammars” and external data. The sample application I show-cased demonstrated its utility and versatility.

Today I would like to touch upon a few other “pattern” elements that can be embedded in the template. All these patterns, including the ability to specify grammar rules,  make this template-based approach quite powerful and applicable in real-world applications.   

Structure of Template File

The template file can have normal text that will be instantiated, as well as supporting code fragments (only Lisp is supported as of now).

The “text” section starts with the marker “@text” and ends with “@end”. Code section starts with the marker “@code” and ends with “@end”. In case many functions are to be defined, it might be convenient to keep the code in a separate file and reference it using “@code-file” marker.

Here is the overall structure example:

@code-file “utils.lisp”

@text

The actual template text goes here…

@end

Anything in this area (outside of sections) is ignored..

@code

Lisp code goes here…

@end

Supported Patterns

The text section contains the actual text that gets instantiated based on different patterns embedded in it.

A pattern is defined within the delimiters “{{“ and “}}”. The different patterns are

Grammar Pattern:

We saw this example in the earlier article. It is of the form {{Grammar::Non-Terminal}}. During instantiation, the grammar is invoked starting at the specified non-terminal.

Immediate Value:

This has the form {{! $1}}. The variable “$1” specifies the first argument passed to the template processor function. Allowed variables are “$1” … “$5”. As part of template expansion, the variable’s value is directly substituted at the place where the pattern appears.

Function Call:

Similar to the grammar pattern, function application gives tremendous expressive power to the template structure. It looks like this: {{function arg1 arg2 arg3}}. The arguments can be literals or the run-time parameters “$1” … “$5”.

Embedded Template:

It is possible to specify another template file to be instantiated and the result embedded as part of this template instantiation. The syntax is {{<  another-template-file.txt}}. This is another feature of immense value since we can now allow template composition and hence take advantage of reusable structures.

Here is a sample template file.

Template File

Template File

The above template contains one “Immediate Value” pattern and two “Function Call” patterns. You can also see the code section that contains a single function definition and also a reference to an external code file. Here is the code file:

External Lisp Code

External Lisp Code

Instantiating the Template

Template instantiation occurs through the function call “process-template-file”. See the invocation below:

Instantiating the Template

Instantiating the Template

The first argument is the template file to be instantiated and the remaining arguments (optional) represent the run-time arguments “$1” … “$5” we mentioned earlier. You can see how the template gets instantiated.

This example does not use the “Embedded Template” pattern. I will discuss this pattern and its usage in detail in a future article.

Hope you find the idea interesting. iLangGen framework and the template-based generation engine are all written in LispWorks Lisp.

Have a great week!

Tags: , , ,

Subscribe

If you enjoyed this article, subscribe now to receive more just like it.

Subscribe via RSS Feed

Leave a Reply

Your email address will not be published.

Top