Von Dialogflow ES zu Dialogflow CX migrieren

Dialogflow CX-Agenten bieten Ihnen leistungsfähigere Tools und Steuerelemente für Unterhaltungen als Dialogflow ES-Agenten. Wenn Ihr Dialogflow ES-Agent komplexe Unterhaltungen verarbeitet, sollten Sie eine Migration zu Dialogflow CX in Betracht ziehen.

In diesem Leitfaden wird beschrieben, wie Sie einen Agenten von Dialogflow ES zu Dialogflow CX migrieren. Diese beiden Agententypen weisen viele grundlegende Unterschiede auf, sodass es keine einfache Möglichkeit gibt, diese Migration durchzuführen.

Wenn Sie diesen Leitfaden für eine Migration verwenden, geben Sie bitte positives oder negatives Feedback, indem Sie oben auf den Button Feedback geben klicken. Wir nutzen dieses Feedback, um die automatische Hilfe im Laufe der Zeit zu verbessern.

Auf übergeordneter Ebene wird ein automatisierter/manueller Hybridprozess empfohlen. Sie verwenden ein Tool, das einige Ihrer Dialogflow ES-Agentendaten liest, diese Daten in Ihren Dialogflow CX-Agenten schreibt und eine TODO-Liste erfasst. Anschließend erstellen Sie Ihren gesamten Dialogflow CX-Agenten anhand von Best Practices, der TODO-Liste und den vom Tool migrierten Daten neu.

Dialogflow CX verstehen

Bevor Sie diese Migration durchführen, sollten Sie sich mit der Funktionsweise von Dialogflow CX-Abläufen vertraut machen. Hier können Sie beginnen:

Sie sollten auch zusätzliche Konzeptdokumente lesen, die Funktionen enthalten, die Sie wahrscheinlich in Ihrem neuen KI-Agenten benötigen. Konzentrieren Sie sich auf Folgendes:

Unterschiede zwischen Dialogflow ES und Dialogflow CX

In diesem Abschnitt werden die wichtigsten Unterschiede zwischen Dialogflow ES und Dialogflow CX aufgeführt. Wenn Sie später manuelle Migrationsschritte ausführen, sollten Sie sich an diesem Abschnitt orientieren.

Struktur und Steuerung des Unterhaltungsverlaufs

Dialogflow ES bietet Folgendes für die Struktur und die Steuerung des Unterhaltungsverlaufs:

  • Intents werden als Bausteine des Agenten verwendet. An jedem Punkt der Unterhaltung wird ein Intent abgeglichen. In gewisser Weise ist jeder Intent ein Knoten für die Unterhaltung.
  • Der Kontext wird zur Steuerung der Unterhaltung verwendet. Mithilfe des Kontexts wird gesteuert, welche Intents zu einem bestimmten Zeitpunkt abgeglichen werden können. Der Kontext läuft nach einer bestimmten Anzahl von Gesprächsrunden ab, sodass diese Art der Steuerung bei langen Unterhaltungen ungenau sein kann.

Dialogflow CX bietet eine Hierarchie von Strukturressourcen und präzisere Steuerelemente für den Konversationspfad:

  • Seiten sind Diagrammknoten für die Unterhaltung. Dialogflow CX-Unterhaltungen ähneln Zustandsmaschinen. Zu jedem Zeitpunkt der Unterhaltung ist eine Seite aktiv. Basierend auf Eingaben oder Ereignissen von Endnutzern kann die Unterhaltung zu einer anderen Seite wechseln. Es ist üblich, dass eine Seite für mehrere Unterhaltungsrunden aktiv bleibt.
  • Abläufe sind Gruppen von zusammengehörigen Seiten. Jeder Ablauf sollte ein übergeordnetes Konversationsthema behandeln.
  • Zustands-Handler werden verwendet, um Übergänge und Antworten zu steuern. Es gibt drei Arten von Zustands-Handlern:
    • Intent-Route: Enthält einen Intent, der übereinstimmen muss, optionale Antworten und einen optionalen Seitenübergang.
    • Bedingungsroute: Enthält eine Bedingung, die erfüllt sein muss, optionale Antworten und einen optionalen Seitenübergang.
    • Ereignis-Handler: Enthält einen Ereignisnamen, der aufgerufen werden muss, optionale Antworten und einen optionalen Seitenübergang.
  • Mit dem Bereich wird gesteuert, ob ein Zustands-Handler aufgerufen werden kann. Die meisten Handler sind mit einer Seite oder einem gesamten Ablauf verknüpft. Wenn die zugehörige Seite oder der zugehörige Ablauf aktiv ist, befindet sich der Handler im Geltungsbereich und kann aufgerufen werden. Eine Intent-Route in Dialogflow CX im Bereich ähnelt einem Intent in Dialogflow ES mit einem aktiven Eingabekontext.

