Partilhar via


Formato de arquivo .lg

APLICA-SE A: SDK v4

O arquivo .lg descreve modelos de geração de linguagem com referências de entidade e sua composição. Este artigo aborda os vários conceitos expressos com o formato de arquivo .lg.

Caracteres especiais

Comentários

Use > para criar um comentário. Todas as linhas que têm esse prefixo serão ignoradas pelo analisador.

> This is a comment.

Personagem de fuga

Use \ como um personagem de fuga.

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

Matrizes e objetos

Criar uma matriz

Para criar uma matriz, use a sintaxe ${[object1, object2, ...]} . Por exemplo, esta expressão:

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

Retorna a matriz ['a', 'b', 'c'].

Criar um objeto

Para criar um objeto, use a sintaxe ${{key1:value1, key2:value2, ...}} . Por exemplo, esta expressão:

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

Retorna o seguinte objeto JSON:

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

Modelos

Os modelos são o conceito central do sistema de geração de línguas. Cada modelo tem um nome e um dos seguintes:

  • uma lista de valores de texto de variação
  • uma definição de conteúdo estruturado
  • um conjunto de condições, cada uma com:

Nomes de modelos

Os nomes dos modelos diferenciam maiúsculas de minúsculas e só podem conter letras, sublinhados e números. Segue-se um exemplo de um modelo denominado TemplateName.

# TemplateName

Os modelos não podem começar com um número, e qualquer parte de um nome de modelo dividido por . não pode começar com um número.

Variações de resposta do modelo

As variações são expressas como uma lista de Markdown. Você pode prefixar cada variação usando o -caractere , ', ou + .

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

# Template2
* text variation 1
* text variation 2

# Template3
+ one
+ two

Modelo de resposta simples

Um modelo de resposta simples inclui uma ou mais variações de texto que são usadas para composição e expansão. Uma das variações fornecidas será selecionada aleatoriamente pela biblioteca LG.

Aqui está um exemplo de um modelo simples que inclui duas variações.

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

Modelo de resposta condicional

Os modelos de resposta condicional permitem criar conteúdo selecionado com base em uma condição. Todas as condições são expressas usando expressões adaptativas.

Importante

Os modelos condicionais não podem ser aninhados em um único modelo de resposta condicional. Use a composição em um modelo de resposta estruturado para aninhar condicionais.

Modelo If-else

O modelo if-else permite criar um modelo que seleciona uma coleção com base em uma ordem em cascata de condições. A avaliação é de cima para baixo e para quando uma condição é avaliada ou true o bloco ELSE é atingido.

As expressões condicionais são incluídas entre chaves ${}. Aqui está um exemplo que mostra uma definição simples de modelo de resposta condicional IF ELSE.

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

Aqui está outro exemplo que mostra uma definição de modelo de resposta condicional if-else. Observe que você pode incluir referências a outros modelos de resposta simples ou condicional na variação para qualquer uma das condições.

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

Mudar de modelo

O modelo de opção permite criar um modelo que corresponde ao valor de uma expressão a uma cláusula CASE e produz saída com base nesse caso. As expressões de condição estão entre chaves ${}.

Veja como você pode especificar um bloco SWITCH CASE DEFAULT na LG.

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

Aqui está um exemplo mais complicado de SWITCH CASE DEFAULT:

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

Nota

Como os modelos condicionais, os modelos de alternância não podem ser aninhados.

Modelo de resposta estruturado

Os modelos de resposta estruturada permitem definir uma estrutura complexa que suporta as principais funcionalidades da LG, como modelos, composição e substituição, deixando a interpretação da resposta estruturada para o chamador da biblioteca LG.

Para aplicativos de bot, suportamos nativamente:

  • definição da atividade
  • Definição do cartão

Leia sobre modelos de resposta de estrutura para obter mais informações.

Composição e expansão do modelo

Referências a modelos

