Migrazione da Dialogflow ES a Dialogflow CX

Gli agenti Dialogflow CX ti offrono strumenti e controlli di conversazione più potenti rispetto agli agenti Dialogflow ES. Se l'agente Dialogflow ES gestisce conversazioni complesse, ti consigliamo di eseguire la migrazione a Dialogflow CX.

Questa guida descrive come eseguire la migrazione di un agente da Dialogflow ES a Dialogflow CX. Questi due tipi di agenti presentano molte differenze fondamentali, quindi non esiste un modo semplice per eseguire questa migrazione.

Se utilizzi questa guida per una migrazione, fornisci un feedback positivo o negativo facendo clic sul pulsante Invia feedback in alto. Utilizzeremo questo feedback per migliorare questa guida nel tempo.

A livello generale, il processo consigliato è un processo ibrido automatizzato/manuale. Utilizzerai uno strumento che legge alcuni dati dell'agente Dialogflow ES, li scrive nell'agente Dialogflow CX e acquisisce un elenco di cose da fare. Poi, ricrea l'intero agente Dialogflow CX utilizzando le best practice, l'elenco di cose da fare e i dati di cui è stata eseguita la migrazione con lo strumento.

Comprendi Dialogflow CX

Prima di tentare questa migrazione, devi avere una solida conoscenza del funzionamento dei flussi di Dialogflow CX. Puoi iniziare da qui:

Dovresti anche leggere altri documenti sui concetti che presentano funzionalità di cui probabilmente avrai bisogno nel nuovo agente. Concentrati sui seguenti aspetti:

Comprendi le differenze tra Dialogflow ES e Dialogflow CX

Questa sezione elenca le differenze più importanti tra Dialogflow ES e Dialogflow CX. Quando esegui i passaggi di migrazione manuale in un secondo momento, consulta questa sezione per indicazioni.

Controllo della struttura e del percorso della conversazione

Dialogflow ES fornisce quanto segue per il controllo della struttura e del percorso di conversazione:

  • Gli intent vengono utilizzati come elementi di base dell'agente. In qualsiasi momento della conversazione, viene trovato un intent corrispondente e, in un certo senso, ogni intent è un nodo della conversazione.
  • Context viene utilizzato per controllare la conversazione. Il contesto viene utilizzato per controllare quali intent possono essere abbinati in un determinato momento. Il contesto scade dopo un certo numero di turni di conversazione, quindi questo tipo di controllo può essere impreciso per le conversazioni lunghe.

Dialogflow CX fornisce una gerarchia di risorse strutturali e controlli più precisi sul percorso della conversazione:

  • Le pagine sono i nodi del grafico della conversazione. Le conversazioni di Dialogflow CX sono simili alle macchine a stati. In qualsiasi momento della conversazione, una pagina è attiva. In base all'input o agli eventi dell'utente finale, la conversazione può passare a un'altra pagina. È comune che una pagina rimanga attiva per più turni di conversazione.
  • I flussi sono gruppi di pagine correlate. Ogni flusso deve gestire un argomento di conversazione di alto livello.
  • I gestori di stato vengono utilizzati per controllare le transizioni e le risposte. Esistono tre tipi di gestori dello stato:
    • Percorso di intent: contiene un intent che deve essere abbinato, risposte facoltative e una transizione di pagina facoltativa.
    • Percorso condizionale: contiene una condizione che deve essere soddisfatta, risposte facoltative e una transizione di pagina facoltativa.
    • Gestore di eventi: contiene un nome evento che deve essere richiamato, risposte facoltative e una transizione di pagina facoltativa.
  • L'ambito viene utilizzato per controllare se è possibile chiamare un gestore dello stato. La maggior parte dei gestori è associata a una pagina o a un intero flusso. Se la pagina o il flusso associato è attivo, il gestore è incluso nell'ambito e può essere chiamato. Una route di intent Dialogflow CX nell'ambito è simile a un intent Dialogflow ES con un contesto di input attivo.

Quando progetti i flussi e le pagine dell'agente, assicurati di comprendere i consigli riportati nella sezione sui flussi della guida alla progettazione degli agenti.

Compilazione di moduli

