Format de fichier .lg

S’APPLIQUE À : SDK v4

Le fichier .lg décrit les modèles de génération de langage avec des références d’entité et leur composition. Cet article décrit les différents concepts exprimés par le biais du format de fichier .lg.

Caractères spéciaux

Commentaires

Utilisez > pour créer un commentaire. Toutes les lignes qui contiennent ce préfixe seront ignorées par l’analyseur.

> This is a comment.

Caractère d’échappement

Utilisez \ comme caractère d'échappement.

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

Tableaux et objets

Création d’un tableau

Pour créer un tableau, utilisez la syntaxe ${[objet1, objet2, ...]}. Par exemple, cette expression :

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

Retourne le tableau ['a', 'b', 'c'].

Créer un objet

Pour créer un objet, utilisez la syntaxe ${{clé1:valeur1, clé2:valeur2, ...}}. Par exemple, cette expression :

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

Retourne l’objet JSON suivant :

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

Modèles

Les modèles sont le concept fondamental du système de génération de langage. Chaque modèle a un nom et l’un des éléments suivants :

  • Une liste de valeurs de texte de variante
  • Une définition de contenu structurée
  • Une collection de conditions, chacune avec :

Noms de modèles

Les noms de modèles respectent la casse et ne peuvent contenir que des lettres, des traits de soulignement et des nombres. Voici un exemple de modèle nommé TemplateName.

# TemplateName

Les modèles ne peuvent pas commencer par un nombre et toute partie d’un nom de modèle divisé par . ne peut pas commencer par un nombre.

Variantes de réponse de modèle

Les variantes sont exprimées sous la forme d’une liste Markdown. Vous pouvez préfixer chaque variante à l’aide du caractère -, ' ou +.

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

# Template2
* text variation 1
* text variation 2

# Template3
+ one
+ two

Modèle de réponse simple

Un modèle de réponse simple comprend une ou plusieurs variantes de texte utilisées pour la composition et l’expansion. L’une des variantes fournies est choisie au hasard par la bibliothèque de génération de langage.

Voici un exemple de modèle simple incluant deux variantes.

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

Modèle de réponse conditionnelle

Les modèles de réponse conditionnelle vous permettent de créer du contenu qui est sélectionné en fonction d’une condition. Toutes les conditions sont exprimées à l’aide d’expressions adaptatives.

Important

Les modèles conditionnels ne peuvent pas être imbriqués dans un modèle de réponse conditionnelle unique. Utilisez une composition dans un modèle de réponse structuré pour imbriquer des conditions.

Modèle if-else

Le modèle if-else vous permet de créer un modèle qui choisit une collection en fonction d’un ordre de conditions en cascade. L’évaluation est hiérarchisée et s’arrête lorsqu’une condition prend la valeur true ou que le bloc ELSE est atteint.

Les expressions conditionnelles sont entourées d’accolades ${}. Voici un exemple montrant une définition de modèle de réponse conditionnelle IF ELSE simple.

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

Voici un autre exemple qui illustre une définition de modèle de réponse conditionnelle if-else. Notez que vous pouvez inclure des références à d’autres modèles de réponse simple ou conditionnelle dans la variante de l’une des conditions.

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

Modèle switch

Le modèle switch vous permet de concevoir un modèle qui établit une correspondance entre la valeur d’une expression et une clause CASE, et produit une sortie basée sur ce cas. Les expressions conditionnelles sont entourées d’accolades ${}.

Voici comment vous pouvez spécifier un bloc SWITCH CASE DEFAULT dans la génération de langage.

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

Voici un exemple SWITCH CASE DEFAULT plus complexe :

> 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()}

Remarque

À l’instar des modèles conditionnels, les modèles switch ne peuvent pas être imbriqués.

Modèle de réponse structurée

Les modèles de réponse structurée vous permettent de définir une structure complexe qui prend en charge les principales fonctionnalités de génération de langage, telles que la création de modèles, la composition et la substitution, tout en laissant l’interprétation de la réponse structurée à l’appelant de la bibliothèque de génération de langage.

Pour les applications bot, nous prenons en charge en mode natif les éléments suivants :

  • définition de l'activité
  • définition de la carte

Pour plus d’informations, consultez Modèles de réponse structurés.

Composition et expansion de modèle

Références à des modèles

Le texte de la variante peut inclure des références à un autre modèle nommé pour faciliter la composition et la résolution de réponses sophistiquées. Les références à d’autres modèles nommés sont notées à l’aide d’accolades, par exemple ${<NomModele>()}.

> 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

L’appel du modèle GreetingReply peut entraîner l’une des résolutions d’expansion suivantes :

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