Wenn Sie die Abläufe und Seiten Ihres Agenten entwerfen, sollten Sie die Hinweise im Abschnitt „Ablauf“ des Leitfadens zum Agenten-Design beachten.

Formular ausfüllen

Dialogflow ES verwendet Slot-Füllung, um erforderliche Parameter von Endnutzern zu erfassen:

  • Diese Parameter sind Intent-Parameter, die als erforderlich gekennzeichnet sind.
  • Der Intent wird so lange abgeglichen, bis alle erforderlichen Parameter erfasst wurden.
  • Sie können einen Prompt definieren, in dem der Endnutzer aufgefordert wird, einen Wert anzugeben.

Dialogflow CX verwendet das Ausfüllen von Formularen, um erforderliche Parameter von Endnutzern zu erfassen:

  • Diese Parameter sind einer Seite zugeordnet und werden erfasst, während die Seite aktiv ist.
  • Sie verwenden Bedingungsrouten für Seiten, um festzulegen, dass das Ausfüllen des Formulars abgeschlossen ist. Diese Bedingungsrouten führen in der Regel zu einer anderen Seite.
  • Sie können einen Prompt sowie Handler für erneute Prompts definieren, um mehrere Versuche zur Erfassung eines Werts ordnungsgemäß zu verarbeiten.

Übergänge

Dialogflow ES wechselt automatisch von einem Intent zum nächsten, wenn die Eingabe des Endnutzers mit einem Intent übereinstimmt. Diese Übereinstimmung kann nur für Intents ohne Eingabekontext oder Intents mit einem aktiven Eingabekontext auftreten.

Dialogflow CX wechselt von einer Seite zur nächsten, wenn ein Zustands-Handler im Bereich die Anforderungen erfüllt und ein Übergangsziel bereitstellt. Mit diesen Übergängen können Sie Endnutzer zuverlässig durch Unterhaltungen führen. Es gibt mehrere Möglichkeiten, diese Übergänge zu steuern:

  • Der Intent-Abgleich kann eine Intent-Route auslösen.
  • Wenn eine Bedingung erfüllt ist, kann eine Bedingungsroute ausgelöst werden.
  • Der Aufruf eines Ereignisses kann einen Event-Handler auslösen.
  • Handler für erneute Aufforderungen können einen Übergang auslösen, wenn der Endnutzer nach mehreren Versuchen keinen Wert angibt.
  • Sie können symbolische Übergangsziele für Übergangsziele verwenden.

Agentenantworten

Antworten von Dialogflow ES-Agenten werden an Endnutzer gesendet, wenn ein Intent übereinstimmt:

  • Der Agent kann eine Nachricht für die Antwort aus einer Liste möglicher Antworten auswählen.
  • Antworten können plattformspezifisch sein und Formate für Rich-Response-Antworten verwenden.
  • Antworten können durch Webhooks gesteuert werden.

Die Antworten des Dialogflow CX-Agenten werden an den Endnutzer gesendet, wenn die Auftragsausführung aufgerufen wird. Im Gegensatz zum Dialogflow ES-Fulfillment, das immer einen Webhook umfasst, kann das Dialogflow CX-Fulfillment einen Webhook aufrufen, je nachdem, ob für die Fulfillment-Ressource ein Webhook konfiguriert ist. Sowohl statische als auch dynamische Antworten, die auf Webhook-Antworten basieren, werden durch die Auftragsausführung gesteuert. Es gibt mehrere Möglichkeiten, Antworten des KI-Agenten zu erstellen:

  • Die Ausführung kann für jede Art von Zustands-Handler bereitgestellt werden.
  • Mehrere Antworten können während einer Unterhaltung über die Antwortwarteschlange verkettet werden. Diese Funktion kann in einigen Fällen das Design Ihres Agenten vereinfachen.
  • Dialogflow CX unterstützt keine integrierten plattformspezifischen Antworten. Es bietet jedoch mehrere Antworttypen, einschließlich einer benutzerdefinierten Nutzlast, die für plattformspezifische Antworten verwendet werden kann.