Dialogflow ES utilizza la compilazione degli slot per raccogliere i parametri obbligatori dall'utente finale:

  • Questi parametri sono parametri di intent contrassegnati come obbligatori.
  • L'intent continua a essere abbinato finché non vengono raccolti tutti i parametri obbligatori.
  • Puoi definire un prompt che chieda all'utente finale di fornire un valore.

Dialogflow CX utilizza la compilazione dei moduli per raccogliere i parametri obbligatori dall'utente finale:

  • Questi parametri sono associati a una pagina e vengono raccolti mentre la pagina è attiva.
  • Utilizza i percorsi condizionali per le pagine per determinare che la compilazione del modulo è completa. Questi percorsi di condizione in genere passano a un'altra pagina.
  • Puoi definire un prompt e i gestori di nuovi prompt per gestire in modo ottimale più tentativi di raccolta di un valore.

Transizioni

Dialogflow ES passa automaticamente da un intent all'altro quando l'input utente finale viene associato a un intent. Questa corrispondenza può verificarsi solo per gli intent che non hanno un contesto di input o per gli intent che hanno un contesto di input attivo.

Dialogflow CX passa da una pagina all'altra quando un gestore dello stato nell'ambito soddisfa i requisiti e fornisce un target di transizione. Utilizzando queste transizioni, puoi guidare in modo affidabile gli utenti finali attraverso le conversazioni. Esistono diversi modi per controllare queste transizioni:

  • La corrispondenza degli intent può attivare un percorso di intent.
  • La soddisfazione di una condizione può attivare un percorso condizionale.
  • La chiamata di un evento può attivare un gestore di eventi.
  • I gestori di nuovi prompt possono causare una transizione quando l'utente finale non riesce a fornire un valore dopo più tentativi.
  • Puoi utilizzare i target di transizione simbolici per i target di transizione.

Risposte dell'agente

Le risposte dell'agente Dialogflow ES vengono inviate all'utente finale quando viene trovato un intent corrispondente:

  • L'agente può selezionare un messaggio per la risposta da un elenco di possibili risposte.
  • Le risposte possono essere specifiche per la piattaforma, che può utilizzare formati di risposta avanzata.
  • Le risposte possono essere gestite dai webhook.

Le risposte dell'agente Dialogflow CX vengono inviate all'utente finale quando viene chiamato il fulfillment. A differenza del fulfillment di Dialogflow ES, che prevede sempre un webhook, il fulfillment di Dialogflow CX può prevedere o meno la chiamata di un webhook, a seconda che la risorsa di fulfillment abbia o meno un webhook configurato. Sia le risposte statiche che quelle dinamiche basate sulle risposte del webhook sono controllate dal fulfillment. Esistono diversi modi per creare le risposte dell'agente:

  • Il fulfillment può essere fornito a qualsiasi tipo di gestore di stato.
  • È possibile concatenare più risposte durante un turno di conversazione tramite la coda di risposte. In alcuni casi, questa funzionalità può semplificare la progettazione dell'agente.
  • Dialogflow CX non supporta le risposte integrate specifiche per la piattaforma. Tuttavia, fornisce diversi tipi di risposta, tra cui un payload personalizzato che può essere utilizzato per risposte specifiche per la piattaforma.

Parametri

I parametri di Dialogflow ES hanno le seguenti caratteristiche:

  • Definito solo negli intent.
  • Impostati da input utente finale, eventi, webhook e chiamate API.
  • Riferimento nelle risposte, nei prompt dei parametri, nel codice webhook e nei valori parametro:
    • Il formato di riferimento di base è $parameter-name.
    • I riferimenti supportano la sintassi dei suffissi .original, .partial e .recent.
    • I riferimenti possono specificare il contesto attivo: #context-name.parameter-name.
    • I riferimenti possono specificare i parametri evento: #event-name.parameter-name.

