Modificando um diálogo usando a API
A API REST suporta modificar seu diálogo programaticamente. É possível usar a API /dialog_nodes para criar, excluir ou modificar nós de diálogo.
Um diálogo é uma árvore de nós interconectados e deve estar em conformidade com determinadas regras para ser válido. Qualquer mudança feita em um nó de diálogo pode ter efeitos em cascata em outros nós ou na estrutura de seu diálogo. Antes de
usar a API /dialog_nodes para modificar seu diálogo, certifique-se de entender como suas mudanças afetam o restante do diálogo. É possível fazer uma cópia de backup do diálogo atual. Para obter mais informações, consulte Fazendo backup e restaurando dados
Um diálogo válido sempre satisfaz os critérios a seguir:
-
Cada nó do diálogo possui um ID exclusivo (a propriedade
dialog_node). -
Um nó-filho está ciente de seu nó pai (a propriedade
parent). No entanto, um nó pai não está ciente de seus filhos. -
Um nó está ciente de seu irmão anterior imediato, se houver (a propriedade
previous_sibling). Todos os irmãos que compartilham o pai formam uma lista vinculada com cada nó apontando para o nó anterior. -
Apenas um filho de um pai pode ser o primeiro irmão (o que significa que seu
previous_siblingé nulo. -
Um nó não pode apontar para um irmão anterior que seja um filho de um pai diferente.
-
Dois nós não podem apontar para o mesmo irmão anterior.
-
Um nó pode especificar outro nó que deve ser executado em seguida (a propriedade
next_step). -
Um nó não pode ser seu próprio pai ou seu próprio irmão.
-
Um nó deve ter uma propriedade de tipo que contenha um dos valores a seguir. Se nenhuma propriedade de tipo for especificada, o tipo será
standard.event_handler: um manipulador que está definido para um nó de quadro ou um nó de intervalo individual.
Na ferramenta, é possível definir um manipulador de nó de quadro clicando no link Gerenciar manipuladores em um nó com intervalos. (A interface com o usuário da ferramenta não expõe o manipulador de eventos de nível de intervalo, mas é possível definir um por meio da API.)
frame: um nó com um ou mais nós-filhos do tiposlot. Quaisquer nós-filhos de intervalo necessários devem ser preenchidos antes que o serviço possa sair do nó de quadro.
O tipo de nó do quadro é representado como um nó com intervalos na ferramenta. O nó que contém os slots é representado como um nó de type=
frame. É o nó pai para cada slot, que é representado como um nó filho do tiposlot.response_condition: uma resposta condicional.
Na ferramenta, é possível incluir uma ou mais respostas condicionais em um nó. Cada resposta condicional que você define é representada no JSON subjacente como um nó individual de type=
response_condition.slot: um nó-filho de um nó do tipoframe.
Esse tipo de nó é representado na ferramenta como sendo um dos vários slots que são incluídos em um único nó Esse único nó é representado no JSON como um nó pai do tipo
frame.standard: um nó de diálogo típico. Este é o tipo padrão.
-
Para nós do tipo
slotque possuem o mesmo nó pai, a ordem irmã (especificada pela propriedadeprevious_sibling) reflete a ordem na qual os slots são processados. -
Um nó do tipo
slotdeve ter um nó pai do tipoframe. -
Um nó do tipo
framedeve ter pelo menos um nó-filho do tiposlot. -
Um nó do tipo
response_conditiondeve ter um nó pai do tipostandardouframe. -
Os nós do tipo
response_conditioneevent_handlernão podem ter filhos. -
Um nó do tipo
event_handlertambém deve ter uma propriedadeevent_nameque contém um dos valores a seguir para identificar o tipo de evento do nó:filled: define o que fazer se o usuário fornecer um valor que atenda à condição especificada no campo Verificar de um slot e o slot for preenchido. Um manipulador com esse nome estará presente somente se uma condição de Localizado estiver definida para o intervalo.focus: Define a pergunta para mostrar que solicita que o usuário forneça as informações necessárias pelo slot. Um manipulador com esse nome estará presente somente se o intervalo for necessário.generic: define uma condição para observar que pode direcionar questões não relacionadas que os usuários podem perguntar ao preencher um intervalo ou nó com intervalos.input: atualiza o contexto da mensagem para incluir uma variável de contexto com o valor que é coletado do usuário para preencher o intervalo. Um manipulador com esse nome deve estar presente para cada intervalo no nó de quadro.nomatch: define o que fazer se a resposta do usuário para o prompt de intervalo não contém um valor válido. Um manipulador com esse nome está presente somente se uma condição de Não localizado está definida para o intervalo.
O diagrama a seguir ilustra onde na interface com o usuário da ferramenta você define o código que é acionado para cada evento nomeado.
Manipuladores de Eventos -
Um nó do tipo
event_handlercom um event_name degenericpode ter um pai do tiposlotouframe. -
Um nó do tipo
event_handlercom um event_name defocus,input,filledounomatchdeve ter um pai do tiposlot. -
Se mais de um event_handler com o mesmo event_name estiver associado ao mesmo nó pai, a ordem dos irmãos será a ordem na qual os manipuladores de eventos são executados.
-
Para os nós
event_handlercom o mesmo nó pai de intervalo, a ordem de execução é a mesma independentemente do posicionamento das definições de nó. Os eventos são acionados nesta ordem por event_name:- foco
- entrada
- filled
- generic*
- nomatch
*Se um
event_handlercom o event_namegenericfor definido para esse slot ou para o quadro pai, ele será executado entre os nós event_handler preenchido e nomatch.
Os exemplos a seguir mostram como várias modificações podem causar mudanças em cascata.
Criando um nó
Considere a árvore de diálogo simples a seguir:
Podemos criar um novo nó ao fazer uma solicitação POST para /dialog_nodes com o corpo a seguir:
{
"dialog_node": "node_8"
}
O diálogo agora é semelhante a este:
Como o node_8 foi criado sem especificar um valor para parent ou previous_sibling, ele agora é o primeiro nó no diálogo. Além de criar node_8, o serviço também modificou node_1 para que sua propriedade previous_sibling aponte para o novo nó.
É possível criar um nó em outro lugar no diálogo especificando o pai e irmão anteriores:
{
"dialog_node": "node_9",
"parent": "node_2",
"previous_sibling": "node_5"
}
Os valores especificados para parent e previous_node devem ser válidos:
- Ambos os valores devem referir-se a nós existentes.
- O pai especificado deve ser o mesmo que o pai do irmão anterior (ou
nullse o irmão anterior não tiver pai). - O pai não pode ser um nó do tipo
response_conditionouevent_handler.
O diálogo resultante é semelhante a este:
Além de criar o node_9, o serviço atualiza automaticamente a propriedade previous_sibling de node_6 para que aponte para o novo nó.
Movendo um nó para um pai diferente
Mova node_5 para um pai diferente usando o método POST /dialog_nodes/node_5 com o corpo a seguir:
{
"parent": "node_1"
}
O valor especificado para parent deve ser válido:
- Ele deve referir-se a um nó existente.
- Ele não deve fazer referência ao nó modificado (um nó não pode ser seu próprio pai).
- Ele não deve fazer referência a um descendente do nó modificado.
- Ele não deve referir-se a um nó do tipo
response_conditionouevent_handler.
Isso resulta na estrutura mudada a seguir:
Várias coisas aconteceram aqui:
- Quando node_5 mudou para seu novo pai, node_7 foi com ele (porque o valor de
parentpara node_7 não mudou). Quando você move um nó, todos os descendentes desse nó permanecem com ele. - Como nós não especificamos um valor
previous_siblingpara node_5, agora ele é o primeiro irmão sob node_1. - A propriedade
previous_siblingde node_4 foi atualizada paranode_5. - A propriedade
previous_siblingde node_9 foi atualizada paranullporque agora é o primeiro irmão sob node_2.
Resequenciando irmãos
Agora configure node_5 como o segundo irmão em vez do primeiro usando o método POST /dialog_nodes/node_5 com o corpo a seguir:
{
"previous_sibling": "node_4"
}
Quando você modifica previous_sibling, o novo valor deve ser válido:
- Ele deve referir-se a um nó existente
- Ele não deve fazer referência ao nó que é modificado (um nó não pode ser seu próprio irmão)
- Ele deve referir-se a um filho do mesmo pai (todos os irmãos devem ter o mesmo pai)
A estrutura muda conforme a seguir:
O Node_7 permanece com seu pai Além disso, node_4 é modificado para que seu previous_sibling seja null porque agora ele é o primeiro irmão.
Excluindo um nó
Exclua node_1 usando o método DELETE /dialog_nodes/node_1.
O resultado é:
Node_1, node_4, node_5 e node_7 foram todos excluídos. Quando você exclui um nó, todos os descendentes desse nó são excluídos também. Portanto, se você excluir um nó raiz, estará
excluindo uma ramificação inteira da árvore de diálogo.. Quaisquer outras referências ao nó excluído (como referências next_step) serão mudadas para null.
Além disso, node_2 é atualizado para apontar para node_8 como seu novo irmão anterior.
Renomeando um nó
Renomeie node_2 usando o método POST /dialog_nodes/node_2 com o corpo a seguir:
{
"dialog_node": "node_X"
}
A estrutura do diálogo não foi alterada, mas vários nós foram modificados para refletir o nome alterado:
- As propriedades
parentde node_9 e node_6 - A propriedade
previous_siblingde node_3
Quaisquer outras referências ao nó excluído (como referências next_step) também são mudadas.