Parameter

Dialogflow ES-Parameter haben die folgenden Merkmale:

  • Nur in Intents definiert.
  • Wird durch Endnutzereingaben, Ereignisse, Webhooks und API-Aufrufe festgelegt.
  • Referenziert in Antworten, Parameteraufforderungen, Webhook-Code und Parameterwerten:
    • Das grundlegende Referenzformat ist $parameter-name.
    • Referenzen unterstützen die Suffix-Syntax .original, .partial und .recent.
    • In Verweisen kann der aktive Kontext angegeben werden: #context-name.parameter-name.
    • In Verweisen können Ereignisparameter angegeben werden: #event-name.parameter-name.

Dialogflow CX-Parameter haben die folgenden Merkmale:

  • In Intents und Seitenformularen definiert.
  • Intent- und Formularparameter werden an Sitzungsparameter weitergegeben, wo sie für die Dauer der Sitzung referenziert werden können.
  • Wird durch Endnutzereingaben, Webhooks, Voreinstellungen für Fulfillment-Parameter und API-Aufrufe festgelegt.
  • In Antworten, Parameteraufforderungen, Handlern für erneute Aufforderungen, Parametervoreinstellungen und Webhook-Code referenziert:
    • Das Referenzformat ist $session.params.parameter-id für Sitzungsparameter und $intent.params.parameter-id für Intent-Parameter.
    • Verweise auf Intent-Parameter unterstützen die Suffixsyntax .original und .resolved. Sitzungsparameter unterstützen diese Syntax nicht.

Systementitäten

Dialogflow ES unterstützt viele Systementitäten.

Dialogflow CX unterstützt viele der gleichen Systementitäten, es gibt jedoch einige Unterschiede. Prüfen Sie bei der Migration, ob die Systementitäten, die Sie in Dialogflow ES verwenden, auch von Dialogflow CX für dieselbe Sprache unterstützt werden. Wenn nicht, sollten Sie benutzerdefinierte Entitäten dafür erstellen.

Ereignisse

Dialogflow ES-Ereignisse haben die folgenden Merkmale:

  • Kann über API-Aufrufe oder Webhooks aufgerufen werden, um eine Intent-Übereinstimmung zu finden.
  • Kann Parameter festlegen.
  • Eine kleine Anzahl von Ereignissen wird von Integrationsplattformen aufgerufen.

Dialogflow CX-Ereignisse haben die folgenden Merkmale:

  • Kann über API-Aufrufe oder Webhooks aufgerufen werden, um einen Event Handler aufzurufen.
  • Parameter können nicht festgelegt werden.
  • Viele integrierte Ereignisse können verwendet werden, um fehlende Eingaben von Endnutzern, nicht erkannte Eingaben von Endnutzern, durch einen Webhook ungültig gemachte Parameter und Webhook-Fehler zu verarbeiten.
  • Aufrufe können durch dieselben Bereichsregeln wie andere Zustandshandler gesteuert werden.

Integrierte Intents

Dialogflow ES unterstützt die folgenden integrierten Intents:

Im Folgenden wird die Unterstützung von Dialogflow CX für integrierte Intents beschrieben:

  • Begrüßungs-Intents werden unterstützt.
  • Fallback-Intents werden nicht bereitgestellt. Verwenden Sie stattdessen die no-match-Ereignisse in Ereignis-Handlern.
  • Verwenden Sie für negative Beispiele den negativen Standard-Intent.
  • Vordefinierte Follow-up-Intents werden nicht bereitgestellt. Sie müssen diese Intents nach Bedarf für Ihren Agenten erstellen. Sie müssen beispielsweise wahrscheinlich einen Intent erstellen, um negative Antworten auf eine Frage des Agenten zu verarbeiten („nein“, „nein danke“, „nein, ich nicht“ usw.). Dialogflow CX-Intents können im gesamten Agenten wiederverwendet werden, sodass Sie sie nur einmal definieren müssen. Wenn Sie für diese häufigen Intents unterschiedliche Intent-Routen in verschiedenen Bereichen verwenden, haben Sie eine viel bessere Kontrolle über die Unterhaltung.

