.lg file format

APPLIES TO: SDK v4

The .lg file describes language generation templates with entity references and their composition. This article covers the various concepts expressed with the .lg file format.

Special Characters

Comments

Use > to create a comment. All lines that have this prefix will be skipped by the parser.

> This is a comment.

Escape character

Use \ as an escape character.

# TemplateName
- You can say cheese and tomato \[toppings are optional\]

Arrays and objects

Create an array

To create an array, use the ${[object1, object2, ...]} syntax. For example, this expression:

${['a', 'b', 'c']}

Returns the array ['a', 'b', 'c'].

Create an object

To create an object, use the ${{key1:value1, key2:value2, ...}} syntax. For example, this expression:

${{user: {name: "Wilson", age: 27}}}

Returns the following JSON object:

{
  "user": {
    "name": "Wilson",
    "age": 27
  }
}

Templates

Templates are the core concept of the language generation system. Each template has a name and one of the following:

  • a list of one-of variation text values
  • a structured content definition
  • a collection of conditions, each with:

Template names

Template names are case-sensitive and can only contain letters, underscores, and numbers. The following is an example of a template named TemplateName.

# TemplateName

Templates cannot start with a number, and any part of a template name split by . cannot start with a number.

Template response variations

Variations are expressed as a Markdown list. You can prefix each variation using the -, ', or + character.

# Template1
- text variation 1
- text variation 2
- one
- two

# Template2
* text variation 1
* text variation 2

# Template3
+ one
+ two

Simple response template

A simple response template includes one or more variations of text that are used for composition and expansion. One of the variations provided will be selected at random by the LG library.

Here is an example of a simple template that includes two variations.

> Greeting template with two variations.
# GreetingPrefix
- Hi
- Hello

Conditional response template

Conditional response templates let you author content that's selected based on a condition. All conditions are expressed using adaptive expressions.

Important

Conditional templates cannot be nested in a single conditional response template. Use composition in a structured response template to nest conditionals.

If-else template

The if-else template lets you build a template that picks a collection based on a cascading order of conditions. Evaluation is top-down and stops when a condition evaluates to true or the ELSE block is hit.

Conditional expressions are enclosed in braces ${}. Here's an example that shows a simple IF ELSE conditional response template definition.

> time of day greeting reply template with conditions.
# timeOfDayGreeting
- IF: ${timeOfDay == 'morning'}
    - good morning
- ELSE:
    - good evening

Here's another example that shows an if-else conditional response template definition. Note that you can include references to other simple or conditional response templates in the variation for any of the conditions.

# timeOfDayGreeting
- IF: ${timeOfDay == 'morning'}
    - ${morningTemplate()}
- ELSEIF: ${timeOfDay == 'afternoon'}
    - ${afternoonTemplate()}
- ELSE:
    - I love the evenings! Just saying. ${eveningTemplate()}

Switch template

The switch template lets you design a template that matches an expression's value to a CASE clause and produces output based on that case. Condition expressions are enclosed in braces ${}.

Here's how you can specify a SWITCH CASE DEFAULT block in LG.

# TestTemplate
- SWITCH: ${condition}
- CASE: ${case-expression-1}
    - output1
- CASE: ${case-expression-2}
    - output2
- DEFAULT:
   - final output

Here's a more complicated SWITCH CASE DEFAULT example:

> Note: Any of the cases can include reference to one or more templates.
# greetInAWeek
- SWITCH: ${dayOfWeek(utcNow())}
- CASE: ${0}
    - Happy Sunday!
-CASE: ${6}
    - Happy Saturday!
-DEFAULT:
    - ${apology-phrase()}, ${defaultResponseTemplate()}

Note

Like conditional templates, switch templates cannot be nested.

Structured response template

Structured response templates let you define a complex structure that supports major LG functionality, like templating, composition, and substitution, while leaving the interpretation of the structured response up to the caller of the LG library.

For bot applications, we natively support:

  • activity definition
  • card definition

Read about structure response templates for more information.

Template composition and expansion

References to templates

Variation text can include references to another named template to aid with composition and resolution of sophisticated responses. References to other named templates are denoted using braces, such as ${<TemplateName>()}.

> Example of a template that includes composition reference to another template.
# GreetingReply
- ${GreetingPrefix()}, ${timeOfDayGreeting()}

# GreetingPrefix
- Hi
- Hello

# timeOfDayGreeting
- IF: ${timeOfDay == 'morning'}
    - good morning
- ELSEIF: ${timeOfDay == 'afternoon'}
    - good afternoon
- ELSE:
    - good evening

Calling the GreetingReply template can result in one of the following expansion resolutions:

Hi, good morning
Hi, good afternoon
Hi, good evening
Hello, good morning
Hello, good afternoon
Hello, good evening

Entities

When used directly within a one-of variation text, entity references are denoted by enclosing them in braces, such as ${entityName}, or without braces when used as a parameter.

Entities can be used as a parameter:

Using prebuilt functions in variations

