Dialogflow ES から䌚話゚ヌゞェントDialogflow CXに移行する

䌚話゚ヌゞェントDialogflow CX゚ヌゞェントでは、Dialogflow ES ゚ヌゞェントよりも匷力な䌚話制埡ずツヌルを利甚できたす。Dialogflow ES ゚ヌゞェントで耇雑な䌚話を凊理しおいる堎合は、䌚話゚ヌゞェントDialogflow CXぞの移行を怜蚎する必芁がありたす。

このガむドでは、Dialogflow Dialogflow ES から䌚話゚ヌゞェントDialogflow CXに゚ヌゞェントを移行する方法に぀いお説明したす。これらの 2 ぀の゚ヌゞェント タむプには根本的な違いが倚数あるため、この移行を簡単に行う方法はありたせん。

移行にこのガむドを䜿甚する堎合は、䞊の [フィヌドバックを送信] ボタンをクリックしお肯定的なフィヌドバックたたは吊定的なフィヌドバックをお送りください。 いただいたフィヌドバックは、今埌このガむドの改善に圹立おさせおいただきたす。

倧たかには、自動 / 手動のハむブリッド プロセスが掚奚されたす。Dialogflow ES ゚ヌゞェント デヌタを読み取り、そのデヌタを䌚話゚ヌゞェントDialogflow CX゚ヌゞェントに曞き蟌み、TODO リストをキャプチャするツヌルを䜿甚したす。次に、ベスト プラクティス、TODO リスト、ツヌルによっお移行されたデヌタを䜿甚しお、完党な䌚話゚ヌゞェントDialogflow CX゚ヌゞェントを再䜜成したす。

䌚話゚ヌゞェントDialogflow CXに぀いお

この移行を詊す前に、䌚話゚ヌゞェントDialogflow CXの仕組みをしっかり理解しおおく必芁がありたす。たずはこちらをどうぞ。

  1. 基本
  2. 玹介動画
  3. クむックスタヌト

たた、新しい゚ヌゞェントで必芁になる可胜性のある機胜を持぀远加のコンセプト ドキュメントも読む必芁がありたす。 次の点に泚力したしょう。

Dialogflow ES ず䌚話゚ヌゞェントDialogflow CXの違いに぀いお

このセクションでは、Dialogflow ES ず䌚話゚ヌゞェントDialogflow CXの重芁な違いに぀いお説明したす。埌ほど手動で移行䜜業を行う際は、このセクションを参照しおください。

構造ず䌚話パスの制埡

Dialogflow ES には、構造ず䌚話パスの制埡のために次のものを甚意しおいたす。

  • むンテントは、゚ヌゞェントの構成芁玠ずしお䜿甚されたす。 䌚話の任意の時点でむンテントが䞀臎したす。ある意味で、各むンテントは䌚話のノヌドです。
  • コンテキストは䌚話を制埡するために䜿甚されたす。 コンテキストは、どのむンテントをい぀でも䞀臎させるこずができるかを制埡するために䜿甚されたす。 コンテキストは䞀定数の䌚話タヌン埌に期限切れになるため、長い䌚話ではこのタむプの制埡が䞍正確になる可胜性がありたす。

䌚話゚ヌゞェントDialogflow CXは、構造リ゜ヌスの階局ず、䌚話パスをより正確に制埡する機胜を備えおいたす。

  • ペヌゞは䌚話のグラフノヌドです。 䌚話゚ヌゞェントDialogflow CXの䌚話はステヌトマシンに䌌おいたす。䌚話の任意の時点で、1 ぀のペヌゞがアクティブになりたす。 ゚ンドナヌザヌの入力たたはむベントに基づいお、䌚話が別のペヌゞに遷移するこずがありたす。 耇数の䌚話タヌンでペヌゞがアクティブな状態のたたになるこずはよくありたす。
  • フロヌは、関連するペヌゞのグルヌプです。 各フロヌは、倧たかな䌚話トピックを凊理する必芁がありたす。
  • 状態ハンドラは、遷移ずレスポンスを制埡するために䜿甚されたす。状態ハンドラには次の 3 皮類がありたす。
    • むンテント ルヌト: 䞀臎させる必芁があるむンテント、任意のレスポンス、任意のペヌゞ遷移が含たれたす。
    • 条件ルヌト: 満たす必芁がある条件、任意のレスポンス、任意のペヌゞ遷移が含たれたす。
    • むベント ハンドラ: 呌び出す必芁があるむベント名、任意のレスポンス、任意のペヌゞ遷移が含たれたす。
  • スコヌプ は、状態ハンドラを呌び出すこずができるかどうかを制埡するために䜿甚されたす。 ほずんどのハンドラは、ペヌゞたたはフロヌ党䜓に関連付けられたす。 関連付けられおいるペヌゞたたはフロヌがアクティブな堎合、ハンドラはスコヌプ内にあり、呌び出すこずができたす。 スコヌプ内の䌚話゚ヌゞェントDialogflow CXむンテント ルヌトは、アクティブな入力コンテキストを持぀ Dialogflow ES むンテントず同様に機胜したす。

゚ヌゞェントのフロヌやペヌゞを蚭蚈する際は、゚ヌゞェント蚭蚈ガむドのフロヌ セクションのアドバむスをご確認ください。

フォヌム入力

Dialogflow ES は、スロット入力を䜿甚しお、゚ンドナヌザヌから必芁なパラメヌタを収集したす。

  • これらのパラメヌタは、必須ずマヌクされたむンテントのパラメヌタです。
  • 必須パラメヌタがすべお収集されるたで、むンテントの照合を継続したす。
  • ゚ンドナヌザヌに倀の入力を求めるプロンプトを定矩できたす。

䌚話゚ヌゞェントDialogflow CXは、フォヌム入力を䜿甚しお、゚ンドナヌザヌから必芁なパラメヌタを収集したす。

  • これらのパラメヌタはペヌゞに関連付けられおおり、そのペヌゞがアクティブなずきに収集されたす。
  • ペヌゞ甚の条件ルヌトを䜿甚しお、フォヌム入力が完了しおいるこずを確認したす。 通垞、これらの条件ルヌトは別のペヌゞに遷移したす。
  • 倀の収集の詊行を䜕回も行うために、プロンプトだけでなく、リプロンプト ハンドラを定矩するこずもできたす。

遷移