Entités

Lorsqu’elles sont utilisées directement dans un texte de variante ponctuelle, les références d’entités sont notées entre accolades, par exemple ${entityName}, ou sans accolades lorsqu’elles sont utilisées comme paramètre.

Les entités peuvent être utilisées comme paramètre :

Utilisation des fonctions prédéfinies dans des variantes

Les fonctions prédéfinies prises en charge par des expressions adaptatives peuvent également être utilisées en ligne dans un texte de variante ponctuelle pour obtenir une composition de texte encore plus puissante. Pour utiliser une expression inline, entourez-la simplement d’accolades.

# 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.

L’exemple ci-dessus utilise la fonction join prédéfinie pour répertorier toutes les valeurs de la collection recentTasks.

Étant donné que les modèles et les fonctions prédéfinies partagent la même signature d’appel, un nom de modèle ne peut pas être identique à un nom de fonction prédéfinie.

Un nom de modèle ne doit pas correspondre à un nom de fonction prédéfinie. La fonction prédéfinie est prioritaire. Pour éviter de tels conflits, vous pouvez ajouter lg. lorsque vous référencez le nom de votre modèle. Par exemple :

> 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')}

Texte multiligne dans les variantes

Chaque variante peut inclure du texte multiligne entre guillemets triples.

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

Une variante multiligne peut demander un modèle d’expansion et une substitution d’entité en mettant l’opération demandée entre accolades, ${}.

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

Avec la prise en charge multiligne, le sous-système de génération de langage peut résoudre entièrement un élément JSON ou XML complexe (par exemple un texte SSML encapsulé pour contrôler la réponse énoncée par le bot).

Paramétrage de modèles

Pour faciliter la réutilisation contextuelle, les modèles peuvent être paramétrés. Différents appelants du modèle peuvent passer des valeurs différentes pour une utilisation dans la résolution de l’expansion.

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

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

# timeOfDayGreeting
- ${timeOfDayGreetingTemplate(timeOfDay)}

Importation de références externes

Vous pouvez fractionner vos modèles de génération de langage en fichiers distincts et référencer un modèle d’un fichier à un autre. Vous pouvez utiliser des liens de style Markdown pour importer des modèles définis dans un autre fichier.

[Link description](filePathOrUri)