I parametri di Dialogflow CX hanno le seguenti caratteristiche:

  • Definiti negli intent e nei moduli delle pagine.
  • I parametri di intent e modulo vengono propagati ai parametri di sessione, dove sono disponibili per il riferimento per la durata della sessione.
  • Impostati dall'input utente finale, dai webhook, dal valore preimpostato del parametro di fulfillment e dalle chiamate API.
  • Riferimento in risposte, prompt dei parametri, gestori di nuovi prompt, preset dei parametri e codice webhook:
    • Il formato di riferimento è $session.params.parameter-id per i parametri di sessione e $intent.params.parameter-id per i parametri di intent.
    • I riferimenti ai parametri di intent supportano la sintassi dei suffissi .original e .resolved. I parametri di sessione non supportano questa sintassi.

Entità di sistema

Dialogflow ES supporta molte entità di sistema.

Dialogflow CX supporta molte delle stesse entità di sistema, ma esistono alcune differenze. Durante la migrazione, verifica che le entità di sistema che utilizzi in Dialogflow ES siano supportate anche da Dialogflow CX per la stessa lingua. In caso contrario, dovresti creare entità personalizzate per questi elementi.

Eventi

Gli eventi di Dialogflow ES hanno le seguenti caratteristiche:

  • Può essere richiamato da chiamate API o webhook per trovare un intent corrispondente.
  • Può impostare i parametri.
  • Un numero limitato di eventi viene richiamato dalle piattaforme di integrazione.

Gli eventi Dialogflow CX hanno le seguenti caratteristiche:

  • Può essere richiamato da chiamate API o webhook per chiamare un gestore di eventi.
  • Impossibile impostare i parametri.
  • Molti eventi integrati possono essere utilizzati per gestire la mancanza di input utente dell'utente finale, l'input utente finale non riconosciuto, i parametri invalidati da un webhook e gli errori del webhook.
  • Le chiamate possono essere controllate dalle stesse regole di definizione dell'ambito di altri gestori di stato.

Intent integrati

Dialogflow ES supporta i seguenti intent integrati:

Di seguito è descritto il supporto di Dialogflow CX per gli intent integrati:

  • Gli intent di benvenuto sono supportati.
  • Gli intent di fallback non vengono forniti. Utilizza invece gli eventi no-match nei gestori di eventi.
  • Per gli esempi negativi, utilizza l'intent negativo predefinito.
  • Non vengono forniti intent di follow-up predefiniti. Devi creare questi intent in base alle esigenze del tuo agente. Ad esempio, probabilmente dovrai creare un intent per gestire le risposte negative a una domanda dell'agente ("no", "no grazie", "no, non voglio" e così via). Gli intent di Dialogflow CX sono riutilizzabili nell'agente, quindi devi definirli una sola volta. L'utilizzo di percorsi di intent diversi per questi intent comuni, in ambiti diversi, ti offre un controllo molto migliore sulla conversazione.

Webhook

I webhook di Dialogflow ES hanno le seguenti caratteristiche:

  • Puoi configurare un servizio webhook per l'agente.
  • Ogni intent può essere contrassegnato come utilizzatore del webhook.
  • Non è previsto un supporto integrato per la gestione degli errori dei webhook.
  • Le azioni o i nomi degli intent vengono utilizzati dai webhook per determinare da dove sono stati chiamati nell'agente.
  • La console fornisce l'editor in linea.

I webhook di Dialogflow CX hanno le seguenti caratteristiche:

  • Puoi configurare più servizi webhook per l'agente.
  • Ogni fulfillment può facoltativamente specificare una chiamata webhook.
  • È disponibile il supporto integrato per la gestione degli errori del webhook.
  • Un webhook di fulfillment di Dialogflow CX contiene un tag. Questo tag è simile a un'azione Dialogflow ES, ma viene utilizzato solo quando vengono chiamati i webhook. Il servizio webhook può utilizzare questi tag per determinare da dove è stato chiamato nell'agente.
  • La console non dispone di un editor di codice webhook integrato. È comune utilizzare Cloud Run Functions, ma esistono molte opzioni.

Quando esegui la migrazione a Dialogflow CX, devi modificare il codice del webhook, poiché le proprietà della richiesta e della risposta sono diverse.

Integrazioni

Le integrazioni di Dialogflow ES e le integrazioni di Dialogflow CX supportano piattaforme diverse. Per le piattaforme supportate da entrambi i tipi di agenti, potrebbero esserci differenze nella configurazione.

