Compartilhar via


Modelo de resposta estruturada

APLICA-SE A: SDK v4

Os modelos de resposta estruturada permitem que os desenvolvedores definam uma estrutura complexa que dá suporte à ampla funcionalidade de LG (geração de linguagem), como criação de modelos, composição, deixando a interpretação da resposta estruturada para o chamador da biblioteca LG.

Para aplicativos de bot, o seguinte suporte é fornecido:

O modelo de atividade do Bot Framework inclui vários campos personalizáveis. As propriedades mostradas abaixo são as mais usadas e podem ser configuradas por meio de uma definição de modelo de atividade:

Propriedade Caso de uso
Texto Exibir o texto usado pelo canal a ser renderizado visualmente
Speak Texto falado usado pelo canal a ser renderizado de maneira audível
Anexos Lista de anexos com o respectivo tipo. Usado por canais para serem renderizados como cartões de interface do usuário ou outros tipos de anexo de arquivo genéricos.
SuggestedActions Lista de ações renderizadas como sugestões para o usuário.
InputHint Controla o estado do fluxo de captura de áudio em dispositivos que dão suporte à entrada falada. Os valores possíveis incluem accepting, expecting ou ignoring.

Não há nenhum comportamento de fallback padrão implementado pelo resolvedor de modelo. Se uma propriedade não for especificada, ela permanecerá não especificada. Por exemplo, a propriedade Speak não é atribuída automaticamente para ser a propriedade Text se apenas a propriedade Text é especificada.

Definição

Esta é a definição de um modelo estruturado:

# TemplateName
> this is a comment
[Structure-name
    Property1 = <plain text> .or. <plain text with template reference> .or. <expression>
    Property2 = list of values are denoted via '|'. e.g. a | b
> this is a comment about this specific property
    Property3 = Nested structures are achieved through composition
]

Veja um exemplo de um modelo de texto básico:

# AskForAge.prompt
[Activity
    Text = ${GetAge()}
    Speak = ${GetAge()}
]

# GetAge
- how old are you?
- what is your age?

Este é um exemplo de texto com uma ação sugerida. Use | para indicar uma lista.

> With '|' you are making attachments a list.
# AskForAge.prompt
[Activity
    Text = ${GetAge()}
    SuggestedActions = 10 | 20 | 30
]

Este é um exemplo de uma definição de cartão Hero:

# HeroCard
[Herocard
    title = Hero Card Example
    subtitle = Microsoft Bot Framework
    text = Build and connect intelligent bots to interact with your users naturally wherever they are, from text/sms to Skype, Slack, Office 365 mail and other popular services.
    images = https://sec.ch9.ms/ch9/7ff5/e07cfef0-aa3b-40bb-9baa-7c9ef8ff7ff5/buildreactionbotframework_960.jpg
    buttons = Option 1| Option 2| Option 3
]

Observação

A LG fornece alguma variabilidade na definição do cartão, que é convertida para se alinhar com a definição do cartão do SDK. Por exemplo, ambos os campos de image e images têm suporte em todas as definições de cartão na LG, embora só images tenha suporte na definição de cartão do SDK.

Os valores definidos em todos os campos de image e images e em um cartão HeroCard ou miniatura são combinados e convertidos em uma lista de imagens no cartão gerado. Para os outros tipos de cartões, o último valor definido no modelo será atribuído ao campo de image. Os valores atribuídos ao campo de image/images podem ser uma sequência, uma expressão adaptável ou uma matriz no formato que usa |.

Veja abaixo a combinação dos modelos anteriores:

# AskForAge.prompt
[Activity
    Text = ${GetAge()}
    Speak = ${GetAge()}
    Attachments = ${HeroCard()}
    SuggestedActions = 10 | 20 | 30
    InputHint = expecting
]

# GetAge
- how old are you?
- what is your age?

# HeroCard
[Herocard
    title = Hero Card Example
    subtitle = Microsoft Bot Framework
    text = Build and connect intelligent bots to interact with your users naturally wherever they are, from text/sms to Skype, Slack, Office 365 mail and other popular services.
    images = https://sec.ch9.ms/ch9/7ff5/e07cfef0-aa3b-40bb-9baa-7c9ef8ff7ff5/buildreactionbotframework_960.jpg
    buttons = Option 1| Option 2| Option 3
]

Por padrão, qualquer referência de modelo é avaliada uma vez durante a avaliação de um modelo estruturado.

Por exemplo, # AskForAge.prompt retorna o mesmo texto de resolução para as propriedades Speak e Text.

# AskForAge.prompt
[Activity
    Text = ${GetAge()}
    Speak = ${GetAge()}
]

# GetAge
- how old are you?
- what is your age?

Use <TemplateName>!() para solicitar uma nova avaliação em cada referência dentro de um modelo estruturado.