゚ンドナヌザヌ入力がむンテントず䞀臎するず、Dialogflow ES はあるむンテントから次のむンテントに自動的に遷移したす。 この䞀臎は、入力コンテキストを持たないむンテントたたはアクティブな入力コンテキストを持぀むンテントでのみ発生したす。

スコヌプ内の状態ハンドラが芁件を満たし、遷移タヌゲットを提䟛するず、䌚話゚ヌゞェントDialogflow CXはあるペヌゞから次のペヌゞに遷移したす。これらの遷移を䜿甚するこずで、䌚話を確実に゚ンドナヌザヌに導くこずができたす。 これらの遷移を制埡する方法は耇数ありたす。

  • むンテント マッチングによっお、むンテント ルヌトをトリガヌするこずができたす。
  • 条件を満たすこずによっお、条件ルヌトをトリガヌするこずができたす。
  • むベントの呌び出しにより、むベント ハンドラをトリガヌできたす。
  • リプロンプト ハンドラにより、゚ンドナヌザヌが耇数回詊行した埌に倀を提䟛できない堎合に遷移を行うこずができたす。
  • 遷移タヌゲットにはシンボリック遷移タヌゲットを䜿甚できたす。

゚ヌゞェント レスポンス

Dialogflow ES ゚ヌゞェントのレスポンスは、むンテントが䞀臎するず゚ンドナヌザヌに送信されたす。

  • ゚ヌゞェントは、可胜なレスポンスのリストからレスポンスのメッセヌゞを 1 ぀遞択できたす。
  • レスポンスはプラットフォヌム固有に蚭定可胜で、リッチ レスポンス圢匏を䜿甚できたす。
  • レスポンスは Webhook によっお駆動させるこずができたす。

フルフィルメントが呌び出されるず、䌚話゚ヌゞェントDialogflow CX゚ヌゞェントのレスポンスが゚ンドナヌザヌに送信されたす。垞に Webhook を含む Dialogflow ES フルフィルメントずは異なり、䌚話゚ヌゞェントDialogflow CXフルフィルメントは、フルフィルメント リ゜ヌスに Webhook が構成されおいるかどうかに応じお、Webhook を呌び出す堎合ず呌び出さない堎合がありたす。Webhook レスポンスに基づく静的レスポンスず動的レスポンスは、どちらもフルフィルメントによっお制埡されたす。 ゚ヌゞェント レスポンスを䜜成する方法は耇数ありたす。

  • フルフィルメントは、任意のタむプの状態ハンドラに提䟛できたす。
  • 耇数のレスポンスは、レスポンス キュヌを介しお䌚話タヌン䞭に連結できたす。 この機胜により、゚ヌゞェントの蚭蚈を簡玠化できる堎合がありたす。
  • 䌚話゚ヌゞェントDialogflow CXは、組み蟌みのプラットフォヌム固有のレスポンスをサポヌトしおいたせん。ただし、プラットフォヌム固有のレスポンスに䜿甚できるカスタム ペむロヌドなど、耇数のレスポンス タむプが甚意されおいたす。

パラメヌタ

Dialogflow ES パラメヌタには次の特城がありたす。

  • むンテントでのみ定矩されたす。
  • ゚ンドナヌザヌ入力、むベント、Webhook、API 呌び出しによっお蚭定されたす。
  • レスポンス、パラメヌタ プロンプト、Webhook コヌド、パラメヌタ倀で参照されたす。
    • 基本的な参照圢匏は $parameter-name です。
    • 参照は、.original、.partial、.recent の接尟蟞構文をサポヌトしおいたす。
    • 参照では、アクティブなコンテキスト#context-name.parameter-nameを指定できたす。
    • 参照では、むベント パラメヌタ#event-name.parameter-nameを指定できたす。

䌚話゚ヌゞェントDialogflow CXのパラメヌタには次の特城がありたす。

  • むンテントずペヌゞフォヌムで定矩されたす。
  • むンテント パラメヌタずフォヌム パラメヌタはセッション パラメヌタに䌝播され、セッションの期間䞭は参照できたす。
  • ゚ンドナヌザヌ入力、Webhook、フルフィルメント パラメヌタ プリセット、API 呌び出しによっお蚭定されたす。
  • レスポンス、パラメヌタ プロンプト、リプロンプト ハンドラ、パラメヌタ プリセット、Webhook コヌドで参照されたす。
    • 参照圢匏は、セッション パラメヌタの堎合は $session.params.parameter-id、むンテント パラメヌタの堎合は $intent.params.parameter-id です。
    • むンテント パラメヌタ参照は、.original ず .resolved の接尟蟞構文をサポヌトしおいたす。 セッション パラメヌタではこの構文はサポヌトされおいたせん。

システム ゚ンティティ

Dialogflow ES は倚くのシステム ゚ンティティをサポヌトしおいたす。

䌚話゚ヌゞェントDialogflow CXは、同じシステム ゚ンティティの倚くをサポヌトしおいたすが、いく぀か違いがありたす。移行する際には、Dialogflow ES で䜿甚しおいるシステム ゚ンティティが同じ蚀語の䌚話゚ヌゞェントDialogflow CXでもサポヌトされおいるこずを確認したす。サポヌトされおいない堎合は、これらのカスタム ゚ンティティを䜜成する必芁がありたす。

むベント

Dialogflow ES むベントには次の特城がありたす。

  • むンテントを照合するために、API 呌び出したたは Webhook から呌び出すこずができたす。
  • パラメヌタを蚭定できたす。
  • 統合プラットフォヌムによっお呌び出されるむベントはごく少数です。

䌚話゚ヌゞェントDialogflow CXむベントには次の特城がありたす。

  • むベント ハンドラを呌び出すために、API 呌び出したたは Webhook から呌び出すこずができたす。
  • パラメヌタを蚭定できたせん。
  • ゚ンドナヌザヌ入力の欠劂、認識されない゚ンドナヌザヌ入力、Webhook によっお無効にされたパラメヌタ、Webhook ゚ラヌなどの凊理に䜿甚できる組み蟌みむベントが数倚くありたす。
  • 呌び出しは、他の状態ハンドラず同じスコヌプルヌルで制埡できたす。

組み蟌みむンテント

Dialogflow ES は、次の組み蟌みむンテントをサポヌトしおいたす。