Se l'integrazione di Dialogflow ES che utilizzavi non è supportata da Dialogflow CX, potresti dover cambiare piattaforma o implementare l'integrazione autonomamente.

Altre funzionalità esclusive di Dialogflow CX

Esistono molte altre funzionalità fornite solo da Dialogflow CX. Ti consigliamo di valutare l'utilizzo di queste funzionalità durante la migrazione. Ad esempio:

Best practice

Prima della migrazione, acquisisci familiarità con le best practice per la progettazione degli agenti Dialogflow CX. Molte di queste best practice di Dialogflow CX sono simili a quelle di Dialogflow ES, ma alcune sono specifiche di Dialogflow CX.

Informazioni sullo strumento di migrazione

Lo strumento di migrazione copia la maggior parte dei dati di Dialogflow ES nell'agente Dialogflow CX e scrive in un file TODO con un elenco di elementi di cui è necessario eseguire la migrazione manuale. Lo strumento copia solo i tipi di entità personalizzate e le frasi di addestramento degli intent. Ti consigliamo di personalizzare questo strumento in base alle tue esigenze specifiche.

Codice dello strumento di migrazione

Ecco il codice per lo strumento. Ti consigliamo di esaminare il codice di questo strumento per capire cosa fa. Potresti voler modificare questo codice per gestire situazioni specifiche nell'agente. Nei passaggi seguenti, eseguirai questo strumento.

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

Migrazione degli strumenti dei tipi di entità

I tipi di entità Dialogflow ES e i tipi di entità Dialogflow CX sono molto simili, quindi sono il tipo di dati più facile da migrare. Lo strumento copia semplicemente i tipi di entità così come sono.

Migrazione degli intent dello strumento

Gli intent di Dialogflow ES e gli intent di Dialogflow CX sono molto diversi.

Gli intent di Dialogflow ES vengono utilizzati come elementi di base dell'agente e contengono frasi di addestramento, risposte, contesto per il controllo della conversazione, configurazioni di webhook, eventi, azioni e parametri di compilazione degli slot.

Dialogflow CX ha spostato la maggior parte di questi dati in altre risorse. Gli intent di Dialogflow CX hanno solo frasi di addestramento e parametri, il che li rende riutilizzabili nell'agente. Lo strumento copia solo questi due tipi di dati di intent nei tuoi intent di Dialogflow CX.

Limitazioni dello strumento di migrazione

Lo strumento di migrazione non supporta quanto segue:

  • Mega agenti: lo strumento non può leggere da più sub-agenti, ma puoi chiamarlo più volte per ogni sub-agente.
  • Agenti multilingue: devi modificare lo strumento per creare frasi di addestramento e voci di entità multilingue.
  • Verifica delle entità di sistema per lingue diverse dall'inglese: lo strumento crea elementi TODO quando trova entità di sistema non supportate da Dialogflow CX, partendo dal presupposto che l'inglese sia la lingua predefinita e che utilizzi una regione degli Stati Uniti. Il supporto delle entità di sistema varia in base alla lingua e alla regione. Per altre lingue e regioni, devi modificare lo strumento per eseguire questo controllo.

Passaggi essenziali per la migrazione

Le sottosezioni seguenti descrivono i passaggi di migrazione da eseguire. Non è necessario seguire questi passaggi manuali in ordine e potresti anche doverli eseguire contemporaneamente o in un ordine diverso. Leggi i passaggi e inizia a pianificare le modifiche prima di apportarle effettivamente.

Dopo aver eseguito lo strumento di migrazione, puoi ricreare l'agente Dialogflow CX. Dovrai comunque eseguire un po' di lavoro di migrazione, ma la maggior parte dei dati inseriti manualmente sarà presente nell'agente Dialogflow CX e nel file TODO.

Crea l'agente Dialogflow CX

Se non l'hai ancora fatto, crea il tuo agente Dialogflow CX. Assicurati di utilizzare la stessa lingua predefinita dell'agente Dialogflow ES.

Esegui lo strumento di migrazione