Prebuilt functions supported by adaptive expressions can also be used inline in a one-of variation text to achieve even more powerful text composition. To use an expression inline, simply wrap it in braces.

# RecentTasks
- IF: ${count(recentTasks) == 1}
    - Your most recent task is ${recentTasks[0]}. You can let me know if you want to add or complete a task.
- ELSEIF: ${count(recentTasks) == 2}
    - Your most recent tasks are ${join(recentTasks, ', ', ' and ')}. You can let me know if you want to add or complete a task.
- ELSEIF: ${count(recentTasks) > 2}
    - Your most recent ${count(recentTasks)} tasks are ${join(recentTasks, ', ', ' and ')}. You can let me know if you want to add or complete a task.
- ELSE:
    - You don't have any tasks.

The example above uses the join prebuilt function to list all values in the recentTasks collection.

Given templates and prebuilt functions share the same invocation signature, a template name cannot be the same as a prebuilt function name.

A template name should not match a prebuilt function name. The prebuilt function takes precedence. To avoid such conflicts, you can prepend lg. when referencing your template name. For example:

> Custom length function with one parameter.
# length(a)
- This is use's customized length function

# myfunc1
> will call prebuilt function length, and return 2
- ${length('hi')}

# mufunc2
> this calls the lg template and output 'This is use's customized length function'
- ${lg.length('hi')}

Multiline text in variations

Each one-of variation can include multiline text enclosed in triple quotes.

# MultiLineExample
    - ```This is a multiline list
        - one
        - two
        ```
    - ```This is a multiline variation
        - three
        - four
    ```

Multiline variation can request template expansion and entity substitution by enclosing the requested operation in braces, ${}.

# MultiLineExample
    - ```
        Here is what I have for the order
        - Title: ${reservation.title}
        - Location: ${reservation.location}
        - Date/ time: ${reservation.dateTimeReadBack}
    ```

With multiline support, you can have the Language Generation sub-system fully resolve a complex JSON or XML (like SSML wrapped text to control bot's spoken reply).

Parametrization of templates

To aid with contextual reusability, templates can be parametrized. Different callers to the template can pass in different values for use in expansion resolution.

# timeOfDayGreetingTemplate (param1)
- IF: ${param1 == 'morning'}
    - good morning
- ELSEIF: ${param1 == 'afternoon'}
    - good afternoon
- ELSE:
    - good evening

# morningGreeting
- ${timeOfDayGreetingTemplate('morning')}

# timeOfDayGreeting
- ${timeOfDayGreetingTemplate(timeOfDay)}

Importing external references

You can split your language generation templates into separate files and reference a template from one file in another. You can use Markdown-style links to import templates defined in another file.

[Link description](filePathOrUri)

All templates defined in the target file will be pulled in. Ensure that your template names are unique (or namespaced with # \<namespace>.\<templatename>) across files being pulled in.

[Shared](../shared/common.lg)

Functions injected by LG

Adaptive expressions provide the ability to inject a custom set of functions. Read functions injected from the LG library for more information.

Options

Developers can set parser options to further customize how input is evaluated. Use the > !# notation to set parser options.

Important

The last setting found in the file trumps any prior setting found in the same document.

Strict option

Developers who do not want to allow a null result for a null evaluated result can implement the strict option. Below is an example of a simple strict option:

> !# @strict = true
# template
- hi

If the strict option is on, null errors will throw a friendly message.

# welcome
- hi ${name}

If name is null, the diagnostic would be 'name' evaluated to null. [welcome] Error occurred when evaluating '- hi ${name}'.. If strict is set to false or not set, a compatible result will be given. The above sample would produce hi null.

replaceNull option

Developers can create delegates to replace null values in evaluated expressions by using the replaceNull option:

> !# @replaceNull = ${path} is undefined

In the above example, the null input in the path variable would be replaced with ${path} is undefined. The following input, where user.name is null: :

hi ${user.name}

Would result in hi user.name is undefined.

lineBreakStyle option

Developers can set options for how the LG system renders line breaks using the lineBreakStyle option. Two modes are currently supported:

  • default: line breaks in multiline text create normal line breaks.
  • markdown: line breaks in multiline text will be automatically converted to two lines to create a newline

The example below shows how to set the lineBreakStyle option to markdown:

> !# @lineBreakStyle = markdown

Namespace option

You can register a namespace for the LG templates you want to export. If there is no namespace specified, the namespace will be set to the filename without an extension.

The example below shows how to set the namespace option to foo:

> !# @Namespace = foo

Exports option

You can specify a list of LG templates to export. The exported templates can be called like prebuilt functions.

The example below shows how to set the exports option to template1, template2:

> !# @Namespace = foo
> !# @Exports = template1, template2

# template1(a, b)
- ${a + b}

# template2(a, b)
- ${join(a, b)}

Use foo.template1(1,2), foo.template2(['a', 'b', 'c'], ',') to call these exported templates.

Additional Resources