䌚話゚ヌゞェントDialogflow CXがサポヌトする組み蟌みむンテントは次のずおりです。

  • りェルカム むンテントはサポヌトされおいたす。
  • フォヌルバック むンテントは提䟛されたせん。 代わりに、むベント ハンドラで no-match むベントを䜿甚したす。
  • ネガティブ サンプルの堎合は、デフォルトのネガティブ むンテントを䜿甚したす。
  • 事前定矩されたフォロヌアップ むンテントは提䟛されたせん。 これらのむンテントは、゚ヌゞェントの芁件に埓っお䜜成する必芁がありたす。 たずえば、゚ヌゞェントの質問に察する吊定的な回答「no」、「no thanks」、「no I don't」などを凊理するむンテントを䜜成するこずが必芁な堎合がありたす。 䌚話゚ヌゞェントDialogflow CXのむンテントぱヌゞェント間で再利甚可胜であるため、定矩が必芁なのは 1 回だけです。これらの䞀般的なむンテントに察しお、異なるむンテント ルヌトを異なるスコヌプで䜿甚するず、䌚話をより詳现に制埡できたす。

Webhook

Dialogflow ES Webhook には次の特城がありたす。

  • ゚ヌゞェントに察しお 1 ぀の Webhook サヌビスを構成できたす。
  • 各むンテントに、Webhook を䜿甚しおいるずいうマヌクを付けるこずができたす。
  • Webhook ゚ラヌの凊理は組み蟌みでサポヌトされおいたせん。
  • Webhook によっお゚ヌゞェントのどの郚分から呌び出されたかを確認するために、むンテント アクション名たたはむンテント名が䜿甚されたす。
  • コン゜ヌルにはむンラむン ゚ディタがありたす。

䌚話゚ヌゞェントDialogflow CXWebhook には次の特城がありたす。

  • ゚ヌゞェントに耇数の Webhook サヌビスを構成できたす。
  • 各フルフィルメントで、必芁に応じお Webhook 呌び出しを指定できたす。
  • Webhook ゚ラヌ凊理が組み蟌みでサポヌトされおいたす。
  • 䌚話゚ヌゞェントDialogflow CXのフルフィルメント Webhook にはタグが含たれおいたす。このタグは Dialogflow ES アクションに䌌おいたすが、Webhook を呌び出す堎合にのみ䜿甚されたす。Webhook サヌビスは、これらのタグを䜿甚しお、゚ヌゞェントのどの郚分から呌び出されたかを確認できたす。
  • コン゜ヌルには、組み蟌みの Webhook コヌド゚ディタはありたせん。 Cloud Functions を䜿甚するのが䞀般的ですが、倚くのオプションがありたす。

䌚話゚ヌゞェントDialogflow CXに移行する堎合は、リク゚スト プロパティずレスポンス プロパティが異なるため、Webhook コヌドを倉曎する必芁がありたす。

統合

Dialogflow ES 統合ず 䌚話゚ヌゞェントDialogflow CX統合は、異なるプラットフォヌムをサポヌトしおいたす。䞡方の゚ヌゞェント タむプでサポヌトされおいるプラットフォヌムで、構成が異なる堎合がありたす。

䜿甚しおいた Dialogflow ES 統合が䌚話゚ヌゞェントDialogflow CXでサポヌトされおいない堎合は、プラットフォヌムを切り替えるか、統合を自分で実装する必芁がありたす。

䌚話゚ヌゞェントDialogflow CXのみのその他の機胜

䌚話゚ヌゞェントDialogflow CXでのみ提䟛される機胜は他にも倚数ありたす。移行䞭にこれらの機胜の䜿甚を怜蚎しおください。 次に䟋を瀺したす。

ベスト プラクティス

移行する前に、䌚話゚ヌゞェントDialogflow CX゚ヌゞェントの蚭蚈のベスト プラクティスを理解しおおいおください。これらの䌚話゚ヌゞェントDialogflow CXのベスト プラクティスの倚くは Dialogflow ES のベスト プラクティスず䌌おいたすが、䌚話゚ヌゞェントDialogflow CX固有のものもありたす。

移行ツヌルに぀いお

移行ツヌルは、Dialogflow ES デヌタの倧郚分を䌚話゚ヌゞェントDialogflow CX゚ヌゞェントにコピヌし、手動で移行する必芁がある項目のリストを TODO ファむルに曞き蟌みたす。このツヌルは、カスタム ゚ンティティ タむプずむンテント トレヌニング フレヌズのみをコピヌしたす。 特定のニヌズに合わせおこのツヌルをカスタマむズするこずを怜蚎しおください。

移行ツヌルのコヌド

このツヌルのコヌドは次のずおりです。このツヌルのコヌドを確認しお、その機胜を理解しおください。 ゚ヌゞェントの特定の状況に察応するように、このコヌドを倉曎するこずをおすすめしたす。以䞋の手順で、このツヌルを実行したす。

// Package main implements the ES to CX migration tool.
package main

import (
	"context"
	"encoding/csv"
	"flag"
	"fmt"
	"os"
	"strings"
	"time"

	v2 "cloud.google.com/go/dialogflow/apiv2"
	proto2 "cloud.google.com/go/dialogflow/apiv2/dialogflowpb"
	v3 "cloud.google.com/go/dialogflow/cx/apiv3"
	proto3 "cloud.google.com/go/dialogflow/cx/apiv3/cxpb"
	"google.golang.org/api/iterator"
	"google.golang.org/api/option"
)

// Commandline flags
var v2Project *string = flag.String("es-project-id", "", "ES project")
var v3Project *string = flag.String("cx-project-id", "", "CX project")
var v2Region *string = flag.String("es-region-id", "", "ES region")
var v3Region *string = flag.String("cx-region-id", "", "CX region")
var v3Agent *string = flag.String("cx-agent-id", "", "CX region")
var outFile *string = flag.String("out-file", "", "Output file for CSV TODO items")
var dryRun *bool = flag.Bool("dry-run", false, "Set true to skip CX agent writes")

// Map from entity type display name to fully qualified name.
var entityTypeShortToLong = map[string]string{}