O texto de variação pode incluir referências a outro modelo nomeado para ajudar na composição e resolução de respostas sofisticadas. As referências a outros modelos nomeados são indicadas usando chaves, como ${<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

Chamar o GreetingReply modelo pode resultar em uma das seguintes resoluções de expansão:

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

Entidades

Quando usadas diretamente em um texto de variação, as referências de entidade são indicadas colocando-as entre chaves, como ${entityName}, ou sem chaves quando usadas como parâmetro.

As entidades podem ser usadas como parâmetro:

Usando funções pré-construídas em variações

Funções pré-construídas suportadas por expressões adaptáveis também podem ser usadas em linha em um texto de variação para obter uma composição de texto ainda mais poderosa. Para usar uma expressão embutida, basta envolvê-la em chaves.

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

O exemplo acima usa a função join prebuilt para listar todos os valores na recentTasks coleção.

Como os modelos e as funções pré-criadas compartilham a mesma assinatura de invocação, um nome de modelo não pode ser o mesmo que um nome de função pré-construído.

Um nome de modelo não deve corresponder a um nome de função pré-criado. A função pré-construída tem precedência. Para evitar esses conflitos, você pode antecipar lg. ao fazer referência ao nome do modelo. Por exemplo:

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

Texto multilinha em variações

Cada uma das variações pode incluir texto de várias linhas entre aspas triplas.

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

A variação de várias linhas pode solicitar expansão de modelo e substituição de entidade colocando a operação solicitada em chaves, ${}.

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

Com suporte a várias linhas, você pode fazer com que o subsistema Language Generation resolva totalmente um JSON ou XML complexo (como texto quebrado SSML para controlar a resposta falada do bot).

Parametrização de modelos

Para ajudar na reutilização contextual, os modelos podem ser parametrizados. Diferentes chamadores para o modelo podem passar valores diferentes para uso na resolução de expansão.

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

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

# timeOfDayGreeting
- ${timeOfDayGreetingTemplate(timeOfDay)}

Importação de referências externas

Você pode dividir seus modelos de geração de idiomas em arquivos separados e fazer referência a um modelo de um arquivo em outro. Você pode usar links no estilo Markdown para importar modelos definidos em outro arquivo.

[Link description](filePathOrUri)

Todos os modelos definidos no arquivo de destino serão puxados. Certifique-se de que os nomes dos modelos são exclusivos (ou namespaces com # \<namespace>.\<templatename>) entre os arquivos que estão sendo puxados.

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

Funções injetadas pela LG

As expressões adaptativas fornecem a capacidade de injetar um conjunto personalizado de funções. Leia as funções injetadas da biblioteca LG para obter mais informações.

Opções

Os desenvolvedores podem definir opções de analisador para personalizar ainda mais como a entrada é avaliada. Use a notação para definir as opções do > !# analisador.

Importante

A última configuração encontrada no arquivo supera qualquer configuração anterior encontrada no mesmo documento.

Opção estrita

Os desenvolvedores que não querem permitir um resultado nulo para um resultado avaliado nulo podem implementar a opção strict. Abaixo está um exemplo de uma opção estrita simples:

> !# @strict = true
# template
- hi

Se a opção estrita estiver ativada, erros nulos lançarão uma mensagem amigável.

# welcome
- hi ${name}

Se name for null, o diagnóstico será 'name' avaliado como null. [bem-vindo] Ocorreu um erro ao avaliar '- oi ${name}'.. Se strict estiver definido como false ou não definido, será dado um resultado compatível. A amostra acima produziria hi null.

opção replaceNull

Os desenvolvedores podem criar delegados para substituir valores nulos em expressões avaliadas usando a opção replaceNull :

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

No exemplo acima, a entrada nula na variável seria substituída path por ${path} é indefinido. A seguinte entrada, onde user.name é null: :

hi ${user.name}

Resultaria em oi user.name é indefinido.

opção lineBreakStyle

Os desenvolvedores podem definir opções para como o sistema LG processa quebras de linha usando a opção lineBreakStyle . Atualmente, há suporte para dois modos:

  • default: quebras de linha em texto com várias linhas criam quebras de linha normais.
  • markdown: quebras de linha em texto com várias linhas serão automaticamente convertidas em duas linhas para criar uma nova linha

O exemplo abaixo mostra como definir a opção lineBreakStyle como markdown:

> !# @lineBreakStyle = markdown

Opção de namespace

Você pode registrar um namespace para os modelos LG que deseja exportar. Se não houver nenhum namespace especificado, o namespace será definido como o nome do arquivo sem uma extensão.

O exemplo abaixo mostra como definir a opção de namespace como foo:

> !# @Namespace = foo

Opção de exportação

Você pode especificar uma lista de modelos LG para exportar. Os modelos exportados podem ser chamados como funções pré-construídas.

O exemplo abaixo mostra como definir a opção de exportação como 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'], ',') para chamar esses modelos exportados.

Escopo do cache

As opções de escopo de cache permitem controlar quando o avaliador LG reavalia uma expressão que já viu antes e quando armazena e usa um resultado armazenado em cache.

  • O cache global é eficaz no ciclo de vida de uma avaliação. A LG armazena em cache todos os resultados da avaliação e, se o nome do modelo e os parâmetros forem os mesmos, retorna o resultado do cache.
  • O escopo do cache local é o padrão. Na mesma camada, se o modelo anterior tiver sido chamado com o mesmo nome de modelo e os mesmos parâmetros, o resultado armazenado em cache será retornado diretamente.
  • Nenhum escopo de cache desabilita todo o escopo de cache e cada vez retorna o novo resultado.

Para obter exemplos, consulte os exemplos de escopo de cache global e local .

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

Observe que a opção de escopo do cache não diferencia maiúsculas de minúsculas.

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

Observe que o escopo do cache segue o escopo do arquivo .lg do Microsoft Entry.

Digamos que você tenha dois arquivos: e b.lg, mostrado abaixo: a.lg

a.lg

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

B.LG

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

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

Se você executar o código a seguir, notará que template2 usa o resultado armazenado em cache do primeiro resultado avaliado devido à global opção de escopo do cache em 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

Executar novamente a influência da marca

Se o nome do modelo terminar com "!", o modelo forçará a reexecução. Esse resultado não será adicionado ao cache, independentemente do escopo do cache.

Digamos que você tenha o seguinte modelo:

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

template1!() e o resultado é adicionado ao cache. O segundo template1() fecha o resultado do primeiro template1(). A chamada final usa os resultados armazenados no cache.

Exemplo de escopo de cache global

Digamos que você tenha os seguintes modelos:

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

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

# template3
- ${template2()}

template2 seria avaliada uma vez, e a segunda execução aplicaria template3 o cache da primeira.

Outro exemplo está no seguinte trecho de código:

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

Um modelo é analisado usando a Templates.ParseFile() função e os resultados da avaliação do modelo são armazenados em result1. Observe que os resultados da segunda avaliação, , result2descartam todos os resultados armazenados anteriormente em cache.

Exemplo de escopo de cache local

Os exemplos a seguir mostram quando o escopo do cache local funciona e não funciona. Suponha que e subT() são modelos que t() usam um parâmetro:

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

Recursos Adicionais