Webhooks

Dialogflow ES-Webhooks haben die folgenden Merkmale:

  • Sie können einen Webhook-Dienst für den Agent konfigurieren.
  • Jeder Intent kann so markiert werden, dass er den Webhook verwendet.
  • Es gibt keine integrierte Unterstützung für die Behandlung von Webhook-Fehlern.
  • Intent-Aktionen oder Intent-Namen werden von Webhooks verwendet, um zu bestimmen, von wo im Agent sie aufgerufen wurden.
  • Die Console bietet die Direktbearbeitung.

Dialogflow CX-Webhooks haben die folgenden Merkmale:

  • Sie können mehrere Webhook-Dienste für den Agent konfigurieren.
  • Für jede Auftragsausführung kann optional ein Webhook-Aufruf angegeben werden.
  • Es gibt eine integrierte Unterstützung für die Webhook-Fehlerbehandlung.
  • Ein Dialogflow CX-Webhook für die Auftragsausführung enthält ein Tag. Dieses Tag ähnelt einer Dialogflow ES-Aktion, wird aber nur beim Aufrufen von Webhooks verwendet. Der Webhook-Dienst kann diese Tags verwenden, um zu ermitteln, von wo im Agent er aufgerufen wurde.
  • Die Konsole hat keinen integrierten Webhook-Code-Editor. Häufig werden Cloud Run Functions verwendet, es gibt aber viele Optionen.

Wenn Sie zu Dialogflow CX migrieren, müssen Sie Ihren Webhook-Code ändern, da die Anfrage- und Antwortattribute unterschiedlich sind.

Integrationen

Dialogflow ES-Integrationen und Dialogflow CX-Integrationen unterstützen verschiedene Plattformen. Bei Plattformen, die von beiden Agententypen unterstützt werden, kann es Unterschiede in der Konfiguration geben.

Wenn die von Ihnen verwendete Dialogflow ES-Integration von Dialogflow CX nicht unterstützt wird, müssen Sie möglicherweise die Plattform wechseln oder die Integration selbst implementieren.

Weitere Funktionen, die nur in Dialogflow CX verfügbar sind

Es gibt viele weitere Funktionen, die nur von Dialogflow CX bereitgestellt werden. Sie sollten diese Funktionen während der Migration verwenden. Beispiel:

Best Practices

Machen Sie sich vor der Migration mit den Best Practices für das Design von Dialogflow CX-Agenten vertraut. Viele dieser Best Practices für Dialogflow CX ähneln den Best Practices für Dialogflow ES, einige sind jedoch nur für Dialogflow CX relevant.

Informationen zum Migrationstool

Das Migrationstool kopiert den Großteil der Dialogflow ES-Daten in Ihren Dialogflow CX-Agenten und schreibt eine TODO-Datei mit einer Liste von Elementen, die manuell migriert werden müssen. Das Tool kopiert nur benutzerdefinierte Entitätstypen und Trainingsformulierungen für Intents. Sie sollten dieses Tool an Ihre spezifischen Anforderungen anpassen.

Code für das Migrationstool

Hier ist der Code für das Tool. Sie sollten sich den Code für dieses Tool ansehen, um zu verstehen, was es tut. Sie können diesen Code ändern, um bestimmte Situationen in Ihrem Agent zu verarbeiten. In den folgenden Schritten führen Sie dieses Tool aus.

// 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()
}

Toolmigration von Entitätstypen

Dialogflow ES-Entitätstypen und Dialogflow CX-Entitätstypen sind sehr ähnlich und daher der am einfachsten zu migrierende Datentyp. Das Tool kopiert Entitätstypen einfach so, wie sie sind.

Toolmigration von Intents

Dialogflow ES-Intents und Dialogflow CX-Intents unterscheiden sich stark.

Dialogflow ES-Intents werden als Bausteine des Agenten verwendet und enthalten Trainingsformulierungen, Antworten, Kontext für die Unterhaltungssteuerung, Webhook-Konfigurationen, Ereignisse, Aktionen und Parameter für die Slot-Befüllung.