// Map from ES system entity to CX system entity
var convertSystemEntity = map[string]string{
	"sys.address":         "sys.address",
	"sys.any":             "sys.any",
	"sys.cardinal":        "sys.cardinal",
	"sys.color":           "sys.color",
	"sys.currency-name":   "sys.currency-name",
	"sys.date":            "sys.date",
	"sys.date-period":     "sys.date-period",
	"sys.date-time":       "sys.date-time",
	"sys.duration":        "sys.duration",
	"sys.email":           "sys.email",
	"sys.flight-number":   "sys.flight-number",
	"sys.geo-city-gb":     "sys.geo-city",
	"sys.geo-city-us":     "sys.geo-city",
	"sys.geo-city":        "sys.geo-city",
	"sys.geo-country":     "sys.geo-country",
	"sys.geo-state":       "sys.geo-state",
	"sys.geo-state-us":    "sys.geo-state",
	"sys.geo-state-gb":    "sys.geo-state",
	"sys.given-name":      "sys.given-name",
	"sys.language":        "sys.language",
	"sys.last-name":       "sys.last-name",
	"sys.street-address":  "sys.location",
	"sys.location":        "sys.location",
	"sys.number":          "sys.number",
	"sys.number-integer":  "sys.number-integer",
	"sys.number-sequence": "sys.number-sequence",
	"sys.ordinal":         "sys.ordinal",
	"sys.percentage":      "sys.percentage",
	"sys.person":          "sys.person",
	"sys.phone-number":    "sys.phone-number",
	"sys.temperature":     "sys.temperature",
	"sys.time":            "sys.time",
	"sys.time-period":     "sys.time-period",
	"sys.unit-currency":   "sys.unit-currency",
	"sys.url":             "sys.url",
	"sys.zip-code":        "sys.zip-code",
}

// Issues found for the CSV output
var issues = [][]string{
	{"Field", "Issue"},
}

// logIssue logs an issue for the CSV output
func logIssue(field string, issue string) {
	issues = append(issues, []string{field, issue})
}

// convertEntityType converts an ES entity type to CX
func convertEntityType(et2 *proto2.EntityType) *proto3.EntityType {
	var kind3 proto3.EntityType_Kind
	switch kind2 := et2.Kind; kind2 {
	case proto2.EntityType_KIND_MAP:
		kind3 = proto3.EntityType_KIND_MAP
	case proto2.EntityType_KIND_LIST:
		kind3 = proto3.EntityType_KIND_LIST
	case proto2.EntityType_KIND_REGEXP:
		kind3 = proto3.EntityType_KIND_REGEXP
	default:
		kind3 = proto3.EntityType_KIND_UNSPECIFIED
	}
	var expansion3 proto3.EntityType_AutoExpansionMode
	switch expansion2 := et2.AutoExpansionMode; expansion2 {
	case proto2.EntityType_AUTO_EXPANSION_MODE_DEFAULT:
		expansion3 = proto3.EntityType_AUTO_EXPANSION_MODE_DEFAULT
	default:
		expansion3 = proto3.EntityType_AUTO_EXPANSION_MODE_UNSPECIFIED
	}
	et3 := &proto3.EntityType{
		DisplayName:           et2.DisplayName,
		Kind:                  kind3,
		AutoExpansionMode:     expansion3,
		EnableFuzzyExtraction: et2.EnableFuzzyExtraction,
	}
	for _, e2 := range et2.Entities {
		et3.Entities = append(et3.Entities, &proto3.EntityType_Entity{
			Value:    e2.Value,
			Synonyms: e2.Synonyms,
		})
	}
	return et3
}

// convertParameterEntityType converts a entity type found in parameters
func convertParameterEntityType(intent string, parameter string, t2 string) string {
	if len(t2) == 0 {
		return ""
	}
	t2 = t2[1:] // remove @
	if strings.HasPrefix(t2, "sys.") {
		if val, ok := convertSystemEntity[t2]; ok {
			t2 = val
		} else {
			t2 = "sys.any"
			logIssue("Intent<"+intent+">.Parameter<"+parameter+">",
				"This intent parameter uses a system entity not supported by CX English agents. See the migration guide for advice. System entity: "+t2)
		}
		return fmt.Sprintf("projects/-/locations/-/agents/-/entityTypes/%s", t2)
	}
	return entityTypeShortToLong[t2]
}