Tous les modèles définis dans le fichier cible seront extraits. Assurez-vous que les noms de vos modèles sont uniques (ou avec un espace de noms # \<namespace>.\<templatename>) pour tous les fichiers en cours d’extraction.

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

Fonctions injectées par la génération de langage

Les expressions adaptatives permettent d’injecter un jeu personnalisé de fonctions. Pour plus d’informations, consultez Fonctions injectées à partir de la bibliothèque de génération de langage.

Options

Les développeurs peuvent définir des options d’analyseur pour personnaliser davantage l’évaluation de l’entrée. Utilisez la notation > !# pour définir les options de l’analyseur.

Important

Le dernier paramètre trouvé dans le fichier prévaut sur tout paramètre antérieur trouvé dans le même document.

Option strict

Les développeurs qui ne souhaitent pas autoriser un résultat null pour un résultat évalué comme null peuvent implémenter l’option strict. Vous trouverez ci-dessous un exemple simple d’option strict :

> !# @strict = true
# template
- hi

Si l’option strict est activée, les erreurs null génèrent un message convivial.

# welcome
- hi ${name}

Si le nom est null, le diagnostic est 'name' evaluated to null. [welcome] Error occurred when evaluating '- hi ${name}'.. Si l’option strict a la valeur false ou n’est pas définie, un résultat compatible sera fourni. L’exemple ci-dessus génère hi null.

Option replaceNull

Les développeurs peuvent créer des délégués pour remplacer des valeurs NULL dans des expressions évaluées à l’aide de l’option replaceNull :

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

Dans l’exemple ci-dessus, l’entrée null de la variable path est remplacée par ${path} is undefined. L’entrée suivante, où user.name a la valeur null :

hi ${user.name}

Se traduirait par hi user.name is undefined.

Option lineBreakStyle

Les développeurs peuvent définir des options de rendu des sauts de ligne par le système de génération de langage à l’aide de l’option lineBreakStyle. Deux modes sont actuellement pris en charge :

  • default : les sauts de ligne dans un texte multiligne créent des sauts de ligne normaux.
  • markdown : les sauts de ligne dans un texte multiligne sont convertis automatiquement en deux lignes pour créer un saut de ligne

L’exemple ci-dessous montre comment définir l’option lineBreakStyle sur markdown :

> !# @lineBreakStyle = markdown

Option Espace de noms

Vous pouvez inscrire un espace de noms pour les modèles LG que vous voulez exporter. Si aucun espace de noms n’est spécifié, l’espace de noms est défini sur le nom de fichier sans extension.

L’exemple ci-dessous montre comment définir l’option Espace de noms sur foo :

> !# @Namespace = foo

Option Exportations

Vous pouvez spécifier une liste de modèles LG à exporter. Les modèles exportés peuvent être appelés comme des fonctions prédéfinies.

L’exemple ci-dessous montre comment définir l’option Exportations sur template1, template2 :

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

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

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

Utilisez foo.template1(1,2), foo.template2(['a', 'b', 'c'], ',') pour appeler ces modèles exportés.

Étendue du cache

Les options d’étendue du cache vous permettent de contrôler quand l’évaluateur LG réévalue une expression qu’il a vue avant et quand il stocke et utilise un résultat mis en cache.

  • Le cache global est efficace dans le cycle de vie d’une évaluation. LG met en cache tous les résultats d’évaluation, et si le nom et les paramètres du modèle sont identiques, retourne le résultat du cache.
  • L’étendue du cache local est la valeur par défaut. Dans la même couche, si le modèle précédent a été appelé avec le même nom de modèle et les mêmes paramètres, le résultat mis en cache est directement retourné.
  • L’étendue de cache Aucune désactive toute l’étendue du cache, et retourne chaque fois le nouveau résultat.

Pour obtenir des exemples, consultez les exemples d’étendue globale et locale de cache.

> !# @cacheScope= global // global cache
> !# @cacheScope= local // local cache
> !# @cacheScope= none // none cache
> !# @cacheScope= xxx // fallback to local cache

Notez que l’option d’étendue du cache ne respecte pas la casse.

> !# @cacheScope= global // ok
> !# @CACHESCOPE= global // ok
> !# @cachescope= global // ok

Notez que l’étendue du cache suit l’étendue du fichier Microsoft Entrance .lg.

Supposons que vous avez deux fichiers : a.lg et b.lg, comme illustré ci-dessous :

a.lg

> !# @cacheScope= global
 [import](b.lg)

b.lg

> !# @cacheScope= none
# template1
- ${template2()} ${template2()}

# template2
- ${rand(1, 10000000)}

Si vous exécutez le code suivant, vous remarquerez que template2 utilise le résultat mis en cache du premier résultat évalué en raison de l’option d’étendue du cache global dans a.lg :

var templates = Templates.ParseFile("a.lg");
var result = templates.Evaluate("template1"); // the second "template2" would use the cache of the first evaluate result

Influence de la marque de réexécution

Si le nom du modèle se termine par « ! », le modèle force la réexécution. Ce résultat n’est pas ajouté au cache, quelle que soit l’étendue du cache.

Supposons que vous ayez le modèle suivant :

# template2
- ${template1()} ${template1!()} ${template1()}

template1!() se déclenche et le résultat est ajouté au cache. Le deuxième template1() frappe le résultat du premier template1(). L’appel final utilise les résultats stockés dans le cache.

Exemple d’étendue globale du cache

Supposez que vous disposiez des modèles suivants :

# template1
- ${template2()} ${template3()}

# template2
- ${rand(1, 10)}
- abc
- hi

# template3
- ${template2()}

template2 serait évaluée une fois, et la deuxième exécution dans template3 appliquerait le cache du premier.

Autre exemple : l’extrait de code suivant :

var templates = Templates.ParseFile("xxx.lg");
var result1 = templates.Evaluate("template", null, new EvaluationOptions { CacheScope = LGCacheScope.Global});

// The second evaluation would drop all the results cached before.
var result2 = templates.Evaluate("template", null, new EvaluationOptions { CacheScope = LGCacheScope.Global});

Un modèle est analysé à l’aide de la fonction Templates.ParseFile(), et les résultats d’évaluation du modèle sont stockés dans result1. Notez que les résultats de la deuxième évaluation, result2, suppriment tous les résultats précédemment mis en cache.

Exemple d’étendue du cache local

Les exemples suivants montrent quand l’étendue du cache local fonctionne et ne fonctionne pas. Supposons que t() et subT() sont des modèles qui prennent un paramètre :

>  Cache works, the second template call would re-use the first's result.
# template1
- ${t(param)} ${t(param)}

> Cache doesn't work because param1's value is different with param2's. value)
# template2
- ${t(param1)} ${t(param2)}

> Cache doesn't work because of different layers.
# template3
- ${subT(param1)} ${t(param2)}

# subT(param)
- ${t(param)}

Ressources complémentaires