Dialogflow CX hat die meisten dieser Daten in andere Ressourcen verschoben. Dialogflow CX-Intents haben nur Trainingsformulierungen und Parameter, sodass Intents im gesamten Agenten wiederverwendet werden können. Das Tool kopiert nur diese beiden Arten von Intent-Daten in Ihre Dialogflow CX-Intents.

Einschränkungen des Migrationstools

Folgendes wird vom Migrationstool nicht unterstützt:

  • Mega-Agenten: Das Tool kann nicht von mehreren Sub-Agenten lesen, aber Sie können das Tool mehrmals für jeden Sub-Agenten aufrufen.
  • Mehrsprachige KI-Agenten: Sie sollten das Tool so anpassen, dass mehrsprachige Trainingsformulierungen und Entitätseinträge erstellt werden.
  • Prüfung von Systementitäten für nicht englische Sprachen: Das Tool erstellt TODO-Elemente, wenn es Systementitäten findet, die nicht von Dialogflow CX unterstützt werden. Dabei wird davon ausgegangen, dass Englisch die Standardsprache ist und eine US-Region verwendet wird. Die Unterstützung von Systementitäten variiert je nach Sprache und Region. Für andere Sprachen und Regionen sollten Sie das Tool so anpassen, dass diese Prüfung durchgeführt wird.

Wichtige Migrationsschritte

In den folgenden Abschnitten werden die erforderlichen Migrationsschritte beschrieben. Sie müssen diese manuellen Schritte nicht in der angegebenen Reihenfolge ausführen. Möglicherweise müssen Sie diese Schritte sogar gleichzeitig oder in einer anderen Reihenfolge ausführen. Lesen Sie sich die Schritte durch und planen Sie Ihre Änderungen, bevor Sie sie tatsächlich vornehmen.

Nachdem Sie das Migrationstool ausgeführt haben, können Sie Ihren Dialogflow CX-Agenten neu erstellen. Sie müssen zwar noch einiges an Migrationsarbeit leisten, aber der Großteil der manuell eingegebenen Daten ist in Ihrem Dialogflow CX-Agenten und der TODO-Datei vorhanden.

Dialogflow CX-Agent erstellen

Erstellen Sie Ihren Dialogflow CX-Agenten, falls noch nicht geschehen. Achten Sie darauf, dieselbe Standardsprache wie für Ihren Dialogflow ES-Agenten zu verwenden.

Migrationstool ausführen

Führen Sie die folgenden Schritte aus, um das Tool auszuführen:

  1. Installieren Sie Go auf Ihrem Computer, falls noch nicht geschehen.
  2. Erstellen Sie ein Verzeichnis für den Toolcode mit dem Namen migrate.
  3. Kopieren Sie den Toolcode oben in eine Datei mit dem Namen main.go in diesem Verzeichnis.
  4. Ändern Sie den Code bei Bedarf für Ihren Fall.
  5. Erstellen Sie in diesem Verzeichnis ein Go-Modul. Beispiel:

    go mod init migrate
    
  6. Installieren Sie die Go-Clientbibliotheken für Dialogflow ES V2 und Dialogflow CX V3:

    go get cloud.google.com/go/dialogflow/apiv2
    go get cloud.google.com/go/dialogflow/cx/apiv3
    
  7. Prüfen Sie, ob Sie die Authentifizierung der Clientbibliothek eingerichtet haben.

  8. Führen Sie das Tool aus und speichern Sie die Ausgabe in einer Datei:

    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
    

Fehlerbehebung bei Problemen mit dem Umstellungstool

Wenn beim Ausführen des Tools Fehler auftreten, prüfen Sie Folgendes:

Fehler Lösung
RPC-Fehler, dass in einem Teil der Trainingsformulierung ein Parameter erwähnt wird, der nicht für den Intent definiert ist. Das kann passieren, wenn Sie zuvor die Dialogflow ES API verwendet haben, um Intent-Parameter auf eine Weise zu erstellen, die nicht mit den Trainingsformulierungen übereinstimmte. Benennen Sie den Dialogflow ES-Parameter in der Console um, prüfen Sie, ob Ihre Trainingsformulierungen den Parameter richtig verwenden, und klicken Sie dann auf „Speichern“. Das kann auch passieren, wenn Ihre Trainingsformulierungen auf nicht vorhandene Parameter verweisen.