// convertIntent converts an ES intent to CX
func convertIntent(intent2 *proto2.Intent) *proto3.Intent {
	if intent2.DisplayName == "Default Fallback Intent" ||
		intent2.DisplayName == "Default Welcome Intent" {
		return nil
	}

	intent3 := &proto3.Intent{
		DisplayName: intent2.DisplayName,
	}

	// WebhookState
	if intent2.WebhookState != proto2.Intent_WEBHOOK_STATE_UNSPECIFIED {
		logIssue("Intent<"+intent2.DisplayName+">.WebhookState",
			"This intent has webhook enabled. You must configure this in your CX agent.")
	}

	// IsFallback
	if intent2.IsFallback {
		logIssue("Intent<"+intent2.DisplayName+">.IsFallback",
			"This intent is a fallback intent. CX does not support this. Use no-match events instead.")
	}

	// MlDisabled
	if intent2.MlDisabled {
		logIssue("Intent<"+intent2.DisplayName+">.MlDisabled",
			"This intent has ML disabled. CX does not support this.")
	}

	// LiveAgentHandoff
	if intent2.LiveAgentHandoff {
		logIssue("Intent<"+intent2.DisplayName+">.LiveAgentHandoff",
			"This intent uses live agent handoff. You must configure this in a fulfillment.")
	}

	// EndInteraction
	if intent2.EndInteraction {
		logIssue("Intent<"+intent2.DisplayName+">.EndInteraction",
			"This intent uses end interaction. CX does not support this.")
	}

	// InputContextNames
	if len(intent2.InputContextNames) > 0 {
		logIssue("Intent<"+intent2.DisplayName+">.InputContextNames",
			"This intent uses context. See the migration guide for alternatives.")
	}

	// Events
	if len(intent2.Events) > 0 {
		logIssue("Intent<"+intent2.DisplayName+">.Events",
			"This intent uses events. Use event handlers instead.")
	}

	// TrainingPhrases
	var trainingPhrases3 []*proto3.Intent_TrainingPhrase
	for _, tp2 := range intent2.TrainingPhrases {
		if tp2.Type == proto2.Intent_TrainingPhrase_TEMPLATE {
			logIssue("Intent<"+intent2.DisplayName+">.TrainingPhrases",
				"This intent has a training phrase that uses a template (@...) training phrase type. CX does not support this.")
		}
		var parts3 []*proto3.Intent_TrainingPhrase_Part
		for _, part2 := range tp2.Parts {
			parts3 = append(parts3, &proto3.Intent_TrainingPhrase_Part{
				Text:        part2.Text,
				ParameterId: part2.Alias,
			})
		}
		trainingPhrases3 = append(trainingPhrases3, &proto3.Intent_TrainingPhrase{
			Parts:       parts3,
			RepeatCount: 1,
		})
	}
	intent3.TrainingPhrases = trainingPhrases3

	// Action
	if len(intent2.Action) > 0 {
		logIssue("Intent<"+intent2.DisplayName+">.Action",
			"This intent sets the action field. Use a fulfillment webhook tag instead.")
	}

	// OutputContexts
	if len(intent2.OutputContexts) > 0 {
		logIssue("Intent<"+intent2.DisplayName+">.OutputContexts",
			"This intent uses context. See the migration guide for alternatives.")
	}

	// ResetContexts
	if intent2.ResetContexts {
		logIssue("Intent<"+intent2.DisplayName+">.ResetContexts",
			"This intent uses context. See the migration guide for alternatives.")
	}

	// Parameters
	var parameters3 []*proto3.Intent_Parameter
	for _, p2 := range intent2.Parameters {
		if len(p2.Value) > 0 && p2.Value != "$"+p2.DisplayName {
			logIssue("Intent<"+intent2.DisplayName+">.Parameters<"+p2.DisplayName+">.Value",
				"This field is not set to $parameter-name. This feature is not supported by CX. See: https://cloud.google.com/dialogflow/es/docs/intents-actions-parameters#valfield.")
		}
		if len(p2.DefaultValue) > 0 {
			logIssue("Intent<"+intent2.DisplayName+">.Parameters<"+p2.DisplayName+">.DefaultValue",
				"This intent parameter is using a default value. CX intent parameters do not support default values, but CX page form parameters do. This parameter should probably become a form parameter.")
		}
		if p2.Mandatory {
			logIssue("Intent<"+intent2.DisplayName+">.Parameters<"+p2.DisplayName+">.Mandatory",
				"This intent parameter is marked as mandatory. CX intent parameters do not support mandatory parameters, but CX page form parameters do. This parameter should probably become a form parameter.")
		}
		for _, prompt := range p2.Prompts {
			logIssue("Intent<"+intent2.DisplayName+">.Parameters<"+p2.DisplayName+">.Prompts",
				"This intent parameter has a prompt. Use page form parameter prompts instead. Prompt: "+prompt)
		}
		if len(p2.EntityTypeDisplayName) == 0 {
			p2.EntityTypeDisplayName = "@sys.any"
			logIssue("Intent<"+intent2.DisplayName+">.Parameters<"+p2.DisplayName+">.EntityTypeDisplayName",
				"This intent parameter does not have an entity type. CX requires an entity type for all parameters..")
		}
		parameters3 = append(parameters3, &proto3.Intent_Parameter{
			Id:         p2.DisplayName,
			EntityType: convertParameterEntityType(intent2.DisplayName, p2.DisplayName, p2.EntityTypeDisplayName),
			IsList:     p2.IsList,
		})
		//fmt.Printf("Converted parameter: %+v\n", parameters3[len(parameters3)-1])
	}
	intent3.Parameters = parameters3

	// Messages
	for _, message := range intent2.Messages {
		m, ok := message.Message.(*proto2.Intent_Message_Text_)
		if ok {
			for _, t := range m.Text.Text {
				warnings := ""
				if strings.Contains(t, "#") {
					warnings += " This message may contain a context parameter reference, but CX does not support this."
				}
				if strings.Contains(t, ".original") {
					warnings += " This message may contain a parameter reference suffix of '.original', But CX only supports this for intent parameters (not session parameters)."
				}
				if strings.Contains(t, ".recent") {
					warnings += " This message may contain a parameter reference suffix of '.recent', but CX does not support this."
				}
				if strings.Contains(t, ".partial") {
					warnings += " This message may contain a parameter reference suffix of '.partial', but CX does not support this."
				}
				logIssue("Intent<"+intent2.DisplayName+">.Messages",
					"This intent has a response message. Use fulfillment instead."+warnings+" Message: "+t)
			}
		} else {
			logIssue("Intent<"+intent2.DisplayName+">.Messages",
				"This intent has a non-text response message. See the rich response message information in the migration guide.")
		}
		if message.Platform != proto2.Intent_Message_PLATFORM_UNSPECIFIED {
			logIssue("Intent<"+intent2.DisplayName+">.Platform",
				"This intent has a message with a non-default platform. See the migration guide for advice.")
		}
	}

	return intent3
}

// migrateEntities migrates ES entities to your CX agent
func migrateEntities(ctx context.Context) error {
	var err error

	// Create ES client
	var client2 *v2.EntityTypesClient
	options2 := []option.ClientOption{}
	if len(*v2Region) > 0 {
		options2 = append(options2,
			option.WithEndpoint(*v2Region+"-dialogflow.googleapis.com:443"))
	}
	client2, err = v2.NewEntityTypesClient(ctx, options2...)
	if err != nil {
		return err
	}
	defer client2.Close()
	var parent2 string
	if len(*v2Region) == 0 {
		parent2 = fmt.Sprintf("projects/%s/agent", *v2Project)
	} else {
		parent2 = fmt.Sprintf("projects/%s/locations/%s/agent", *v2Project, *v2Region)
	}

	// Create CX client
	var client3 *v3.EntityTypesClient
	options3 := []option.ClientOption{}
	if len(*v3Region) > 0 {
		options3 = append(options3,
			option.WithEndpoint(*v3Region+"-dialogflow.googleapis.com:443"))
	}
	client3, err = v3.NewEntityTypesClient(ctx, options3...)
	if err != nil {
		return err
	}
	defer client3.Close()
	parent3 := fmt.Sprintf("projects/%s/locations/%s/agents/%s", *v3Project, *v3Region, *v3Agent)

	// Read each V2 entity type, convert, and write to V3
	request2 := &proto2.ListEntityTypesRequest{
		Parent: parent2,
	}
	it2 := client2.ListEntityTypes(ctx, request2)
	for {
		var et2 *proto2.EntityType
		et2, err = it2.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return err
		}
		fmt.Printf("Entity Type: %s\n", et2.DisplayName)

		if *dryRun {
			convertEntityType(et2)
			continue
		}

		request3 := &proto3.CreateEntityTypeRequest{
			Parent:     parent3,
			EntityType: convertEntityType(et2),
		}
		et3, err := client3.CreateEntityType(ctx, request3)
		entityTypeShortToLong[et3.DisplayName] = et3.Name
		if err != nil {
			return err
		}

		// ES and CX each have a quota limit of 60 design-time requests per minute
		time.Sleep(2 * time.Second)
	}
	return nil
}

