API を使用したダイアログの変更
REST API は、プログラムによるダイアログの変更をサポートします。 /dialog_nodes API を使用して、ダイアログ・ノードを作成、削除、または変更できます。
ダイアログは、相互接続されたノードのツリーであり、有効であるためには特定の規則に準拠する必要があります。 ダイアログ・ノードに変更を加えると、他のノードやダイアログの構造にカスケード効果が生じる可能性があります。 /dialog_nodes API を使用してダイアログを変更する前に、変更がダイアログの残りの部分に与える影響を理解しておく必要があります。 現行ダイアログのバックアップ・コピーを作成できます。詳しくは、 データのバックアップとリストア を参照してください。
有効なダイアログは必ず以下の基準を満たしています。
-
ダイアログ・ノードごとに固有 ID があります (
dialog_nodeプロパティー)。 -
下位ノードはその親ノードを認識しています (
parentプロパティー)。 一方、親ノードはその子を認識していません。 -
ノードは、その直前の兄弟が存在すればそれを認識しています (
previous_siblingプロパティー)。 親を共有するすべての兄弟はリンク・リストを形成し、各ノードは前のノードを指します。 -
最初の兄弟になることができるのは、親の 1 つの子のみです (つまり、その
previous_siblingはヌルです)。 -
ノードは、異なる親の子である直前の兄弟を指すことはできません。
-
直前の同じ兄弟を 2 つのノードが指すことはできません。
-
ノードは、次に実行される別のノードを指定できます (
next_stepプロパティー)。 -
ノードは、自身の親にも自身の兄弟にもなれません。
-
ノードには、以下のいずれかの値を含むタイプ・プロパティーが必要です。 タイプ・プロパティーが指定されていない場合、タイプは
standardになります。event_handler: フレーム・ノードまたは個々のスロット・ノードに対して定義されたハンドラー。
ツールから、スロット付きノードの**「ハンドラーの管理 (Manage handlers)」**リンクをクリックして、フレーム・ノードのハンドラーを定義できます。 (スロット・レベルのイベント・ハンドラーはツールのユーザー・インターフェースに表示されませんが、API を使用して定義できます。)
frame:slotタイプの子ノードを 1 つ以上持つノード。 必要なすべての子スロット・ノードに情報が取り込まれるまで、サービスはフレーム・ノードを終了できません。
フレーム・ノード・タイプは、ツールではスロット付きのノードとして表されます。 スロットを含むノードは、タイプ =
frameのノードとして表されます。これは各スロットの親ノードであり、slotタイプの子ノードとして表されます。response_condition: 条件付き応答。
ツールでは、1 つのノードに 1 つ以上の条件付き応答を追加できます。 定義した各条件付き応答は、基礎 JSON では、
response_conditionタイプの個々のノードとして表されます。slot:frameタイプのノードの子ノード。
このノード・タイプは、単一ノードに追加される複数のスロットの 1 つとしてツールに表示されます。 その単一ノードは、JSON では
frameタイプの親ノードとして表されます。standard: 標準的なダイアログ・ノード。 これがデフォルトのタイプです。
-
同じ親ノードを持つタイプ
slotのノードの場合、兄弟順序 (previous_siblingプロパティーで指定) は、スロットが処理される順序を反映します。 -
slotタイプのノードには、frameタイプの親ノードが必要です。 -
frameタイプのノードには、slotタイプの子ノードが 1 つ以上必要です。 -
response_conditionタイプのノードには、standardまたはframeタイプの親ノードが必要です。 -
response_conditionおよびevent_handlerタイプのノードは、子ノードを持つことができません。 -
event_handlerタイプのノードには、ノード・イベントのタイプを示す以下のいずれかの値を含むevent_nameプロパティーも必要です。filled: スロットの 「チェック対象 (Check for)」 フィールドに指定されている条件を満たす値をユーザーが指定し、スロットが入力された場合の対処方法を定義します。 この名前のハンドラーは、Found 条件をスロットに定義した場合にのみ存在します。focus: スロットに必要な情報を提供するようユーザーにプロンプトを出す質問を定義します。 この名前のハンドラーは、スロットが必要な場合にのみ存在します。generic: スロットまたはスロット付きノードの入力中に、ユーザーが尋ねる可能性がある無関係の質問に対処する条件を定義します。input: スロットに情報を取り込むためにユーザーから収集した値を持つコンテキスト変数を含むように、メッセージ・コンテキストを更新します。 この名前のハンドラーは、フレーム・ノードのスロットごとに存在する必要があります。nomatch: スロット・プロンプトに対するユーザーの応答に有効な値が含まれていない場合の処理を定義します。 この名前のハンドラーは、Not Found 条件をスロットに定義した場合にのみ存在します。
以下の図は、名前付きイベントごとにトリガーされるコードを定義するツール・ユーザー・インターフェース内の場所を示しています。
イベント・ハンドラー -
イベント名が
event_handlerのgenericタイプのノードは、slotまたはframeタイプの親を持つことができます。 -
イベント名が
event_handler、focus、input、またはfilledのnomatchタイプのノードには、slotタイプの親が必要です。 -
同じ event_name を持つ複数の event_handler が同じ親ノードに関連付けられている場合、兄弟の順序は、イベント・ハンドラーが実行される順序になります。
-
同じ親スロット・ノードを持つ
event_handlerノードの実行順序は、ノード定義の配置に関係なく、同じです。 event_name による次の順序で、イベントはトリガーされます。- フォーカス
- input
- filled
- generic*
- nomatch
- event_name
genericを持つevent_handlerがこのスロットまたは親フレームに定義されている場合は、充てんされた event_handler ノードと nomatch event_handler ノードの間で実行されます。
以下の例は、さまざまな変更が加えられることによって連鎖的に変化が起こる場合に、それがどのように生じるかを示しています。
ノードの作成
次のシンプルなダイアログ・ツリーを考えてみます。
次の本体を含む POST 要求を /dialog_nodes に行うことによって、新しいノードを作成できます。
{
"dialog_node": "node_8"
}
ダイアログは次のようになります。
node_8 は、parent の値も previous_sibling の値も指定せずに作成されたので、ダイアログ内の最初のノードになりました。 サービスは、 node_8 の作成に加えて、 node_1 も変更して、その previous_sibling プロパティーが新規ノードを指すようにしました。
次のように親と直前の兄弟を指定することにより、ダイアログ内の他の場所にノードを作成できます。
{
"dialog_node": "node_9",
"parent": "node_2",
"previous_sibling": "node_5"
}
parent および previous_node に指定する値は、以下の有効な値でなければなりません。
- 両方の値とも既存のノードを参照していなければなりません。
- 指定した親は、直前の兄弟の親と同じでなければなりません (直前の兄弟に親がない場合は
null)。 - 親を
response_conditionまたはevent_handlerタイプのノードにすることはできません。
結果のダイアログは次のようになります。
node_9 を作成することに加えて、サービスは previous_siblingnode_6* の * プロパティーを自動的に更新して、新しいノードを指すようにします。
異なる親へのノードの移動
以下の本文を含む POST /dialog_nodes/node_5 メソッドを使用して、 node_5 を別の親に移動します。
{
"parent": "node_1"
}
parent に指定する値は、次のとおり有効でなければなりません。
- 既存のノードを参照していなければなりません。
- 変更されるノードを参照していてはなりません (ノードはそれ自体の親であってはなりません)。
- 変更されるノードの子孫を参照してはなりません。
response_conditionまたはevent_handlerタイプのノードを参照していてはなりません。
この結果、次のような構造に変わります。
ここでいくつかのことが起こりました。
- node_5 がその親に移動したとき、node_7 もそれと一緒に移動しました (
parentnode_7** の ** 値が変わらなかったため)。 ノードを移動すると、そのノードのすべての子孫はそのノードに付き添います。 previous_siblingnode_5** の ** 値を指定しなかったので、このノードが node_1 の下の最初の兄弟になりました。previous_siblingnode_4** の ** プロパティーがnode_5に更新されました。- node_9 の
previous_siblingプロパティーは、 node_2 の下の最初の兄弟になったため、nullに更新されました。
兄弟の並べ直し
ここで、以下の本体を持つ POST /dialog_nodes/node_5 メソッドを使用して、 node_5 を最初の兄弟ではなく 2 番目の兄弟として設定します。
{
"previous_sibling": "node_4"
}
previous_sibling を変更する場合、新しい値は次のとおり有効でなければなりません。
- 既存のノードを参照していなければなりません。
- 変更されるノードを参照することはできません (ノードをそれ自体の兄弟にすることはできません)。
- 同じ親の子を参照していなければなりません (すべての兄弟に同じ親がなければなりません)。
次のように構造が変わります。
Node_7 は、その親のままです。 さらに、 node_4 が変更され、その previous_sibling が null になりました。これは、これが現在最初の兄弟であるためです。
ノードの削除
DELETE /dialog_nodes/node_1 メソッドを使用して、 node_1 を削除します。
結果は以下のようになります。
Node_1、 node_4、 node_5、および node_7 がすべて削除されました。 ノードを削除すると、そのノードのすべての子孫も削除されます。 したがって、ルート・ノードを削除すると、ダイアログ・ツリーのブランチ全体が削除されます。 削除されたノードへの他の参照 (next_step 参照など) はすべて、null に変更されます。
さらに、node_2 が更新されて、その新しい直前の兄弟として node_8 を指すようになります。
ノードの名前変更
以下の本体を持つ POST /dialog_nodes/node_2 メソッドを使用して、 node_2 の名前を変更します。
{
"dialog_node": "node_X"
}
ダイアログの構造は変更されませんでしたが、変更された名前を反映するように複数のノードが変更されました。
parentnode_9** と node_6 の ** プロパティーprevious_siblingnode_3** の ** プロパティー
削除されたノードへの他の参照 (next_step 参照など) もすべて変更されます。