Per eseguire lo strumento, segui questi passaggi:

  1. Se non l'hai ancora fatto, installa Go sulla tua macchina.
  2. Crea una directory per il codice dello strumento denominata migrate.
  3. Copia il codice dello strumento riportato sopra in un file denominato main.go in questa directory.
  4. Se necessario, modifica il codice in base al tuo caso.
  5. Crea un modulo Go in questa directory. Ad esempio:

    go mod init migrate
    
  6. Installa le librerie client Go di Dialogflow ES V2 e Dialogflow CX V3:

    go get cloud.google.com/go/dialogflow/apiv2
    go get cloud.google.com/go/dialogflow/cx/apiv3
    
  7. Assicurati di aver configurato l'autenticazione della libreria client.

  8. Esegui lo strumento e salva l'output nel file:

    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
    

Risoluzione dei problemi dello strumento di migrazione

Se si verificano errori durante l'esecuzione dello strumento, controlla quanto segue:

Errore Risoluzione
Errore RPC che indica che una parte della frase di addestramento menziona un parametro non definito per l'intent. Questo può accadere se in precedenza hai utilizzato l'API Dialogflow ES per creare parametri di intent in un modo non coerente con le frasi di addestramento. Per risolvere il problema, rinomina il parametro Dialogflow ES dalla console, verifica che le frasi di addestramento utilizzino il parametro correttamente e poi fai clic su Salva. Questo può accadere anche se le frasi di addestramento fanno riferimento a parametri inesistenti.

Dopo aver corretto gli errori, dovrai cancellare gli intent e le entità dell'agente Dialogflow CX prima di eseguire nuovamente lo strumento di migrazione.

Spostamento dei dati degli intent di Dialogflow ES in Dialogflow CX

Lo strumento esegue la migrazione dei parametri e delle frasi di addestramento degli intent agli intent di Dialogflow CX, ma esistono molti altri campi degli intent di Dialogflow ES di cui eseguire la migrazione manualmente.

Un intent Dialogflow ES potrebbe richiedere una pagina Dialogflow CX corrispondente, un intent Dialogflow CX corrispondente o entrambi.

Se viene utilizzata una corrispondenza di intent Dialogflow ES per trasferire la conversazione da un determinato nodo di conversazione a un altro, l'agente deve avere due pagine correlate a questo intent:

  • La pagina originale che contiene il percorso dell'intent, che passerà alla pagina successiva: il percorso dell'intent nella pagina originale potrebbe contenere messaggi di fulfillment di Dialogflow CX simili alle risposte dell'intent di Dialogflow ES. In questa pagina potrebbero essere presenti molti percorsi di intent. Mentre la pagina originale è attiva, questi percorsi di intent possono indirizzare la conversazione verso molti percorsi possibili. Molti intent di Dialogflow ES condivideranno la stessa pagina originale di Dialogflow CX corrispondente.
  • La pagina successiva, che è la destinazione della transizione per la route dell'intent nella pagina originale: il fulfillment di ingresso di Dialogflow CX per la pagina successiva potrebbe avere messaggi di fulfillment di Dialogflow CX simili alle risposte dell'intent di Dialogflow ES.

Se un intent Dialogflow ES contiene parametri obbligatori, devi creare una pagina Dialogflow CX corrispondente con gli stessi parametri in un modulo.

È comune che un intent Dialogflow CX e una pagina Dialogflow CX condividano lo stesso elenco di parametri, il che significa che un singolo intent Dialogflow ES ha una pagina Dialogflow CX corrispondente e un intent Dialogflow CX corrispondente. Quando viene trovato un intent di Dialogflow CX con parametri in un percorso di intent, la conversazione spesso passa a una pagina con gli stessi parametri. I parametri estratti dalla corrispondenza dell'intent vengono propagati ai parametri di sessione, che sono disponibili per compilare parzialmente o completamente i parametri del modulo della pagina.

Gli intent di fallback e gli intent di follow-up predefiniti non esistono in Dialogflow CX. Consulta gli intent integrati.

La tabella seguente descrive come mappare dati di intent specifici da Dialogflow ES alle risorse Dialogflow CX:

Dati degli intent di Dialogflow ES Dati Dialogflow CX corrispondenti Azione richiesta
Frasi di addestramento Frasi di addestramento dell'intent Migrazione eseguita dallo strumento. Lo strumento verifica il supporto delle entità di sistema e crea elementi TODO per le entità di sistema non supportate.
Risposte dell'agente Messaggi di risposta del fulfillment Visualizza le risposte dell'agente.
Contesto per il controllo della conversazione Nessuno Consulta Controllo della struttura e del percorso di conversazione.
Impostazione webhook Configurazione del webhook di fulfillment Consulta la sezione Webhook.
Eventi Gestori di eventi a livello di flusso o di pagina Vedi la sezione Eventi.
Azioni Tag webhook di fulfillment Consulta la sezione Webhook.
Parametri Parametri di intent e/o parametri del modulo della pagina Migrazione ai parametri di intent per strumento. Se i parametri sono obbligatori, lo strumento crea elementi DA FARE per un'eventuale migrazione a una pagina. Consulta i parametri.
Prompt dei parametri Prompt dei parametri del modulo della pagina Consulta la sezione Compilazione dei moduli.

Crea flussi

Crea un flusso per ogni argomento di conversazione di alto livello. Gli argomenti di ogni flusso devono essere distinti, in modo che la conversazione non passi continuamente da un flusso all'altro.

Se utilizzavi un mega-agente, ogni agente secondario deve diventare uno o più flussi.

Inizia con percorsi di conversazione di base

È consigliabile testare l'agente con il simulatore durante l'iterazione delle modifiche. Pertanto, inizialmente dovresti concentrarti sui percorsi di conversazione di base all'inizio della conversazione ed eseguire test man mano che apporti modifiche. Una volta che questi funzionano, passa a percorsi di conversazione più dettagliati.

Gestori degli stati a livello di flusso e a livello di pagina

Quando crei i gestori degli stati, valuta se devono essere applicati a livello di flusso o di pagina. Un gestore a livello di flusso è nell'ambito ogni volta che il flusso (e quindi qualsiasi pagina al suo interno) è attivo. Un gestore a livello di pagina è attivo solo quando la pagina specifica è attiva. I gestori a livello di flusso sono simili agli intent di Dialogflow ES senza contesto di input. I gestori a livello di pagina sono simili agli intent di Dialogflow ES con contesto di input.

Codice webhook

Le proprietà della richiesta e della risposta del webhook sono diverse per Dialogflow CX. Consulta la sezione sui webhook.

Connettori di conoscenza

Dialogflow CX non supporta ancora i connettori di conoscenza. Dovrai implementarli come intent normali o attendere che Dialogflow CX supporti i connettori di conoscenza.

Impostazioni dell'agente

Esamina le impostazioni dell'agente Dialogflow ES e modifica le impostazioni dell'agente Dialogflow CX in base alle esigenze.

Utilizza il file TODO

Lo strumento di migrazione genera un file CSV. Gli elementi di questo elenco si concentrano su dati specifici che potrebbero richiedere attenzione. Importa questo file in un foglio di lavoro. Risolvi ogni elemento nel foglio di lavoro, utilizzando una colonna per contrassegnare il completamento.

Migrazione dell'utilizzo delle API

Se il tuo sistema utilizza l'API Dialogflow ES per le chiamate di runtime o design-time, dovrai aggiornare questo codice per utilizzare l'API Dialogflow CX. Se utilizzi solo le chiamate di rilevamento dell'intent in fase di runtime, questo aggiornamento dovrebbe essere abbastanza semplice.

Integrazioni

Se l'agente utilizza integrazioni, consulta la sezione Integrazioni e apporta le modifiche necessarie.

Le sottosezioni seguenti descrivono i passaggi di migrazione consigliati.

Convalida

Utilizza la convalida dell'agente per verificare che l'agente segua le best practice.

Test

Durante l'esecuzione dei passaggi di migrazione manuale descritti sopra, devi testare l'agente con il simulatore. Una volta che l'agente sembra funzionare, devi confrontare le conversazioni tra gli agenti Dialogflow ES e Dialogflow CX e verificare che il comportamento sia simile o migliorato.

Durante il test di queste conversazioni con il simulatore, devi creare scenari di test per evitare future regressioni.

Ambienti

Esamina gli ambienti Dialogflow ES e aggiorna gli ambienti Dialogflow CX in base alle necessità.