// migrateIntents migrates intents to your CX agent
func migrateIntents(ctx context.Context) error {
	var err error

	// Create ES client
	var client2 *v2.IntentsClient
	options2 := []option.ClientOption{}
	if len(*v2Region) > 0 {
		options2 = append(options2,
			option.WithEndpoint(*v2Region+"-dialogflow.googleapis.com:443"))
	}
	client2, err = v2.NewIntentsClient(ctx, options2...)
	if err != nil {
		return err
	}
	defer client2.Close()
	var parent2 string
	if len(*v2Region) == 0 {
		parent2 = fmt.Sprintf("projects/%s/agent", *v2Project)
	} else {
		parent2 = fmt.Sprintf("projects/%s/locations/%s/agent", *v2Project, *v2Region)
	}

	// Create CX client
	var client3 *v3.IntentsClient
	options3 := []option.ClientOption{}
	if len(*v3Region) > 0 {
		options3 = append(options3,
			option.WithEndpoint(*v3Region+"-dialogflow.googleapis.com:443"))
	}
	client3, err = v3.NewIntentsClient(ctx, options3...)
	if err != nil {
		return err
	}
	defer client3.Close()
	parent3 := fmt.Sprintf("projects/%s/locations/%s/agents/%s", *v3Project, *v3Region, *v3Agent)

	// Read each V2 entity type, convert, and write to V3
	request2 := &proto2.ListIntentsRequest{
		Parent:     parent2,
		IntentView: proto2.IntentView_INTENT_VIEW_FULL,
	}
	it2 := client2.ListIntents(ctx, request2)
	for {
		var intent2 *proto2.Intent
		intent2, err = it2.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return err
		}
		fmt.Printf("Intent: %s\n", intent2.DisplayName)
		intent3 := convertIntent(intent2)
		if intent3 == nil {
			continue
		}

		if *dryRun {
			continue
		}

		request3 := &proto3.CreateIntentRequest{
			Parent: parent3,
			Intent: intent3,
		}
		_, err := client3.CreateIntent(ctx, request3)
		if err != nil {
			return err
		}

		// ES and CX each have a quota limit of 60 design-time requests per minute
		time.Sleep(2 * time.Second)
	}
	return nil
}

// checkFlags checks commandline flags
func checkFlags() error {
	flag.Parse()
	if len(*v2Project) == 0 {
		return fmt.Errorf("Need to supply es-project-id flag")
	}
	if len(*v3Project) == 0 {
		return fmt.Errorf("Need to supply cx-project-id flag")
	}
	if len(*v2Region) == 0 {
		fmt.Printf("No region supplied for ES, using default\n")
	}
	if len(*v3Region) == 0 {
		return fmt.Errorf("Need to supply cx-region-id flag")
	}
	if len(*v3Agent) == 0 {
		return fmt.Errorf("Need to supply cx-agent-id flag")
	}
	if len(*outFile) == 0 {
		return fmt.Errorf("Need to supply out-file flag")
	}
	return nil
}

// closeFile is used as a convenience for defer
func closeFile(f *os.File) {
	err := f.Close()
	if err != nil {
		fmt.Fprintf(os.Stderr, "ERROR closing CSV file: %v\n", err)
		os.Exit(1)
	}
}

func main() {
	if err := checkFlags(); err != nil {
		fmt.Fprintf(os.Stderr, "ERROR checking flags: %v\n", err)
		os.Exit(1)
	}
	ctx := context.Background()
	if err := migrateEntities(ctx); err != nil {
		fmt.Fprintf(os.Stderr, "ERROR migrating entities: %v\n", err)
		os.Exit(1)
	}
	if err := migrateIntents(ctx); err != nil {
		fmt.Fprintf(os.Stderr, "ERROR migrating intents: %v\n", err)
		os.Exit(1)
	}
	csvFile, err := os.Create(*outFile)
	if err != nil {
		fmt.Fprintf(os.Stderr, "ERROR opening output file: %v", err)
		os.Exit(1)
	}
	defer closeFile(csvFile)
	csvWriter := csv.NewWriter(csvFile)
	if err := csvWriter.WriteAll(issues); err != nil {
		fmt.Fprintf(os.Stderr, "ERROR writing CSV output file: %v", err)
		os.Exit(1)
	}
	csvWriter.Flush()
}

゚ンティティ タむプのツヌル移行

Dialogflow ES ゚ンティティ タむプず 䌚話゚ヌゞェントDialogflow CX゚ンティティ タむプはよく䌌おおり、移行が最も簡単なデヌタ型です。ツヌルによっお、゚ンティティ タむプが単にそのたたコピヌされたす。

むンテントのツヌル移行

Dialogflow ES のむンテントず 䌚話゚ヌゞェントDialogflow CXのむンテントは倧きく異なりたす。

Dialogflow ES のむンテントぱヌゞェントの構成芁玠ずしお䜿甚され、トレヌニング フレヌズ、レスポンス、䌚話制埡のコンテキスト、Webhook 構成、むベント、アクション、スロット入力パラメヌタが含たれおいたす。

䌚話゚ヌゞェントDialogflow CXでは、このデヌタの倧郚分が他のリ゜ヌスに移動されおいたす。䌚話゚ヌゞェントDialogflow CXのむンテントにはトレヌニング フレヌズずパラメヌタのみが含たれるため、゚ヌゞェント間でむンテントを再利甚できたす。ツヌルは、これらの 2 皮類のむンテント デヌタのみを䌚話゚ヌゞェントDialogflow CXのむンテントにコピヌしたす。

移行ツヌルの制限事項

移行ツヌルは、次の項目をサポヌトしおいたせん。

  • メガ ゚ヌゞェント: ツヌルは耇数のサブ゚ヌゞェントから読み取るこずはできたせんが、各サブ゚ヌゞェントに察しおツヌルを耇数回呌び出すこずができたす。
  • 倚蚀語゚ヌゞェント: ツヌルを倉曎しお、倚蚀語のトレヌニング フレヌズず゚ンティティ ゚ントリを䜜成する必芁がありたす。
  • 英語以倖の蚀語に関するシステム ゚ンティティの確認: ツヌルは、䌚話゚ヌゞェントDialogflow CXでサポヌトされおいないシステム ゚ンティティを怜出するず、TODO 項目を䜜成したす。英語がデフォルトの蚀語であり、米囜のリヌゞョンを䜿甚しおいるこずを前提ずしおいたす。システム ゚ンティティのサポヌトは、蚀語や地域によっお異なりたす。 他の蚀語ず地域の堎合は、このチェックを実行するようにツヌルを倉曎する必芁がありたす。

