Modifica di una finestra di dialogo utilizzando l'API
L'API REST supporta la modifica programmatica del dialogo. Puoi utilizzare l'API /dialog_nodes per creare, eliminare o modificare i nodi di dialogo.
Una finestra di dialogo è una struttura ad albero di nodi interconnessi e deve essere conforme a determinate regole per essere valida. Qualsiasi modifica apportata a un nodo di dialogo potrebbe avere effetti a cascata su altri nodi o sulla struttura
del tuo dialogo. Prima di utilizzare l'API /dialog_nodes per la modifica del tuo dialogo, assicurati di comprendere in che modo le tue modifiche influenzano il resto del dialogo. È possibile eseguire una copia di backup della finestra
di dialogo corrente Per ulteriori informazioni, consultare Backup e ripristino dei dati.
Un dialogo valido soddisfa sempre i seguenti criteri:
-
Ogni nodo di dialogo ha un ID univoco (la proprietà
dialog_node). -
Un nodo figlio è consapevole del suo nodo padre (la proprietà
parent). Tuttavia, un nodo padre non è consapevole dei suoi nodi figlio. -
Un nodo è consapevole del suo immediato elemento di pari livello precedente, se presente (la proprietà
previous_sibling). Tutti gli elementi di pari livello che condividono il parent formano un elenco collegato, con ciascun nodo che punta al nodo precedente. -
Solo un elemento secondario di un elemento principale può essere il primo elemento di pari livello (ciò significa che il relativo
previous_siblingè null). -
Un nodo non può puntare a un elemento di pari livello precedente che è figlio di un padre diverso.
-
Due nodi non possono puntare allo stesso elemento di pari livello precedente.
-
Un nodo può specificare un altro nodo da eseguire successivamente (la proprietà
next_step). -
Un nodo non può essere il suo proprio padre o elemento di pari livello.
-
Un nodo deve avere una proprietà tipo che contiene uno dei seguenti valori. Se non vengono specificate proprietà tipo, il tipo è
standard.event_handler: un gestore definito per un nodo frame o un singolo nodo slot.
Dallo strumento, puoi definire un gestore nodo frame facendo clic sul link Gestisci gestori da un nodo con slot. (L'interfaccia utente dello strumento non mostra il gestore eventi a livello dello slot, ma puoi definirne uno tramite l'API.)
frame: un nodo con uno o più nodi figlio di tiposlot. I nodi slot figlio necessari devono essere riempiti prima che il servizio possa uscire dal nodo frame.
Il tipo di nodo frame viene rappresentato come un nodo con slot nello strumento. Il nodo che contiene gli slot è rappresentato come un nodo di tipo=
frame. È il nodo parent di ogni slot, rappresentato come un nodo child di tiposlot.response_condition: una risposta condizionale.
Nello strumento, puoi aggiungere una o più risposte condizionali a un nodo. Ciascuna risposta condizionale che definisci viene rappresentata nel JSON sottostante come un singolo nodo type=
response_condition.slot: un nodo figlio di un nodo di tipoframe.
Questo tipo di nodo è rappresentato nello strumento come uno dei più slot aggiunti a un singolo nodo. Tale singolo nodo viene rappresentato nel JSON come un nodo padre di tipo
frame.standard: un nodo di dialogo tipico. Questo è il tipo predefinito.
-
Per i nodi di tipo
slotche hanno lo stesso nodo principale, l'ordine di pari livello (specificato nella proprietàprevious_sibling) riflette l'ordine in cui vengono elaborati gli slot. -
Un nodo di tipo
slotdeve avere un nodo padre di tipoframe. -
Un nodo di tipo
framedeve avere almeno un nodo figlio di tiposlot. -
Un nodo di tipo
response_conditiondeve avere un nodo padre di tipostandardoframe. -
I nodi di tipo
response_conditioneevent_handlernon possono avere figli. -
Un nodo di tipo
event_handlerdeve avere anche una proprietàevent_nameche contenga uno dei seguenti valori per identificare il tipo di evento nodo:filled: definisce cosa fare se l'utente fornisce un valore che soddisfa la condizione specificata nel campo Controlla di uno slot e lo slot viene riempito. Un gestore con questo nome è presente solo se per lo slot viene definita una condizione Trovato.focus: definisce la domanda da mostrare che richiede all'utente di fornire le informazioni necessarie allo slot. Un gestore con questo nome è presente solo se lo slot è necessario.generic: definisce una condizione da controllare che può far fronte a domande non correlate che gli utenti potrebbero porre durante il riempimento di uno slot o di un nodo con slot.input: aggiorna il contesto del messaggio per includere una variabile di contesto con il valore raccolto dall'utente per riempire lo slot. Per ciascuno slot presente nel nodo frame deve essere presente un gestore con questo nome.nomatch: definisce quali operazioni eseguire se la risposta dell'utente alla richiesta dello slot non contiene un valore valido. Un gestore con questo nome è presente solo se per lo slot viene definita una condizione Non trovato.
Il seguente diagramma illustra dove nell'interfaccia utente dello strumento viene definito il codice attivato per ciascun evento denominato.
Gestori eventi -
Un nodo di tipo
event_handlercon un event_namegenericpuò avere un padre di tiposlotoframe. -
Un nodo di tipo
event_handlercon un event_namefocus,input,filledonomatchdeve avere un padre di tiposlot. -
Se più di un event_handler con lo stesso event_name è associato allo stesso nodo parent, l'ordine degli elementi di pari livello è l'ordine in cui vengono eseguiti i gestori eventi.
-
Per i nodi
event_handlercon lo stesso nodo slot padre, l'ordine di esecuzione è lo stesso indipendentemente dal posizionamento delle definizioni di nodo. Gli eventi vengono attivati in questo ordine da event_name:- focus
- input
- filled
- generic*
- nomatch
*Se un
event_handlercon event_namegenericè definito per questo slot o per il frame principale, viene eseguito tra i nodi event_handler riempiti e nomatch.
I seguenti esempi mostrano come varie modifiche potrebbero comportare delle modifiche a cascata:
Creazione di un nodo
Considera la semplice struttura ad albero di dialogo riportata di seguito:
Possiamo creare un nuovo nodo effettuando una richiesta POST a /dialog_nodes con il seguente corpo:
{
"dialog_node": "node_8"
}
Il dialogo adesso sarà simile al seguente:
Poiché node_8 è stato creato senza specificare un valore per parent o previous_sibling, è ora il primo nodo nel dialogo. Oltre a creare node_8, il servizio ha anche modificato node_1 in modo che la sua proprietà previous_sibling punti al nuovo nodo.
Puoi creare un nodo in un'altra parte nel dialogo specificando l'elemento padre e quello di pari livello:
{
"dialog_node": "node_9",
"parent": "node_2",
"previous_sibling": "node_5"
}
I valori specificati per parent e previous_node devono essere validi:
- Entrambi i valori devono fare riferimento a nodi esistenti.
- Il padre specificato deve essere uguale al padre dell'elemento di pari livello precedente (o
null, se l'elemento di pari livello precedente non ha un padre). - Il padre non può essere un nodo di tipo
response_conditionoevent_handler.
Il dialogo risultate è simile al seguente:
Oltre a creare node_9, il servizio aggiorna automaticamente la proprietà previous_sibling di node_6 in modo che punti al nuovo nodo.
Spostamento di un nodo in un padre diverso
Spostare node_5 in un elemento parent differente utilizzando il metodo POST /dialog_nodes/node_5 con il seguente corpo:
{
"parent": "node_1"
}
Il valore specificato per parent deve essere valido:
- Deve fare riferimento a un nodo esistente.
- Non deve fare riferimento al nodo modificato (un nodo non può essere il proprio parent).
- Non deve fare riferimento a un discendente del nodo modificato.
- Non deve fare riferimento a un nodo di tipo
response_conditionoevent_handler.
Questo produce la seguente struttura modificata:
Qui sono successe diverse cose:
- Quando node_5 è stato spostato nel suo nuovo padre, node_7 è andato con lui (perché il valore
parentper node_7 non è cambiato). Quando sposti un nodo, tutti i discendenti di tale nodo restano con lui. - Poiché non abbiamo specificato un valore
previous_siblingper node_5, questo è adesso il primo nodo di pari livello sotto node_1. - La proprietà
previous_siblingdi node_4 è stata aggiornata anode_5. - La proprietà
previous_siblingdi node_9 è stata aggiornata innullperché ora è il primo elemento di pari livello in node_2.
Risequenza degli elementi di pari livello
Impostare ora node_5 come secondo elemento di pari livello invece del primo utilizzando il metodo POST /dialog_nodes/node_5 con il seguente body:
{
"previous_sibling": "node_4"
}
Quando modifichi previous_sibling, il nuovo valore deve essere valido:
- Deve fare riferimento a un nodo esistente
- Non deve fare riferimento al nodo modificato (un nodo non può essere il proprio elemento di pari livello)
- Deve fare riferimento al figlio dello stesso padre (tutti gli elementi di pari livello devono avere lo stesso padre)
La struttura cambia come segue:
Node_7 rimane con il relativo parent. Inoltre, node_4 viene modificato in modo che previous_sibling sia null poiché ora è il primo elemento di pari livello.
Eliminazione di un nodo
Eliminare node_1 utilizzando il metodo DELETE /dialog_nodes/node_1.
Il risultato è:
Node_1, node_4, node_5 e node_7 sono stati tutti eliminati. Quando elimini un nodo, vengono eliminati anche tutti i discendenti di tale nodo. Pertanto, se elimini un nodo root,
stai eliminando un intero ramo della struttura ad albero di dialogo. Qualsiasi altro riferimento al nodo eliminato (ad esempio, i riferimenti next_step) viene modificato in null.
Inoltre, node_2 viene aggiornato per puntare a node_8 come suo nuovo elemento di pari livello precedente.
Ridenominazione di un nodo
Rinominare node_2 utilizzando il metodo POST /dialog_nodes/node_2 con il seguente corpo:
{
"dialog_node": "node_X"
}
La struttura del dialogo non è stata modificata, ma sono stati modificati più nodi per riflettere il nome modificato:
- Le proprietà
parentdi node_9 e node_6 - La proprietà
previous_siblingdi node_3
Viene modificato anche qualsiasi altro riferimento al nodo eliminato (ad esempio, i riferimenti next_step).