Nachdem Sie die Fehler behoben haben, müssen Sie die Intents und Entitäten des Dialogflow CX-Agenten löschen, bevor Sie das Migrationstool noch einmal ausführen.

Dialogflow ES-Intent-Daten in Dialogflow CX verschieben

Das Tool migriert Intent-Trainingsformulierungen und -Parameter zu Dialogflow CX-Intents. Es gibt jedoch viele andere Dialogflow ES-Intent-Felder, die manuell migriert werden müssen.

Für einen Dialogflow ES-Intent ist möglicherweise eine entsprechende Dialogflow CX-Seite, ein entsprechender Dialogflow CX-Intent oder beides erforderlich.

Wenn eine Dialogflow ES-Intent-Übereinstimmung verwendet wird, um die Unterhaltung von einem bestimmten Unterhaltungsknoten zu einem anderen zu übertragen, sollten Sie zwei Seiten in Ihrem Agent haben, die sich auf diesen Intent beziehen:

  • Die ursprüngliche Seite, die die Intent-Route enthält, die zur nächsten Seite übergeht: Die Intent-Route auf der ursprünglichen Seite kann Dialogflow CX-Ausführungsnachrichten enthalten, die den Dialogflow ES-Intent-Antworten ähneln. Auf dieser Seite können viele Intent-Routen vorhanden sein. Während die ursprüngliche Seite aktiv ist, können diese Intent-Routen die Unterhaltung auf viele mögliche Pfade umleiten. Viele Dialogflow ES-Intents haben dieselbe entsprechende Dialogflow CX-Originalseite.
  • Die nächste Seite, die das Übergangsziel für die Intent-Route auf der ursprünglichen Seite ist: Die Dialogflow CX-Eintragsausführung für die nächste Seite kann Dialogflow CX-Ausführungsnachrichten enthalten, die den Dialogflow ES-Intent-Antworten ähneln.

Wenn ein Dialogflow ES-Intent erforderliche Parameter enthält, sollten Sie eine entsprechende Dialogflow CX-Seite mit denselben Parametern in einem Formular erstellen.

Es ist üblich, dass ein Dialogflow CX-Intent und eine Dialogflow CX-Seite dieselbe Parameterliste haben. Das bedeutet, dass ein einzelner Dialogflow ES-Intent eine entsprechende Dialogflow CX-Seite und einen entsprechenden Dialogflow CX-Intent hat. Wenn ein Dialogflow CX-Intent mit Parametern in einer Intent-Route übereinstimmt, wechselt die Unterhaltung oft zu einer Seite mit denselben Parametern. Die aus der Intent-Übereinstimmung extrahierten Parameter werden an Sitzungsparameter weitergegeben, die zum teilweisen oder vollständigen Ausfüllen von Seitenformularparametern verfügbar sind.

Fallback-Intents und vordefinierte Follow-up-Intents sind in Dialogflow CX nicht vorhanden. Weitere Informationen finden Sie unter Integrierte Intents.

In der folgenden Tabelle wird beschrieben, wie Sie bestimmte Intent-Daten von Dialogflow ES zu Dialogflow CX-Ressourcen zuordnen:

Dialogflow ES-Intent-Daten Entsprechende Dialogflow CX-Daten Dringend
Trainingssätze Trainingsformulierungen für Intents Per Tool migriert. Das Tool prüft, ob Systementitäten unterstützt werden, und erstellt TODO-Elemente für nicht unterstützte Systementitäten.
Agentenantworten Antwortnachrichten für die Auftragsausführung Antworten des KI-Agenten ansehen
Kontext für die Unterhaltungssteuerung Keine Weitere Informationen finden Sie unter Struktur und Steuerung des Unterhaltungspfads.
Webhook-Einstellung Webhook-Konfiguration für Auftragsausführung Weitere Informationen finden Sie unter Webhooks.
Ereignisse Ereignis-Handler auf Ablauf- oder Seitenebene Weitere Informationen finden Sie unter Ereignisse.
Aktionen Webhook-Tags für Auftragsausführung Weitere Informationen finden Sie unter Webhooks.
Parameter Intent-Parameter und/oder Seitenformularparameter Migriert zu Intent-Parametern nach Tool. Wenn die Parameter erforderlich sind, erstellt das Tool TODO-Elemente, um sie möglicherweise auf eine Seite zu migrieren. Siehe Parameter.
Parameter-Prompts Prompts für Seitenformularparameter Weitere Informationen finden Sie unter Formulare ausfüllen.