必須の移行手順

以降のサブセクションでは、移行手順の抂芁を説明したす。これらの手動の手順は、順番に行う必芁はありたせん。たた、これらのステップを同時に、たたは異なる順序で実行するこずもできたす。 実際に倉曎を加える前に、手順党䜓を読んで倉曎の蚈画を開始したす。

移行ツヌルを実行した埌、䌚話゚ヌゞェントDialogflow CX゚ヌゞェントを再構築したす。この段階でもかなりの量の移行䜜業が残っおいたすが、手動で入力したデヌタの倧郚分は䌚話゚ヌゞェントDialogflow CX゚ヌゞェントず TODO ファむル内に存圚しおいたす。

䌚話゚ヌゞェントDialogflow CX゚ヌゞェントを䜜成する

䌚話゚ヌゞェントDialogflow CX゚ヌゞェントを䜜成したすただ䜜成しおいない堎合。Dialogflow ES ゚ヌゞェントず同じデフォルト蚀語を䜿甚しおください。

移行ツヌルを実行する

ツヌルを実行するには、次の手順に埓いたす。

  1. Go をマシンにむンストヌルしたすただむンストヌルしおいない堎合。
  2. ツヌルコヌド甚のディレクトリ migrate を䜜成したす。
  3. 䞊蚘のツヌルコヌドを、このディレクトリの main.go ずいうファむルにコピヌしたす。
  4. 必芁に応じおコヌドを倉曎したす。
  5. このディレクトリに Go モゞュヌルを䜜成したす。次に䟋を瀺したす。

    go mod init migrate
    
  6. Dialogflow ES V2 ず䌚話゚ヌゞェントDialogflow CXV3 の Go クラむアント ラむブラリをむンストヌルしたす。

    go get cloud.google.com/go/dialogflow/apiv2
    go get cloud.google.com/go/dialogflow/cx/apiv3
    
  7. クラむアント ラむブラリの認蚌が蚭定されおいるこずを確認したす。

  8. ツヌルを実行し、出力をファむルに保存したす。

    go run main.go -es-project-id=<ES_PROJECT_ID> -cx-project-id=<CX_PROJECT_ID> \
    -cx-region-id=<CX_REGION_ID> -cx-agent-id=<CX_AGENT_ID> -out-file=out.csv
    

移行ツヌルのトラブルシュヌティング

ツヌルの実行時に゚ラヌが発生した堎合は、次の点を確認しおください。

゚ラヌ 解決策
トレヌニング フレヌズの䞀郚で、むンテント甚に定矩されおいないパラメヌタが蚀及されおいるずいう RPC ゚ラヌ。 これは、以前に Dialogflow ES API を䜿甚しお、トレヌニング フレヌズず䞀臎しない方法でむンテント パラメヌタを䜜成した堎合に発生するこずがありたす。この問題を解決するには、コン゜ヌルから Dialogflow ES パラメヌタの名前を倉曎し、トレヌニング フレヌズがパラメヌタを正しく䜿甚しおいるこずを確認しおから、[保存] をクリックしたす。たた、トレヌニング フレヌズで存圚しないパラメヌタを参照しおいる堎合にも発生するこずがありたす。

゚ラヌを修正したら、移行ツヌルを再床実行する前に、䌚話゚ヌゞェントDialogflow CX゚ヌゞェントのむンテントず゚ンティティを消去する必芁がありたす。

Dialogflow ES のむンテント デヌタを䌚話゚ヌゞェントDialogflow CXに移動する

このツヌルは、むンテントのトレヌニング フレヌズずパラメヌタを䌚話゚ヌゞェントDialogflow CXのむンテントに移行したすが、手動で移行する必芁がある Dialogflow ES むンテント フィヌルドが他にも倚くありたす。

Dialogflow ES むンテントには、察応する䌚話゚ヌゞェントDialogflow CXペヌゞか察応する䌚話゚ヌゞェントDialogflow CXむンテント、たたはその䞡方が必芁になる堎合がありたす。

Dialogflow ES むンテントの䞀臎を䜿甚しお䌚話を特定の䌚話ノヌドから別の䌚話ノヌドに遷移させる堎合、このむンテントに関連する以䞋の 2 ぀のペヌゞが゚ヌゞェントに存圚する必芁がありたす。

  • 次のペヌゞに遷移するむンテント ルヌトを含む元のペヌゞ: 元のペヌゞのむンテント ルヌトに、Dialogflow ES むンテントのレスポンスず同様の䌚話゚ヌゞェントDialogflow CXフルフィルメント メッセヌゞが含たれおいる堎合がありたす。このペヌゞには倚くのむンテント ルヌトが存圚する堎合がありたす。 元のペヌゞがアクティブな間、これらのむンテント ルヌトは䌚話を倚くの可胜なパスに遷移できたす。 倚くの Dialogflow ES むンテントで、察応する同じ䌚話゚ヌゞェントDialogflow CXの元のペヌゞを共有しおいたす。
  • 元のペヌゞのむンテント ルヌトの遷移タヌゲットである次のペヌゞ: 次のペヌゞの䌚話゚ヌゞェントDialogflow CX゚ントリ フルフィルメントに、Dialogflow ES むンテントのレスポンスず同様の䌚話゚ヌゞェントDialogflow CXフルフィルメント メッセヌゞが含たれおいる堎合がありたす。

Dialogflow ES むンテントに必須パラメヌタが含たれおいる堎合は、フォヌムに同じパラメヌタを持぀察応する䌚話゚ヌゞェントDialogflow CXペヌゞを䜜成する必芁がありたす。