No exemplo abaixo, Speak e Text podem ter um texto de resolução diferente, porque GetAge é reavaliado em cada instância.

[Activity
    Text = ${GetAge()}
    Speak = ${GetAge!()}
]

# GetAge
- how old are you?
- what is your age?

Veja como exibir um carrossel de cartões:

# AskForAge.prompt
[Activity
> Defaults to carousel layout in case of list of cards
    Attachments = ${foreach($cardValues, item, HeroCard(item)}
]

# AskForAge.prompt_2
[Activity
> Explicitly specify an attachment layout
    Attachments = ${foreach($cardValues, item, HeroCard(item)}
    AttachmentLayout = list
]

# HeroCard (title, subtitle, text)
[Herocard
    title = ${title}
    subtitle = ${subtitle}
    text = ${text}
    images = https://sec.ch9.ms/ch9/7ff5/e07cfef0-aa3b-40bb-9baa-7c9ef8ff7ff5/buildreactionbotframework_960.jpg
    buttons = Option 1| Option 2| Option 3
]

Use \ como um caractere de escape.

> You can use '\' as an escape character
> \${GetAge()} would not be evaluated as expression, would be parsed as '${getAge()}' string
# AskForAge.prompt
[Activity
        Text = \${GetAge()}
        SuggestedActions = 10 \| cards | 20 \| cards
]

Composição de modelo estruturado

Há suporte para o seguinte comportamento de composição nos modelos estruturados:

  • A composição tem reconhecimento de contexto da estrutura. Se o modelo de destino referenciado também for um modelo estruturado, o tipo de estrutura deverá ser correspondente. Por exemplo, um ActivityTemplate pode ser referenciado em outro ActivityTemplate.
  • As referências a um modelo de resposta simples ou condicional podem existir em qualquer lugar dentro de um modelo estruturado.

Suponha que você tenha o seguinte modelo:

# T1
[Activity
    Text = ${T2()}
    Speak = foo bar ${T3().speak}
]

# T2
- This is awesome

# T3
[Activity
    Speak = I can also speak!
]

Uma chamada a evaluateTemplate('T1') resultará na seguinte estrutura interna:

[Activity
    Text = This is awesome
    Speak = I can also speak!
]

Referência completa a outro modelo estruturado

Você pode incluir uma referência a outro modelo estruturado como uma propriedade em outro modelo estruturado ou como uma referência em outro modelo de resposta simples ou condicional

Este é um exemplo de referência completa a outro modelo estruturado:

# ST1
[MyStruct
    Text = foo
    ${ST2()}
]
# ST2
[MyStruct
    Speak = bar
]

Com esse conteúdo, uma chamada a evaluateTemplate('ST1') resultará na seguinte estrutura interna:

[MyStruct
    Text = foo
    Speak = bar
]

Quando a mesma propriedade existir no modelo de chamada, bem como no modelo chamado, o conteúdo no chamador substituirá qualquer conteúdo no modelo chamado.

Aqui está um exemplo:

# ST1
[MyStruct
    Text = foo
    ${ST2()}
]
# ST2
[MyStruct
    Speak = bar
    Text = zoo
]

Com esse contexto, uma chamada a evaluateTemplate('ST1') resultará na seguinte estrutura interna:

[MyStruct
    Text = foo
    Speak = bar
]

Observe que esse estilo de composição só pode existir no nível raiz. Se houver uma referência a outro modelo estruturado dentro de uma propriedade, a resolução será contextual para essa propriedade.

Referência de arquivo externo no anexo estruturado

Há duas funções predefinidas usadas para referenciar arquivos externamente

  1. fromFile(fileAbsoluteOrRelativePath) carrega um arquivo especificado. O conteúdo retornado por esta função dará suporte à avaliação do conteúdo. Referências de modelo, propriedades e expressões são avaliadas.
  2. ActivityAttachment(content, contentType) define o contentType se ele ainda não estiver especificado no conteúdo.

Com essas duas funções predefinidas, você pode extrair qualquer conteúdo definido externamente, incluindo todos os tipos de cartões. Use a seguinte LG estruturada para compor uma atividade:

# AdaptiveCard
[Activity
                Attachments = ${ActivityAttachment(json(fromFile('../../card.json')), 'adaptiveCard')}
]

# HeroCard
[Activity
                Attachments = ${ActivityAttachment(json(fromFile('../../card.json')), 'heroCard')}
]

Use também anexos, vistos abaixo:

# AdaptiveCard
[Attachment
    contenttype = adaptivecard
    content = ${json(fromFile('../../card.json'))}
]

# HeroCard
[Attachment
    contenttype = herocard
    content = ${json(fromFile('../../card.json'))}
]

Informações adicionais