Abläufe erstellen

Erstellen Sie für jedes allgemeine Gesprächsthema einen Ablauf. Die Themen in jedem Ablauf sollten sich voneinander unterscheiden, damit die Unterhaltung nicht häufig zwischen Abläufen hin- und herwechselt.

Wenn Sie einen Mega-Agenten verwendet haben, sollte jeder Sub-Agent zu einem oder mehreren Abläufen werden.

Mit einfachen Unterhaltungspfaden beginnen

Am besten testen Sie Ihren Agenten mit dem Simulator, während Sie Änderungen vornehmen. Konzentrieren Sie sich also zu Beginn der Unterhaltung auf die grundlegenden Unterhaltungspfade und testen Sie, während Sie Änderungen vornehmen. Sobald diese funktionieren, können Sie zu detaillierteren Unterhaltungspfaden übergehen.

Zustandshandler auf Ablaufebene im Vergleich zu Zustandshandlern auf Seitenebene

Überlegen Sie beim Erstellen von Status-Handlern, ob sie auf Ablauf- oder Seitenebene angewendet werden sollen. Ein Handler auf Ablaufebene ist immer dann im Bereich, wenn der Ablauf (und damit jede Seite im Ablauf) aktiv ist. Ein Handler auf Seitenebene ist nur aktiv, wenn die entsprechende Seite aktiv ist. Handler auf Ablaufebene ähneln Dialogflow ES-Intents ohne Eingabekontext. Handler auf Seitenebene ähneln Dialogflow ES-Intents mit Eingabekontext.

Webhook-Code

Die Webhook-Anfrage- und -Antwortattribute unterscheiden sich für Dialogflow CX. Weitere Informationen finden Sie im Abschnitt zu Webhooks.

Wissensconnectors

Dialogflow CX unterstützt noch keine Wissens-Connectors. Sie müssen diese als normale Intents implementieren oder warten, bis Dialogflow CX Wissens-Connectors unterstützt.

Agent-Einstellungen

Prüfen Sie die Einstellungen für den Dialogflow ES-Agenten und passen Sie die Einstellungen für den Dialogflow CX-Agenten nach Bedarf an.

TODO-Datei verwenden

Das Migrationstool gibt eine CSV-Datei aus. Die Elemente in dieser Liste beziehen sich auf bestimmte Daten, die möglicherweise Aufmerksamkeit erfordern. Importieren Sie diese Datei in eine Tabelle. Lösen Sie jedes Element in der Tabelle und verwenden Sie eine Spalte, um die Fertigstellung zu markieren.

Migration der API-Nutzung

Wenn Ihr System die Dialogflow ES API für Laufzeit- oder Designzeitaufrufe verwendet, müssen Sie diesen Code aktualisieren, um die Dialogflow CX API zu verwenden. Wenn Sie die Intent-Erkennungsaufrufe nur zur Laufzeit verwenden, sollte diese Aktualisierung ziemlich einfach sein.

Integrationen

Wenn Ihr Agent Integrationen verwendet, lesen Sie den Abschnitt zu Integrationen und nehmen Sie die erforderlichen Änderungen vor.

In den folgenden Abschnitten werden die empfohlenen Migrationsschritte beschrieben.

Validierung

Verwenden Sie die Agent-Validierung, um zu prüfen, ob Ihr Agent den Best Practices entspricht.

Test

Während Sie die oben beschriebenen manuellen Migrationsschritte ausführen, sollten Sie Ihren Agenten mit dem Simulator testen. Sobald Ihr Agent funktioniert, sollten Sie die Unterhaltungen zwischen Ihren Dialogflow ES- und Dialogflow CX-Agenten vergleichen und prüfen, ob das Verhalten ähnlich oder verbessert ist.

Wenn Sie diese Unterhaltungen mit dem Simulator testen, sollten Sie Testläufe erstellen, um zukünftige Regressionen zu vermeiden.

Umgebungen

Prüfen Sie Ihre Dialogflow ES-Umgebungen und aktualisieren Sie Ihre Dialogflow CX-Umgebungen nach Bedarf.