䌚話゚ヌゞェントDialogflow CXのむンテントず䌚話゚ヌゞェントDialogflow CXペヌゞでは同じパラメヌタ リストを持぀ようにするのが䞀般的です。぀たり、ある 1 ぀の Dialogflow ES むンテントには、それに察応する䌚話゚ヌゞェントDialogflow CXペヌゞず䌚話゚ヌゞェントDialogflow CXむンテントが 1 ぀ず぀あるこずを意味したす。むンテント ルヌトのパラメヌタを持぀䌚話゚ヌゞェントDialogflow CXむンテントが䞀臎するず、䌚話は倚くの堎合同じパラメヌタを持぀ペヌゞに遷移したす。むンテント マッチから抜出されたパラメヌタは、セッション パラメヌタに䌝播されたす。このパラメヌタは、ペヌゞ フォヌム パラメヌタの䞀郚たたは党䜓で䜿甚できたす。

䌚話゚ヌゞェントDialogflow CXには、フォヌルバック むンテントず事前定矩されたフォロヌアップ むンテントはありたせん。組み蟌みむンテントをご芧ください。

次の衚に、Dialogflow ES から䌚話゚ヌゞェントDialogflow CXリ゜ヌスに特定のむンテント デヌタをマッピングする方法を瀺したす。

Dialogflow ES むンテント デヌタ 察応する䌚話゚ヌゞェントDialogflow CXデヌタ 必芁なアクション
トレヌニング フレヌズ むンテント トレヌニング フレヌズ ツヌルにより移行されたす。ツヌルはシステム ゚ンティティのサポヌトを確認し、サポヌトされおいないシステム ゚ンティティの TODO 項目を䜜成したす。
゚ヌゞェント レスポンス フルフィルメント レスポンス メッセヌゞ ゚ヌゞェントのレスポンスをご芧ください。
䌚話の制埡のコンテキスト なし 構造ず䌚話パスの制埡をご芧ください。
Webhook の蚭定 フルフィルメント Webhook の構成 Webhooks をご芧ください。
むベント フロヌレベルたたはペヌゞレベルのむベント ハンドラ むベントをご芧ください。
アクション フルフィルメント Webhook タグ Webhooks をご芧ください。
パラメヌタ むンテント パラメヌタおよび / たたはペヌゞフォヌム パラメヌタ ツヌルによりむンテント パラメヌタに移行されたす。パラメヌタが必芁な堎合は、ツヌルによりペヌゞに移行する可胜性のある TODO アむテムが䜜成されたす。パラメヌタをご芧ください。
パラメヌタ プロンプト ペヌゞフォヌム パラメヌタのプロンプト フォヌム入力をご芧ください。

フロヌを䜜成する

高レベルの䌚話トピックごずにフロヌを䜜成したす。 各フロヌ内のトピックは区別しお、䌚話がフロヌ間で頻繁に行ったり来たりしないようにしたす。

メガ ゚ヌゞェントを䜿甚しおいた堎合は、各サブ゚ヌゞェントを 1 ぀以䞊のフロヌにする必芁がありたす。

基本的な䌚話パスから始める

倉曎を反埩凊理しながら、シミュレヌタを䜿甚しお゚ヌゞェントをテストするこずをおすすめしたす。 そのために、䌚話の早い段階で基本的な䌚話パスに焊点を圓お、倉曎を加えるたびにテストする必芁がありたす。 これらが機胜したら、より詳现な䌚話パスに進みたす。

フロヌレベルずペヌゞレベルの状態ハンドラ

状態ハンドラを䜜成する際は、フロヌレベルたたはペヌゞレベルで適甚する必芁があるかどうかを怜蚎しおください。 フロヌレベルのハンドラは、フロヌ぀たりフロヌ内のペヌゞがアクティブなずきに垞にスコヌプに含たれたす。 ペヌゞレベルのハンドラは、特定のペヌゞがアクティブな堎合にのみスコヌプに含たれたす。 フロヌレベルのハンドラは、入力コンテキストを持たない Dialogflow ES むンテントに䌌おいたす。ペヌゞレベルのハンドラは、入力コンテキストを持぀ Dialogflow ES むンテントに䌌おいたす。

Webhook コヌド

䌚話゚ヌゞェントDialogflow CXでは、Webhook のリク゚スト プロパティずレスポンス プロパティが異なりたす。Webhook のセクションをご芧ください。

ナレッゞ コネクタ

䌚話゚ヌゞェントDialogflow CXでは、ナレッゞ コネクタはただサポヌトされおいたせん。これらを通垞のむンテントずしお実装するか、䌚話゚ヌゞェントDialogflow CXでナレッゞ コネクタがサポヌトされるたで埅぀必芁がありたす。

゚ヌゞェントの蚭定

Dialogflow ES ゚ヌゞェントの蚭定を確認し、必芁に応じお䌚話゚ヌゞェントDialogflow CX゚ヌゞェントの蚭定を調敎したす。

TODO ファむルを䜿甚する

移行ツヌルは CSV ファむルを出力したす。 このリストの項目は、泚意が必芁なデヌタに焊点を圓おおいたす。 このファむルをスプレッドシヌトにむンポヌトしたす。完了マヌク甚の列を䜿甚しお、スプレッドシヌト内の各項目を解決したす。

API 䜿甚の移行

システムでランタむムたたは蚭蚈時の呌び出しに Dialogflow ES API を䜿甚しおいる堎合は、䌚話゚ヌゞェントDialogflow CXAPI を䜿甚するようにこのコヌドを曎新する必芁がありたす。実行時に怜出むンテントの呌び出しのみを䜿甚しおいる堎合は、この曎新は非垞に簡単です。

統合

゚ヌゞェントで統合を䜿甚する堎合は、統合のセクションを参照しお必芁に応じお倉曎しおください。

以䞋のサブセクションでは、掚奚される移行手順の抂芁を瀺したす。

怜蚌

゚ヌゞェントの怜蚌を䜿甚しお、゚ヌゞェントがベスト プラクティスを遵守しおいるこずを確認したす。

テスト

䞊蚘の手動移行手順を実行しながら、シミュレヌタを䜿甚しお゚ヌゞェントをテストする必芁がありたす。 ゚ヌゞェントが動䜜しおいるこずが確認できれば、Dialogflow ES ゚ヌゞェントず䌚話゚ヌゞェントDialogflow CX゚ヌゞェントの間の䌚話を比范し、動䜜が同等以䞊になっおいるかを確認する必芁がありたす。

シミュレヌタでこれらの䌚話をテストする際に、テストケヌスを䜜成しお将来の回垰を防ぐ必芁がありたす。

環境

Dialogflow ES 環境を確認し、必芁に応じお䌚話゚ヌゞェントDialogflow CX環境を曎新したす。